diff options
Diffstat (limited to 'comm/suite/components/pref/content')
70 files changed, 9174 insertions, 0 deletions
diff --git a/comm/suite/components/pref/content/pref-advanced.js b/comm/suite/components/pref/content/pref-advanced.js new file mode 100644 index 0000000000..1f1c290329 --- /dev/null +++ b/comm/suite/components/pref/content/pref-advanced.js @@ -0,0 +1,90 @@ +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const {AppConstants} = ChromeUtils.import("resource://gre/modules/AppConstants.jsm"); +const {ShellService} = ChromeUtils.import("resource:///modules/ShellService.jsm"); + +var defaultClient = 0; +var defaultApps = 0; + +function Startup() +{ + InitPlatformIntegration(); + CrashReportsCheck(); +} + +/** + * System preferences + */ + +function InitPlatformIntegration() { + if (ShellService) { + try { + this.defaultApps = ShellService.shouldBeDefaultClientFor; + ["Browser", "Mail", "News", "Rss"].forEach(function(aType) { + let button = document.getElementById("setDefault" + aType); + try { + let client = Ci.nsIShellService[aType.toUpperCase()]; + let isDefault = ShellService.isDefaultClient(false, client); + if (isDefault) { + this.defaultClient |= client; + } + button.disabled = isDefault; + document.getElementById("defaultClientGroup").hidden = false; + } catch (e) { + button.hidden = true; + } + }); + } catch (e) { + } + } +} + +function ApplySetAsDefaultClient() { + let pane = document.getElementById("advanced_pane"); + ShellService.setDefaultClient(false, false, pane.defaultClient); + ShellService.shouldBeDefaultClientFor = pane.defaultApps; +} + +function onSetDefault(aButton, aType) { + if (document.documentElement.instantApply) { + ShellService.setDefaultClient(false, false, Ci.nsIShellService[aType]); + ShellService.shouldBeDefaultClientFor |= Ci.nsIShellService[aType]; + } else { + this.defaultClient |= Ci.nsIShellService[aType]; + this.defaultApps |= Ci.nsIShellService[aType]; + window.addEventListener("dialogaccept", this.ApplySetAsDefaultClient, true); + } + + aButton.disabled = true; +} + +function onNewsChange(aChecked) { + let snws = document.getElementById("network.protocol-handler.external.snews"); + let nntp = document.getElementById("network.protocol-handler.external.nntp"); + + if (!snws.locked) + snws.value = aChecked; + + if (!nntp.locked) + nntp.value = aChecked; +} + +function CrashReportsCheck() +{ + if (AppConstants.MOZ_CRASHREPORTER) { + var cr = Cc["@mozilla.org/toolkit/crash-reporter;1"] + .getService(Ci.nsICrashReporter); + document.getElementById("crashReports").hidden = !cr.enabled; + document.getElementById("submitCrashes").checked = cr.submitReports; + } +} + +function updateSubmitCrashes(aChecked) +{ + Cc["@mozilla.org/toolkit/crash-reporter;1"] + .getService(Ci.nsICrashReporter) + .submitReports = aChecked; +} diff --git a/comm/suite/components/pref/content/pref-advanced.xul b/comm/suite/components/pref/content/pref-advanced.xul new file mode 100644 index 0000000000..6b77581e4c --- /dev/null +++ b/comm/suite/components/pref/content/pref-advanced.xul @@ -0,0 +1,174 @@ +<?xml version="1.0"?> + +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<!DOCTYPE overlay [ + <!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd"> %brandDTD; + <!ENTITY % prefAdvancedDTD SYSTEM "chrome://communicator/locale/pref/pref-advanced.dtd"> %prefAdvancedDTD; +]> + +<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <prefpane id="advanced_pane" + label="&pref.advanced.title;" + script="chrome://communicator/content/pref/pref-advanced.js"> + + <preferences id="advanced_preferences"> + <preference id="shell.checkDefaultClient" + name="shell.checkDefaultClient" + type="bool"/> + <preference id="pref.browser.disable_button.default_browser" + name="pref.browser.disable_button.default_browser" + type="bool" + readonly="true"/> + <preference id="system.windows.lock_ui.defaultMailClient" + name="system.windows.lock_ui.defaultMailClient" + type="bool" + readonly="true"/> + <preference id="system.windows.lock_ui.defaultNewsClient" + name="system.windows.lock_ui.defaultNewsClient" + type="bool" + readonly="true"/> + <preference id="system.windows.lock_ui.defaultFeedClient" + name="system.windows.lock_ui.defaultFeedClient" + type="bool" + readonly="true"/> + <preference id="network.protocol-handler.external.mailto" + name="network.protocol-handler.external.mailto" + type="bool" + inverted="true"/> + <preference id="network.protocol-handler.external.news" + name="network.protocol-handler.external.news" + type="bool" + inverted="true"/> + <preference id="network.protocol-handler.external.snews" + name="network.protocol-handler.external.snews" + type="bool" + inverted="true"/> + <preference id="network.protocol-handler.external.nntp" + name="network.protocol-handler.external.nntp" + type="bool" + inverted="true"/> + <preference id="print.use_native_print_dialog" + name="print.use_native_print_dialog" + type="bool"/> + <preference id="print.use_global_printsettings" + name="print.use_global_printsettings" + type="bool"/> + <preference id="devtools.debugger.remote-enabled" + name="devtools.debugger.remote-enabled" + type="bool"/> + <preference id="devtools.debugger.force-local" + name="devtools.debugger.force-local" + inverted="true" + type="bool"/> + <preference id="devtools.debugger.prompt-connection" + name="devtools.debugger.prompt-connection" + type="bool"/> + <preference id="devtools.debugger.remote-port" + name="devtools.debugger.remote-port" + type="int"/> + </preferences> + + <groupbox id="defaultClientGroup" hidden="true"> + <caption label="&prefCheckDefault.caption;"/> + <checkbox id="checkDefaultClient" + label="&prefCheckDefaultClient.label;" + accesskey="&prefCheckDefaultClient.accesskey;" + preference="shell.checkDefaultClient"/> + <vbox> + <separator class="thin"/> + + <description>&defaultClientFor.description;</description> + <hbox class="indent" align="center"> + <button id="setDefaultBrowser" + label="&setDefaultBrowser.label;" + accesskey="&setDefaultBrowser.accesskey;" + oncommand="onSetDefault(this, 'BROWSER');" + preference="pref.browser.disable_button.default_browser"/> + <button id="setDefaultMail" + label="&setDefaultMail.label;" + accesskey="&setDefaultMail.accesskey;" + oncommand="onSetDefault(this, 'MAIL');" + preference="system.windows.lock_ui.defaultMailClient"/> + <button id="setDefaultNews" + label="&setDefaultNews.label;" + accesskey="&setDefaultNews.accesskey;" + oncommand="onSetDefault(this, 'NEWS');" + preference="system.windows.lock_ui.defaultNewsClient"/> + <button id="setDefaultRss" + label="&setDefaultFeed.label;" + accesskey="&setDefaultFeed.accesskey;" + oncommand="onSetDefault(this, 'RSS');" + preference="system.windows.lock_ui.defaultFeedClient"/> + </hbox> + </vbox> + + <separator class="thin"/> + + <description>&useInternalSettings.description;</description> + <hbox class="indent" align="center"> + <checkbox id="useInternalMail" + label="&useInternalMail.label;" + accesskey="&useInternalMail.accesskey;" + preference="network.protocol-handler.external.mailto"/> + <checkbox id="useInternalNews" + label="&useInternalNews.label;" + accesskey="&useInternalNews.accesskey;" + oncommand="onNewsChange(this.checked);" + preference="network.protocol-handler.external.news"/> + </hbox> + </groupbox> + + <groupbox id="printing"> + <caption label="&printing.label;"/> + <checkbox id="nglayoutUseNativePrintDialog" + label="&useNativePrintDialog.label;" + accesskey="&useNativePrintDialog.accesskey;" + preference="print.use_native_print_dialog"/> + <checkbox id="printUseGlobalPrintSettings" + label="&useGlobalPrintSettings.label;" + accesskey="&useGlobalPrintSettings.accesskey;" + preference="print.use_global_printsettings"/> + </groupbox> + + <groupbox id="crashReports" hidden="true"> + <caption id="crashReportsCaption" label="&crashReports.caption;"/> + <checkbox id="submitCrashes" + label="&submitCrashes.label;" + accesskey="&submitCrashes.accesskey;" + oncommand="updateSubmitCrashes(this.checked);"/> + </groupbox> + + <groupbox id="devTools"> + <caption id="devToolsCaption" label="&devTools.caption;"/> + <checkbox id="allowDebugger" + label="&allowDebugger.label;" + accesskey="&allowDebugger.accesskey;" + preference="devtools.debugger.remote-enabled"/> + <checkbox id="allowRemoteConnections" + label="&allowRemoteConnections.label;" + accesskey="&allowRemoteConnections.accesskey;" + preference="devtools.debugger.force-local"/> + <checkbox id="connectionPrompt" + label="&connectionPrompt.label;" + accesskey="&connectionPrompt.accesskey;" + preference="devtools.debugger.prompt-connection"/> + + <hbox align="center"> + <label id="remoteDebuggerPortBefore" + value="&remoteDebuggerPort.label;" + accesskey="&remoteDebuggerPort.accesskey;" + control="remoteDebuggerPort"/> + <textbox id="remoteDebuggerPort" + type="number" + min="0" + max="65535" + size="5" + preference="devtools.debugger.remote-port" + aria-labelledby="remoteDebuggerPortBefore remoteDebuggerPort"/> + </hbox> + </groupbox> + </prefpane> +</overlay> diff --git a/comm/suite/components/pref/content/pref-appearance.js b/comm/suite/components/pref/content/pref-appearance.js new file mode 100644 index 0000000000..a54b14786d --- /dev/null +++ b/comm/suite/components/pref/content/pref-appearance.js @@ -0,0 +1,102 @@ +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Load spell-checker module to properly determine language strings +var {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm"); + +function Startup() +{ + SwitchLocales_Load(); + NumberLocales_Load(); +} + +/** + * From locale switcher's switch.js: + * Load available locales into selection menu + */ +function SwitchLocales_Load() { + var menulist = document.getElementById("switchLocales"); + + var cr = Cc["@mozilla.org/chrome/chrome-registry;1"] + .getService(Ci.nsIToolkitChromeRegistry); + + var langNames = document.getElementById("languageNamesBundle"); + var regNames = document.getElementById("regionNamesBundle"); + + var matched = false; + var currentLocale = Services.locale.getRequestedLocale() || undefined; + var locales = cr.getLocalesForPackage("global"); + + while (locales.hasMore()) { + var locale = locales.getNext(); + + var parts = locale.split(/-/); + + var displayName; + try { + displayName = langNames.getString(parts[0]); + if (parts.length > 1) { + try { + displayName += " (" + regNames.getString(parts[1].toLowerCase()) + ")"; + } + catch (e) { + displayName += " (" + parts[1] + ")"; + } + } + } + catch (e) { + displayName = locale; + } + + var item = menulist.appendItem(displayName, locale); + if (!matched && currentLocale && currentLocale == locale) { + matched = true; + menulist.selectedItem = item; + } + } + // If somehow we have not found the current locale, select the first in list. + if (!matched) { + menulist.selectedIndex = 1; + } +} + +/** + * Determine the appropriate value to set and set it. + */ +function SelectLocale(aElement) { + var locale = aElement.value; + var currentLocale = Services.locale.getRequestedLocale() || undefined; + if (!currentLocale || (currentLocale && currentLocale != locale)) { + Services.locale.setRequestedLocales([locale]); + } +} + +/** + * When starting up, determine application and regional locale settings + * and add the respective strings to the prefpane labels. + */ +function NumberLocales_Load() +{ + const osprefs = + Cc["@mozilla.org/intl/ospreferences;1"] + .getService(Ci.mozIOSPreferences); + + let appLocale = Services.locale.appLocalesAsBCP47[0]; + let rsLocale = osprefs.regionalPrefsLocales[0]; + let names = Services.intl.getLocaleDisplayNames(undefined, [appLocale, rsLocale]); + + let appLocaleRadio = document.getElementById("appLocale"); + let rsLocaleRadio = document.getElementById("rsLocale"); + let prefutilitiesBundle = document.getElementById("bundle_prefutilities"); + + let appLocaleLabel = prefutilitiesBundle.getFormattedString("appLocale.label", + [names[0]]); + let rsLocaleLabel = prefutilitiesBundle.getFormattedString("rsLocale.label", + [names[1]]); + appLocaleRadio.setAttribute("label", appLocaleLabel); + rsLocaleRadio.setAttribute("label", rsLocaleLabel); + appLocaleRadio.accessKey = prefutilitiesBundle.getString("appLocale.accesskey"); + rsLocaleRadio.accessKey = prefutilitiesBundle.getString("rsLocale.accesskey"); +} diff --git a/comm/suite/components/pref/content/pref-appearance.xul b/comm/suite/components/pref/content/pref-appearance.xul new file mode 100644 index 0000000000..132e0a614e --- /dev/null +++ b/comm/suite/components/pref/content/pref-appearance.xul @@ -0,0 +1,103 @@ +<?xml version="1.0"?> + +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<!DOCTYPE overlay [ + <!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd"> %brandDTD; + <!ENTITY % prefAppearanceDTD SYSTEM "chrome://communicator/locale/pref/pref-appearance.dtd"> %prefAppearanceDTD; +]> + +<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <prefpane id="appearance_pane" + label="&pref.appearance.title;" + script="chrome://communicator/content/pref/pref-appearance.js"> + + <preferences id="appearance_preferences"> + <preference id="general.startup.browser" + name="general.startup.browser" + type="bool"/> + <preference id="browser.chrome.toolbar_style" + name="browser.chrome.toolbar_style" + type="int"/> + <preference id="browser.chrome.toolbar_tips" + name="browser.chrome.toolbar_tips" + type="bool"/> + <preference id="browser.toolbars.grippyhidden" + name="browser.toolbars.grippyhidden" + type="bool"/> + <preference id="intl.regional_prefs.use_os_locales" + name="intl.regional_prefs.use_os_locales" + type="bool"/> + </preferences> + + <hbox> + <groupbox id="generalStartupPreferences" align="start" flex="1"> + <caption label="&onStartLegend.label;"/> + + <checkbox id="generalStartupBrowser" + label="&navCheck.label;" + accesskey="&navCheck.accesskey;" + preference="general.startup.browser"/> + </groupbox> + + <groupbox id="toolbarStyleBox" align="start" flex="1"> + <caption label="&showToolsLegend.label;"/> + + <radiogroup id="toolbarStyle" + preference="browser.chrome.toolbar_style"> + <radio value="2" + label="&picsNtextRadio.label;" + accesskey="&picsNtextRadio.accesskey;"/> + <radio value="0" + label="&picsOnlyRadio.label;" + accesskey="&picsOnlyRadio.accesskey;"/> + <radio value="1" + label="&textonlyRadio.label;" + accesskey="&textonlyRadio.accesskey;"/> + </radiogroup> + </groupbox> + </hbox> + + <vbox class="box-padded" align="start"> + <checkbox id="showHideTooltips" + label="&showHideTooltips.label;" + accesskey="&showHideTooltips.accesskey;" + preference="browser.chrome.toolbar_tips"/> + </vbox> +#ifndef XP_MACOSX + <vbox class="box-padded" + align="start"> + <checkbox id="showHideGrippies" + label="&showHideGrippies.label;" + accesskey="&showHideGrippies.accesskey;" + preference="browser.toolbars.grippyhidden"/> + </vbox> +#endif + <groupbox id="switchLocaleBox" align="start"> + <caption label="&pref.locales.title;"/> + <description>&selectLocale.label;</description> + + <menulist id="switchLocales" + onselect="SelectLocale(this);"/> + + </groupbox> + + <groupbox id="dateTimeFormatting" align="start"> + <caption label="&dateTimeFormatting.label;"/> + <radiogroup id="formatLocale" + preference="intl.regional_prefs.use_os_locales" + orient="vertical"> + <radio id="appLocale" + value="false"/> + <!-- label and accesskey will be set dynamically --> + <radio id="rsLocale" + value="true"/> + <!-- label and accesskey will be set dynamically --> + </radiogroup> + </groupbox> + + <description>&restartOnLocaleChange.label;</description> + </prefpane> +</overlay> diff --git a/comm/suite/components/pref/content/pref-applicationManager.js b/comm/suite/components/pref/content/pref-applicationManager.js new file mode 100644 index 0000000000..83d18953ef --- /dev/null +++ b/comm/suite/components/pref/content/pref-applicationManager.js @@ -0,0 +1,100 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm"); + +var gAppManagerDialog = { + _removed: [], + + init: function appManager_init() { + this.handlerInfo = window.arguments[0]; + + var bundle = document.getElementById("appManagerBundle"); + var contentText; + if (this.handlerInfo.type == TYPE_MAYBE_FEED) + contentText = bundle.getString("descriptionHandleWebFeeds"); + else { + var description = gApplicationsPane._describeType(this.handlerInfo); + var key = + (this.handlerInfo.wrappedHandlerInfo instanceof Ci.nsIMIMEInfo) ? + "descriptionHandleFile" : + "descriptionHandleProtocol"; + contentText = bundle.getFormattedString(key, [description]); + } + document.getElementById("appDescription").textContent = contentText; + + var list = document.getElementById("appList"); + var apps = this.handlerInfo.possibleApplicationHandlers.enumerate(); + while (apps.hasMoreElements()) { + let app = apps.getNext(); + if (!gApplicationsPane.isValidHandlerApp(app)) + continue; + + app.QueryInterface(Ci.nsIHandlerApp); + var item = list.appendItem(app.name); + item.className = "listitem-iconic"; + item.setAttribute("image", + gApplicationsPane._getIconURLForHandlerApp(app)); + item.app = app; + } + + list.selectedIndex = 0; + }, + + onOK: function appManager_onOK() { + if (!this._removed.length) { + // return early to avoid calling the |store| method. + return; + } + + for (var i = 0; i < this._removed.length; ++i) + this.handlerInfo.removePossibleApplicationHandler(this._removed[i]); + + this.handlerInfo.store(); + }, + + onCancel: function appManager_onCancel() { + // do nothing + }, + + remove: function appManager_remove() { + var list = document.getElementById("appList"); + this._removed.push(list.selectedItem.app); + var index = list.selectedIndex; + list.removeItemAt(index); + if (list.getRowCount() == 0) { + // The list is now empty, make the bottom part disappear + document.getElementById("appDetails").hidden = true; + } + else { + // Select the item at the same index, if we removed the last + // item of the list, select the previous item + if (index == list.getRowCount()) + --index; + list.selectedIndex = index; + } + }, + + onSelect: function appManager_onSelect() { + var list = document.getElementById("appList"); + if (!list.selectedItem) { + document.getElementById("cmd_delete").setAttribute("disabled", "true"); + return; + } + document.getElementById("cmd_delete").removeAttribute("disabled"); + var app = list.selectedItem.app; + var address = ""; + if (app instanceof Ci.nsILocalHandlerApp) + address = app.executable.path; + else if (app instanceof Ci.nsIWebHandlerApp) + address = app.uriTemplate; + else if (app instanceof Ci.nsIWebContentHandlerInfo) + address = app.uri; + document.getElementById("appLocation").value = address; + var bundle = document.getElementById("appManagerBundle"); + var appType = app instanceof Ci.nsILocalHandlerApp ? "descriptionLocalApp" + : "descriptionWebApp"; + document.getElementById("appType").value = bundle.getString(appType); + } +}; diff --git a/comm/suite/components/pref/content/pref-applicationManager.xul b/comm/suite/components/pref/content/pref-applicationManager.xul new file mode 100644 index 0000000000..38988e1080 --- /dev/null +++ b/comm/suite/components/pref/content/pref-applicationManager.xul @@ -0,0 +1,56 @@ +<?xml version="1.0"?> + +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<?xml-stylesheet href="chrome://communicator/skin/"?> + +<!DOCTYPE dialog SYSTEM "chrome://communicator/locale/pref/pref-applicationManager.dtd"> + +<dialog id="appManager" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + buttons="accept,cancel" + onload="gAppManagerDialog.init();" + ondialogaccept="gAppManagerDialog.onOK();" + ondialogcancel="gAppManagerDialog.onCancel();" + title="&appManager.title;" + style="&appManager.style;" + persist="screenX screenY"> + + <script src="chrome://communicator/content/pref/pref-applications.js"/> + <script src="chrome://communicator/content/pref/pref-applicationManager.js"/> + + <commandset id="appManagerCommandSet"> + <command id="cmd_delete" + oncommand="gAppManagerDialog.remove();" + disabled="true"/> + </commandset> + + <keyset id="appManagerKeyset"> + <key id="delete" keycode="VK_DELETE" command="cmd_delete"/> + </keyset> + + <stringbundleset id="appManagerBundleset"> + <stringbundle id="appManagerBundle" + src="chrome://communicator/locale/pref/pref-applicationManager.properties"/> + </stringbundleset> + + <description id="appDescription"/> + <separator class="thin"/> + <hbox flex="1"> + <listbox id="appList" onselect="gAppManagerDialog.onSelect();" flex="1"/> + <vbox> + <button id="remove" + label="&remove.label;" + accesskey="&remove.accesskey;" + command="cmd_delete"/> + <spacer flex="1"/> + </vbox> + </hbox> + <vbox id="appDetails"> + <separator class="thin"/> + <label id="appType"/> + <textbox id="appLocation" readonly="true" class="plain"/> + </vbox> +</dialog> diff --git a/comm/suite/components/pref/content/pref-applications.js b/comm/suite/components/pref/content/pref-applications.js new file mode 100644 index 0000000000..b3ca0d71fd --- /dev/null +++ b/comm/suite/components/pref/content/pref-applications.js @@ -0,0 +1,1606 @@ +/* -*- Mode: Java; tab-width: 2; c-basic-offset: 2; -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const {AppConstants} = ChromeUtils.import("resource://gre/modules/AppConstants.jsm"); +const {ShellService} = ChromeUtils.import("resource:///modules/ShellService.jsm"); +// Needed as this script is also loaded by pref-applicationManager.xul. +const {XPCOMUtils} = + ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm"); + +function Startup() +{ + gApplicationsPane.init(); +} + +XPCOMUtils.defineLazyServiceGetters(this, { + gCategoryManager: ["@mozilla.org/categorymanager;1", "nsICategoryManager"], + gHandlerService: ["@mozilla.org/uriloader/handler-service;1", "nsIHandlerService"], + gMIMEService: ["@mozilla.org/mime;1", "nsIMIMEService"], + gWebContentConverterService: ["@mozilla.org/embeddor.implemented/web-content-handler-registrar;1", "nsIWebContentConverterService"], +}); + +//****************************************************************************// +// Constants & Enumeration Values + +const TYPE_MAYBE_FEED = "application/vnd.mozilla.maybe.feed"; +const TYPE_MAYBE_VIDEO_FEED = "application/vnd.mozilla.maybe.video.feed"; +const TYPE_MAYBE_AUDIO_FEED = "application/vnd.mozilla.maybe.audio.feed"; + +/* + * Preferences where we store handling information about the feed type. + * + * browser.feeds.handler + * - "messenger", "reader" (clarified further using the .default preference), + * or "ask" -- indicates the default handler being used to process feeds; + * "messenger" is obsolete, use "reader" instead; to specify that the + * handler is messenger, set browser.feeds.handler.default to "messenger"; + * + * browser.feeds.handler.default + * - "messenger", "client" or "web" -- indicates the chosen feed reader used + * to display feeds, either transiently (i.e., when the "use as default" + * checkbox is unchecked, corresponds to when browser.feeds.handler=="ask") + * or more permanently (i.e., the item displayed in the dropdown in Feeds + * preferences) + * + * browser.feeds.handler.webservice + * - the URL of the currently selected web service used to read feeds + * + * browser.feeds.handlers.application + * - nsIFile, stores the current client-side feed reading app if one has + * been chosen + */ +const PREF_FEED_SELECTED_APP = "browser.feeds.handlers.application"; +const PREF_FEED_SELECTED_WEB = "browser.feeds.handlers.webservice"; +const PREF_FEED_SELECTED_ACTION = "browser.feeds.handler"; +const PREF_FEED_SELECTED_READER = "browser.feeds.handler.default"; + +const PREF_VIDEO_FEED_SELECTED_APP = "browser.videoFeeds.handlers.application"; +const PREF_VIDEO_FEED_SELECTED_WEB = "browser.videoFeeds.handlers.webservice"; +const PREF_VIDEO_FEED_SELECTED_ACTION = "browser.videoFeeds.handler"; +const PREF_VIDEO_FEED_SELECTED_READER = "browser.videoFeeds.handler.default"; + +const PREF_AUDIO_FEED_SELECTED_APP = "browser.audioFeeds.handlers.application"; +const PREF_AUDIO_FEED_SELECTED_WEB = "browser.audioFeeds.handlers.webservice"; +const PREF_AUDIO_FEED_SELECTED_ACTION = "browser.audioFeeds.handler"; +const PREF_AUDIO_FEED_SELECTED_READER = "browser.audioFeeds.handler.default"; + +// The nsHandlerInfoAction enumeration values in nsIHandlerInfo identify +// the actions the application can take with content of various types. +const kActionChooseApp = -2; +const kActionManageApp = -1; + +//****************************************************************************// +// Utilities + +function getFileDisplayName(aFile) { + if (AppConstants.platform == "win" && + aFile instanceof Ci.nsILocalFileWin) { + try { + return aFile.getVersionInfoField("FileDescription"); + } catch (e) {} + } else if (AppConstants.platform == "macosx" && + aFile instanceof Ci.nsILocalFileMac) { + try { + return aFile.bundleDisplayName; + } catch (e) {} + } + return aFile.leafName; +} + +function getLocalHandlerApp(aFile) { + var localHandlerApp = Cc["@mozilla.org/uriloader/local-handler-app;1"] + .createInstance(Ci.nsILocalHandlerApp); + localHandlerApp.name = getFileDisplayName(aFile); + localHandlerApp.executable = aFile; + + return localHandlerApp; +} + +/** + * An enumeration of items in a JS array. + * + * FIXME: use ArrayConverter once it lands (bug 380839). + * + * @constructor + */ +function ArrayEnumerator(aItems) { + this._index = 0; + this._contents = aItems; +} + +ArrayEnumerator.prototype = { + _index: 0, + + hasMoreElements: function() { + return this._index < this._contents.length; + }, + + getNext: function() { + return this._contents[this._index++]; + } +}; + +function isFeedType(t) { + return t == TYPE_MAYBE_FEED || t == TYPE_MAYBE_VIDEO_FEED || t == TYPE_MAYBE_AUDIO_FEED; +} + +//****************************************************************************// +// HandlerInfoWrapper + +/** + * This object wraps nsIHandlerInfo with some additional functionality + * the Applications prefpane needs to display and allow modification of + * the list of handled types. + * + * We create an instance of this wrapper for each entry we might display + * in the prefpane, and we compose the instances from various sources, + * including the handler service. + * + * We don't implement all the original nsIHandlerInfo functionality, + * just the stuff that the prefpane needs. + * + * In theory, all of the custom functionality in this wrapper should get + * pushed down into nsIHandlerInfo eventually. + */ +function HandlerInfoWrapper(aType, aHandlerInfo) { + this.type = aType; + this.wrappedHandlerInfo = aHandlerInfo; +} + +HandlerInfoWrapper.prototype = { + // The wrapped nsIHandlerInfo object. In general, this object is private, + // but there are a couple cases where callers access it directly for things + // we haven't (yet?) implemented, so we make it a public property. + wrappedHandlerInfo: null, + + + //**************************************************************************// + // nsIHandlerInfo + + // The MIME type or protocol scheme. + type: null, + + get description() { + if (this.wrappedHandlerInfo.description) + return this.wrappedHandlerInfo.description; + + if (this.primaryExtension) { + var extension = this.primaryExtension.toUpperCase(); + return gApplicationsPane._prefsBundle.getFormattedString("fileEnding", + [extension]); + } + + return this.type; + }, + + get preferredApplicationHandler() { + return this.wrappedHandlerInfo.preferredApplicationHandler; + }, + + set preferredApplicationHandler(aNewValue) { + this.wrappedHandlerInfo.preferredApplicationHandler = aNewValue; + + // Make sure the preferred handler is in the set of possible handlers. + if (aNewValue) + this.addPossibleApplicationHandler(aNewValue); + }, + + get possibleApplicationHandlers() { + return this.wrappedHandlerInfo.possibleApplicationHandlers; + }, + + addPossibleApplicationHandler(aNewHandler) { + var possibleApps = this.possibleApplicationHandlers.enumerate(); + while (possibleApps.hasMoreElements()) { + if (possibleApps.getNext().equals(aNewHandler)) + return; + } + this.possibleApplicationHandlers.appendElement(aNewHandler); + }, + + removePossibleApplicationHandler(aHandler) { + var defaultApp = this.preferredApplicationHandler; + if (defaultApp && aHandler.equals(defaultApp)) { + // If the app we remove was the default app, we must make sure + // it won't be used anymore + this.alwaysAskBeforeHandling = true; + this.preferredApplicationHandler = null; + } + + var handlers = this.possibleApplicationHandlers; + for (var i = 0; i < handlers.length; ++i) { + var handler = handlers.queryElementAt(i, Ci.nsIHandlerApp); + if (handler.equals(aHandler)) { + handlers.removeElementAt(i); + break; + } + } + }, + + get hasDefaultHandler() { + return this.wrappedHandlerInfo.hasDefaultHandler; + }, + + get defaultDescription() { + return this.wrappedHandlerInfo.defaultDescription; + }, + + // What to do with content of this type. + get preferredAction() { + // If the action is to use a helper app, but we don't have a preferred + // handler app, then switch to using the system default, if any; otherwise + // fall back to saving to disk, which is the default action in nsMIMEInfo. + // Note: "save to disk" is an invalid value for protocol info objects, + // but the alwaysAskBeforeHandling getter will detect that situation + // and always return true in that case to override this invalid value. + if (this.wrappedHandlerInfo.preferredAction == Ci.nsIHandlerInfo.useHelperApp && + !gApplicationsPane.isValidHandlerApp(this.preferredApplicationHandler)) { + return this.wrappedHandlerInfo.hasDefaultHandler ? + Ci.nsIHandlerInfo.useSystemDefault : + Ci.nsIHandlerInfo.saveToDisk; + } + + return this.wrappedHandlerInfo.preferredAction; + }, + + set preferredAction(aNewValue) { + this.wrappedHandlerInfo.preferredAction = aNewValue; + }, + + get alwaysAskBeforeHandling() { + // If this is a protocol type and the preferred action is "save to disk", + // which is invalid for such types, then return true here to override that + // action. This could happen when the preferred action is to use a helper + // app, but the preferredApplicationHandler is invalid, and there isn't + // a default handler, so the preferredAction getter returns save to disk + // instead. + if (!(this.wrappedHandlerInfo instanceof Ci.nsIMIMEInfo) && + this.preferredAction == Ci.nsIHandlerInfo.saveToDisk) + return true; + + return this.wrappedHandlerInfo.alwaysAskBeforeHandling; + }, + + set alwaysAskBeforeHandling(aNewValue) { + this.wrappedHandlerInfo.alwaysAskBeforeHandling = aNewValue; + }, + + + //**************************************************************************// + // nsIMIMEInfo + + // The primary file extension associated with this type, if any. + get primaryExtension() { + try { + if (this.wrappedHandlerInfo instanceof Ci.nsIMIMEInfo && + this.wrappedHandlerInfo.primaryExtension) + return this.wrappedHandlerInfo.primaryExtension; + } catch(ex) {} + + return null; + }, + + //**************************************************************************// + // Storage + + store() { + gHandlerService.store(this.wrappedHandlerInfo); + }, + + + //**************************************************************************// + // Icons + + get smallIcon() { + return this._getIcon(16); + }, + + get largeIcon() { + return this._getIcon(32); + }, + + _getIcon(aSize) { + if (this.primaryExtension) + return "moz-icon://goat." + this.primaryExtension + "?size=" + aSize; + + if (this.wrappedHandlerInfo instanceof Ci.nsIMIMEInfo) + return "moz-icon://goat?size=" + aSize + "&contentType=" + this.type; + + // We're falling back to a generic icon when we can't get a URL for one + // (for example in the case of protocol schemes). + return null; + }, + + // The type class is used for setting icons through CSS for types that don't + // explicitly set their icons. + typeClass: "unknown" + +}; + + +//****************************************************************************// +// Feed Handler Info + +/** + * This object implements nsIHandlerInfo for the feed types. It's a separate + * object because we currently store handling information for the feed type + * in a set of preferences rather than the nsIHandlerService-managed datastore. + * + * This object inherits from HandlerInfoWrapper in order to get functionality + * that isn't special to the feed type. + * + * XXX Should we inherit from HandlerInfoWrapper? After all, we override + * most of that wrapper's properties and methods, and we have to dance around + * the fact that the wrapper expects to have a wrappedHandlerInfo, which we + * don't provide. + */ + +function FeedHandlerInfo(aMIMEType) { + HandlerInfoWrapper.call(this, aMIMEType, null); +} + +FeedHandlerInfo.prototype = { + __proto__: HandlerInfoWrapper.prototype, + + //**************************************************************************// + // nsIHandlerInfo + + get description() { + return gApplicationsPane._prefsBundle.getString(this.typeClass); + }, + + get preferredApplicationHandler() { + switch (document.getElementById(this._prefSelectedReader).value) { + case "client": + var file = document.getElementById(this._prefSelectedApp).value; + if (file) + return getLocalHandlerApp(file); + + return null; + + case "web": + var uri = document.getElementById(this._prefSelectedWeb).value; + if (!uri) + return null; + return gWebContentConverterService.getWebContentHandlerByURI(this.type, uri); + + case "messenger": + default: + // When the pref is set to messenger, we handle feeds internally, + // we don't forward them to a local or web handler app, so there is + // no preferred handler. + return null; + } + }, + + set preferredApplicationHandler(aNewValue) { + if (aNewValue instanceof Ci.nsILocalHandlerApp) { + document.getElementById(this._prefSelectedApp).value = aNewValue.executable; + document.getElementById(this._prefSelectedReader).value = "client"; + } + else if (aNewValue instanceof Ci.nsIWebContentHandlerInfo) { + document.getElementById(this._prefSelectedWeb).value = aNewValue.uri; + document.getElementById(this._prefSelectedReader).value = "web"; + // Make the web handler be the new "auto handler" for feeds. + // Note: we don't have to unregister the auto handler when the user picks + // a non-web handler (local app, RSS News & Blogs, etc.) because the service + // only uses the "auto handler" when the selected reader is a web handler. + // We also don't have to unregister it when the user turns on "always ask" + // (i.e. preview in browser), since that also overrides the auto handler. + gWebContentConverterService.setAutoHandler(this.type, aNewValue); + } + }, + + _possibleApplicationHandlers: null, + + get possibleApplicationHandlers() { + if (this._possibleApplicationHandlers) + return this._possibleApplicationHandlers; + + // A minimal implementation of nsIMutableArray. It only supports the two + // methods its callers invoke, namely appendElement, nsIArray::enumerate + // and nsIArray::indexOf. + this._possibleApplicationHandlers = { + _inner: [], + _removed: [], + + QueryInterface: XPCOMUtils.generateQI([Ci.nsIMutableArray, Ci.nsIArray]), + + get length() { + return this._inner.length; + }, + + enumerate: function() { + return new ArrayEnumerator(this._inner); + }, + + indexOf: function indexOf(startIndex, element) { + return this._inner.indexOf(element, startIndex); + }, + + appendElement: function(aHandlerApp) { + this._inner.push(aHandlerApp); + }, + + removeElementAt: function(aIndex) { + this._removed.push(this._inner[aIndex]); + this._inner.splice(aIndex, 1); + }, + + queryElementAt: function(aIndex, aInterface) { + return this._inner[aIndex].QueryInterface(aInterface); + }, + }; + + // Add the selected local app if it's different from the OS default handler. + // Unlike for other types, we can store only one local app at a time for the + // feed type, since we store it in a preference that historically stores + // only a single path. But we display all the local apps the user chooses + // while the prefpane is open, only dropping the list when the user closes + // the prefpane, for maximum usability and consistency with other types. + var preferredAppFile = document.getElementById(this._prefSelectedApp).value; + if (preferredAppFile) { + let preferredApp = getLocalHandlerApp(preferredAppFile); + let defaultApp = this._defaultApplicationHandler; + if (!defaultApp || !defaultApp.equals(preferredApp)) + this._possibleApplicationHandlers.appendElement(preferredApp); + } + + // Add the registered web handlers. There can be any number of these. + var webHandlers = gWebContentConverterService.getContentHandlers(this.type); + for (let webHandler of webHandlers) + this._possibleApplicationHandlers.appendElement(webHandler); + + return this._possibleApplicationHandlers; + }, + + __defaultApplicationHandler: undefined, + get _defaultApplicationHandler() { + if (this.__defaultApplicationHandler !== undefined) + return this.__defaultApplicationHandler; + + var defaultFeedReader = null; + try { + defaultFeedReader = ShellService.defaultFeedReader; + } + catch(ex) { + // no default reader + } + + if (defaultFeedReader) { + let handlerApp = Cc["@mozilla.org/uriloader/local-handler-app;1"] + .createInstance(Ci.nsIHandlerApp); + handlerApp.name = getFileDisplayName(defaultFeedReader); + handlerApp.QueryInterface(Ci.nsILocalHandlerApp); + handlerApp.executable = defaultFeedReader; + + this.__defaultApplicationHandler = handlerApp; + } + else { + this.__defaultApplicationHandler = null; + } + + return this.__defaultApplicationHandler; + }, + + get hasDefaultHandler() { + try { + if (ShellService.defaultFeedReader) + return true; + } + catch(ex) { + // no default reader + } + + return false; + }, + + get defaultDescription() { + if (this.hasDefaultHandler) + return this._defaultApplicationHandler.name; + + // Should we instead return null? + return ""; + }, + + // What to do with content of this type. + get preferredAction() { + switch (document.getElementById(this._prefSelectedAction).value) { + + case "reader": { + let preferredApp = this.preferredApplicationHandler; + let defaultApp = this._defaultApplicationHandler; + + // If we have a valid preferred app, return useSystemDefault if it's + // the default app; otherwise return useHelperApp. + if (gApplicationsPane.isValidHandlerApp(preferredApp)) { + if (defaultApp && defaultApp.equals(preferredApp)) + return Ci.nsIHandlerInfo.useSystemDefault; + + return Ci.nsIHandlerInfo.useHelperApp; + } + + // The pref is set to "reader", but we don't have a valid preferred app. + // What do we do now? Not sure this is the best option (perhaps we + // should direct the user to the default app, if any), but for now let's + // direct the user to live bookmarks. + return Ci.nsIHandlerInfo.handleInternally; + } + + // If the action is "ask", then alwaysAskBeforeHandling will override + // the action, so it doesn't matter what we say it is, it just has to be + // something that doesn't cause the controller to hide the type. + case "ask": + case "messenger": + default: + return Ci.nsIHandlerInfo.handleInternally; + } + }, + + set preferredAction(aNewValue) { + switch (aNewValue) { + + case Ci.nsIHandlerInfo.handleInternally: + document.getElementById(this._prefSelectedReader).value = "messenger"; + break; + + case Ci.nsIHandlerInfo.useHelperApp: + document.getElementById(this._prefSelectedAction).value = "reader"; + // The controller has already set preferredApplicationHandler + // to the new helper app. + break; + + case Ci.nsIHandlerInfo.useSystemDefault: + document.getElementById(this._prefSelectedAction).value = "reader"; + this.preferredApplicationHandler = this._defaultApplicationHandler; + break; + } + }, + + get alwaysAskBeforeHandling() { + return document.getElementById(this._prefSelectedAction).value == "ask"; + }, + + set alwaysAskBeforeHandling(aNewValue) { + if (aNewValue) + document.getElementById(this._prefSelectedAction).value = "ask"; + else + document.getElementById(this._prefSelectedAction).value = "reader"; + }, + + // Whether or not we are currently storing the action selected by the user. + // We use this to suppress notification-triggered updates to the list when + // we make changes that may spawn such updates, specifically when we change + // the action for the feed type, which results in feed preference updates, + // which spawn "pref changed" notifications that would otherwise cause us + // to rebuild the view unnecessarily. + _storingAction: false, + + + //**************************************************************************// + // nsIMIMEInfo + + primaryExtension: "xml", + + + //**************************************************************************// + // Storage + + // Changes to the preferred action and handler take effect immediately + // (we write them out to the preferences right as they happen), + // so we when the controller calls store() after modifying the handlers, + // the only thing we need to store is the removal of possible handlers + // XXX Should we hold off on making the changes until this method gets called? + store() { + for (let app of this._possibleApplicationHandlers._removed) { + if (app instanceof Ci.nsILocalHandlerApp) { + let pref = document.getElementById(PREF_FEED_SELECTED_APP); + var preferredAppFile = pref.value; + if (preferredAppFile) { + let preferredApp = getLocalHandlerApp(preferredAppFile); + if (app.equals(preferredApp)) + pref.reset(); + } + } + else { + app.QueryInterface(Ci.nsIWebContentHandlerInfo); + gWebContentConverterService.removeContentHandler(app.contentType, + app.uri); + } + } + this._possibleApplicationHandlers._removed = []; + }, + + + //**************************************************************************// + // Icons + + smallIcon: null, + + largeIcon: null, + + // The type class is used for setting icons through CSS for types that don't + // explicitly set their icons. + typeClass: "webFeed", +}; + +var feedHandlerInfo = { + __proto__: new FeedHandlerInfo(TYPE_MAYBE_FEED), + _prefSelectedApp: PREF_FEED_SELECTED_APP, + _prefSelectedWeb: PREF_FEED_SELECTED_WEB, + _prefSelectedAction: PREF_FEED_SELECTED_ACTION, + _prefSelectedReader: PREF_FEED_SELECTED_READER, + typeClass: "webFeed", +}; + +var videoFeedHandlerInfo = { + __proto__: new FeedHandlerInfo(TYPE_MAYBE_VIDEO_FEED), + _prefSelectedApp: PREF_VIDEO_FEED_SELECTED_APP, + _prefSelectedWeb: PREF_VIDEO_FEED_SELECTED_WEB, + _prefSelectedAction: PREF_VIDEO_FEED_SELECTED_ACTION, + _prefSelectedReader: PREF_VIDEO_FEED_SELECTED_READER, + typeClass: "videoPodcastFeed", +}; + +var audioFeedHandlerInfo = { + __proto__: new FeedHandlerInfo(TYPE_MAYBE_AUDIO_FEED), + _prefSelectedApp: PREF_AUDIO_FEED_SELECTED_APP, + _prefSelectedWeb: PREF_AUDIO_FEED_SELECTED_WEB, + _prefSelectedAction: PREF_AUDIO_FEED_SELECTED_ACTION, + _prefSelectedReader: PREF_AUDIO_FEED_SELECTED_READER, + typeClass: "audioPodcastFeed", +}; + + +//****************************************************************************// +// Prefpane Controller + +var gApplicationsPane = { + // The set of types the app knows how to handle. A hash of HandlerInfoWrapper + // objects, indexed by type. + _handledTypes: {}, + + // The list of types we can show, sorted by the sort column/direction. + // An array of HandlerInfoWrapper objects. We build this list when we first + // load the data and then rebuild it when users change a pref that affects + // what types we can show or change the sort column/direction. + // Note: this isn't necessarily the list of types we *will* show; if the user + // provides a filter string, we'll only show the subset of types in this list + // that match that string. + _visibleTypes: [], + + // A count of the number of times each visible type description appears. + // We use these counts to determine whether or not to annotate descriptions + // with their types to distinguish duplicate descriptions from each other. + // A hash of integer counts, indexed by string description. + _visibleTypeDescriptionCount: {}, + + + //**************************************************************************// + // Convenience & Performance Shortcuts + + // These get defined by init(). + _brandShortName : null, + _prefsBundle : null, + _list : null, + _filter : null, + + + //**************************************************************************// + // Initialization & Destruction + + init() { + // Initialize shortcuts to some commonly accessed elements & values. + this._brandShortName = + document.getElementById("bundleBrand").getString("brandShortName"); + this._prefsBundle = document.getElementById("bundlePrefApplications"); + this._list = document.getElementById("handlersView"); + this._filter = document.getElementById("filter"); + + // Observe preferences that influence what we display so we can rebuild + // the view when they change. + Services.prefs.addObserver(PREF_FEED_SELECTED_APP, this); + Services.prefs.addObserver(PREF_FEED_SELECTED_WEB, this); + Services.prefs.addObserver(PREF_FEED_SELECTED_ACTION, this); + + Services.prefs.addObserver(PREF_VIDEO_FEED_SELECTED_APP, this); + Services.prefs.addObserver(PREF_VIDEO_FEED_SELECTED_WEB, this); + Services.prefs.addObserver(PREF_VIDEO_FEED_SELECTED_ACTION, this); + + Services.prefs.addObserver(PREF_AUDIO_FEED_SELECTED_APP, this); + Services.prefs.addObserver(PREF_AUDIO_FEED_SELECTED_WEB, this); + Services.prefs.addObserver(PREF_AUDIO_FEED_SELECTED_ACTION, this); + + // Listen for window unload so we can remove our preference observers. + window.addEventListener("unload", this); + + // Listen for user events on the listbox and its children + this._list.addEventListener("select", this); + this._list.addEventListener("command", this); + + // Figure out how we should be sorting the list. We persist sort settings + // across sessions, so we can't assume the default sort column/direction. + this._sortColumn = document.getElementById("typeColumn"); + if (document.getElementById("actionColumn").hasAttribute("sortDirection")) { + this._sortColumn = document.getElementById("actionColumn"); + // The typeColumn element always has a sortDirection attribute, + // either because it was persisted or because the default value + // from the xul file was used. If we are sorting on the other + // column, we should remove it. + document.getElementById("typeColumn").removeAttribute("sortDirection"); + } + + // Load the data and build the list of handlers. + this._loadData(); + this._rebuildVisibleTypes(); + this._sortVisibleTypes(); + this._rebuildView(); + + // Notify observers that the UI is now ready + Services.obs.notifyObservers(window, "app-handler-pane-loaded"); + }, + + destroy() { + this._list.removeEventListener("command", this); + this._list.removeEventListener("select", this); + window.removeEventListener("unload", this); + Services.prefs.removeObserver(PREF_FEED_SELECTED_APP, this); + Services.prefs.removeObserver(PREF_FEED_SELECTED_WEB, this); + Services.prefs.removeObserver(PREF_FEED_SELECTED_ACTION, this); + + Services.prefs.removeObserver(PREF_VIDEO_FEED_SELECTED_APP, this); + Services.prefs.removeObserver(PREF_VIDEO_FEED_SELECTED_WEB, this); + Services.prefs.removeObserver(PREF_VIDEO_FEED_SELECTED_ACTION, this); + + Services.prefs.removeObserver(PREF_AUDIO_FEED_SELECTED_APP, this); + Services.prefs.removeObserver(PREF_AUDIO_FEED_SELECTED_WEB, this); + Services.prefs.removeObserver(PREF_AUDIO_FEED_SELECTED_ACTION, this); + }, + + + //**************************************************************************// + // nsISupports + + QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, + Ci.nsIDOMEventListener]), + + //**************************************************************************// + // nsIObserver + + observe(aSubject, aTopic, aData) { + // Rebuild the list when there are changes to preferences that influence + // whether or not to show certain entries in the list. + if (aTopic == "nsPref:changed" && !this._storingAction) { + // All the prefs we observe can affect what we display, so we rebuild + // the view when any of them changes. + this._rebuildView(); + } + }, + + + //**************************************************************************// + // nsIDOMEventListener + + handleEvent(aEvent) { + switch (aEvent.type) { + case "unload": + this.destroy(); + break; + case "select": + if (this._list.selectedItem) + this._list.setAttribute("lastSelectedType", + this._list.selectedItem.type); + break; + case "command": + var target = aEvent.originalTarget; + switch (target.localName) { + case "listitem": + if (!this._list.disabled && + target.type == this._list.getAttribute("lastSelectedType")) + this._list.selectedItem = target; + break; + case "listcell": + this.rebuildActionsMenu(); + break; + case "menuitem": + switch (parseInt(target.value)) { + case kActionChooseApp: + this.chooseApp(); + break; + case kActionManageApp: + this.manageApp(); + break; + default: + this.onSelectAction(target); + break; + } + break; + } + } + }, + + + //**************************************************************************// + // Composed Model Construction + + _loadData() { + this._loadFeedHandler(); + this._loadApplicationHandlers(); + }, + + _loadFeedHandler() { + this._handledTypes[TYPE_MAYBE_FEED] = feedHandlerInfo; + + this._handledTypes[TYPE_MAYBE_VIDEO_FEED] = videoFeedHandlerInfo; + + this._handledTypes[TYPE_MAYBE_AUDIO_FEED] = audioFeedHandlerInfo; + }, + + /** + * Load the set of handlers defined by the application datastore. + */ + _loadApplicationHandlers() { + var wrappedHandlerInfos = gHandlerService.enumerate(); + while (wrappedHandlerInfos.hasMoreElements()) { + let wrappedHandlerInfo = + wrappedHandlerInfos.getNext().QueryInterface(Ci.nsIHandlerInfo); + let type = wrappedHandlerInfo.type; + + let handlerInfoWrapper; + if (type in this._handledTypes) + handlerInfoWrapper = this._handledTypes[type]; + else { + handlerInfoWrapper = new HandlerInfoWrapper(type, wrappedHandlerInfo); + this._handledTypes[type] = handlerInfoWrapper; + } + } + }, + + + //**************************************************************************// + // View Construction + + _rebuildVisibleTypes() { + // Reset the list of visible types and the visible type description counts. + this._visibleTypes = []; + this._visibleTypeDescriptionCount = {}; + + for (let type in this._handledTypes) { + let handlerInfo = this._handledTypes[type]; + + // We couldn't find any reason to exclude the type, so include it. + this._visibleTypes.push(handlerInfo); + + if (handlerInfo.description in this._visibleTypeDescriptionCount) + this._visibleTypeDescriptionCount[handlerInfo.description]++; + else + this._visibleTypeDescriptionCount[handlerInfo.description] = 1; + } + }, + + _rebuildView() { + // Clear the list of entries (the first 2 elements are <listcols> and + // <listhead>, they should never get removed). + while (this._list.childNodes.length > 2) + this._list.lastChild.remove(); + + var visibleTypes = this._visibleTypes; + + // If the user is filtering the list, then only show matching types. + if (this._filter.value) + visibleTypes = visibleTypes.filter(this._matchesFilter, this); + + for (let visibleType of visibleTypes) { + let item = document.createElement("listitem"); + item.setAttribute("allowevents", "true"); + item.setAttribute("type", visibleType.type); + item.setAttribute("typeDescription", this._describeType(visibleType)); + if (visibleType.smallIcon) + item.setAttribute("typeIcon", visibleType.smallIcon); + else + item.setAttribute("typeClass", visibleType.typeClass); + item.setAttribute("actionDescription", + this._describePreferredAction(visibleType)); + + if (!this._setIconClassForPreferredAction(visibleType, item)) { + var sysIcon = this._getIconURLForPreferredAction(visibleType); + if (sysIcon) + item.setAttribute("actionIcon", sysIcon); + else + item.setAttribute("appHandlerIcon", "app"); + } + + this._list.appendChild(item); + } + }, + + _matchesFilter(aType) { + var filterValue = this._filter.value.toLowerCase(); + return this._describeType(aType).toLowerCase().includes(filterValue) || + this._describePreferredAction(aType).toLowerCase().includes(filterValue); + }, + + /** + * Describe, in a human-readable fashion, the type represented by the given + * handler info object. Normally this is just the description provided by + * the info object, but if more than one object presents the same description, + * then we annotate the duplicate descriptions with the type itself to help + * users distinguish between those types. + * + * @param aHandlerInfo {nsIHandlerInfo} the type being described + * @returns {string} a description of the type + */ + _describeType(aHandlerInfo) { + if (this._visibleTypeDescriptionCount[aHandlerInfo.description] > 1) + return this._prefsBundle.getFormattedString("typeDescriptionWithType", + [aHandlerInfo.description, + aHandlerInfo.type]); + + return aHandlerInfo.description; + }, + + /** + * Describe, in a human-readable fashion, the preferred action to take on + * the type represented by the given handler info object. + * + * XXX Should this be part of the HandlerInfoWrapper interface? It would + * violate the separation of model and view, but it might make more sense + * nonetheless (f.e. it would make sortTypes easier). + * + * @param aHandlerInfo {nsIHandlerInfo} the type whose preferred action + * is being described + * @returns {string} a description of the action + */ + _describePreferredAction(aHandlerInfo) { + // alwaysAskBeforeHandling overrides the preferred action, so if that flag + // is set, then describe that behavior instead. For most types, this is + // the "alwaysAsk" string, but for the feed type we show something special. + if (aHandlerInfo.alwaysAskBeforeHandling) { + if (isFeedType(aHandlerInfo.type)) + return this._prefsBundle.getFormattedString("previewInApp", + [this._brandShortName]); + return this._prefsBundle.getString("alwaysAsk"); + } + + // The nsHandlerInfoAction enumeration values in nsIHandlerInfo identify + // the actions the application can take with content of various types. + // But since we've stopped support for plugins, there's no value + // identifying the "use plugin" action, so we use this constant instead. + const kActionUsePlugin = -3; + + switch (aHandlerInfo.preferredAction) { + case Ci.nsIHandlerInfo.saveToDisk: + return this._prefsBundle.getString("saveFile"); + + case Ci.nsIHandlerInfo.useHelperApp: + var preferredApp = aHandlerInfo.preferredApplicationHandler; + var name = (preferredApp instanceof Ci.nsILocalHandlerApp) ? + getFileDisplayName(preferredApp.executable) : + preferredApp.name; + return this._prefsBundle.getFormattedString("useApp", [name]); + + case Ci.nsIHandlerInfo.handleInternally: + // For the feed type, handleInternally means News & Blogs. + if (isFeedType(aHandlerInfo.type)) + return this._prefsBundle.getFormattedString("addNewsBlogsInApp", + [this._brandShortName]); + + // For other types, handleInternally looks like either useHelperApp + // or useSystemDefault depending on whether or not there's a preferred + // handler app. + return (this.isValidHandlerApp(aHandlerInfo.preferredApplicationHandler)) ? + aHandlerInfo.preferredApplicationHandler.name : + aHandlerInfo.defaultDescription; + + // XXX Why don't we say the app will handle the type internally? + // Is it because the app can't actually do that? But if that's true, + // then why would a preferredAction ever get set to this value + // in the first place? + + case Ci.nsIHandlerInfo.useSystemDefault: + return this._prefsBundle.getFormattedString("useDefault", + [aHandlerInfo.defaultDescription]); + + // We no longer support plugins, select "ask" instead: + case kActionUsePlugin: + return this._prefsBundle.getString("alwaysAsk"); + } + // we should never end up here but do a return to end up with a value + return null; + }, + + /** + * Whether or not the given handler app is valid. + * + * @param aHandlerApp {nsIHandlerApp} the handler app in question + * + * @returns {boolean} whether or not it's valid + */ + isValidHandlerApp(aHandlerApp) { + if (!aHandlerApp) + return false; + + if (aHandlerApp instanceof Ci.nsILocalHandlerApp) + return this._isValidHandlerExecutable(aHandlerApp.executable); + + if (aHandlerApp instanceof Ci.nsIWebHandlerApp) + return aHandlerApp.uriTemplate; + + if (aHandlerApp instanceof Ci.nsIWebContentHandlerInfo) + return aHandlerApp.uri; + + if (aHandlerApp instanceof Ci.nsIGIOMimeApp) + return aHandlerApp.command; + + return false; + }, + + _isValidHandlerExecutable(aExecutable) { + var file = Services.dirsvc.get("XREExeF", + Ci.nsIFile); + return aExecutable && + aExecutable.exists() && + aExecutable.isExecutable() && + aExecutable.leafName != file.leafName; + }, + + /** + * Rebuild the actions menu for the selected entry. Gets called by + * the listcell constructor when an entry in the list gets selected. + * Note that this would not work from onselect on the listbox because + * the XBL needs to be applied _before_ calling this function! + */ + rebuildActionsMenu() { + var typeItem = this._list.selectedItem; + var handlerInfo = this._handledTypes[typeItem.type]; + var cell = + document.getAnonymousElementByAttribute(typeItem, "anonid", "action-cell"); + var menu = + document.getAnonymousElementByAttribute(cell, "anonid", "action-menu"); + var menuPopup = menu.menupopup; + + // Clear out existing items. + while (menuPopup.hasChildNodes()) + menuPopup.lastChild.remove(); + + { + let askMenuItem = document.createElement("menuitem"); + askMenuItem.setAttribute("class", "handler-action"); + askMenuItem.setAttribute("value", Ci.nsIHandlerInfo.alwaysAsk); + let label; + if (isFeedType(handlerInfo.type)) + label = this._prefsBundle.getFormattedString("previewInApp", + [this._brandShortName]); + else + label = this._prefsBundle.getString("alwaysAsk"); + askMenuItem.setAttribute("label", label); + askMenuItem.setAttribute("tooltiptext", label); + askMenuItem.setAttribute("appHandlerIcon", "ask"); + menuPopup.appendChild(askMenuItem); + } + + // Create a menu item for saving to disk. + // Note: this option isn't available to protocol types, since we don't know + // what it means to save a URL having a certain scheme to disk, nor is it + // available to feeds, since the feed code doesn't implement the capability. + if ((handlerInfo.wrappedHandlerInfo instanceof Ci.nsIMIMEInfo) && + !isFeedType(handlerInfo.type)) { + let saveMenuItem = document.createElement("menuitem"); + saveMenuItem.setAttribute("class", "handler-action"); + saveMenuItem.setAttribute("value", Ci.nsIHandlerInfo.saveToDisk); + let label = this._prefsBundle.getString("saveFile"); + saveMenuItem.setAttribute("label", label); + saveMenuItem.setAttribute("tooltiptext", label); + saveMenuItem.setAttribute("appHandlerIcon", "save"); + menuPopup.appendChild(saveMenuItem); + } + + // If this is the feed type, add a News & Blogs item. + if (isFeedType(handlerInfo.type)) { + let internalMenuItem = document.createElement("menuitem"); + internalMenuItem.setAttribute("class", "handler-action"); + internalMenuItem.setAttribute("value", Ci.nsIHandlerInfo.handleInternally); + let label = this._prefsBundle.getFormattedString("addNewsBlogsInApp", + [this._brandShortName]); + internalMenuItem.setAttribute("label", label); + internalMenuItem.setAttribute("tooltiptext", label); + internalMenuItem.setAttribute("appHandlerIcon", "feed"); + menuPopup.appendChild(internalMenuItem); + } + + // Add a separator to distinguish these items from the helper app items + // that follow them. + let menuSeparator = document.createElement("menuseparator"); + menuPopup.appendChild(menuSeparator); + + // Create a menu item for the OS default application, if any. + if (handlerInfo.hasDefaultHandler) { + let defaultMenuItem = document.createElement("menuitem"); + defaultMenuItem.setAttribute("class", "handler-action"); + defaultMenuItem.setAttribute("value", Ci.nsIHandlerInfo.useSystemDefault); + let label = this._prefsBundle.getFormattedString("useDefault", + [handlerInfo.defaultDescription]); + defaultMenuItem.setAttribute("label", label); + defaultMenuItem.setAttribute("tooltiptext", handlerInfo.defaultDescription); + let sysIcon = this._getIconURLForSystemDefault(handlerInfo); + if (sysIcon) + defaultMenuItem.setAttribute("image", sysIcon); + else + defaultMenuItem.setAttribute("appHandlerIcon", "app"); + + menuPopup.appendChild(defaultMenuItem); + } + + // Create menu items for possible handlers. + let preferredApp = handlerInfo.preferredApplicationHandler; + let possibleApps = handlerInfo.possibleApplicationHandlers.enumerate(); + var possibleAppMenuItems = []; + while (possibleApps.hasMoreElements()) { + let possibleApp = possibleApps.getNext(); + if (!this.isValidHandlerApp(possibleApp)) + continue; + + let menuItem = document.createElement("menuitem"); + menuItem.setAttribute("class", "handler-action"); + menuItem.setAttribute("value", Ci.nsIHandlerInfo.useHelperApp); + let label; + if (possibleApp instanceof Ci.nsILocalHandlerApp) + label = getFileDisplayName(possibleApp.executable); + else + label = possibleApp.name; + label = this._prefsBundle.getFormattedString("useApp", [label]); + menuItem.setAttribute("label", label); + menuItem.setAttribute("tooltiptext", label); + let sysIcon = this._getIconURLForHandlerApp(possibleApp); + if (sysIcon) + menuItem.setAttribute("image", sysIcon); + else + menuItem.setAttribute("appHandlerIcon", "app"); + + // Attach the handler app object to the menu item so we can use it + // to make changes to the datastore when the user selects the item. + menuItem.handlerApp = possibleApp; + + menuPopup.appendChild(menuItem); + possibleAppMenuItems.push(menuItem); + } + +// Add gio handlers + if (Cc["@mozilla.org/gio-service;1"]) { + let gIOSvc = Cc["@mozilla.org/gio-service;1"] + .getService(Ci.nsIGIOService); + var gioApps = gIOSvc.getAppsForURIScheme(typeItem.type); + let enumerator = gioApps.enumerate(); + let possibleHandlers = handlerInfo.possibleApplicationHandlers; + while (enumerator.hasMoreElements()) { + let handler = enumerator.getNext().QueryInterface(Ci.nsIHandlerApp); + // OS handler share the same name, it's most likely the same app, skipping... + if (handler.name == handlerInfo.defaultDescription) { + continue; + } + // Check if the handler is already in possibleHandlers + let appAlreadyInHandlers = false; + for (let i = possibleHandlers.length - 1; i >= 0; --i) { + let app = possibleHandlers.queryElementAt(i, Ci.nsIHandlerApp); + // nsGIOMimeApp::Equals is able to compare with Ci.nsILocalHandlerApp + if (handler.equals(app)) { + appAlreadyInHandlers = true; + break; + } + } + if (!appAlreadyInHandlers) { + let menuItem = document.createElement("menuitem"); + menuItem.setAttribute("action", Ci.nsIHandlerInfo.useHelperApp); + let label = this._prefsBundle.getFormattedString("useApp", [handler.name]); + menuItem.setAttribute("label", label); + menuItem.setAttribute("tooltiptext", label); + menuItem.setAttribute("image", this._getIconURLForHandlerApp(handler)); + + // Attach the handler app object to the menu item so we can use it + // to make changes to the datastore when the user selects the item. + menuItem.handlerApp = handler; + + menuPopup.appendChild(menuItem); + possibleAppMenuItems.push(menuItem); + } + } + } + + // Create a menu item for selecting a local application. + let canOpenWithOtherApp = true; + if (AppConstants.platform == "win") { + // On Windows, selecting an application to open another application + // would be meaningless so we special case executables. + let executableType = gMIMEService.getTypeFromExtension("exe"); + canOpenWithOtherApp = handlerInfo.type != executableType; + } + if (canOpenWithOtherApp) + { + let menuItem = document.createElement("menuitem"); + menuItem.setAttribute("class", "handler-action"); + menuItem.setAttribute("value", kActionChooseApp); + let label = this._prefsBundle.getString("useOtherApp"); + menuItem.setAttribute("label", label); + menuItem.setAttribute("tooltiptext", label); + menuPopup.appendChild(menuItem); + } + + // Create a menu item for managing applications. + if (possibleAppMenuItems.length) { + let menuItem = document.createElement("menuseparator"); + menuPopup.appendChild(menuItem); + menuItem = document.createElement("menuitem"); + menuItem.setAttribute("class", "handler-action"); + menuItem.setAttribute("value", kActionManageApp); + menuItem.setAttribute("label", this._prefsBundle.getString("manageApp")); + menuPopup.appendChild(menuItem); + } + + // Select the item corresponding to the preferred action. If the always + // ask flag is set, it overrides the preferred action. Otherwise we pick + // the item identified by the preferred action (when the preferred action + // is to use a helper app, we have to pick the specific helper app item). + if (handlerInfo.alwaysAskBeforeHandling) + menu.value = Ci.nsIHandlerInfo.alwaysAsk; + else if (handlerInfo.preferredAction == Ci.nsIHandlerInfo.useHelperApp && + preferredApp) + menu.selectedItem = + possibleAppMenuItems.filter(v => v.handlerApp.equals(preferredApp))[0]; + else + menu.value = handlerInfo.preferredAction; + }, + + + //**************************************************************************// + // Sorting & Filtering + + _sortColumn: null, + + /** + * Sort the list when the user clicks on a column header. + */ + sort(event) { + var column = event.target; + + // If the user clicked on a new sort column, remove the direction indicator + // from the old column. + if (this._sortColumn && this._sortColumn != column) + this._sortColumn.removeAttribute("sortDirection"); + + this._sortColumn = column; + + // Set (or switch) the sort direction indicator. + if (column.getAttribute("sortDirection") == "ascending") + column.setAttribute("sortDirection", "descending"); + else + column.setAttribute("sortDirection", "ascending"); + + this._sortVisibleTypes(); + this._rebuildView(); + }, + + /** + * Sort the list of visible types by the current sort column/direction. + */ + _sortVisibleTypes() { + if (!this._sortColumn) + return; + + var t = this; + + function sortByType(a, b) { + return t._describeType(a).toLowerCase() + .localeCompare(t._describeType(b).toLowerCase()); + } + + function sortByAction(a, b) { + return t._describePreferredAction(a).toLowerCase() + .localeCompare(t._describePreferredAction(b).toLowerCase()); + } + + switch (this._sortColumn.getAttribute("value")) { + case "type": + this._visibleTypes.sort(sortByType); + break; + case "action": + this._visibleTypes.sort(sortByAction); + break; + } + + if (this._sortColumn.getAttribute("sortDirection") == "descending") + this._visibleTypes.reverse(); + }, + + + //**************************************************************************// + // Changes + + onSelectAction(aActionItem) { + this._storingAction = true; + + try { + this._storeAction(aActionItem); + } + finally { + this._storingAction = false; + } + }, + + _storeAction(aActionItem) { + var typeItem = this._list.selectedItem; + var handlerInfo = this._handledTypes[typeItem.type]; + + let action = parseInt(aActionItem.getAttribute("value")); + + // Set the preferred application handler. + // We leave the existing preferred app in the list when we set + // the preferred action to something other than useHelperApp so that + // legacy datastores that don't have the preferred app in the list + // of possible apps still include the preferred app in the list of apps + // the user can choose to handle the type. + if (action == Ci.nsIHandlerInfo.useHelperApp) + handlerInfo.preferredApplicationHandler = aActionItem.handlerApp; + + // Set the preferred action. + handlerInfo.preferredAction = action; + + // Set the "always ask" flag. + handlerInfo.alwaysAskBeforeHandling = action == Ci.nsIHandlerInfo.alwaysAsk; + + handlerInfo.store(); + + // Make sure the handler info object is flagged to indicate that there is + // now some user configuration for the type. + + // Update the action label and image to reflect the new preferred action. + typeItem.setAttribute("actionDescription", + this._describePreferredAction(handlerInfo)); + if (!this._setIconClassForPreferredAction(handlerInfo, typeItem)) { + var sysIcon = this._getIconURLForPreferredAction(handlerInfo); + if (sysIcon) + typeItem.setAttribute("actionIcon", sysIcon); + else + typeItem.setAttribute("appHandlerIcon", "app"); + } + }, + + manageApp() { + var typeItem = this._list.selectedItem; + var handlerInfo = this._handledTypes[typeItem.type]; + + document.documentElement.openSubDialog("chrome://communicator/content/pref/pref-applicationManager.xul", + "", handlerInfo); + + // Rebuild the actions menu so that we revert to the previous selection, + // or "Always ask" if the previous default application has been removed + this.rebuildActionsMenu(); + + // update the listitem too. Will be visible when selecting another row + typeItem.setAttribute("actionDescription", + this._describePreferredAction(handlerInfo)); + if (!this._setIconClassForPreferredAction(handlerInfo, typeItem)) { + var sysIcon = this._getIconURLForPreferredAction(handlerInfo); + if (sysIcon) + typeItem.setAttribute("actionIcon", sysIcon); + else + typeItem.setAttribute("appHandlerIcon", "app"); + } + }, + + handlerApp: null, + + finishChooseApp() { + if (this.handlerApp) { + // Add the app to the type's list of possible handlers. + let handlerInfo = this._handledTypes[this._list.selectedItem.type]; + handlerInfo.addPossibleApplicationHandler(this.handlerApp); + } + + // Rebuild the actions menu whether the user picked an app or canceled. + // If they picked an app, we want to add the app to the menu and select it. + // If they canceled, we want to go back to their previous selection. + this.rebuildActionsMenu(); + + // If the user picked a new app from the menu, select it. + if (this.handlerApp) { + var actionsCell = + document.getAnonymousElementByAttribute(this._list.selectedItem, + "anonid", "action-cell"); + var actionsMenu = + document.getAnonymousElementByAttribute(actionsCell, + "anonid", "action-menu"); + let menuItems = actionsMenu.menupopup.childNodes; + for (let i = 0; i < menuItems.length; i++) { + let menuItem = menuItems[i]; + if (menuItem.handlerApp && + menuItem.handlerApp.equals(this.handlerApp)) { + actionsMenu.selectedIndex = i; + this.onSelectAction(menuItem); + break; + } + } + } + }, + + chooseApp() { + this.handlerApp = null; + + if (AppConstants.platform == "win") { + let params = {}; + let handlerInfo = this._handledTypes[this._list.selectedItem.type]; + + if (isFeedType(handlerInfo.type)) { + // MIME info will be null, create a temp object. + params.mimeInfo = + gMIMEService.getFromTypeAndExtension(handlerInfo.type, + handlerInfo.primaryExtension); + } else { + params.mimeInfo = handlerInfo.wrappedHandlerInfo; + } + + params.title = this._prefsBundle.getString("fpTitleChooseApp"); + params.description = handlerInfo.description; + params.filename = null; + params.handlerApp = null; + + window.openDialog("chrome://global/content/appPicker.xul", null, + "chrome,modal,centerscreen,titlebar,dialog=yes", + params); + + if (this.isValidHandlerApp(params.handlerApp)) { + this.handlerApp = params.handlerApp; + } + this.finishChooseApp(); + } else if (Services.prefs.getBoolPref("browser.download.useAppChooser", true) && ("@mozilla.org/applicationchooser;1" in Cc)) { + let mimeInfo; + let handlerInfo = this._handledTypes[this._list.selectedItem.type]; + if (isFeedType(handlerInfo.type)) { + // MIME info will be null, create a temp object. + mimeInfo = + gMIMEService.getFromTypeAndExtension(handlerInfo.type, + handlerInfo.primaryExtension); + } else { + mimeInfo = handlerInfo.wrappedHandlerInfo; + } + + var appChooser = Cc["@mozilla.org/applicationchooser;1"] + .createInstance(Ci.nsIApplicationChooser); + appChooser.init(window, this._prefsBundle.getString("fpTitleChooseApp")); + var contentTypeDialogObj = this; + let appChooserCallback = function appChooserCallback_done(aResult) { + if (aResult) { + contentTypeDialogObj.handlerApp = aResult.QueryInterface(Ci.nsILocalHandlerApp); + } + contentTypeDialogObj.finishChooseApp(); + }; + appChooser.open(mimeInfo.MIMEType, appChooserCallback); + // The finishChooseApp is called from appChooserCallback + } else { + let fp = Cc["@mozilla.org/filepicker;1"] + .createInstance(Ci.nsIFilePicker); + let winTitle = this._prefsBundle.getString("fpTitleChooseApp"); + fp.init(window, winTitle, Ci.nsIFilePicker.modeOpen); + fp.appendFilters(Ci.nsIFilePicker.filterApps); + + // Prompt the user to pick an app. If they pick one, and it's a valid + // selection, then add it to the list of possible handlers. + fp.open(rv => { + if (rv == Ci.nsIFilePicker.returnOK && fp.file && + this._isValidHandlerExecutable(fp.file)) { + let handlerApp = Cc["@mozilla.org/uriloader/local-handler-app;1"] + .createInstance(Ci.nsILocalHandlerApp); + handlerApp.name = getFileDisplayName(fp.file); + handlerApp.executable = fp.file; + this.handlerApp = handlerApp; + } + this.finishChooseApp(); + }); + } + }, + + _setIconClassForPreferredAction(aHandlerInfo, aElement) { + // If this returns true, the attribute that CSS sniffs for was set to something + // so you shouldn't manually set an icon URI. + // This removes the existing actionIcon attribute if any, even if returning false. + aElement.removeAttribute("actionIcon"); + + if (aHandlerInfo.alwaysAskBeforeHandling) { + aElement.setAttribute("appHandlerIcon", "ask"); + return true; + } + + switch (aHandlerInfo.preferredAction) { + case Ci.nsIHandlerInfo.saveToDisk: + aElement.setAttribute("appHandlerIcon", "save"); + return true; + + case Ci.nsIHandlerInfo.handleInternally: + if (isFeedType(aHandlerInfo.type)) { + aElement.setAttribute("appHandlerIcon", "feed"); + return true; + } + break; + } + aElement.removeAttribute("appHandlerIcon"); + return false; + }, + + _getIconURLForPreferredAction(aHandlerInfo) { + switch (aHandlerInfo.preferredAction) { + case Ci.nsIHandlerInfo.useSystemDefault: + return this._getIconURLForSystemDefault(aHandlerInfo); + + case Ci.nsIHandlerInfo.useHelperApp: + let preferredApp = aHandlerInfo.preferredApplicationHandler; + if (this.isValidHandlerApp(preferredApp)) + return this._getIconURLForHandlerApp(preferredApp); + break; + } + // This should never happen, but if preferredAction is set to some weird + // value, then fall back to the generic application icon. + return null; + }, + + _getIconURLForHandlerApp(aHandlerApp) { + if (aHandlerApp instanceof Ci.nsILocalHandlerApp) + return this._getIconURLForFile(aHandlerApp.executable); + + if (Services.prefs.getBoolPref("browser.chrome.favicons")) { // q.v. Bug 514671 + if (aHandlerApp instanceof Ci.nsIWebHandlerApp) + return this._getIconURLForWebApp(aHandlerApp.uriTemplate); + + if (aHandlerApp instanceof Ci.nsIWebContentHandlerInfo) + return this._getIconURLForWebApp(aHandlerApp.uri); + } + + // We know nothing about other kinds of handler apps. + return ""; + }, + + _getIconURLForFile(aFile) { + var fph = Services.io.getProtocolHandler("file") + .QueryInterface(Ci.nsIFileProtocolHandler); + var urlSpec = fph.getURLSpecFromFile(aFile); + + return "moz-icon://" + urlSpec + "?size=16"; + }, + + _getIconURLForWebApp(aWebAppURITemplate) { + var uri = Services.io.newURI(aWebAppURITemplate); + + // Unfortunately we need to use favicon.ico here, but we don't know + // about any other possibility to retrieve an icon for the web app/site + // without loading a specific full URL and parsing it for a possible + // shortcut icon. + + return /^https?/.test(uri.scheme) ? uri.resolve("/favicon.ico") : ""; + }, + + _getIconURLForSystemDefault(aHandlerInfo) { + // Handler info objects for MIME types on some OSes implement a property bag + // interface from which we can get an icon for the default app, so if we're + // dealing with a MIME type on one of those OSes, then try to get the icon. + if ("wrappedHandlerInfo" in aHandlerInfo) { + let wrappedHandlerInfo = aHandlerInfo.wrappedHandlerInfo; + + if (wrappedHandlerInfo instanceof Ci.nsIMIMEInfo && + wrappedHandlerInfo instanceof Ci.nsIPropertyBag) { + try { + let url = wrappedHandlerInfo.getProperty("defaultApplicationIconURL"); + if (url) + return url + "?size=16"; + } + catch(ex) {} + } + } + + // If this isn't a MIME type object on an OS that supports retrieving + // the icon, or if we couldn't retrieve the icon for some other reason, + // then use a generic icon. + return null; + } + +}; diff --git a/comm/suite/components/pref/content/pref-applications.xul b/comm/suite/components/pref/content/pref-applications.xul new file mode 100644 index 0000000000..351c254252 --- /dev/null +++ b/comm/suite/components/pref/content/pref-applications.xul @@ -0,0 +1,113 @@ +<?xml version="1.0"?> + +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<!DOCTYPE overlay [ + <!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd"> %brandDTD; + <!ENTITY % prefApplicationsDTD SYSTEM "chrome://communicator/locale/pref/pref-applications.dtd"> %prefApplicationsDTD; +]> + +<overlay id="ApplicationsPaneOverlay" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + + <prefpane id="applications_pane" + label="&pref.applications.title;" + script="chrome://communicator/content/pref/pref-applications.js"> + + <preferences id="feedsPreferences"> + <preference id="browser.feeds.handler" + name="browser.feeds.handler" + type="string"/> + <preference id="browser.feeds.handler.default" + name="browser.feeds.handler.default" + type="string"/> + <preference id="browser.feeds.handlers.application" + name="browser.feeds.handlers.application" + type="file"/> + <preference id="browser.feeds.handlers.webservice" + name="browser.feeds.handlers.webservice" + type="string"/> + + <preference id="browser.videoFeeds.handler" + name="browser.videoFeeds.handler" + type="string"/> + <preference id="browser.videoFeeds.handler.default" + name="browser.videoFeeds.handler.default" + type="string"/> + <preference id="browser.videoFeeds.handlers.application" + name="browser.videoFeeds.handlers.application" + type="file"/> + <preference id="browser.videoFeeds.handlers.webservice" + name="browser.videoFeeds.handlers.webservice" + type="string"/> + + <preference id="browser.audioFeeds.handler" + name="browser.audioFeeds.handler" + type="string"/> + <preference id="browser.audioFeeds.handler.default" + name="browser.audioFeeds.handler.default" + type="string"/> + <preference id="browser.audioFeeds.handlers.application" + name="browser.audioFeeds.handlers.application" + type="file"/> + <preference id="browser.audioFeeds.handlers.webservice" + name="browser.audioFeeds.handlers.webservice" + type="string"/> + + <preference id="pref.downloads.disable_button.edit_actions" + name="pref.downloads.disable_button.edit_actions" + type="bool"/> + <preference id="browser.download.useAppChooser" + name="browser.download.useAppChooser" + type="bool"/> + </preferences> + + <stringbundleset id="appBundleset"> + <stringbundle id="bundleBrand" + src="chrome://branding/locale/brand.properties"/> + <stringbundle id="bundlePrefApplications" + src="chrome://communicator/locale/pref/pref-applications.properties"/> + </stringbundleset> + + <hbox align="center"> + <textbox id="filter" + flex="1" + type="search" + placeholder="&search.placeholder;" + clickSelectsAll="true" + aria-controls="handlersView" + oncommand="gApplicationsPane._rebuildView();"/> + </hbox> + + <separator class="thin"/> + + <listbox id="handlersView" persist="lastSelectedType" flex="1" + preference="pref.downloads.disable_button.edit_actions"> + <listcols> + <listcol width="1" flex="1"/> + <listcol width="1" flex="1"/> + </listcols> + <listhead> + <listheader id="typeColumn" label="&typeColumn.label;" value="type" + accesskey="&typeColumn.accesskey;" persist="sortDirection" + onclick="gApplicationsPane.sort(event);" + sortDirection="ascending"/> + <listheader id="actionColumn" label="&actionColumn2.label;" value="action" + accesskey="&actionColumn2.accesskey;" persist="sortDirection" + onclick="gApplicationsPane.sort(event);"/> + </listhead> + </listbox> +#ifdef XP_LINUX + <separator class="thin"/> + + <hbox align="center"> + <checkbox id="downloadUseAppChooser" + label="&useAppChooser.label;" + accesskey="&useAppChooser.accesskey;" + preference="browser.download.useAppChooser"/> + </hbox> +#endif + </prefpane> +</overlay> diff --git a/comm/suite/components/pref/content/pref-cache.js b/comm/suite/components/pref/content/pref-cache.js new file mode 100644 index 0000000000..be2245b98b --- /dev/null +++ b/comm/suite/components/pref/content/pref-cache.js @@ -0,0 +1,113 @@ +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +var {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm"); +const {DownloadUtils} = ChromeUtils.import("resource://gre/modules/DownloadUtils.jsm"); + +var {AppConstants} = ChromeUtils.import( + "resource://gre/modules/AppConstants.jsm" +); + +function Startup() +{ + updateActualCacheSize(); +} + +// Needs to be global because the cache service only keeps a weak reference. +var CacheObserver = { + /* nsICacheStorageConsumptionObserver */ + onNetworkCacheDiskConsumption: function(aConsumption) { + var actualSizeLabel = document.getElementById("cacheSizeInfo"); + var sizeStrings = DownloadUtils.convertByteUnits(aConsumption); + var prefStrBundle = document.getElementById("bundle_prefutilities"); + var sizeStr = prefStrBundle.getFormattedString("cacheSizeInfo", + sizeStrings); + actualSizeLabel.textContent = sizeStr; + }, + + /* nsISupports */ + QueryInterface: XPCOMUtils.generateQI( + [Ci.nsICacheStorageConsumptionObserver, + Ci.nsISupportsWeakReference]) +}; + +// because the cache is in kilobytes, and the UI is in megabytes. +function ReadCacheDiskCapacity() +{ + var pref = document.getElementById("browser.cache.disk.capacity"); + return pref.value >> 10; +} + +function WriteCacheDiskCapacity(aField) +{ + return aField.value << 10; +} + +function ReadCacheFolder(aField) +{ + var pref = document.getElementById("browser.cache.disk.parent_directory"); + var file = pref.value; + + if (!file) + { + try + { + // no disk cache folder pref set; default to profile directory + file = GetSpecialDirectory(Services.dirsvc.has("ProfLD") ? "ProfLD" + : "ProfD"); + } + catch (ex) {} + } + + if (file) { + aField.file = file; + aField.label = AppConstants.platform == "macosx" ? file.leafName : file.path; + } +} + +function CacheSelectFolder() +{ + let fp = Cc["@mozilla.org/filepicker;1"] + .createInstance(Ci.nsIFilePicker); + let title = document.getElementById("bundle_prefutilities") + .getString("cachefolder"); + + fp.init(window, title, Ci.nsIFilePicker.modeGetFolder); + fp.displayDirectory = + document.getElementById("browser.cache.disk.parent_directory").value; + fp.appendFilters(Ci.nsIFilePicker.filterAll); + + fp.open(rv => { + if (rv != Ci.nsIFilePicker.returnOK || !fp.file) { + return; + } + document.getElementById("browser.cache.disk.parent_directory").value = fp.file; + }); +} + +function ClearDiskAndMemCache() +{ + Services.cache2.clear(); + updateActualCacheSize(); +} + +function updateCacheSizeUI(cacheSizeEnabled) +{ + document.getElementById("browserCacheDiskCacheBefore").disabled = cacheSizeEnabled; + document.getElementById("browserCacheDiskCache").disabled = cacheSizeEnabled; + document.getElementById("browserCacheDiskCacheAfter").disabled = cacheSizeEnabled; +} + +function ReadSmartSizeEnabled() +{ + var enabled = document.getElementById("browser.cache.disk.smart_size.enabled").value; + updateCacheSizeUI(enabled); + return enabled; +} + +function updateActualCacheSize() +{ + Services.cache2.asyncGetDiskConsumption(CacheObserver); +} diff --git a/comm/suite/components/pref/content/pref-cache.xul b/comm/suite/components/pref/content/pref-cache.xul new file mode 100644 index 0000000000..6b60ddef2b --- /dev/null +++ b/comm/suite/components/pref/content/pref-cache.xul @@ -0,0 +1,142 @@ +<?xml version="1.0"?> +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<!DOCTYPE overlay [ +<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd"> +%brandDTD; +<!ENTITY % prefCacheDTD SYSTEM "chrome://communicator/locale/pref/pref-cache.dtd"> +%prefCacheDTD; +]> + +<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <prefpane id="cache_pane" + label="&pref.cache.title;" + script="chrome://communicator/content/pref/pref-cache.js"> + + <preferences> + <preference id="browser.cache.disk.capacity" + name="browser.cache.disk.capacity" + type="int"/> + <preference id="browser.cache.disk.smart_size.enabled" + name="browser.cache.disk.smart_size.enabled" + type="bool"/> + <preference id="pref.advanced.cache.disable_button.clear_disk" + name="pref.advanced.cache.disable_button.clear_disk" + type="bool"/> + <preference id="browser.cache.check_doc_frequency" + name="browser.cache.check_doc_frequency" + type="int"/> + <preference id="network.prefetch-next" + name="network.prefetch-next" + type="bool"/> + <preference id="browser.cache.disk.parent_directory" + name="browser.cache.disk.parent_directory" + type="file"/> + <preference id="browser.cache.disk.enable" + name="browser.cache.disk.enable" + type="bool"/> + <preference id="browser.cache.memory.enable" + name="browser.cache.memory.enable" + type="bool"/> + </preferences> + + <groupbox> + <caption label="&pref.cache.caption;"/> + + <description>&cachePara;</description> + + <vbox align="start"> + <label id="cacheSizeInfo"/> + <checkbox id="allowSmartSize" + label="&cacheCheck.label;" + accesskey="&cacheCheck.accesskey;" + onsyncfrompreference="return document.getElementById('cache_pane').ReadSmartSizeEnabled();" + preference="browser.cache.disk.smart_size.enabled"/> + </vbox> + <hbox align="center"> + <label id="browserCacheDiskCacheBefore" + value="&diskCacheUpTo.label;" + accesskey="&diskCacheUpTo.accesskey;" + control="browserCacheDiskCache"/> + <textbox id="browserCacheDiskCache" + size="5" + type="number" + aria-labelledby="browserCacheDiskCacheBefore browserCacheDiskCache browserCacheDiskCacheAfter" + preference="browser.cache.disk.capacity" + onsyncfrompreference="return document.getElementById('cache_pane').ReadCacheDiskCapacity();" + onsynctopreference="return document.getElementById('cache_pane').WriteCacheDiskCapacity(this);"/> + <label id="browserCacheDiskCacheAfter" + value="&spaceMbytes;"/> + <button label="&clearDiskCache.label;" + accesskey="&clearDiskCache.accesskey;" + oncommand="ClearDiskAndMemCache();" + id="clearDiskCache" + preference="pref.advanced.cache.disable_button.clear_disk"/> + </hbox> + + <vbox> + <label value="&diskCacheFolder.label;"/> + <hbox align="center"> + <filefield id="browserCacheDiskCacheFolder" + flex="1" + preference="browser.cache.disk.parent_directory" + preference-editable="true" + onsyncfrompreference="return document.getElementById('cache_pane').ReadCacheFolder(this);"/> + <button label="&chooseDiskCacheFolder.label;" + accesskey="&chooseDiskCacheFolder.accesskey;" + oncommand="CacheSelectFolder();" + id="chooseDiskCacheFolder"> + <observes element="browserCacheDiskCacheFolder" + attribute="disabled"/> + </button> + </hbox> + </vbox> + <description>&diskCacheFolderExplanation;</description> + + <separator class="thin"/> + + <label control="browserCacheCheckDocFrequency" + value="&docCache.label;" + accesskey="&docCache.accesskey;"/> + <hbox align="start"> + <menulist id="browserCacheCheckDocFrequency" + class="indent" + preference="browser.cache.check_doc_frequency"> + <menupopup> + <menuitem value="1" label="&checkEveryTime.label;"/> + <menuitem value="3" label="&checkAutomatically.label;"/> + <menuitem value="0" label="&checkOncePerSession.label;"/> + <menuitem value="2" label="&checkNever.label;"/> + </menupopup> + </menulist> + </hbox> + + </groupbox> + + <groupbox id="prefetch"> + <caption id="prefetchLabel" label="&prefetchTitle.label;"/> + <vbox id="prefetchBox" align="start"> + <checkbox id="enablePrefetch" + label="&enablePrefetch.label;" + accesskey="&enablePrefetch.accesskey;" + preference="network.prefetch-next"/> + </vbox> + </groupbox> + + <groupbox id="debugCache"> + <caption label="&debugCache.label;"/> + <hbox align="center"> + <checkbox id="browserEnableDiskCache" + label="&debugEnableDiskCache.label;" + accesskey="&debugEnableDiskCache.accesskey;" + preference="browser.cache.disk.enable"/> + <checkbox id="browserEnableCache" + label="&debugEnableMemCache.label;" + accesskey="&debugEnableMemCache.accesskey;" + preference="browser.cache.memory.enable"/> + </hbox> + </groupbox> + + </prefpane> +</overlay> diff --git a/comm/suite/components/pref/content/pref-colors.js b/comm/suite/components/pref/content/pref-colors.js new file mode 100644 index 0000000000..619af1bd5e --- /dev/null +++ b/comm/suite/components/pref/content/pref-colors.js @@ -0,0 +1,26 @@ +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +function Startup() +{ + ToggleCustomColorPickers(document.getElementById("browser.display.use_system_colors").value); +} + +function ToggleCustomColorPickers(aChecked) +{ + TogglePickerDisability(aChecked, "browserForegroundColor"); + TogglePickerDisability(aChecked, "browserBackgroundColor"); +} + +function TogglePickerDisability(aDisable, aPicker) +{ + var element = document.getElementById(aPicker); + aDisable = aDisable || + document.getElementById(element.getAttribute("preference")).locked; + + element.disabled = aDisable; + element = document.getElementById(aPicker + "Label"); + element.disabled = aDisable; +} diff --git a/comm/suite/components/pref/content/pref-colors.xul b/comm/suite/components/pref/content/pref-colors.xul new file mode 100644 index 0000000000..97c5d0c631 --- /dev/null +++ b/comm/suite/components/pref/content/pref-colors.xul @@ -0,0 +1,131 @@ +<?xml version="1.0"?> +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<!DOCTYPE overlay SYSTEM "chrome://communicator/locale/pref/pref-colors.dtd"> + +<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <prefpane id="colors_pane" + label="&pref.colors.title;" + script="chrome://communicator/content/pref/pref-colors.js"> + + <preferences id="colors_preferences"> + <preference id="browser.display.foreground_color" + name="browser.display.foreground_color" + type="string"/> + <preference id="browser.display.background_color" + name="browser.display.background_color" + type="string"/> + <preference id="browser.display.use_system_colors" + name="browser.display.use_system_colors" + type="bool" + onchange="ToggleCustomColorPickers(this.value);"/> + <preference id="browser.anchor_color" + name="browser.anchor_color" + type="string"/> + <preference id="browser.active_color" + name="browser.active_color" + type="string"/> + <preference id="browser.visited_color" + name="browser.visited_color" + type="string"/> + <preference id="browser.underline_anchors" + name="browser.underline_anchors" + type="bool"/> + <preference id="browser.display.document_color_use" + name="browser.display.document_color_use" + type="int"/> + </preferences> + <hbox> + <groupbox flex="1" id="pageColours"> + <caption label="&color;"/> + <hbox align="center"> + <label id="browserForegroundColorLabel" + value="&textColor.label;" + accesskey="&textColor.accesskey;" + flex="1" + control="browserForegroundColor"/> + <colorpicker id="browserForegroundColor" + type="button" + palettename="standard" + preference="browser.display.foreground_color"/> + </hbox> + <hbox align="center" style="margin-top: 5px"> + <label id="browserBackgroundColorLabel" + value="&backgroundColor.label;" + accesskey="&backgroundColor.accesskey;" + flex="1" + control="browserBackgroundColor"/> + <colorpicker id="browserBackgroundColor" + type="button" + palettename="standard" + preference="browser.display.background_color"/> + </hbox> + <separator class="thin"/> + <hbox align="center"> + <checkbox id="browserUseSystemColors" + label="&useSystemColors.label;" + accesskey="&useSystemColors.accesskey;" + preference="browser.display.use_system_colors"/> + </hbox> + </groupbox> + + <groupbox flex="1"> + <caption label="&links;"/> + <hbox align="center"> + <label value="&linkColor.label;" + accesskey="&linkColor.accesskey;" + flex="1" + control="browserAnchorColor"/> + <colorpicker id="browserAnchorColor" + type="button" + palettename="standard" + preference="browser.anchor_color"/> + </hbox> + <hbox align="center" style="margin-top: 5px"> + <label value="&activeLinkColor.label;" + accesskey="&activeLinkColor.accesskey;" + flex="1" + control="browserActiveColor"/> + <colorpicker id="browserActiveColor" + type="button" + palettename="standard" + preference="browser.active_color"/> + </hbox> + <hbox align="center" style="margin-top: 5px"> + <label value="&visitedLinkColor.label;" + accesskey="&visitedLinkColor.accesskey;" + flex="1" + control="browserVisitedColor"/> + <colorpicker id="browserVisitedColor" + type="button" + palettename="standard" + preference="browser.visited_color"/> + </hbox> + <separator class="thin"/> + <hbox align="center"> + <checkbox id="browserUnderlineAnchors" + label="&underlineLinks.label;" + accesskey="&underlineLinks.accesskey;" + preference="browser.underline_anchors"/> + </hbox> + </groupbox> + </hbox> + + <groupbox> + <caption label="&someProvColors;"/> + + <radiogroup id="browserDocumentColorUse" + preference="browser.display.document_color_use"> + <radio value="1" label="&alwaysUseDocumentColors.label;" + accesskey="&alwaysUseDocumentColors.accesskey;"/> + <radio value="2" label="&useMyColors.label;" + accesskey="&useMyColors.accesskey;"/> + <radio value="0" label="&automaticColors.label;" + accesskey="&automaticColors.accesskey;"/> + </radiogroup> + + </groupbox> + </prefpane> +</overlay> diff --git a/comm/suite/components/pref/content/pref-content.js b/comm/suite/components/pref/content/pref-content.js new file mode 100644 index 0000000000..964c216a28 --- /dev/null +++ b/comm/suite/components/pref/content/pref-content.js @@ -0,0 +1,141 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +var {AppConstants} = ChromeUtils.import( + "resource://gre/modules/AppConstants.jsm" +); + +var minMinValue; +var maxMinValue; + +/** + * When starting up, obtain min and max values for the zoom-range controls + * from the first and last values of the zoom-levels array. + */ +function Startup() +{ + let minElement = document.getElementById("minZoom"); + let maxElement = document.getElementById("maxZoom"); + let minMaxLimit = 200; + let maxMinLimit = 50; // allow reasonable amounts of overlap + let zoomValues = Services.prefs.getCharPref("toolkit.zoomManager.zoomValues") + .split(",").map(parseFloat); + zoomValues.sort((a, b) => a - b); + + let firstValue = Math.round(100 * zoomValues[0]); + let lastValue = Math.round(100 * zoomValues[zoomValues.length - 1]); + + minMinValue = firstValue; + minElement.min = minMinValue; + minElement.max = lastValue > minMaxLimit ? minMaxLimit : lastValue; + + maxMinValue = firstValue < maxMinLimit ? maxMinLimit : firstValue; + maxElement.min = maxMinValue; + maxElement.max = lastValue; + + /* defaultZoom stuff */ + + let defaultElement = document.getElementById("defaultZoom"); + + defaultElement.min = Services.prefs.getIntPref("zoom.minPercent"); + defaultElement.max = Services.prefs.getIntPref("zoom.maxPercent"); + + var zoomValue = Services.contentPrefs2 + .getCachedGlobal("browser.content.full-zoom", null); + if (zoomValue && zoomValue.value) { + defaultElement.value = Math.round(zoomValue.value * 100); + return; + } + + defaultElement.value = 100; + Services.contentPrefs2.getGlobal("browser.content.full-zoom", null, { + handleResult(pref) { + defaultElement.value = Math.round(pref.value * 100); + }, + handleCompletion(reason) {} + }); +} + +/** + * Suspend "min" value while manually typing in a number. + */ +function DisableMinCheck(element) +{ + element.min = 0; +} + +/** + * Modify the maxZoom setting if minZoom was chosen to be larger than it. + */ +function AdjustMaxZoom() +{ + let minElement = document.getElementById("minZoom"); + let maxElement = document.getElementById("maxZoom"); + let maxPref = document.getElementById("zoom.maxPercent"); + + if(minElement.valueNumber > maxElement.valueNumber) + maxPref.value = minElement.value; + + minElement.min = minMinValue; + + let defaultElement = document.getElementById("defaultZoom"); + if (defaultElement.valueNumber < minElement.valueNumber) { + defaultElement.valueNumber = minElement.valueNumber; + SetDefaultZoom(); + } + defaultElement.min = minElement.valueNumber; +} + +/** + * Modify the minZoom setting if maxZoom was chosen to be smaller than it, + * adjusting maxZoom first if it's below maxMinValue. + */ +function AdjustMinZoom() +{ + let minElement = document.getElementById("minZoom"); + let maxElement = document.getElementById("maxZoom"); + let minPref = document.getElementById("zoom.minPercent"); + let maxValue = maxElement.valueNumber < maxMinValue ? + maxMinValue : maxElement.valueNumber; + + if(maxValue < minElement.valueNumber) + minPref.value = maxValue; + + maxElement.min = maxMinValue; + + let defaultElement = document.getElementById("defaultZoom"); + if (defaultElement.valueNumber > maxElement.valueNumber) { + defaultElement.valueNumber = maxElement.valueNumber; + SetDefaultZoom(); + } + defaultElement.max = maxElement.valueNumber; +} + +/** + * Set default zoom. + */ +function SetDefaultZoom() +{ + let defaultElement = document.getElementById("defaultZoom"); + + if (defaultElement.valueNumber == 100) { + Services.contentPrefs2.removeGlobal("browser.content.full-zoom", null); + return; + } + + let new_value = defaultElement.valueNumber / 100.; + Services.contentPrefs2.setGlobal("browser.content.full-zoom", new_value, + null); +} + +/** + * When the user toggles the layers.acceleration.disabled pref, + * sync its new value to the gfx.direct2d.disabled pref too. + */ +function updateHardwareAcceleration(aVal) +{ + if (AppConstants.platform == "win") { + document.getElementById("gfx.direct2d.disabled").value = aVal; + } +} diff --git a/comm/suite/components/pref/content/pref-content.xul b/comm/suite/components/pref/content/pref-content.xul new file mode 100644 index 0000000000..513027c03c --- /dev/null +++ b/comm/suite/components/pref/content/pref-content.xul @@ -0,0 +1,131 @@ +<?xml version="1.0"?> + +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<!DOCTYPE overlay [ + <!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd"> %brandDTD; + <!ENTITY % prefContentDTD SYSTEM "chrome://communicator/locale/pref/pref-content.dtd"> %prefContentDTD; +]> + +<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <prefpane id="content_pane" + label="&pref.content.title;" + script="chrome://communicator/content/pref/pref-content.js"> + + <preferences id="content_preferences"> + <preference id="general.autoScroll" + name="general.autoScroll" + type="bool"/> + <preference id="general.smoothScroll" + name="general.smoothScroll" + type="bool"/> + <preference id="zoom.minPercent" + name="zoom.minPercent" + type="int"/> + <preference id="zoom.maxPercent" + name="zoom.maxPercent" + type="int"/> + <preference id="browser.zoom.full" + name="browser.zoom.full" + type="bool" inverted="true"/> + <preference id="browser.zoom.siteSpecific" + name="browser.zoom.siteSpecific" + type="bool"/> + <preference id="browser.zoom.showZoomStatusPanel" + name="browser.zoom.showZoomStatusPanel" + type="bool"/> + <preference id="browser.enable_automatic_image_resizing" + name="browser.enable_automatic_image_resizing" + type="bool"/> + <preference id="gfx.direct2d.disabled" + name="gfx.direct2d.disabled" + type="bool" inverted="true"/> + <preference id="layers.acceleration.disabled" + name="layers.acceleration.disabled" + type="bool" inverted="true" + onchange="updateHardwareAcceleration(this.value);"/> + </preferences> + + <description>&pref.content.description;</description> + + <groupbox id="scrollingGroup" align="start"> + <caption label="&scrolling.label;"/> + + <checkbox id="useAutoScroll" + label="&useAutoScroll.label;" + accesskey="&useAutoScroll.accesskey;" + preference="general.autoScroll"/> + <checkbox id="useSmoothScroll" + label="&useSmoothScroll.label;" + accesskey="&useSmoothScroll.accesskey;" + preference="general.smoothScroll"/> + </groupbox> + + <groupbox id="zoomPreferences" align="start"> + <caption label="&zoomPrefs.label;"/> + + <hbox align="center"> + <label value="&minZoom.label;" + accesskey="&minZoom.accesskey;" + control="minZoom"/> + <textbox id="minZoom" + type="number" + size="3" + increment="10" + preference="zoom.minPercent" + oninput="DisableMinCheck(this);" + onchange="AdjustMaxZoom();"/> + <label value="&maxZoom.label;" + accesskey="&maxZoom.accesskey;" + control="maxZoom"/> + <textbox id="maxZoom" + type="number" + size="3" + increment="10" + preference="zoom.maxPercent" + oninput="DisableMinCheck(this);" + onchange="AdjustMinZoom();"/> + <label value="&percent.label;"/> + </hbox> + + <checkbox id="textZoomOnly" + label="&textZoomOnly.label;" + accesskey="&textZoomOnly.accesskey;" + preference="browser.zoom.full"/> + <checkbox id="zoomSiteSpecific" + label="&siteSpecific.label;" + accesskey="&siteSpecific.accesskey;" + preference="browser.zoom.siteSpecific"/> + <checkbox id="showZoomStatusPanel" + label="&showZoomStatusPanel.label;" + accesskey="&showZoomStatusPanel.accesskey;" + preference="browser.zoom.showZoomStatusPanel"/> + <checkbox id="enableAutomaticImageResizing" + label="&enableAutomaticImageResizing.label;" + accesskey="&enableAutomaticImageResizing.accesskey;" + preference="browser.enable_automatic_image_resizing"/> + + <hbox align="center"> + <label value="&defaultZoom.label;" + accesskey="&defaultZoom.accesskey;" + control="defaultZoom"/> + <textbox id="defaultZoom" + type="number" + size="3" + increment="10" + onchange="SetDefaultZoom();"/> + <label value="&percent.label;"/> + </hbox> + </groupbox> + + <vbox class="box-padded" align="start"> + <checkbox id="allowHWAccel" + label="&allowHWAccel.label;" + accesskey="&allowHWAccel.accesskey;" + preference="layers.acceleration.disabled"/> + </vbox> + + </prefpane> +</overlay> diff --git a/comm/suite/components/pref/content/pref-cookies.js b/comm/suite/components/pref/content/pref-cookies.js new file mode 100644 index 0000000000..fd51881735 --- /dev/null +++ b/comm/suite/components/pref/content/pref-cookies.js @@ -0,0 +1,34 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public +* License, v. 2.0. If a copy of the MPL was not distributed with this +* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +function Startup() +{ + SetDisables(false); +} + +function SetDisables(aSetFocus) +{ + // Policy 1 was "ask before accepting" and is no longer valid. + + // const for Cookie Accept Policy + const kCookiesDisabled = 2; + // const for Cookie Lifetime Policy + const kAcceptForNDays = 3; + + var behavior = document.getElementById("networkCookieBehavior"); + var behaviorPref = document.getElementById(behavior.getAttribute("preference")); + + var lifetime = document.getElementById("networkCookieLifetime"); + var lifetimePref = document.getElementById(lifetime.getAttribute("preference")); + var days = document.getElementById("lifetimeDays"); + var daysPref = document.getElementById(days.getAttribute("preference")); + + var cookiesDisabled = (behaviorPref.value == kCookiesDisabled); + lifetime.disabled = cookiesDisabled || lifetimePref.locked; + days.disabled = cookiesDisabled || daysPref.locked || + (lifetimePref.value != kAcceptForNDays); + + if (!days.disabled && aSetFocus) + days.focus(); +} diff --git a/comm/suite/components/pref/content/pref-cookies.xul b/comm/suite/components/pref/content/pref-cookies.xul new file mode 100644 index 0000000000..c41be21dc7 --- /dev/null +++ b/comm/suite/components/pref/content/pref-cookies.xul @@ -0,0 +1,89 @@ +<?xml version="1.0"?> + +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<!DOCTYPE overlay SYSTEM "chrome://communicator/locale/pref/pref-cookies.dtd"> + +<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <prefpane id="cookies_pane" + label="&pref.cookies.title;" + script="chrome://communicator/content/pref/pref-cookies.js"> + <preferences id="cookies_preferences"> + <preference id="network.cookie.cookieBehavior" + name="network.cookie.cookieBehavior" + type="int" + onchange="SetDisables(false);"/> + <preference id="network.cookie.lifetimePolicy" + name="network.cookie.lifetimePolicy" + type="int" + onchange="SetDisables(this.value == '3');"/> + <preference id="network.cookie.lifetime.days" + name="network.cookie.lifetime.days" + type="int"/> + <preference id="pref.advanced.cookies.disable_button.view_cookies" + name="pref.advanced.cookies.disable_button.view_cookies" + type="bool"/> + </preferences> + + <groupbox id="networkCookieAcceptPolicy"> + <caption label="&cookiePolicy.label;"/> + <radiogroup id="networkCookieBehavior" + preference="network.cookie.cookieBehavior"> + <radio value="2" + label="&disableCookies.label;" + accesskey="&disableCookies.accesskey;"/> + <radio value="1" + label="&accNo3rdPartyCookies.label;" + accesskey="&accNo3rdPartyCookies.accesskey;"/> + <radio value="3" + label="&acc3rdPartyVisited.label;" + accesskey="&acc3rdPartyVisited.accesskey;"/> + <radio value="0" + label="&accAllCookies.label;" + accesskey="&accAllCookies.accesskey;"/> + </radiogroup> + </groupbox> + <groupbox id="networkCookieLifetimePolicy"> + <caption label="&cookieRetentionPolicy.label;"/> + <radiogroup id="networkCookieLifetime" + preference="network.cookie.lifetimePolicy"> + <radio value="0" + label="&acceptNormally.label;" + accesskey="&acceptNormally.accesskey;"/> + <radio value="2" + label="&acceptForSession.label;" + accesskey="&acceptForSession.accesskey;"/> + <hbox align="center"> + <radio id="acceptForNDays" + value="3" + label="&acceptforNDays.label;" + accesskey="&acceptforNDays.accesskey;" + aria-labelledby="acceptForNDays lifetimeDays daysLabel"/> + <textbox id="lifetimeDays" + type="number" + max="999" + min="0" + size="3" + maxlength="3" + preference="network.cookie.lifetime.days" + aria-labelledby="acceptForNDays lifetimeDays daysLabel"/> + <label id="daysLabel" + value="&days.label;"/> + </hbox> + </radiogroup> + </groupbox> + <groupbox id="manageCookiesAndSites"> + <caption label="&manageCookies.label;"/> + <description>&manageCookiesDescription.label;</description> + <hbox pack="end"> + <button id="viewCookieButton" + label="&viewCookies.label;" + accesskey="&viewCookies.accesskey;" + preference="pref.advanced.cookies.disable_button.view_cookies" + oncommand="toDataManager('|cookies');"/> + </hbox> + </groupbox> + </prefpane> +</overlay> diff --git a/comm/suite/components/pref/content/pref-debugging.js b/comm/suite/components/pref/content/pref-debugging.js new file mode 100644 index 0000000000..269a0afeac --- /dev/null +++ b/comm/suite/components/pref/content/pref-debugging.js @@ -0,0 +1,15 @@ +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- * +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +function Startup() { + let paintFlashing = document.getElementById("nglayout.debug.paint_flashing"); + enableFlashingChrome(paintFlashing.value); +} + +function enableFlashingChrome(aValue) { + var paintFlashingChrome = document.getElementById("nglayoutDebugPaintFlashingChrome"); + + paintFlashingChrome.disabled = aValue; +} diff --git a/comm/suite/components/pref/content/pref-debugging.xul b/comm/suite/components/pref/content/pref-debugging.xul new file mode 100644 index 0000000000..8e42f6f756 --- /dev/null +++ b/comm/suite/components/pref/content/pref-debugging.xul @@ -0,0 +1,120 @@ +<?xml version="1.0"?> +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<!DOCTYPE overlay SYSTEM "chrome://communicator/locale/pref/pref-debugging.dtd"> + +<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <prefpane id="debugging_pane" + label="&pref.debugging.title;" + script="chrome://communicator/content/pref/pref-debugging.js"> + + <preferences id="debugging_preferences"> + <preference id="nglayout.debug.paint_flashing" + name="nglayout.debug.paint_flashing" + type="bool" + onchange="enableFlashingChrome(this.value);"/> + <preference id="nglayout.debug.paint_flashing_chrome" + name="nglayout.debug.paint_flashing_chrome" + type="bool"/> + <preference id="nglayout.debug.paint_dumping" + name="nglayout.debug.paint_dumping" + type="bool"/> + <preference id="nglayout.debug.invalidate_dumping" + name="nglayout.debug.invalidate_dumping" + type="bool"/> + <preference id="nglayout.debug.event_dumping" + name="nglayout.debug.event_dumping" + type="bool"/> + <preference id="nglayout.debug.motion_event_dumping" + name="nglayout.debug.motion_event_dumping" + type="bool"/> + <preference id="nglayout.debug.crossing_event_dumping" + name="nglayout.debug.crossing_event_dumping" + type="bool"/> + <preference id="layout.reflow.showframecounts" + name="layout.reflow.showframecounts" + type="bool"/> + <preference id="layout.reflow.dumpframecounts" + name="layout.reflow.dumpframecounts" + type="bool"/> + <preference id="layout.reflow.dumpframebyframecounts" + name="layout.reflow.dumpframebyframecounts" + type="bool"/> + <preference id="xul.debug.box" + name="xul.debug.box" + type="bool"/> + <preference id="nglayout.debug.disable_xul_cache" + name="nglayout.debug.disable_xul_cache" + type="bool"/> + </preferences> + + <hbox> + <!-- Event Debugging --> + <groupbox id="eventDebugging" align="start" flex="1"> + <caption label="&debugEvents.label;"/> + <checkbox id="nglayoutDebugPaintFlashing" + label="&debugPaintFlashing.label;" + accesskey="&debugPaintFlashing.accesskey;" + preference="nglayout.debug.paint_flashing"/> + <checkbox id="nglayoutDebugPaintFlashingChrome" + label="&debugPaintFlashingChrome.label;" + accesskey="&debugPaintFlashingChrome.accesskey;" + preference="nglayout.debug.paint_flashing_chrome"/> + <checkbox id="nglayoutDebugPaintDumping" + label="&debugPaintDumping.label;" + accesskey="&debugPaintDumping.accesskey;" + preference="nglayout.debug.paint_dumping"/> + <checkbox id="nglayoutDebugInvalidateDumping" + label="&debugInvalidateDumping.label;" + accesskey="&debugInvalidateDumping.accesskey;" + preference="nglayout.debug.invalidate_dumping"/> + <checkbox id="nglayoutDebugEventDumping" + label="&debugEventDumping.label;" + accesskey="&debugEventDumping.accesskey;" + preference="nglayout.debug.event_dumping"/> + <checkbox id="nglayoutDebugMotionEventDumping" + label="&debugMotionEventDumping.label;" + accesskey="&debugMotionEventDumping.accesskey;" + preference="nglayout.debug.motion_event_dumping"/> + <checkbox id="nglayoutDebugCrossingEventDumping" + label="&debugCrossingEventDumping.label;" + accesskey="&debugCrossingEventDumping.accesskey;" + preference="nglayout.debug.crossing_event_dumping"/> + </groupbox> + + <vbox align="start" flex="1"> + <!-- Reflow Event Debugging --> + <groupbox id="reflowEventDebugging"> + <caption label="&debugReflowEvents.label;"/> + <checkbox id="layoutReflowShowFrameCounts" + label="&debugReflowShowFrameCounts.label;" + accesskey="&debugReflowShowFrameCounts.accesskey;" + preference="layout.reflow.showframecounts"/> + <checkbox id="layoutReflowDumpFrameCounts" + label="&debugReflowDumpFrameCounts.label;" + accesskey="&debugReflowDumpFrameCounts.accesskey;" + preference="layout.reflow.dumpframecounts"/> + <checkbox id="layoutReflowDumpFrameByFrameCounts" + label="&debugReflowDumpFrameByFrameCounts.label;" + accesskey="&debugReflowDumpFrameByFrameCounts.accesskey;" + preference="layout.reflow.dumpframebyframecounts"/> + </groupbox> + + <!-- Render Debugging --> + <groupbox id="renderDebugging"> + <caption label="&debugRendering.label;"/> + <checkbox id="debugXULBoxes" + label="&debugXULBox.label;" + accesskey="&debugXULBox.accesskey;" + preference="xul.debug.box"/> + <checkbox id="nglayoutDebugDisableXULCache" + label="&debugDisableXULCache.label;" + accesskey="&debugDisableXULCache.accesskey;" + preference="nglayout.debug.disable_xul_cache"/> + </groupbox> + </vbox> + </hbox> + </prefpane> +</overlay> diff --git a/comm/suite/components/pref/content/pref-download.js b/comm/suite/components/pref/content/pref-download.js new file mode 100644 index 0000000000..bc52f800b6 --- /dev/null +++ b/comm/suite/components/pref/content/pref-download.js @@ -0,0 +1,197 @@ +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm"); +const { FileUtils } = + ChromeUtils.import("resource://gre/modules/FileUtils.jsm"); + +ChromeUtils.defineModuleGetter(this, "Downloads", + "resource://gre/modules/Downloads.jsm"); + +const kDesktop = 0; +const kDownloads = 1; +const kUserDir = 2; +var gFPHandler; +var gSoundUrlPref; + +function Startup() +{ + // Define globals + gFPHandler = Services.io.getProtocolHandler("file") + .QueryInterface(Ci.nsIFileProtocolHandler); + gSoundUrlPref = document.getElementById("browser.download.finished_sound_url"); + setSoundEnabled(document.getElementById("browser.download.finished_download_sound").value); +} + +/** + * Enables/disables the folder field and Browse button based on whether a + * default download directory is being used. + */ +function readUseDownloadDir() +{ + var downloadFolder = document.getElementById("downloadFolder"); + var chooseFolder = document.getElementById("chooseFolder"); + var preference = document.getElementById("browser.download.useDownloadDir"); + downloadFolder.disabled = !preference.value; + chooseFolder.disabled = !preference.value; +} + +/** + * Displays a file picker in which the user can choose the location where + * downloads are automatically saved, updating preferences and UI in + * response to the choice, if one is made. + */ +function chooseFolder() +{ + return chooseFolderTask().catch(Cu.reportError); +} + +async function chooseFolderTask() +{ + let title = document.getElementById("bundle_prefutilities") + .getString("downloadfolder"); + let folderListPref = document.getElementById("browser.download.folderList"); + let currentDirPref = await _indexToFolder(folderListPref.value); + let defDownloads = await _indexToFolder(kDownloads); + let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker); + + fp.init(window, title, Ci.nsIFilePicker.modeGetFolder); + fp.appendFilters(Ci.nsIFilePicker.filterAll); + // First try to open what's currently configured + if (currentDirPref && currentDirPref.exists()) { + fp.displayDirectory = currentDirPref; + } else if (defDownloads && defDownloads.exists()) { + // Try the system's download dir + fp.displayDirectory = defDownloads; + } else { + // Fall back to Desktop + fp.displayDirectory = await _indexToFolder(kDesktop); + } + + let result = await new Promise(resolve => fp.open(resolve)); + if (result != Ci.nsIFilePicker.returnOK) { + return; + } + + document.getElementById("browser.download.dir").value = fp.file; + folderListPref.value = await _folderToIndex(fp.file); + // Note, the real prefs will not be updated yet, so dnld manager's + // userDownloadsDirectory may not return the right folder after + // this code executes. displayDownloadDirPref will be called on + // the assignment above to update the UI. +} + +/** + * Initializes the download folder display settings based on the user's + * preferences. + */ +function displayDownloadDirPref() +{ + displayDownloadDirPrefTask().catch(Cu.reportError); +} + +async function displayDownloadDirPrefTask() +{ + var folderListPref = document.getElementById("browser.download.folderList"); + var currentDirPref = await _indexToFolder(folderListPref.value); // file + var prefutilitiesBundle = document.getElementById("bundle_prefutilities"); + var iconUrlSpec = gFPHandler.getURLSpecFromFile(currentDirPref); + var downloadFolder = document.getElementById("downloadFolder"); + downloadFolder.image = "moz-icon://" + iconUrlSpec + "?size=16"; + + // Display a 'pretty' label or the path in the UI. + switch (folderListPref.value) { + case kDesktop: + downloadFolder.label = prefutilitiesBundle.getString("desktopFolderName"); + break; + case kDownloads: + downloadFolder.label = prefutilitiesBundle.getString("downloadsFolderName"); + break; + default: + downloadFolder.label = currentDirPref ? currentDirPref.path : ""; + break; + } +} + +/** + * Returns the Downloads folder. If aFolder is "Desktop", then the Downloads + * folder returned is the desktop folder; otherwise, it is a folder whose name + * indicates that it is a download folder and whose path is as determined by + * the XPCOM directory service via the download manager's attribute + * defaultDownloadsDirectory. + * + * @throws if aFolder is not "Desktop" or "Downloads" + */ +async function _getDownloadsFolder(aFolder) +{ + switch (aFolder) { + case "Desktop": + return Services.dirsvc.get("Desk", Ci.nsIFile); + case "Downloads": + let downloadsDir = await Downloads.getSystemDownloadsDirectory(); + return new FileUtils.File(downloadsDir); + } + throw "ASSERTION FAILED: folder type should be 'Desktop' or 'Downloads'"; +} + +/** + * Determines the type of the given folder. + * + * @param aFolder + * the folder whose type is to be determined + * @returns integer + * kDesktop if aFolder is the Desktop or is unspecified, + * kDownloads if aFolder is the Downloads folder, + * kUserDir otherwise + */ +async function _folderToIndex(aFolder) +{ + if (!aFolder || aFolder.equals(await _getDownloadsFolder("Desktop"))) { + return kDesktop; + } + + if (aFolder.equals(await _getDownloadsFolder("Downloads"))) { + return kDownloads; + } + + return kUserDir; + } + +/** + * Converts an integer into the corresponding folder. + * + * @param aIndex + * an integer + * @returns the Desktop folder if aIndex == kDesktop, + * the Downloads folder if aIndex == kDownloads, + * the folder stored in browser.download.dir + */ +async function _indexToFolder(aIndex) +{ + var folder; + switch (aIndex) { + case kDownloads: + folder = await _getDownloadsFolder("Downloads"); + break; + case kDesktop: + folder = await _getDownloadsFolder("Desktop"); + break; + default: + folder = document.getElementById("browser.download.dir").value; + break; + } + if (!folder || + !folder.exists()) { + return ""; + } + + return folder; +} + +function setSoundEnabled(aEnable) +{ + EnableElementById("downloadSndURL", aEnable, false); + document.getElementById("downloadSndPlay").disabled = !aEnable; +} diff --git a/comm/suite/components/pref/content/pref-download.xul b/comm/suite/components/pref/content/pref-download.xul new file mode 100644 index 0000000000..e3f626204c --- /dev/null +++ b/comm/suite/components/pref/content/pref-download.xul @@ -0,0 +1,120 @@ +<?xml version="1.0"?> +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<!DOCTYPE overlay [ +<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd"> +%brandDTD; +<!ENTITY % prefDownloadDTD SYSTEM "chrome://communicator/locale/pref/pref-download.dtd"> +%prefDownloadDTD; +]> + +<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <prefpane id="download_pane" + label="&pref.download.title;" + script="chrome://communicator/content/pref/pref-download.js"> + + <preferences> + <preference id="browser.download.manager.behavior" + name="browser.download.manager.behavior" + type="int"/> + <preference id="browser.download.manager.focusWhenStarting" + name="browser.download.manager.focusWhenStarting" + type="bool" inverted="true"/> + <preference id="browser.download.useDownloadDir" + name="browser.download.useDownloadDir" + type="bool"/> + <preference id="browser.download.dir" + name="browser.download.dir" + type="file"/> + <preference id="browser.download.folderList" + name="browser.download.folderList" + type="int" + onchange="displayDownloadDirPref();"/> + <preference id="browser.download.finished_download_sound" + name="browser.download.finished_download_sound" + type="bool" + onchange="setSoundEnabled(this.value);"/> + <preference id="browser.download.finished_sound_url" + name="browser.download.finished_sound_url" + type="string"/> + </preferences> + + <groupbox> + <caption label="&downloadBehavior.label;"/> + <radiogroup id="downloadBehavior" + preference="browser.download.manager.behavior"> + <radio value="2" + label="&doNothing.label;" + accesskey="&doNothing.accesskey;"/> + <radio value="1" + label="&openProgressDialog.label;" + accesskey="&openProgressDialog.accesskey;"/> + <radio value="0" + label="&openDM.label;" + accesskey="&openDM.accesskey;"/> + </radiogroup> + <checkbox id="focusWhenStarting" + class="indent" + preference="browser.download.manager.focusWhenStarting" + label="&flashWhenOpen.label;" + accesskey="&flashWhenOpen.accesskey;"/> + </groupbox> + + <groupbox> + <caption label="&downloadLocation.label;"/> + <radiogroup id="saveWhere" + preference="browser.download.useDownloadDir" + onsyncfrompreference="return document.getElementById('download_pane').readUseDownloadDir();"> + <hbox id="saveToRow"> + <radio id="saveTo" value="true" + label="&saveTo.label;" + accesskey="&saveTo.accesskey;" + aria-labelledby="saveTo downloadFolder"/> + <filefield id="downloadFolder" flex="1" + preference="browser.download.dir" + preference-editable="true" + aria-labelledby="saveTo" + onsyncfrompreference="document.getElementById('download_pane').displayDownloadDirPref();"/> + <button id="chooseFolder" oncommand="chooseFolder();" + label="&chooseDownloadFolder.label;" + accesskey="&chooseDownloadFolder.accesskey;"/> + </hbox> + <radio id="alwaysAsk" value="false" + label="&alwaysAsk.label;" + accesskey="&alwaysAsk.accesskey;"/> + </radiogroup> + </groupbox> + + <groupbox> + <caption label="&finishedBehavior.label;"/> + <hbox align="center"> + <checkbox id="finishedNotificationSound" + label="&playSound.label;" + preference="browser.download.finished_download_sound" + accesskey="&playSound.accesskey;"/> + </hbox> + + <hbox align="center" class="indent"> + <filefield id="downloadSndURL" + flex="1" + preference="browser.download.finished_sound_url" + preference-editable="true" + onsyncfrompreference="return WriteSoundField(this, document.getElementById('download_pane').gSoundUrlPref.value);"/> + <hbox align="center"> + <button id="downloadSndBrowse" + label="&browse.label;" + accesskey="&browse.accesskey;" + oncommand="SelectSound(gSoundUrlPref);"> + <observes element="downloadSndURL" attribute="disabled"/> + </button> + <button id="downloadSndPlay" + label="&playButton.label;" + accesskey="&playButton.accesskey;" + oncommand="PlaySound(gSoundUrlPref.value, false);"/> + </hbox> + </hbox> + </groupbox> + </prefpane> +</overlay> diff --git a/comm/suite/components/pref/content/pref-findasyoutype.js b/comm/suite/components/pref/content/pref-findasyoutype.js new file mode 100644 index 0000000000..fefd5a0d46 --- /dev/null +++ b/comm/suite/components/pref/content/pref-findasyoutype.js @@ -0,0 +1,15 @@ +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +function Startup() +{ + var prefAutostart = document.getElementById("accessibility.typeaheadfind.autostart"); + SetLinksOnlyEnabled(prefAutostart.value); +} + +function SetLinksOnlyEnabled(aEnable) +{ + EnableElementById("findAsYouTypeAutoWhat", aEnable, false); +} diff --git a/comm/suite/components/pref/content/pref-findasyoutype.xul b/comm/suite/components/pref/content/pref-findasyoutype.xul new file mode 100644 index 0000000000..612b3fa768 --- /dev/null +++ b/comm/suite/components/pref/content/pref-findasyoutype.xul @@ -0,0 +1,70 @@ +<?xml version="1.0"?> +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<!DOCTYPE overlay SYSTEM "chrome://communicator/locale/pref/pref-findasyoutype.dtd"> + +<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <prefpane id="findasyoutype_pane" + label="&pref.findAsYouType.title;" + script="chrome://communicator/content/pref/pref-findasyoutype.js"> + + <preferences id="findasyoutype_preferences"> + <preference id="accessibility.typeaheadfind.autostart" + name="accessibility.typeaheadfind.autostart" + onchange="SetLinksOnlyEnabled(this.value);" + type="bool"/> + <preference id="accessibility.typeaheadfind.linksonly" + name="accessibility.typeaheadfind.linksonly" + type="bool"/> + <preference id="accessibility.typeaheadfind.enablesound" + name="accessibility.typeaheadfind.enablesound" + type="bool"/> + <preference id="accessibility.typeaheadfind.enabletimeout" + name="accessibility.typeaheadfind.enabletimeout" + type="bool"/> + <preference id="accessibility.typeaheadfind.usefindbar" + name="accessibility.typeaheadfind.usefindbar" + type="bool"/> + </preferences> + + <groupbox align="start"> + <caption label="&findAsYouTypeBehavior.label;"/> + <checkbox id="findAsYouTypeEnableAuto" + label="&findAsYouTypeEnableAuto.label;" + accesskey="&findAsYouTypeEnableAuto.accesskey;" + preference="accessibility.typeaheadfind.autostart"/> + <radiogroup id="findAsYouTypeAutoWhat" + class="indent" + preference="accessibility.typeaheadfind.linksonly"> + <radio value="false" + label="&findAsYouTypeAutoText.label;" + accesskey="&findAsYouTypeAutoText.accesskey;"/> + <radio value="true" + label="&findAsYouTypeAutoLinks.label;" + accesskey="&findAsYouTypeAutoLinks.accesskey;"/> + </radiogroup> + <description>&findAsYouTypeTip.label;</description> + + <vbox class="box-padded" + align="start"> + <separator class="thin" /> + <checkbox id="findAsYouTypeSound" + label="&findAsYouTypeSound.label;" + accesskey="&findAsYouTypeSound.accesskey;" + preference="accessibility.typeaheadfind.enablesound"/> + <checkbox id="findAsYouTypeTimeout" + label="&findAsYouTypeTimeout.label;" + accesskey="&findAsYouTypeTimeout.accesskey;" + preference="accessibility.typeaheadfind.enabletimeout"/> + <checkbox id="findAsYouTypeFindbarEnable" + label="&findAsYouTypeFindbarEnable.label;" + accesskey="&findAsYouTypeFindbarEnable.accesskey;" + preference="accessibility.typeaheadfind.usefindbar"/> + </vbox> + <description>&findAsYouTypeFindbarEnableTip.label;</description> + </groupbox> + + </prefpane> +</overlay> diff --git a/comm/suite/components/pref/content/pref-fonts.js b/comm/suite/components/pref/content/pref-fonts.js new file mode 100644 index 0000000000..aa226c89af --- /dev/null +++ b/comm/suite/components/pref/content/pref-fonts.js @@ -0,0 +1,220 @@ +/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +var gAllFonts = null; +var gFontEnumerator = null; +var gDisabled = false; + +function GetFontEnumerator() +{ + if (!gFontEnumerator) + { + gFontEnumerator = Cc["@mozilla.org/gfx/fontenumerator;1"] + .createInstance(Ci.nsIFontEnumerator); + } + return gFontEnumerator; +} + +function BuildFontList(aLanguage, aFontType, aMenuList, aPreference) +{ + var defaultFont = null; + // Load Font Lists + var fonts = GetFontEnumerator().EnumerateFonts(aLanguage, aFontType); + if (fonts.length) + { + defaultFont = GetFontEnumerator().getDefaultFont(aLanguage, aFontType); + } + else + { + fonts = GetFontEnumerator().EnumerateFonts(aLanguage, ""); + if (fonts.length) + defaultFont = GetFontEnumerator().getDefaultFont(aLanguage, ""); + } + + if (!gAllFonts) + gAllFonts = GetFontEnumerator().EnumerateAllFonts(); + + // Reset the list + while (aMenuList.hasChildNodes()) + aMenuList.lastChild.remove(); + + // Build the UI for the Default Font and Fonts for this CSS type. + var popup = document.createElement("menupopup"); + var separator; + if (fonts.length > 0) + { + const prefutilitiesBundle = document.getElementById("bundle_prefutilities"); + let label = defaultFont ? + prefutilitiesBundle.getFormattedString("labelDefaultFont2", [defaultFont]) : + prefutilitiesBundle.getString("labelDefaultFontUnnamed"); + let menuitem = document.createElement("menuitem"); + menuitem.setAttribute("label", label); + menuitem.setAttribute("value", ""); // Default Font has a blank value + popup.appendChild(menuitem); + + separator = document.createElement("menuseparator"); + popup.appendChild(separator); + + for (let font of fonts) + { + menuitem = document.createElement("menuitem"); + menuitem.setAttribute("value", font); + menuitem.setAttribute("label", font); + popup.appendChild(menuitem); + } + } + + // Build the UI for the remaining fonts. + if (gAllFonts.length > fonts.length) + { + // Both lists are sorted, and the Fonts-By-Type list is a subset of the + // All-Fonts list, so walk both lists side-by-side, skipping values we've + // already created menu items for. + + if (fonts.length) + { + separator = document.createElement("menuseparator"); + popup.appendChild(separator); + } + + for (i = 0; i < gAllFonts.length; ++i) + { + if (fonts.lastIndexOf(gAllFonts[i], 0) == 0) + { + fonts.shift(); //Remove matched font from array + } + else + { + menuitem = document.createElement("menuitem"); + menuitem.setAttribute("value", gAllFonts[i]); + menuitem.setAttribute("label", gAllFonts[i]); + popup.appendChild(menuitem); + } + } + } + aMenuList.appendChild(popup); + + // Fully populated so re-enable menulist before setting preference, + // unless panel is locked. + if (!gDisabled) + aMenuList.disabled = false; + aMenuList.setAttribute("preference", aPreference.id); + aPreference.setElementValue(aMenuList); +} + +function ReadFontLanguageGroup() +{ + var prefs = [{format: "default", type: "string", element: "defaultFontType", fonttype: "" }, + {format: "name.", type: "unichar", element: "serif", fonttype: "serif" }, + {format: "name.", type: "unichar", element: "sans-serif", fonttype: "sans-serif"}, + {format: "name.", type: "unichar", element: "monospace", fonttype: "monospace" }, + {format: "name.", type: "unichar", element: "cursive", fonttype: "cursive" }, + {format: "name.", type: "unichar", element: "fantasy", fonttype: "fantasy" }, + {format: "name-list.", type: "unichar", element: null, fonttype: "serif" }, + {format: "name-list.", type: "unichar", element: null, fonttype: "sans-serif"}, + {format: "name-list.", type: "unichar", element: null, fonttype: "monospace" }, + {format: "name-list.", type: "unichar", element: null, fonttype: "cursive" }, + {format: "name-list.", type: "unichar", element: null, fonttype: "fantasy" }, + {format: "size.variable", type: "int", element: "sizeVar", fonttype: "" }, + {format: "size.fixed", type: "int", element: "sizeMono", fonttype: "" }, + {format: "minimum-size", type: "int", element: "minSize", fonttype: "" }]; + gDisabled = document.getElementById("browser.display.languageList").locked; + var fontLanguage = document.getElementById("font.language.group"); + if (gDisabled) + fontLanguage.disabled = true; + var languageGroup = fontLanguage.value; + var preferences = document.getElementById("fonts_preferences"); + for (var i = 0; i < prefs.length; ++i) + { + var name = "font."+ prefs[i].format + prefs[i].fonttype + "." + languageGroup; + var preference = document.getElementById(name); + if (!preference) + { + preference = document.createElement("preference"); + preference.id = name; + preference.setAttribute("name", name); + preference.setAttribute("type", prefs[i].type); + preferences.appendChild(preference); + } + + if (!prefs[i].element) + continue; + + var element = document.getElementById(prefs[i].element); + if (element) + { + if (prefs[i].fonttype) + { + // Set an empty label so it does not jump when items are added. + element.setAttribute("label", ""); + // Disable menulist for the moment. + element.disabled = true; + // Lazily populate font lists, each gets re-enabled at the end. + window.setTimeout(BuildFontList, 0, languageGroup, + prefs[i].fonttype, element, preference); + } + else + { + // Unless the panel is locked, make sure these elements are not + // disabled just in case they were in the last language group. + element.disabled = gDisabled; + element.setAttribute("preference", preference.id); + preference.setElementValue(element); + } + } + } +} + +function ReadFontSelection(aElement) +{ + // Determine the appropriate value to select, for the following cases: + // - there is no setting + // - the font selected by the user is no longer present (e.g. deleted from + // fonts folder) + var preference = document.getElementById(aElement.getAttribute("preference")); + if (preference.value) + { + var fontItems = aElement.getElementsByAttribute("value", preference.value); + + // There is a setting that actually is in the list. Respect it. + if (fontItems.length) + return undefined; + } + + var defaultValue = aElement.firstChild.firstChild.getAttribute("value"); + var languagePref = document.getElementById("font.language.group"); + preference = document.getElementById("font.name-list." + aElement.id + "." + languagePref.value); + if (!preference || !preference.hasUserValue) + return defaultValue; + + var fontNames = preference.value.split(","); + + for (var i = 0; i < fontNames.length; ++i) + { + fontItems = aElement.getElementsByAttribute("value", fontNames[i].trim()); + if (fontItems.length) + return fontItems[0].getAttribute("value"); + } + return defaultValue; +} + +function ReadFontPref(aElement, aDefaultValue) +{ + // Check to see if preference value exists, + // if not return given default value. + var preference = document.getElementById(aElement.getAttribute("preference")); + return preference.value || aDefaultValue; +} + +function ReadUseDocumentFonts() +{ + var preference = document.getElementById("browser.display.use_document_fonts"); + return preference.value == 1; +} + +function WriteUseDocumentFonts(aUseDocumentFonts) +{ + return aUseDocumentFonts.checked ? 1 : 0; +} diff --git a/comm/suite/components/pref/content/pref-fonts.xul b/comm/suite/components/pref/content/pref-fonts.xul new file mode 100644 index 0000000000..554f161a73 --- /dev/null +++ b/comm/suite/components/pref/content/pref-fonts.xul @@ -0,0 +1,260 @@ +<?xml version="1.0"?> +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<!DOCTYPE overlay SYSTEM "chrome://communicator/locale/pref/pref-fonts.dtd"> + +<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <prefpane id="fonts_pane" + label="&pref.fonts.title;" + script="chrome://communicator/content/pref/pref-fonts.js"> + <preferences id="fonts_preferences"> + <preference id="font.language.group" + name="font.language.group" + type="wstring"/> + <preference id="browser.display.use_document_fonts" + name="browser.display.use_document_fonts" + type="int"/> + <preference id="browser.display.languageList" + name="browser.display.languageList" + type="wstring"/> + </preferences> + + <groupbox> + <caption align="center"> + <label value="&language.label;" + accesskey="&language.accesskey;" + control="selectLangs"/> + <menulist id="selectLangs" preference="font.language.group" + onsyncfrompreference="document.getElementById('fonts_pane').ReadFontLanguageGroup();"> + <menupopup> + <menuitem value="ar" label="&font.langGroup.arabic;"/> + <menuitem value="x-armn" label="&font.langGroup.armenian;"/> + <menuitem value="x-beng" label="&font.langGroup.bengali;"/> + <menuitem value="zh-CN" label="&font.langGroup.simpl-chinese;"/> + <menuitem value="zh-TW" label="&font.langGroup.trad-chinese;"/> + <menuitem value="zh-HK" label="&font.langGroup.trad-chinese-hk;"/> + <menuitem value="x-cyrillic" label="&font.langGroup.cyrillic;"/> + <menuitem value="x-devanagari" label="&font.langGroup.devanagari;"/> + <menuitem value="x-ethi" label="&font.langGroup.ethiopic;"/> + <menuitem value="x-geor" label="&font.langGroup.georgian;"/> + <menuitem value="el" label="&font.langGroup.el;"/> + <menuitem value="x-gujr" label="&font.langGroup.gujarati;"/> + <menuitem value="x-guru" label="&font.langGroup.gurmukhi;"/> + <menuitem value="he" label="&font.langGroup.hebrew;"/> + <menuitem value="ja" label="&font.langGroup.japanese;"/> + <menuitem value="x-knda" label="&font.langGroup.kannada;"/> + <menuitem value="x-khmr" label="&font.langGroup.khmer;"/> + <menuitem value="ko" label="&font.langGroup.korean;"/> + <menuitem value="x-western" label="&font.langGroup.latin;"/> + <menuitem value="x-mlym" label="&font.langGroup.malayalam;"/> + <menuitem value="x-math" label="&font.langGroup.math;"/> + <menuitem value="x-orya" label="&font.langGroup.odia;"/> + <menuitem value="x-sinh" label="&font.langGroup.sinhala;"/> + <menuitem value="x-tamil" label="&font.langGroup.tamil;"/> + <menuitem value="x-telu" label="&font.langGroup.telugu;"/> + <menuitem value="th" label="&font.langGroup.thai;"/> + <menuitem value="x-tibt" label="&font.langGroup.tibetan;"/> + <menuitem value="x-cans" label="&font.langGroup.canadian;"/> + <menuitem value="x-unicode" label="&font.langGroup.other;"/> + </menupopup> + </menulist> + </caption> + + <separator class="thin"/> + + <grid> + <columns> + <column/> + <column flex="1"/> + <column/> + </columns> + + <rows> + <row align="center"> + <spacer/> + <label value="&typefaces.label;"/> + <label value="&sizes.label;"/> + </row> + <row> + <separator class="thin"/> + </row> + <row align="center"> + <hbox align="center" pack="end"> + <label value="&proportional.label;" + accesskey="&proportional.accesskey;" + control="defaultFontType"/> + </hbox> + <menulist id="defaultFontType" flex="1" style="width: 0px;" + onsyncfrompreference="return document.getElementById('fonts_pane').ReadFontSelection(this);"> + <menupopup> + <menuitem value="serif" + label="&useDefaultFontSerif.label;"/> + <menuitem value="sans-serif" + label="&useDefaultFontSansSerif.label;"/> + </menupopup> + </menulist> + <menulist id="sizeVar" class="small-margin" + onsyncfrompreference="return document.getElementById('fonts_pane').ReadFontPref(this, 16);"> + <menupopup> + <menuitem value="8" label="8"/> + <menuitem value="9" label="9"/> + <menuitem value="10" label="10"/> + <menuitem value="11" label="11"/> + <menuitem value="12" label="12"/> + <menuitem value="13" label="13"/> + <menuitem value="14" label="14"/> + <menuitem value="15" label="15"/> + <menuitem value="16" label="16"/> + <menuitem value="17" label="17"/> + <menuitem value="18" label="18"/> + <menuitem value="20" label="20"/> + <menuitem value="22" label="22"/> + <menuitem value="24" label="24"/> + <menuitem value="26" label="26"/> + <menuitem value="28" label="28"/> + <menuitem value="30" label="30"/> + <menuitem value="32" label="32"/> + <menuitem value="34" label="34"/> + <menuitem value="36" label="36"/> + <menuitem value="40" label="40"/> + <menuitem value="44" label="44"/> + <menuitem value="48" label="48"/> + <menuitem value="56" label="56"/> + <menuitem value="64" label="64"/> + <menuitem value="72" label="72"/> + </menupopup> + </menulist> + </row> + <row> + <separator class="thin"/> + </row> + <row align="center"> + <hbox align="center" pack="end"> + <label value="&serif.label;" + accesskey="&serif.accesskey;" + control="serif"/> + </hbox> + <menulist id="serif" class="prefpanel-font-list" + onsyncfrompreference="return document.getElementById('fonts_pane').ReadFontSelection(this);"/> + <spacer/> + </row> + <row align="center"> + <hbox align="center" pack="end"> + <label value="&sans-serif.label;" + accesskey="&sans-serif.accesskey;" + control="sans-serif"/> + </hbox> + <menulist id="sans-serif" class="prefpanel-font-list" + onsyncfrompreference="return document.getElementById('fonts_pane').ReadFontSelection(this);"/> + <spacer/> + </row> + <row align="center"> + <hbox align="center" pack="end"> + <label value="&cursive.label;" + accesskey="&cursive.accesskey;" + control="cursive"/> + </hbox> + <menulist id="cursive" class="prefpanel-font-list" + onsyncfrompreference="return document.getElementById('fonts_pane').ReadFontSelection(this);"/> + <spacer/> + </row> + <row align="center"> + <hbox align="center" pack="end"> + <label value="&fantasy.label;" + accesskey="&fantasy.accesskey;" + control="fantasy"/> + </hbox> + <menulist id="fantasy" class="prefpanel-font-list" + onsyncfrompreference="return document.getElementById('fonts_pane').ReadFontSelection(this);"/> + <spacer/> + </row> + <row> + <separator class="thin"/> + </row> + <row align="center"> + <hbox align="center" pack="end"> + <label value="&monospace.label;" + accesskey="&monospace.accesskey;" + control="monospace"/> + </hbox> + <menulist id="monospace" class="prefpanel-font-list" + onsyncfrompreference="return document.getElementById('fonts_pane').ReadFontSelection(this);"/> + <menulist id="sizeMono" + onsyncfrompreference="return document.getElementById('fonts_pane').ReadFontPref(this, 12);"> + <menupopup> + <menuitem value="8" label="8"/> + <menuitem value="9" label="9"/> + <menuitem value="10" label="10"/> + <menuitem value="11" label="11"/> + <menuitem value="12" label="12"/> + <menuitem value="13" label="13"/> + <menuitem value="14" label="14"/> + <menuitem value="15" label="15"/> + <menuitem value="16" label="16"/> + <menuitem value="17" label="17"/> + <menuitem value="18" label="18"/> + <menuitem value="20" label="20"/> + <menuitem value="22" label="22"/> + <menuitem value="24" label="24"/> + <menuitem value="26" label="26"/> + <menuitem value="28" label="28"/> + <menuitem value="30" label="30"/> + <menuitem value="32" label="32"/> + <menuitem value="34" label="34"/> + <menuitem value="36" label="36"/> + <menuitem value="40" label="40"/> + <menuitem value="44" label="44"/> + <menuitem value="48" label="48"/> + <menuitem value="56" label="56"/> + <menuitem value="64" label="64"/> + <menuitem value="72" label="72"/> + </menupopup> + </menulist> + </row> + <row> + <separator class="thin"/> + </row> + <row> + <spacer/> + <hbox align="center" pack="end"> + <label value="&minSize.label;" + accesskey="&minSize.accesskey;" + control="minSize"/> + </hbox> + <menulist id="minSize" + onsyncfrompreference="return document.getElementById('fonts_pane').ReadFontPref(this, 0);"> + <menupopup> + <menuitem value="0" label="&minSize.none;"/> + <menuitem value="9" label="9"/> + <menuitem value="10" label="10"/> + <menuitem value="11" label="11"/> + <menuitem value="12" label="12"/> + <menuitem value="13" label="13"/> + <menuitem value="14" label="14"/> + <menuitem value="15" label="15"/> + <menuitem value="16" label="16"/> + <menuitem value="17" label="17"/> + <menuitem value="18" label="18"/> + <menuitem value="20" label="20"/> + <menuitem value="22" label="22"/> + <menuitem value="24" label="24"/> + </menupopup> + </menulist> + </row> + </rows> + </grid> + </groupbox> + + <separator class="thin"/> + + <!-- Unchecking this removes the ability to select dynamic fonts --> + <checkbox id="browserUseDocumentFonts" + label="&useDocumentFonts.label;" + accesskey="&useDocumentFonts.accesskey;" + preference="browser.display.use_document_fonts" + onsyncfrompreference="return document.getElementById('fonts_pane').ReadUseDocumentFonts();" + onsynctopreference="return document.getElementById('fonts_pane').WriteUseDocumentFonts(this);"/> + + </prefpane> +</overlay> diff --git a/comm/suite/components/pref/content/pref-history.js b/comm/suite/components/pref/content/pref-history.js new file mode 100644 index 0000000000..8f22073241 --- /dev/null +++ b/comm/suite/components/pref/content/pref-history.js @@ -0,0 +1,55 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public +* License, v. 2.0. If a copy of the MPL was not distributed with this +* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +function Startup() +{ + var urlbarHistButton = document.getElementById("ClearUrlBarHistoryButton"); + var lastUrlPref = document.getElementById("general.open_location.last_url"); + var locBarPref = document.getElementById("browser.urlbar.historyEnabled"); + + var isBtnDisabled = lastUrlPref.locked || !locBarPref.value; + + try { + if (!isBtnDisabled && !lastUrlPref.hasUserValue) { + var file = GetUrlbarHistoryFile(); + if (!file.exists()) + isBtnDisabled = true; + else { + var connection = Services.storage.openDatabase(file); + isBtnDisabled = !connection.tableExists("urlbarhistory"); + connection.close(); + } + } + urlbarHistButton.disabled = isBtnDisabled; + } + catch(ex) { + } + var globalHistButton = document.getElementById("browserClearHistory"); + var globalHistory = Cc["@mozilla.org/browser/nav-history-service;1"] + .getService(Ci.nsINavHistoryService); + if (!globalHistory.hasHistoryEntries) + globalHistButton.disabled = true; +} + +function prefClearGlobalHistory() +{ + const {PlacesUtils} = ChromeUtils.import("resource://gre/modules/PlacesUtils.jsm"); + PlacesUtils.history.clear(); +} + +function prefClearUrlbarHistory(aButton) +{ + document.getElementById("general.open_location.last_url").valueFromPreferences = ""; + var file = GetUrlbarHistoryFile(); + if (file.exists()) + file.remove(false); + aButton.disabled = true; +} + +function prefUrlBarHistoryToggle(aChecked) +{ + var file = GetUrlbarHistoryFile(); + if (file.exists()) + document.getElementById("ClearUrlBarHistoryButton").disabled = !aChecked; +} diff --git a/comm/suite/components/pref/content/pref-history.xul b/comm/suite/components/pref/content/pref-history.xul new file mode 100644 index 0000000000..63638544c5 --- /dev/null +++ b/comm/suite/components/pref/content/pref-history.xul @@ -0,0 +1,99 @@ +<?xml version="1.0"?> +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<!DOCTYPE overlay SYSTEM "chrome://communicator/locale/pref/pref-history.dtd" > + +<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + + <prefpane id="history_pane" + label="&pref.history.title;" + script="chrome://communicator/content/pref/pref-history.js"> + <preferences id="history_preferences"> + <preference id="places.history.enabled" + name="places.history.enabled" + type="bool"/> + <preference id="pref.browser.history.disable_button.clear_hist" + name="pref.browser.history.disable_button.clear_hist" + type="bool"/> + <preference id="pref.browser.history.disable_button.clear_urlbar" + name="pref.browser.history.disable_button.clear_urlbar" + type="bool"/> + <preference id="browser.urlbar.historyEnabled" + name="browser.urlbar.historyEnabled" + type="bool"/> + <preference id="general.open_location.last_url" + name="general.open_location.last_url" + type="string"/> + <preference id="browser.formfill.enable" + name="browser.formfill.enable" + type="bool"/> + <preference id="browser.formfill.expire_days" + name="browser.formfill.expire_days" + type="int"/> + </preferences> + + <groupbox> + <caption label="&pref.history.caption;"/> + <hbox align="center"> + <description flex="1">&historyPages.label;</description> + <hbox align="center" + pack="end"> + <button label="&clearHistory.label;" + accesskey="&clearHistory.accesskey;" + oncommand="prefClearGlobalHistory();" + id="browserClearHistory" + preference="pref.browser.history.disable_button.clear_hist"/> + </hbox> + </hbox> + <checkbox id="histEnable" + label="&enableHistory.label;" + accesskey="&enableHistory.accesskey;" + preference="places.history.enabled"/> + </groupbox> + + <!-- no honey, I haven't been viewing porn, honest! --> + <groupbox> + <caption label="&locationBarHistory.caption;"/> + <hbox align="center"> + <vbox pack="end"> + <checkbox id="urlbarHistoryEnabled" + label="&urlBarHistoryEnabled.caption;" + accesskey="&urlBarHistoryEnabled.accesskey;" + preference="browser.urlbar.historyEnabled" + oncommand="prefUrlBarHistoryToggle(this.checked);"/> + <hbox align="center" + pack="end"> + <description flex="1">&clearLocationBar.label;</description> + <button id="ClearUrlBarHistoryButton" + label="&clearLocationBarButton.label;" + accesskey="&clearLocationBarButton.accesskey;" + oncommand="prefClearUrlbarHistory(this); this.disabled = true;" + preference="pref.browser.history.disable_button.clear_urlbar"/> + </hbox> + </vbox> + </hbox> + </groupbox> + + <!-- form history --> + <groupbox> + <caption label="&formfillHistory.caption;"/> + <checkbox id="formfillEnable" + label="&enableFormfill.label;" + accesskey="&enableFormfill.accesskey;" + preference="browser.formfill.enable"/> + <hbox align="center"> + <label value="&formfillExpire.label;" + accesskey="&formfillExpire.accesskey;" + control="formfillDay"/> + <textbox id="formfillDay" + type="number" + size="4" + preference="browser.formfill.expire_days"/> + <label value="&formfillDays.label;"/> + </hbox> + </groupbox> + </prefpane> + +</overlay> diff --git a/comm/suite/components/pref/content/pref-http.js b/comm/suite/components/pref/content/pref-http.js new file mode 100644 index 0000000000..eb04b9f274 --- /dev/null +++ b/comm/suite/components/pref/content/pref-http.js @@ -0,0 +1,42 @@ +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +function Startup() { + let compatMode = document.getElementById("uaFirefoxCompat"); + let modeFirefox = + document.getElementById("general.useragent.compatMode.firefox"); + let modeStrict = + document.getElementById("general.useragent.compatMode.strict-firefox"); + + if (modeStrict.value) + compatMode.value = "strict"; + else if (modeFirefox.value) + compatMode.value = "compat"; + else + compatMode.value = "none"; +} + +function updateUAPrefs(aCompatMode) { + let modeFirefox = + document.getElementById("general.useragent.compatMode.firefox"); + // The strict option will only work in builds compiled from a SeaMonkey + // release branch. Additional code needs to be added to the mozilla sources. + // See Bug 1242294 for the needed changes. + let modeStrict = + document.getElementById("general.useragent.compatMode.strict-firefox"); + switch (aCompatMode.value) { + case "strict": + modeStrict.value = true; + modeFirefox.value = false; + break; + case "compat": + modeStrict.value = false; + modeFirefox.value = true; + break; + case "none": + modeStrict.value = false; + modeFirefox.value = false; + } +} diff --git a/comm/suite/components/pref/content/pref-http.xul b/comm/suite/components/pref/content/pref-http.xul new file mode 100644 index 0000000000..bea6545418 --- /dev/null +++ b/comm/suite/components/pref/content/pref-http.xul @@ -0,0 +1,82 @@ +<?xml version="1.0"?> +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<!DOCTYPE overlay SYSTEM "chrome://communicator/locale/pref/pref-http.dtd"> +<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <prefpane id="http_pane" + label="&pref.http.title;" + script="chrome://communicator/content/pref/pref-http.js"> + + <preferences> + <preference id="network.http.version" + name="network.http.version" + type="string"/> + <preference id="network.http.proxy.version" + name="network.http.proxy.version" + type="string"/> + <preference id="general.useragent.compatMode.firefox" + name="general.useragent.compatMode.firefox" + type="bool"/> + <preference id="general.useragent.compatMode.strict-firefox" + name="general.useragent.compatMode.strict-firefox" + type="bool"/> + </preferences> + + <description>&prefPara;</description> + + <hbox align="start"> + <groupbox flex="1"> + <caption label="&prefDirect.label;"/> + <vbox class="indent" align="start"> + <radiogroup id="httpVersion" + preference="network.http.version"> + <radio value="1.0" + label="&prefEnableHTTP10.label;" + accesskey="&prefEnableHTTP10.accesskey;"/> + <radio value="1.1" + label="&prefEnableHTTP11.label;" + accesskey="&prefEnableHTTP11.accesskey;"/> + </radiogroup> + </vbox> + </groupbox> + + <groupbox flex="1"> + <caption label="&prefProxy.label;"/> + <vbox class="indent" align="start"> + <radiogroup id="httpVersionProxy" + preference="network.http.proxy.version"> + <radio value="1.0" + label="&prefEnableHTTP10.label;" + accesskey="&prefEnableHTTP10Proxy.accesskey;"/> + <radio value="1.1" + label="&prefEnableHTTP11.label;" + accesskey="&prefEnableHTTP11Proxy.accesskey;"/> + </radiogroup> + </vbox> + </groupbox> + </hbox> + + <separator class="thin"/> + + <groupbox> + <caption label="&prefUseragent.label;"/> + <radiogroup id="uaFirefoxCompat" + oncommand="updateUAPrefs(this);"> + <radio value="strict" + label="&prefFirefoxStrict.label;" + accesskey="&prefFirefoxStrict.accesskey;"/> + <radio value="none" + label="&prefFirefoxNone.label;" + accesskey="&prefFirefoxNone.accesskey;"/> + <radio value="compat" + label="&prefFirefoxCompat2.label;" + accesskey="&prefFirefoxCompat2.accesskey;"/> + </radiogroup> + </groupbox> + + <description>&prefCompatWarning2.desc;</description> + </prefpane> + +</overlay> diff --git a/comm/suite/components/pref/content/pref-images.xul b/comm/suite/components/pref/content/pref-images.xul new file mode 100644 index 0000000000..92c048dc56 --- /dev/null +++ b/comm/suite/components/pref/content/pref-images.xul @@ -0,0 +1,47 @@ +<?xml version="1.0"?> + +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<!DOCTYPE overlay [ +<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd" > +%brandDTD; +<!ENTITY % prefImagesDTD SYSTEM "chrome://communicator/locale/pref/pref-images.dtd" > +%prefImagesDTD; +]> + +<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <prefpane id="images_pane" + label="&pref.images.title;"> + <preferences id="images_preferences"> + <preference id="permissions.default.image" + name="permissions.default.image" type="int"/> + <preference id="pref.advanced.images.disable_button.view_image" type="bool" + name="pref.advanced.images.disable_button.view_image"/> + </preferences> + + <groupbox id="imagesArea"> + <caption label="&imageBlocking.label;"/> + + <description>&imageDetails;</description> + + <radiogroup id="networkImageBehaviour" + preference="permissions.default.image"> + <radio value="2" label="&loadNoImagesRadio.label;" + accesskey="&loadNoImagesRadio.accesskey;"/> + <radio value="3" label="&loadOrgImagesRadio.label;" + accesskey="&loadOrgImagesRadio.accesskey;"/> + <radio value="1" label="&loadAllImagesRadio.label;" + accesskey="&loadAllImagesRadio.accesskey;"/> + </radiogroup> + + <hbox pack="end"> + <button id="viewImages" + label="&viewPermissions.label;" + accesskey="&viewPermissions.accesskey;" + oncommand="toDataManager('|permissions');" + preference="pref.advanced.images.disable_button.view_image"/> + </hbox> + </groupbox> + </prefpane> +</overlay> diff --git a/comm/suite/components/pref/content/pref-keynav.js b/comm/suite/components/pref/content/pref-keynav.js new file mode 100644 index 0000000000..5210fdbe5c --- /dev/null +++ b/comm/suite/components/pref/content/pref-keynav.js @@ -0,0 +1,54 @@ +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +var {AppConstants} = ChromeUtils.import( + "resource://gre/modules/AppConstants.jsm" +); + +const kTabToLinks = 4; +const kTabToForms = 2; +const kTabToTextboxes = 1; + +function Startup() +{ + if (AppConstants.platform == "macosx") { + document.getElementById("tabNavigationPrefs").setAttribute("hidden", true); + } + + UpdateBrowseWithCaretItems(); +} + +function ReadTabNav(aField) +{ + var curval = document.getElementById("accessibility.tabfocus").value; + // Return the right bit based on the id of "aField" + if (aField.id == "tabNavigationLinks") + return (curval & kTabToLinks) != 0; + + return (curval & kTabToForms) != 0; +} + +function WriteTabNav(aField) +{ + var curval = document.getElementById("accessibility.tabfocus").value; + // Textboxes are always part of the tab order + curval |= kTabToTextboxes; + // Select the bit, we have to change, based on the id of "aField" + var bit = kTabToForms; + if (aField.id == "tabNavigationLinks") + bit = kTabToLinks; + + if (aField.checked) + return curval | bit; + + return curval & ~bit; +} + +function UpdateBrowseWithCaretItems() +{ + document.getElementById("browseWithCaretWarn").disabled = + !document.getElementById("accessibility.browsewithcaret_shortcut.enabled").value || + document.getElementById("accessibility.browsewithcaret").locked; +} diff --git a/comm/suite/components/pref/content/pref-keynav.xul b/comm/suite/components/pref/content/pref-keynav.xul new file mode 100644 index 0000000000..39ea0e7d1f --- /dev/null +++ b/comm/suite/components/pref/content/pref-keynav.xul @@ -0,0 +1,104 @@ +<?xml version="1.0"?> +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<!DOCTYPE overlay SYSTEM "chrome://communicator/locale/pref/pref-keynav.dtd"> + +<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <prefpane id="keynav_pane" + label="&pref.keyNav.title;" + script="chrome://communicator/content/pref/pref-keynav.js"> + + <preferences id="keynav_preferences"> + <preference id="accessibility.tabfocus" + name="accessibility.tabfocus" + type="int"/> + <preference id="accessibility.browsewithcaret" + name="accessibility.browsewithcaret" + type="bool"/> + <preference id="accessibility.browsewithcaret_shortcut.enabled" + name="accessibility.browsewithcaret_shortcut.enabled" + type="bool" + onchange="UpdateBrowseWithCaretItems();"/> + <preference id="accessibility.warn_on_browsewithcaret" + name="accessibility.warn_on_browsewithcaret" + type="bool"/> + <preference id="ui.key.accelKey" + name="ui.key.accelKey" + type="int"/> + <preference id="ui.key.menuAccessKey" + name="ui.key.menuAccessKey" + type="int"/> + </preferences> + + <groupbox id="tabNavigationPrefs" + align="start"> + <caption label="&tabNavigationBehavior.label;"/> + <description>&tabNavigationDesc.label;</description> + + <checkbox id="tabNavigationLinks" + label="&tabNavigationLinks.label;" + accesskey="&tabNavigationLinks.accesskey;" + preference="accessibility.tabfocus" + onsyncfrompreference="return document.getElementById('keynav_pane').ReadTabNav(this);" + onsynctopreference="return document.getElementById('keynav_pane').WriteTabNav(this);"/> + <checkbox id="tabNavigationForms" + label="&tabNavigationForms.label;" + accesskey="&tabNavigationForms.accesskey;" + preference="accessibility.tabfocus" + onsyncfrompreference="return document.getElementById('keynav_pane').ReadTabNav(this);" + onsynctopreference="return document.getElementById('keynav_pane').WriteTabNav(this);"/> + <description>&tabNavigationTextboxes.label;</description> + </groupbox> + + <groupbox id="browseWithCaretPrefs" + align="start"> + <caption label="&accessibilityBrowseWithCaret.label;"/> + <description>&browseWithCaretDesc.label;</description> + <checkbox id="browseWithCaretUse" + label="&browseWithCaretUse.label;" + accesskey="&browseWithCaretUse.accesskey;" + preference="accessibility.browsewithcaret"/> + <checkbox id="browseWithCaretShortCut" + label="&browseWithCaretShortCut.label;" + accesskey="&browseWithCaretShortCut.accesskey;" + preference="accessibility.browsewithcaret_shortcut.enabled"/> + <checkbox id="browseWithCaretWarn" + class="indent" + label="&browseWithCaretWarn.label;" + accesskey="&browseWithCaretWarn.accesskey;" + preference="accessibility.warn_on_browsewithcaret"/> + </groupbox> + + <groupbox id="modifiers"> + <caption label="&modifiers.label;"/> + <hbox align="center"> + <label id="acceleratorKey" + value="&acceleratorKey.label;" + accesskey="&acceleratorKey.accesskey;" + control="acceleratorKeyValue"/> + <textbox id="acceleratorKeyValue" + type="number" + min="0" + max="255" + size="3" + preference="ui.key.accelKey" + aria-labelledby="acceleratorKey acceleratorKeyValue"/> + <label id="menuAccessKey" + value="&menuAccessKey.label;" + accesskey="&menuAccessKey.accesskey;" + control="menuAccessKeyValue"/> + <textbox id="menuAccessKeyValue" + type="number" + min="0" + max="255" + size="3" + preference="ui.key.menuAccessKey" + aria-labelledby="menuAccessKey menuAccessKeyValue"/> + </hbox> + <description>&modifiersDesc.label;</description> + </groupbox> + + </prefpane> +</overlay> diff --git a/comm/suite/components/pref/content/pref-languages-add.js b/comm/suite/components/pref/content/pref-languages-add.js new file mode 100644 index 0000000000..e539b961cc --- /dev/null +++ b/comm/suite/components/pref/content/pref-languages-add.js @@ -0,0 +1,147 @@ +/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +var gLanguageNames; +var gAvailableLanguages; +var gOtherLanguages; +var gSelectedLanguages = []; +var gInvalidLanguages; + +function OnLoadAddLanguages() +{ + gLanguageNames = window.arguments[0]; + gAvailableLanguages = document.getElementById("availableLanguages"); + gSelectedLanguages = document.getElementById("intl.accept_languages").value + .toLowerCase().split(/\s*,\s*/); + gOtherLanguages = document.getElementById("otherLanguages"); + + if (gLanguageNames) + { + for (var i = 0; i < gLanguageNames.length; i++) + { + if (!gSelectedLanguages.includes(gLanguageNames[i][1])) + gAvailableLanguages.appendItem(gLanguageNames[i][0], + gLanguageNames[i][1]); + } + } +} + +function IsRFC1766LangTag(aCandidate) +{ + /* reject bogus lang strings, INCLUDING those with HTTP "q" + values kludged on the end of them + + Valid language codes examples: + i.e. ja-JP-kansai (Kansai dialect of Japanese) + en-US-texas (Texas dialect) + i-klingon-tng (did TOS Klingons speak in non-English?) + sgn-US-MA (Martha Vineyard's Sign Language) + */ + var tags = aCandidate.split('-'); + var checkedTags = 0; + + if (/^[ix]$/.test(tags[0])) + { + if (tags.length < 2) + return false; + checkedTags++; + } + else + /* if not IANA "i" or a private "x" extension, the primary + tag should be a ISO 639 country code, two or three letters long. + we don't check if the country code is bogus or not. + */ + { + if (!/^[a-z]{2,3}$/.test(tags[0])) + return false; + checkedTags++; + + /* the first subtag can be either a 2 letter ISO 3166 country code, + or an IANA registered tag from 3 to 8 characters. + */ + if (tags.length > 1) + { + if (!/^[a-z0-9]{2,8}$/.test(tags[1])) + return false; + + /* do not allow user-assigned ISO 3166 country codes */ + if (/^(aa|zz|x[a-z]|q[m-z])$/.test(tags[1])) + return false; + checkedTags++; + } + } + + /* any remaining subtags must be one to eight alphabetic characters */ + + while (checkedTags < tags.length) + { + if (!/^[a-z0-9]{1,8}$/.test(tags[checkedTags])) + return false; + checkedTags++; + } + return true; +} + +function WriteAddedLanguages(aListbox) +{ + var invalidLangs = []; + // selected languages + var languages = aListbox.selectedItems; + var addedLang = Array.from(languages, e => e.value); + + // user-defined languages + languages = gOtherLanguages.value; + if (languages) + { + let languageIds = languages.replace(/\s+/g, "").toLowerCase().split(","); + for (var i = 0; i < languageIds.length; i++) + { + let languageId = languageIds[i]; + if (IsRFC1766LangTag(languageId)) + { + if (!addedLang.includes(languageId) && + !gSelectedLanguages.includes(languageId)) + addedLang.push(languageId); + } + else + { + invalidLangs.push(languageId); + } + } + } + + if (invalidLangs.length) + gInvalidLanguages = invalidLangs.join(", "); + else + gSelectedLanguages = gSelectedLanguages.concat(addedLang); + + return gSelectedLanguages.join(","); +} + +function OnAccept() +{ + if (!gInvalidLanguages) + return true; + + let prefLangBundle = document.getElementById("prefLangAddBundle"); + const kErrorMsg = prefLangBundle.getString("illegalOtherLanguage") + " " + + gInvalidLanguages; + const kErrorTitle = prefLangBundle.getString("illegalOtherLanguageTitle"); + Services.prompt.alert(this.window, kErrorTitle, kErrorMsg); + + gInvalidLanguages = null; + gOtherLanguages.focus(); + return false; +} + +function HandleDoubleClick() +{ + document.documentElement.acceptDialog(); +} + +function DoBeforeAccept() +{ + gAvailableLanguages.doCommand(); +} diff --git a/comm/suite/components/pref/content/pref-languages-add.xul b/comm/suite/components/pref/content/pref-languages-add.xul new file mode 100644 index 0000000000..0ae11aee9b --- /dev/null +++ b/comm/suite/components/pref/content/pref-languages-add.xul @@ -0,0 +1,54 @@ +<?xml version="1.0"?> <!-- -*- Mode: SGML; indent-tabs-mode: nil; -*- --> +<!-- + + This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<?xml-stylesheet href="chrome://communicator/skin/" type="text/css"?> + +<!DOCTYPE prefwindow SYSTEM "chrome://communicator/locale/pref/pref-languages.dtd" > + + +<prefwindow xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + id="addLanguagesPreferences" + title="&languages.customize.add.title.label;" + type="child" + onload="OnLoadAddLanguages();" + onbeforeaccept="DoBeforeAccept();" + ondialogaccept="return OnAccept();"> + + <script src="chrome://communicator/content/pref/pref-languages-add.js"/> + + <prefpane id="addLanguagesPane"> + <preferences id="addLanguages"> + <preference id="intl.accept_languages" + name="intl.accept_languages" + type="wstring"/> + </preferences> + + <stringbundleset id="langAddBundleset"> + <stringbundle id="prefLangAddBundle" + src="chrome://communicator/locale/pref/pref-languages.properties"/> + </stringbundleset> + + <description style="width: 1px;">&languages.customize.prefAddLangDescript;</description> + <separator class="thin"/> + <description style="width: 1px;">&languages.customize.available.label;</description> + + <listbox id="availableLanguages" + flex="1" + seltype="multiple" + preference="intl.accept_languages" + ondblclick="HandleDoubleClick();" + onsynctopreference="return WriteAddedLanguages(this);"/> + + <hbox align="center"> + <label value="&languages.customize.others.label;" + accesskey="&languages.customize.others.accesskey;" + control="otherLanguages"/> + <textbox id="otherLanguages" size="12" flex="1"/> + <label value="&languages.customize.others.examples;" control="otherLanguages"/> + </hbox> + </prefpane> +</prefwindow> diff --git a/comm/suite/components/pref/content/pref-languages.js b/comm/suite/components/pref/content/pref-languages.js new file mode 100644 index 0000000000..de2895ee11 --- /dev/null +++ b/comm/suite/components/pref/content/pref-languages.js @@ -0,0 +1,200 @@ +/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +var gActiveLanguages; +var gLanguages; +var gLanguageNames = []; +var gLanguageTitles = {}; + +function Startup() +{ + gActiveLanguages = document.getElementById("activeLanguages"); + // gLanguages stores the ordered list of languages, due to the nature + // of childNodes it is live and updates automatically. + gLanguages = gActiveLanguages.childNodes; + + ReadAvailableLanguages(); +} + +function AddLanguage() +{ + document.documentElement.openSubDialog("chrome://communicator/content/pref/pref-languages-add.xul", "addlangwindow", gLanguageNames); +} + +function ReadAvailableLanguages() +{ + var i = 0; + var languagesBundle = document.getElementById("languageNamesBundle"); + var prefLangBundle = document.getElementById("prefLangBundle"); + var regionsBundle = document.getElementById("regionNamesBundle"); + var langStrings = document.getElementById("acceptedBundle").strings; + + while (langStrings.hasMoreElements()) + { + // Progress through the bundle. + var curItem = langStrings.getNext(); + + if (!(curItem instanceof Ci.nsIPropertyElement)) + break; + + var stringNameProperty = curItem.key.split('.'); + + var str = stringNameProperty[0]; + if (str && stringNameProperty[1] == 'accept') + { + var stringLangRegion = str.split('-'); + + if (stringLangRegion[0]) + { + var language = ""; + var region = null; + + try + { + language = languagesBundle.getString(stringLangRegion[0]); + } + catch (ex) {} + + if (stringLangRegion.length > 1) + { + try + { + region = regionsBundle.getString(stringLangRegion[1]); + } + catch (ex) {} + } + + var title; + if (region) + title = prefLangBundle.getFormattedString("languageRegionCodeFormat", + [language, region, str]); + else + title = prefLangBundle.getFormattedString("languageCodeFormat", + [language, str]); + gLanguageTitles[str] = title; + if (curItem.value == "true") + gLanguageNames.push([title, str]); + } + } + } + + // Sort on first element. + gLanguageNames.sort( + function compareFn(a, b) + { + return a[0].localeCompare(b[0]); + } + ); +} + +function ReadActiveLanguages() +{ + var arrayOfPrefs = document.getElementById("intl.accept_languages").value + .toLowerCase().split(/\s*,\s*/); + + // No need to rebuild listitems if languages in prefs and listitems match. + if (InSync(arrayOfPrefs)) + return; + + while (gActiveLanguages.hasChildNodes()) + gActiveLanguages.lastChild.remove(); + + arrayOfPrefs.forEach( + function(aKey) + { + if (aKey) + { + let langTitle = gLanguageTitles.hasOwnProperty(aKey) ? + gLanguageTitles[aKey] : "[" + aKey + "]"; + gActiveLanguages.appendItem(langTitle, aKey); + } + } + ); + + SelectLanguage(); + + return; +} + +// Checks whether listitems and pref values matches, returns false if not. +function InSync(aPrefArray) +{ + // Can't match if they don't have the same length. + if (aPrefArray.length != gLanguages.length) + return false; + + return aPrefArray.every( + function(aElement, aIndex) + { + return aElement == gLanguages[aIndex].value; + } + ); +} + +// Called on onsynctopreference. +function WriteActiveLanguages() +{ + return Array.from(gLanguages, e => e.value).join(","); +} + +function MoveUp() +{ + var selected = gActiveLanguages.selectedItem; + var before = selected.previousSibling; + if (before) + { + before.parentNode.insertBefore(selected, before); + gActiveLanguages.selectItem(selected); + gActiveLanguages.ensureElementIsVisible(selected); + } + + SelectLanguage(); + gActiveLanguages.doCommand(); +} + +function MoveDown() +{ + var selected = gActiveLanguages.selectedItem; + if (selected.nextSibling) + { + var before = selected.nextSibling.nextSibling; + gActiveLanguages.insertBefore(selected, before); + gActiveLanguages.selectItem(selected); + } + + SelectLanguage(); + gActiveLanguages.doCommand(); +} + +function RemoveActiveLanguage(aEvent) +{ + if (aEvent && aEvent.keyCode != aEvent.DOM_VK_DELETE && + aEvent.keyCode != aEvent.DOM_VK_BACK_SPACE) + return; + + var nextNode = null; + + while (gActiveLanguages.selectedItem) + { + var selectedNode = gActiveLanguages.selectedItem; + nextNode = selectedNode.nextSibling || selectedNode.previousSibling; + selectedNode.remove(); + } + + if (nextNode) + gActiveLanguages.selectItem(nextNode); + + SelectLanguage(); + gActiveLanguages.doCommand(); +} + +function SelectLanguage() +{ + var len = gActiveLanguages.selectedItems.length; + EnableElementById("langRemove", len, false); + var selected = gActiveLanguages.selectedItem; + EnableElementById("langDown", (len == 1) && selected.nextSibling, false); + EnableElementById("langUp", (len == 1) && selected.previousSibling, false); +} diff --git a/comm/suite/components/pref/content/pref-languages.xul b/comm/suite/components/pref/content/pref-languages.xul new file mode 100644 index 0000000000..a17deae032 --- /dev/null +++ b/comm/suite/components/pref/content/pref-languages.xul @@ -0,0 +1,124 @@ +<?xml version="1.0"?> <!-- -*- Mode: SGML; indent-tabs-mode: nil; -*- --> +<!-- + + This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<!DOCTYPE overlay [ + <!ENTITY % prefLanguagesDTD SYSTEM "chrome://communicator/locale/pref/pref-languages.dtd"> %prefLanguagesDTD; + <!ENTITY % prefUtilitiesDTD SYSTEM "chrome://communicator/locale/pref/prefutilities.dtd"> %prefUtilitiesDTD; +]> + +<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <prefpane id="languages_pane" + label="&languages.customize.title;" + script="chrome://communicator/content/pref/pref-languages.js"> + + <preferences id="languages_preferences"> + <preference id="intl.accept_languages" + name="intl.accept_languages" + type="wstring"/> + <preference id="pref.browser.language.disable_button.up" + name="pref.browser.language.disable_button.up" + type="bool"/> + <preference id="pref.browser.language.disable_button.down" + name="pref.browser.language.disable_button.down" + type="bool"/> + <preference id="pref.browser.language.disable_button.add" + name="pref.browser.language.disable_button.add" + type="bool"/> + <preference id="pref.browser.language.disable_button.remove" + name="pref.browser.language.disable_button.remove" + type="bool"/> + <preference id="intl.charset.fallback.override" + name="intl.charset.fallback.override" + type="string"/> + </preferences> + + <stringbundleset id="langBundleset"> + <stringbundle id="acceptedBundle" + src="resource://gre/res/language.properties"/> + <stringbundle id="prefLangBundle" + src="chrome://communicator/locale/pref/pref-languages.properties"/> + </stringbundleset> + + <groupbox flex="1"> + <caption label="&langtitle.label;"/> + <description>&languages.customize.prefLangDescript;</description> + <label accesskey="&languages.customize.active.accesskey;" + control="activeLanguages">&languages.customize.active.label;</label> + <hbox flex="1"> + <listbox id="activeLanguages" + flex="1" + style="width: 0px; height: 0px;" + seltype="multiple" + preference="intl.accept_languages" + onkeypress="RemoveActiveLanguage(event);" + onselect="SelectLanguage();" + onsynctopreference="return document.getElementById('languages_pane').WriteActiveLanguages();" + onsyncfrompreference="return document.getElementById('languages_pane').ReadActiveLanguages(this);"/> + <vbox> + <button id="langUp" + class="up" + disabled="true" + label="&languages.customize.moveUp.label;" + accesskey="&languages.customize.moveUp.accesskey;" + preference="pref.browser.language.disable_button.up" + oncommand="MoveUp();"/> + <button id="langDown" + class="down" + disabled="true" + label="&languages.customize.moveDown.label;" + accesskey="&languages.customize.moveDown.accesskey;" + preference="pref.browser.language.disable_button.down" + oncommand="MoveDown();"/> + <spacer flex="1"/> + <button id="langAdd" + label="&languages.customize.addButton.label;" + accesskey="&languages.customize.addButton.accesskey;" + preference="pref.browser.language.disable_button.add" + oncommand="AddLanguage();"/> + <button id="langRemove" + disabled="true" + label="&languages.customize.deleteButton.label;" + accesskey="&languages.customize.deleteButton.accesskey;" + preference="pref.browser.language.disable_button.remove" + oncommand="RemoveActiveLanguage(null);"/> + </vbox> + </hbox> + </groupbox> + + <groupbox align="start"> + <caption label="&languages.customize.Fallback2.grouplabel;"/> + <description>&languages.customize.Fallback2.desc;</description> + <hbox align="center"> + <label value="&languages.customize.Fallback2.label;" + accesskey="&languages.customize.Fallback2.accesskey;" + control="defaultCharsetList"/> + <menulist id="defaultCharsetList" + preference="intl.charset.fallback.override"> + <menupopup> + <menuitem label="&FallbackCharset.auto;" value=""/> + <menuitem label="&FallbackCharset.arabic;" value="windows-1256"/> + <menuitem label="&FallbackCharset.baltic;" value="windows-1257"/> + <menuitem label="&FallbackCharset.ceiso;" value="ISO-8859-2"/> + <menuitem label="&FallbackCharset.cewindows;" value="windows-1250"/> + <menuitem label="&FallbackCharset.simplified;" value="gbk"/> + <menuitem label="&FallbackCharset.traditional;" value="Big5"/> + <menuitem label="&FallbackCharset.cyrillic;" value="windows-1251"/> + <menuitem label="&FallbackCharset.greek;" value="ISO-8859-7"/> + <menuitem label="&FallbackCharset.hebrew;" value="windows-1255"/> + <menuitem label="&FallbackCharset.japanese;" value="Shift_JIS"/> + <menuitem label="&FallbackCharset.korean;" value="EUC-KR"/> + <menuitem label="&FallbackCharset.thai;" value="windows-874"/> + <menuitem label="&FallbackCharset.turkish;" value="windows-1254"/> + <menuitem label="&FallbackCharset.vietnamese;" value="windows-1258"/> + <menuitem label="&FallbackCharset.other;" value="windows-1252"/> + </menupopup> + </menulist> + </hbox> + </groupbox> + + </prefpane> +</overlay> diff --git a/comm/suite/components/pref/content/pref-links.js b/comm/suite/components/pref/content/pref-links.js new file mode 100644 index 0000000000..2ca7a3e921 --- /dev/null +++ b/comm/suite/components/pref/content/pref-links.js @@ -0,0 +1,15 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +function Startup() +{ + ToggleRestrictionGroup(document.getElementById("browser.link.open_newwindow").value); +} + +function ToggleRestrictionGroup(value) +{ + document.getElementById("restrictionGroup").disabled = + value == Ci.nsIBrowserDOMWindow.OPEN_NEWWINDOW || + document.getElementById("browser.link.open_newwindow.restriction").locked; +} diff --git a/comm/suite/components/pref/content/pref-links.xul b/comm/suite/components/pref/content/pref-links.xul new file mode 100644 index 0000000000..6ebb8d9cb2 --- /dev/null +++ b/comm/suite/components/pref/content/pref-links.xul @@ -0,0 +1,78 @@ +<?xml version="1.0"?> +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<!DOCTYPE overlay SYSTEM "chrome://communicator/locale/pref/pref-links.dtd"> + +<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + + <prefpane id="links_pane" + label="&linksHeader.label;" + script="chrome://communicator/content/pref/pref-links.js"> + + <preferences id="links_preferences"> + <preference id="browser.link.open_newwindow" + name="browser.link.open_newwindow" + type="int" + onchange="ToggleRestrictionGroup(this.value);"/> + <preference id="browser.link.open_newwindow.restriction" + name="browser.link.open_newwindow.restriction" + type="int"/> + <preference id="browser.link.open_external" + name="browser.link.open_external" + type="int"/> + </preferences> + + <groupbox> + <caption label="&newWindow.label;"/> + <description>&newWindowDescription.label;</description> + <radiogroup id="newWindowGroup" + class="indent" + preference="browser.link.open_newwindow"> + <radio value="1" + label="&openCurrent.label;" + accesskey="&newWindowGroupCurrent.accesskey;"/> + <radio value="3" + label="&openTab.label;" + accesskey="&newWindowGroupTab.accesskey;"/> + <radio value="2" + label="&openWindow.label;" + accesskey="&newWindowGroupWindow.accesskey;"/> + </radiogroup> + <separator class="thin"/> + <description>&newWindowRestriction.label;</description> + <radiogroup id="restrictionGroup" + class="indent" + preference="browser.link.open_newwindow.restriction"> + <radio value="0" + label="&divertAll.label;" + accesskey="&divertAll.accesskey;"/> + <radio value="2" + label="&divertNoFeatures.label;" + accesskey="&divertNoFeatures.accesskey;"/> + <radio value="1" + label="&dontDivert.label;" + accesskey="&dontDivert.accesskey;"/> + </radiogroup> + </groupbox> + + <groupbox> + <caption label="&external.label;"/> + <description>&externalDescription.label;</description> + <radiogroup id="externalGroup" + class="indent" + preference="browser.link.open_external"> + <radio value="1" + label="&openCurrent.label;" + accesskey="&externalGroupCurrent.accesskey;"/> + <radio value="3" + label="&openTab.label;" + accesskey="&externalGroupTab.accesskey;"/> + <radio value="2" + label="&openWindow.label;" + accesskey="&externalGroupWindow.accesskey;"/> + </radiogroup> + </groupbox> + </prefpane> +</overlay> diff --git a/comm/suite/components/pref/content/pref-locationbar.js b/comm/suite/components/pref/content/pref-locationbar.js new file mode 100644 index 0000000000..042621eb35 --- /dev/null +++ b/comm/suite/components/pref/content/pref-locationbar.js @@ -0,0 +1,42 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +function Startup() +{ + // On systems that has the file view component, autoFill and showPopup will + // return results from local browsing "history", even if autocomplete.enabled + // is turned off, so we'll need to remove the dependent look in the ui. + + if ("@mozilla.org/autocomplete/search;1?name=file" in Cc) + { + // We indent the checkboxes with the class attribute set to "indent", so + // just remove the attribute. + document.getElementById("autoFill").removeAttribute("class"); + document.getElementById("showPopup").removeAttribute("class"); + } + + updateDependent(); +} + +function updateDependent() +{ + var matchHistoryPref = document.getElementById("browser.urlbar.suggest.history"); + EnableElementById("matchOnlyTyped", matchHistoryPref.value); + + var matchBookmarkPref = document.getElementById("browser.urlbar.suggest.bookmark"); + var autoCompleteEnabled = matchHistoryPref.value || matchBookmarkPref.value; + EnableElementById("matchBehavior", autoCompleteEnabled); + + // If autoFill has a class attribute, we don't have the file view component. + // We then need to update autoFill and showPopup. + if (document.getElementById("autoFill").hasAttribute("class")) + { + EnableElementById("autoFill", autoCompleteEnabled); + EnableElementById("showPopup", autoCompleteEnabled); + } + + // We need to update autocomplete.enabled as the backend still respects it. + document.getElementById("browser.urlbar.autocomplete.enabled").value = + autoCompleteEnabled; +} diff --git a/comm/suite/components/pref/content/pref-locationbar.xul b/comm/suite/components/pref/content/pref-locationbar.xul new file mode 100644 index 0000000000..3c781e4c60 --- /dev/null +++ b/comm/suite/components/pref/content/pref-locationbar.xul @@ -0,0 +1,127 @@ +<?xml version="1.0"?> +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<!DOCTYPE overlay SYSTEM "chrome://communicator/locale/pref/pref-locationbar.dtd"> + +<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + + <prefpane id="locationBar_pane" + label="&pref.locationBar.title;" + script="chrome://communicator/content/pref/pref-locationbar.js"> + + <preferences id="locationBar_preferences"> + <!-- The suggest preferences need to come first otherwise the backend + will enable both bookmarks and history if either is enabled --> + <preference id="browser.urlbar.suggest.bookmark" + name="browser.urlbar.suggest.bookmark" + type="bool" + onchange="updateDependent();"/> + <preference id="browser.urlbar.suggest.history" + name="browser.urlbar.suggest.history" + type="bool" + onchange="updateDependent();"/> + <preference id="browser.urlbar.suggest.history.onlyTyped" + name="browser.urlbar.suggest.history.onlyTyped" + type="bool"/> + <preference id="browser.urlbar.autocomplete.enabled" + name="browser.urlbar.autocomplete.enabled" + type="bool"/> + <preference id="browser.urlbar.matchBehavior" + name="browser.urlbar.matchBehavior" + type="int"/> + <preference id="browser.urlbar.autoFill" + name="browser.urlbar.autoFill" + type="bool" + onchange="updateMatchPrefs();"/> + <preference id="browser.urlbar.showPopup" + name="browser.urlbar.showPopup" + type="bool" + onchange="updateMatchPrefs();"/> + <preference id="browser.urlbar.showSearch" + name="browser.urlbar.showSearch" + type="bool"/> + <preference id="browser.urlbar.formatting.enabled" + name="browser.urlbar.formatting.enabled" + type="bool"/> + <preference id="browser.urlbar.highlight.secure" + name="browser.urlbar.highlight.secure" + type="bool"/> + <preference id="browser.fixup.alternate.enabled" + name="browser.fixup.alternate.enabled" + type="bool"/> + <preference id="keyword.enabled" + name="keyword.enabled" + type="bool"/> + </preferences> + + <groupbox> + <caption label="&autoComplete.label;"/> + <checkbox id="matchHistory" + label="&autoCompleteMatchHistory.label;" + accesskey="&autoCompleteMatchHistory.accesskey;" + preference="browser.urlbar.suggest.history"/> + <checkbox id="matchOnlyTyped" + class="indent" + label="&autoCompleteMatchOnlyTyped.label;" + accesskey="&autoCompleteMatchOnlyTyped.accesskey;" + preference="browser.urlbar.suggest.history.onlyTyped"/> + <checkbox id="matchBookmark" + label="&autoCompleteMatchBookmarks.label;" + accesskey="&autoCompleteMatchBookmarks.accesskey;" + preference="browser.urlbar.suggest.bookmark"/> + <hbox align="center" class="indent"> + <label value="&autoCompleteMatch.label;" control="matchBehavior" + accesskey="&autoCompleteMatch.accesskey;"/> + <menulist id="matchBehavior" + preference="browser.urlbar.matchBehavior"> + <menupopup> + <menuitem value="0" label="&autoCompleteMatchAnywhere;"/> + <menuitem value="1" label="&autoCompleteMatchWordsFirst;"/> + <menuitem value="2" label="&autoCompleteMatchWords;"/> + <menuitem value="3" label="&autoCompleteMatchStart;"/> + </menupopup> + </menulist> + </hbox> + <checkbox id="autoFill" + class="indent" + label="&autoCompleteAutoFill.label;" + accesskey="&autoCompleteAutoFill.accesskey;" + preference="browser.urlbar.autoFill"/> + <checkbox id="showPopup" + class="indent" + label="&autoCompleteShowPopup.label;" + accesskey="&autoCompleteShowPopup.accesskey;" + preference="browser.urlbar.showPopup"/> + <checkbox id="showSearch" + label="&showInternetSearch.label;" + accesskey="&showInternetSearch.accesskey;" + preference="browser.urlbar.showSearch"/> + </groupbox> + + <groupbox> + <caption label="&formatting.label;"/> + <checkbox id="domainFormattingEnabled" + label="&domainFormatting.label;" + accesskey="&domainFormatting.accesskey;" + preference="browser.urlbar.formatting.enabled"/> + <checkbox id="highlightSecureEnabled" + label="&highlightSecure.label;" + accesskey="&highlightSecure.accesskey;" + preference="browser.urlbar.highlight.secure"/> + </groupbox> + + <groupbox> + <caption label="&unknownLocations.label;"/> + <checkbox id="domainGuessingEnabled" + label="&domainGuessing.label;" + accesskey="&domainGuessing.accesskey;" + preference="browser.fixup.alternate.enabled"/> + <checkbox id="browserGoBrowsingEnabled" + label="&keywords.label;" + accesskey="&keywords.accesskey;" + preference="keyword.enabled"/> + </groupbox> + </prefpane> +</overlay> diff --git a/comm/suite/components/pref/content/pref-media.xul b/comm/suite/components/pref/content/pref-media.xul new file mode 100644 index 0000000000..3a2411a634 --- /dev/null +++ b/comm/suite/components/pref/content/pref-media.xul @@ -0,0 +1,60 @@ +<?xml version="1.0"?> +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<!DOCTYPE overlay SYSTEM "chrome://communicator/locale/pref/pref-media.dtd"> + +<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + + <prefpane id="media_pane" + label="&pref.media.title;"> + + <preferences id="media_preferences"> + <preference id="media.autoplay.enabled" + name="media.autoplay.enabled" + type="bool"/> + <preference id="media.eme.enabled" + name="media.eme.enabled" + type="bool"/> + <preference id="image.animation_mode" + name="image.animation_mode" + type="string"/> + </preferences> + + <groupbox id="mediaHTML5Preferences" align="start"> + <caption label="&mediaHTML5Preferences.label;"/> + <checkbox id="autoplay" + label="&allowMediaAutoplay.label;" + accesskey="&allowMediaAutoplay.accesskey;" + preference="media.autoplay.enabled"/> + </groupbox> + + <!-- REMOVE #ifndef once EME are ready for prime time, meta bug 1015800 --> +#ifndef RELEASE_OR_BETA + <groupbox id="drmPreferences"> + <caption label="&enableDrmMedia.label;"/> + <checkbox id="emeForSuite" + label="&enableEmeForSuite.label;" + accesskey="&enableEmeForSuite.accesskey;" + preference="media.eme.enabled"/> + </groupbox> +#endif + + <groupbox> + <caption label="&animLoopingTitle.label;"/> + <radiogroup id="imageLooping" + preference="image.animation_mode"> + <radio value="normal" + label="&animLoopAsSpecified.label;" + accesskey="&animLoopAsSpecified.accesskey;"/> + <radio value="once" + label="&animLoopOnce.label;" + accesskey="&animLoopOnce.accesskey;"/> + <radio value="none" + label="&animLoopNever.label;" + accesskey="&animLoopNever.accesskey;"/> + </radiogroup> + </groupbox> + </prefpane> +</overlay> diff --git a/comm/suite/components/pref/content/pref-mousewheel.js b/comm/suite/components/pref/content/pref-mousewheel.js new file mode 100644 index 0000000000..6902a0c3cf --- /dev/null +++ b/comm/suite/components/pref/content/pref-mousewheel.js @@ -0,0 +1,45 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +function doEnabling(aElement) +{ + var preference = document.getElementById(aElement.getAttribute("preference")); + var prefix = aElement.id.replace(/action$/, ""); + var vertical = document.getElementById(prefix + "delta_multiplier_y"); + EnableElement(vertical, preference.value); + updateCheckbox(vertical); + var actionX = document.getElementById(prefix + "action_x"); + if (actionX.value < 0) + doEnablingX(actionX); +} + +function doEnablingX(aElement) +{ + var preference = document.getElementById(aElement.getAttribute("preference")); + var prefix = aElement.id.replace(/action_x$/, ""); + var value = preference.value; + if (value < 0) { + var action = document.getElementById(prefix + "action"); + preference = document.getElementById(action.getAttribute("preference")); + value = preference.value; + } + var horizontal = document.getElementById(prefix + "delta_multiplier_x"); + EnableElement(horizontal, value); + updateCheckbox(horizontal); +} + +function updateCheckbox(aTextbox) +{ + var preference = document.getElementById(aTextbox.getAttribute("preference")); + var checkbox = aTextbox.parentNode.lastChild; + checkbox.checked = preference.value < 0; + checkbox.disabled = !preference.value || aTextbox.disabled +} + +function updateTextbox(aCheckbox) +{ + var textbox = aCheckbox.previousSibling.previousSibling; + var preference = document.getElementById(textbox.getAttribute("preference")); + preference.value = -preference.value; +} diff --git a/comm/suite/components/pref/content/pref-mousewheel.xul b/comm/suite/components/pref/content/pref-mousewheel.xul new file mode 100644 index 0000000000..63346781cc --- /dev/null +++ b/comm/suite/components/pref/content/pref-mousewheel.xul @@ -0,0 +1,298 @@ +<?xml version="1.0"?> +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<!DOCTYPE overlay SYSTEM "chrome://communicator/locale/pref/pref-mousewheel.dtd" > + +<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <prefpane id="mousewheel_pane" + label="&pref.mouseWheel.title;" + script="chrome://communicator/content/pref/pref-mousewheel.js"> + + <preferences id="mousewheel_preferences"> + <preference id="mousewheel.default.action" + name="mousewheel.default.action" + type="int"/> + <preference id="mousewheel.default.delta_multiplier_y" + name="mousewheel.default.delta_multiplier_y" + type="int"/> + <preference id="mousewheel.default.action.override_x" + name="mousewheel.default.action.override_x" + type="int"/> + <preference id="mousewheel.default.delta_multiplier_x" + name="mousewheel.default.delta_multiplier_x" + type="int"/> + <preference id="mousewheel.with_alt.action" + name="mousewheel.with_alt.action" + type="int"/> + <preference id="mousewheel.with_alt.delta_multiplier_y" + name="mousewheel.with_alt.delta_multiplier_y" + type="int"/> + <preference id="mousewheel.with_alt.action.override_x" + name="mousewheel.with_alt.action.override_x" + type="int"/> + <preference id="mousewheel.with_alt.delta_multiplier_x" + name="mousewheel.with_alt.delta_multiplier_x" + type="int"/> + <preference id="mousewheel.with_control.action" + name="mousewheel.with_control.action" + type="int"/> + <preference id="mousewheel.with_control.delta_multiplier_y" + name="mousewheel.with_control.delta_multiplier_y" + type="int"/> + <preference id="mousewheel.with_control.action.override_x" + name="mousewheel.with_control.action.override_x" + type="int"/> + <preference id="mousewheel.with_control.delta_multiplier_x" + name="mousewheel.with_control.delta_multiplier_x" + type="int"/> + <preference id="mousewheel.with_shift.action" + name="mousewheel.with_shift.action" + type="int"/> + <preference id="mousewheel.with_shift.delta_multiplier_y" + name="mousewheel.with_shift.delta_multiplier_y" + type="int"/> + <preference id="mousewheel.with_shift.action.override_x" + name="mousewheel.with_shift.action.override_x" + type="int"/> + <preference id="mousewheel.with_shift.delta_multiplier_x" + name="mousewheel.with_shift.delta_multiplier_x" + type="int"/> + </preferences> + + <description>&mouseWheelPanel.label;</description> + + <tabbox class="spaced"> + <tabs> + <tab label="&usingJustTheWheel.label;"/> +#ifndef XP_MACOSX + <tab label="&usingWheelAndAlt.label2;"/> +#else + <tab label="&usingWheelAndOption.label;"/> +#endif + <tab label="&usingWheelAndCtrl.label2;"/> + <tab label="&usingWheelAndShft.label2;"/> + </tabs> + + <tabpanels> + + <!-- no key modifiers --> + <vbox> + <groupbox> + <caption label="&mouseWheelGroup.label;"/> + <radiogroup id="mousewheel_default_action" + preference="mousewheel.default.action" + onsyncfrompreference="document.getElementById('mousewheel_pane').doEnabling(this);"> + <radio value="0" label="&doNothing.label;" accesskey="&doNothing.accesskey;"/> + <radio value="1" label="&scrollDocument.label;" accesskey="&scrollDocument.accesskey;"/> + <radio value="2" label="&history.label;" accesskey="&history.accesskey;"/> + <radio value="3" label="&zoom.label;" accesskey="&zoom.accesskey;"/> + </radiogroup> + <hbox align="center"> + <label control="mousewheel_default_delta_multiplier_y" + value="&wheelSpeed.label;"/> + <textbox type="number" min="-999999" max="999999" size="6" + id="mousewheel_default_delta_multiplier_y" + accesskey="&wheelSpeed.accesskey;" + preference="mousewheel.default.delta_multiplier_y" + onsyncfrompreference="document.getElementById('mousewheel_pane').updateCheckbox(this);"/> + <label value="%"/> + <checkbox label="&reverseDirection.label;" + accesskey="&reverseDirection.accesskey;" + oncommand="updateTextbox(this);"/> + </hbox> + </groupbox> + + <groupbox> + <caption label="&mouseWheelHorizGroup.label;"/> + <radiogroup id="mousewheel_default_action_x" + preference="mousewheel.default.action.override_x" + onsyncfrompreference="document.getElementById('mousewheel_pane').doEnablingX(this);"> + <radio value="-1" label="&sameAsVertical.label;" accesskey="&sameAsVertical.accesskey;"/> + <radio value="0" label="&doNothing.label;" accesskey="&doNothingHoriz.accesskey;"/> + <radio value="1" label="&scrollDocument.label;" accesskey="&scrollDocumentHoriz.accesskey;"/> + <radio value="2" label="&history.label;" accesskey="&historyHoriz.accesskey;"/> + <radio value="3" label="&zoom.label;" accesskey="&zoomHoriz.accesskey;"/> + </radiogroup> + <hbox align="center"> + <label control="mousewheel_default_delta_multiplier_x" + value="&wheelSpeed.label;"/> + <textbox type="number" min="-999999" max="999999" size="6" + id="mousewheel_default_delta_multiplier_x" + accesskey="&wheelSpeedHoriz.accesskey;" + preference="mousewheel.default.delta_multiplier_x" + onsyncfrompreference="document.getElementById('mousewheel_pane').updateCheckbox(this);"/> + <label value="%"/> + <checkbox label="&reverseDirection.label;" + accesskey="&reverseDirectionHoriz.accesskey;" + oncommand="updateTextbox(this);"/> + </hbox> + </groupbox> + </vbox> + + <!-- alt modifiers --> + <vbox> + <groupbox> + <caption label="&mouseWheelGroup.label;"/> + <radiogroup id="mousewheel_with_alt_action" + preference="mousewheel.with_alt.action" + onsyncfrompreference="document.getElementById('mousewheel_pane').doEnabling(this);"> + <radio value="0" label="&doNothing.label;" accesskey="&doNothing.accesskey;"/> + <radio value="1" label="&scrollDocument.label;" accesskey="&scrollDocument.accesskey;"/> + <radio value="2" label="&history.label;" accesskey="&history.accesskey;"/> + <radio value="3" label="&zoom.label;" accesskey="&zoom.accesskey;"/> + </radiogroup> + <hbox align="center"> + <label control="mousewheel_with_alt_delta_multiplier_y" + value="&wheelSpeed.label;"/> + <textbox type="number" min="-999999" max="999999" size="6" + id="mousewheel_with_alt_delta_multiplier_y" + accesskey="&wheelSpeed.accesskey;" + preference="mousewheel.with_alt.delta_multiplier_y" + onsyncfrompreference="document.getElementById('mousewheel_pane').updateCheckbox(this);"/> + <label value="%"/> + <checkbox label="&reverseDirection.label;" + accesskey="&reverseDirection.accesskey;" + oncommand="updateTextbox(this);"/> + </hbox> + </groupbox> + + <groupbox> + <caption label="&mouseWheelHorizGroup.label;"/> + <radiogroup id="mousewheel_with_alt_action_x" + preference="mousewheel.with_alt.action.override_x" + onsyncfrompreference="document.getElementById('mousewheel_pane').doEnablingX(this);"> + <radio value="-1" label="&sameAsVertical.label;" accesskey="&sameAsVertical.accesskey;"/> + <radio value="0" label="&doNothing.label;" accesskey="&doNothingHoriz.accesskey;"/> + <radio value="1" label="&scrollDocument.label;" accesskey="&scrollDocumentHoriz.accesskey;"/> + <radio value="2" label="&history.label;" accesskey="&historyHoriz.accesskey;"/> + <radio value="3" label="&zoom.label;" accesskey="&zoomHoriz.accesskey;"/> + </radiogroup> + <hbox align="center"> + <label control="mousewheel_with_alt_delta_multiplier_x" + value="&wheelSpeed.label;"/> + <textbox type="number" min="-999999" max="999999" size="6" + id="mousewheel_with_alt_delta_multiplier_x" + accesskey="&wheelSpeedHoriz.accesskey;" + preference="mousewheel.with_alt.delta_multiplier_x" + onsyncfrompreference="document.getElementById('mousewheel_pane').updateCheckbox(this);"/> + <label value="%"/> + <checkbox label="&reverseDirection.label;" + accesskey="&reverseDirectionHoriz.accesskey;" + oncommand="updateTextbox(this);"/> + </hbox> + </groupbox> + </vbox> + + <!-- control modifiers --> + <vbox> + <groupbox> + <caption label="&mouseWheelGroup.label;"/> + <radiogroup id="mousewheel_with_control_action" + preference="mousewheel.with_control.action" + onsyncfrompreference="document.getElementById('mousewheel_pane').doEnabling(this);"> + <radio value="0" label="&doNothing.label;" accesskey="&doNothing.accesskey;"/> + <radio value="1" label="&scrollDocument.label;" accesskey="&scrollDocument.accesskey;"/> + <radio value="2" label="&history.label;" accesskey="&history.accesskey;"/> + <radio value="3" label="&zoom.label;" accesskey="&zoom.accesskey;"/> + </radiogroup> + <hbox align="center"> + <label control="mousewheel_with_control_delta_multiplier_y" + value="&wheelSpeed.label;"/> + <textbox type="number" min="-999999" max="999999" size="6" + id="mousewheel_with_control_delta_multiplier_y" + accesskey="&wheelSpeed.accesskey;" + preference="mousewheel.with_control.delta_multiplier_y" + onsyncfrompreference="document.getElementById('mousewheel_pane').updateCheckbox(this);"/> + <label value="%"/> + <checkbox label="&reverseDirection.label;" + accesskey="&reverseDirection.accesskey;" + oncommand="updateTextbox(this);"/> + </hbox> + </groupbox> + + <groupbox> + <caption label="&mouseWheelHorizGroup.label;"/> + <radiogroup id="mousewheel_with_control_action_x" + preference="mousewheel.with_control.action.override_x" + onsyncfrompreference="document.getElementById('mousewheel_pane').doEnablingX(this);"> + <radio value="-1" label="&sameAsVertical.label;" accesskey="&sameAsVertical.accesskey;"/> + <radio value="0" label="&doNothing.label;" accesskey="&doNothingHoriz.accesskey;"/> + <radio value="1" label="&scrollDocument.label;" accesskey="&scrollDocumentHoriz.accesskey;"/> + <radio value="2" label="&history.label;" accesskey="&historyHoriz.accesskey;"/> + <radio value="3" label="&zoom.label;" accesskey="&zoomHoriz.accesskey;"/> + </radiogroup> + <hbox align="center"> + <label control="mousewheel_with_control_delta_multiplier_x" + value="&wheelSpeed.label;"/> + <textbox type="number" min="-999999" max="999999" size="6" + id="mousewheel_with_control_delta_multiplier_x" + accesskey="&wheelSpeedHoriz.accesskey;" + preference="mousewheel.with_control.delta_multiplier_x" + onsyncfrompreference="document.getElementById('mousewheel_pane').updateCheckbox(this);"/> + <label value="%"/> + <checkbox label="&reverseDirection.label;" + accesskey="&reverseDirectionHoriz.accesskey;" + oncommand="updateTextbox(this);"/> + </hbox> + </groupbox> + </vbox> + + <!-- shift modifiers --> + <vbox> + <groupbox> + <caption label="&mouseWheelGroup.label;"/> + <radiogroup id="mousewheel_with_shift_action" + preference="mousewheel.with_shift.action" + onsyncfrompreference="document.getElementById('mousewheel_pane').doEnabling(this);"> + <radio value="0" label="&doNothing.label;" accesskey="&doNothing.accesskey;"/> + <radio value="1" label="&scrollDocument.label;" accesskey="&scrollDocument.accesskey;"/> + <radio value="2" label="&history.label;" accesskey="&history.accesskey;"/> + <radio value="3" label="&zoom.label;" accesskey="&zoom.accesskey;"/> + </radiogroup> + <hbox align="center"> + <label control="mousewheel_with_shift_delta_multiplier_y" + value="&wheelSpeed.label;"/> + <textbox type="number" min="-999999" max="999999" size="6" + id="mousewheel_with_shift_delta_multiplier_y" + accesskey="&wheelSpeed.accesskey;" + preference="mousewheel.with_shift.delta_multiplier_y" + onsyncfrompreference="document.getElementById('mousewheel_pane').updateCheckbox(this);"/> + <label value="%"/> + <checkbox label="&reverseDirection.label;" + accesskey="&reverseDirection.accesskey;" + oncommand="updateTextbox(this);"/> + </hbox> + </groupbox> + + <groupbox> + <caption label="&mouseWheelHorizGroup.label;"/> + <radiogroup id="mousewheel_with_shift_action_x" + preference="mousewheel.with_shift.action.override_x" + onsyncfrompreference="document.getElementById('mousewheel_pane').doEnablingX(this);"> + <radio value="-1" label="&sameAsVertical.label;" accesskey="&sameAsVertical.accesskey;"/> + <radio value="0" label="&doNothing.label;" accesskey="&doNothingHoriz.accesskey;"/> + <radio value="1" label="&scrollDocument.label;" accesskey="&scrollDocumentHoriz.accesskey;"/> + <radio value="2" label="&history.label;" accesskey="&historyHoriz.accesskey;"/> + <radio value="3" label="&zoom.label;" accesskey="&zoomHoriz.accesskey;"/> + </radiogroup> + <hbox align="center"> + <label control="mousewheel_with_shift_delta_multiplier_x" + value="&wheelSpeed.label;"/> + <textbox type="number" min="-999999" max="999999" size="6" + id="mousewheel_with_shift_delta_multiplier_x" + accesskey="&wheelSpeedHoriz.accesskey;" + preference="mousewheel.with_shift.delta_multiplier_x" + onsyncfrompreference="document.getElementById('mousewheel_pane').updateCheckbox(this);"/> + <label value="%"/> + <checkbox label="&reverseDirection.label;" + accesskey="&reverseDirectionHoriz.accesskey;" + oncommand="updateTextbox(this);"/> + </hbox> + </groupbox> + </vbox> + </tabpanels> + </tabbox> + </prefpane> +</overlay> diff --git a/comm/suite/components/pref/content/pref-navigator.js b/comm/suite/components/pref/content/pref-navigator.js new file mode 100644 index 0000000000..5ff271dc2b --- /dev/null +++ b/comm/suite/components/pref/content/pref-navigator.js @@ -0,0 +1,262 @@ +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const {ShellService} = ChromeUtils.import("resource:///modules/ShellService.jsm"); + +// The contents of this file will be loaded into the scope of the object +// <prefpane id="navigator_pane">! + +// platform integration +const PFINT_NOT_DEFAULT = 0; +const PFINT_DEFAULT = 1; +const PFINT_PENDING = 2; + + +// put "global" definitions here for easy reference +var gDefaultHomePage = ""; +var gHomePagePrefPeak = 0; +var gPreferences = null; + + +// <preferences> access helper methods +function GetHomePagePrefCount() +{ + return document.getElementById("browser.startup.homepage.count").value; +} + +function SetHomePagePrefCount(aCount) +{ + document.getElementById("browser.startup.homepage.count").value = aCount; +} + +function GetHomePagePrefName(aIndex) +{ + var prefname = "browser.startup.homepage"; + if (aIndex > 0) + prefname += "." + aIndex; + return prefname; +} + +function GetHomePagePref(aIndex) +{ + // return the <preference> at aIndex + return document.getElementById(GetHomePagePrefName(aIndex)); +} + +function AddHomePagePref(aIndex) +{ + // create new <preference> for aIndex + var pref = document.createElement("preference"); + var prefname = GetHomePagePrefName(aIndex); + pref.setAttribute("id", prefname); + pref.setAttribute("name", prefname); + pref.setAttribute("type", "wstring"); + gPreferences.appendChild(pref); + return pref; +} + +// homepage group textbox helper methods +function GetHomePageGroup() +{ + return document.getElementById("browserStartupHomepage").value; +} + +function SetHomePageValue(aValue) +{ + document.getElementById("browserStartupHomepage").value = aValue; +} + +// helper methods for reading current page URIs +function GetMostRecentBrowser() +{ + var browserWindow = Services.wm.getMostRecentWindow("navigator:browser"); + return browserWindow && browserWindow.getBrowser(); +} + +function GetCurrentPage() +{ + var tabbrowser = GetMostRecentBrowser(); + return tabbrowser && tabbrowser.currentURI.spec || ""; // ensure string +} + +function GetCurrentGroup() +{ + var uris = []; + var tabbrowser = GetMostRecentBrowser(); + if (tabbrowser) + { + var browsers = tabbrowser.browsers; + var browsersLen = browsers.length; + for (var i = 0; i < browsersLen; ++i) + uris[i] = browsers[i].currentURI.spec; + } + return uris.join("\n"); +} + +// synchronize button states with current input +function CanonifyURLList(aList) +{ + return (aList + "\n").replace(/\n+/g, "\n"); +} + +function UpdateHomePageButtons() +{ + var homePageGroup = CanonifyURLList(GetHomePageGroup()); + var currentPage = CanonifyURLList(GetCurrentPage()); + var currentGroup = CanonifyURLList(GetCurrentGroup()); + + // disable "current page" button if current page is already the homepage + var currentPageButton = document.getElementById("browserUseCurrent"); + currentPageButton.disabled = (homePageGroup == currentPage) || + (currentPage == "\n"); + + // disable "current group" button if current group already set or no group + var currentGroupButton = document.getElementById("browserUseCurrentGroup"); + currentGroupButton.disabled = (homePageGroup == currentGroup) || + (currentGroup == currentPage); + + // disable "restore" button if homepage hasn't changed + var restoreButton = document.getElementById("browserUseDefault"); + restoreButton.disabled = (homePageGroup == gDefaultHomePage); +} + +function UpdateHomePagePrefs() +{ + // update the list of <preference>s to the current settings + var newCount = 1; // current number of homepages + var homePageGroup = CanonifyURLList(GetHomePageGroup()).split("\n"); + GetHomePagePref(0).value = "about:blank"; // in case it's empty + if (homePageGroup[0]) + { + // we have at least one homepage + // (the last index is always empty due to canonification) + newCount = homePageGroup.length - 1 + for (var i = 0; i < newCount; ++i) + { + var pref = GetHomePagePref(i) || AddHomePagePref(i); + pref.value = homePageGroup[i]; + } + } + + // work around bug 410562: + // reset unneeded preferences on dialogaccept only + + // update pref count watermark before setting new number of homepages + var alreadyRequested = (gHomePagePrefPeak > 0); + var oldCount = GetHomePagePrefCount(); + if (gHomePagePrefPeak < oldCount) + gHomePagePrefPeak = oldCount; + SetHomePagePrefCount(newCount); + + var needCleanup = (newCount < gHomePagePrefPeak); + if (document.documentElement.instantApply) + { + // throw away unneeded preferences now + if (needCleanup) + HomePagePrefCleanup(); + } + else if (needCleanup != alreadyRequested) + { + // cleanup necessity changed + if (needCleanup) + { + // register OK handler for the capturing phase + window.addEventListener("dialogaccept", this.HomePagePrefCleanup, true); + } + else + { + // no cleanup necessary, remove OK handler + window.removeEventListener("dialogaccept", this.HomePagePrefCleanup, true); + } + } +} + +function HomePagePrefCleanup() +{ + // remove the old user prefs values that we didn't overwrite + var count = GetHomePagePrefCount(); + for (var j = count; j < gHomePagePrefPeak; ++j) + { + // clear <preference> + var pref = GetHomePagePref(j); + pref.valueFromPreferences = undefined; + pref.remove(); + } + gHomePagePrefPeak = 0; // cleanup done +} + +function UpdateHomePageListFromInput() +{ + UpdateHomePagePrefs(); + UpdateHomePageButtons(); +} + +function UpdateHomePageList(aSingleURL) +{ + // write single URL into input box and set it as the list of homepages + SetHomePageValue(aSingleURL); + UpdateHomePageListFromInput(); +} + +function SelectFile() +{ + let fp = Cc["@mozilla.org/filepicker;1"] + .createInstance(Ci.nsIFilePicker); + let title = document.getElementById("bundle_prefutilities") + .getString("choosehomepage"); + fp.init(window, title, Ci.nsIFilePicker.modeOpen); + fp.appendFilters(Ci.nsIFilePicker.filterAll | + Ci.nsIFilePicker.filterText | + Ci.nsIFilePicker.filterXML | + Ci.nsIFilePicker.filterHTML | + Ci.nsIFilePicker.filterImages); + + fp.open(rv => { + if (rv == Ci.nsIFilePicker.returnOK && fp.fileURL.spec && + fp.fileURL.spec.length > 0) { + UpdateHomePageList(fp.fileURL.spec); + } + }); +} + +function SetHomePageToCurrentPage() +{ + UpdateHomePageList(GetCurrentPage()); +} + +function SetHomePageToCurrentGroup() +{ + UpdateHomePageList(GetCurrentGroup()); +} + +function SetHomePageToDefaultPage() +{ + UpdateHomePageList(gDefaultHomePage); +} + +function Startup() +{ + // homepage groups can have an arbitrary number of <preference>s, + // except for the default (0), thus we create them manually here + gPreferences = document.getElementById("navigator_preferences"); + var count = GetHomePagePrefCount(); + var homePageGroup = GetHomePagePref(0).value + "\n"; + for (var i = 1; i < count; ++i) + homePageGroup += AddHomePagePref(i).value + "\n"; + gDefaultHomePage = CanonifyURLList(GetHomePagePref(0).defaultValue); + SetHomePageValue(homePageGroup); + UpdateHomePageButtons(); +} + +function SwitchPage(aIndex) +{ + document.getElementById("behaviourDeck").selectedIndex = aIndex; +} + +function WriteConcurrentTabs() +{ + var val = document.getElementById("maxConcurrentTabsGroup").value; + return val > 0 ? document.getElementById("maxConcurrentTabs").value : val; +} diff --git a/comm/suite/components/pref/content/pref-navigator.xul b/comm/suite/components/pref/content/pref-navigator.xul new file mode 100644 index 0000000000..2b9888419f --- /dev/null +++ b/comm/suite/components/pref/content/pref-navigator.xul @@ -0,0 +1,188 @@ +<?xml version="1.0"?> + +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<!DOCTYPE overlay [ + <!ENTITY % navigatorDTD SYSTEM "chrome://communicator/locale/pref/pref-navigator.dtd"> %navigatorDTD; +]> + +<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <prefpane id="navigator_pane" + label="&pref.navigator.title;" + script="chrome://communicator/content/pref/pref-navigator.js"> + + <preferences id="navigator_preferences"> + <preference id="browser.startup.page" + name="browser.startup.page" + type="int"/> + <preference id="browser.windows.loadOnNewWindow" + name="browser.windows.loadOnNewWindow" + type="int"/> + <preference id="browser.tabs.loadOnNewTab" + name="browser.tabs.loadOnNewTab" + type="int"/> + <preference id="browser.startup.homepage" + name="browser.startup.homepage" + type="wstring"/> + <preference id="browser.startup.homepage.count" + name="browser.startup.homepage.count" + type="int"/> + <preference id="browser.sessionstore.max_concurrent_tabs" + name="browser.sessionstore.max_concurrent_tabs" + type="int"/> + <preference id="browser.chrome.site_icons" + name="browser.chrome.site_icons" + type="bool"/> + <preference id="browser.chrome.favicons" + name="browser.chrome.favicons" + type="bool"/> + <preference id="pref.browser.homepage.disable_button.select_file" + name="pref.browser.homepage.disable_button.select_file" + type="bool"/> + <preference id="pref.browser.homepage.disable_button.current_page" + name="pref.browser.homepage.disable_button.current_page" + type="bool"/> + <preference id="pref.browser.homepage.disable_button.current_group" + name="pref.browser.homepage.disable_button.current_group" + type="bool"/> + <preference id="pref.browser.homepage.disable_button.default_page" + name="pref.browser.homepage.disable_button.default_page" + type="bool"/> + </preferences> + + <hbox> + <!-- navigator startup / new window / new tab behaviour --> + <groupbox flex="1"> + <caption align="center"> + <label value="&navRadio.label;" + accesskey="&navRadio.accesskey;" + control="selectDisplayOn"/> + <menulist id="selectDisplayOn" + oncommand="SwitchPage(this.selectedIndex);"> + <menupopup> + <menuitem label="&navStartPageMenu.label;"/> + <menuitem label="&newWinPageMenu.label;"/> + <menuitem label="&newTabPageMenu.label;"/> + </menupopup> + </menulist> + </caption> + <deck id="behaviourDeck" flex="1"> + <radiogroup id="startupPage" preference="browser.startup.page"> + <radio value="0" + label="&blankPageRadio.label;" + accesskey="&blankPageRadio.accesskey;"/> + <radio value="1" + label="&homePageRadio.label;" + accesskey="&homePageRadio.accesskey;"/> + <radio value="2" + label="&lastPageRadio.label;" + accesskey="&lastPageRadio.accesskey;"/> + <radio value="3" + label="&restoreSessionRadio.label;" + accesskey="&restoreSessionRadio.accesskey;"/> + </radiogroup> + <radiogroup id="newWinPage" + preference="browser.windows.loadOnNewWindow"> + <radio value="0" + label="&blankPageRadio.label;" + accesskey="&blankPageRadio.accesskey;"/> + <radio value="1" + label="&homePageRadio.label;" + accesskey="&homePageRadio.accesskey;"/> + <radio value="2" + label="&lastPageRadio.label;" + accesskey="&lastPageRadio.accesskey;"/> + </radiogroup> + <radiogroup id="newTabPage" preference="browser.tabs.loadOnNewTab"> + <radio value="0" + label="&blankPageRadio.label;" + accesskey="&blankPageRadio.accesskey;"/> + <radio value="1" + label="&homePageRadio.label;" + accesskey="&homePageRadio.accesskey;"/> + <radio value="2" + label="&lastPageRadio.label;" + accesskey="&lastPageRadio.accesskey;"/> + </radiogroup> + </deck> + </groupbox> + + <!-- session restore background tabs --> + <groupbox flex="1"> + <caption label="&restoreSessionIntro.label;"/> + <radiogroup id="maxConcurrentTabsGroup" + align="start" + preference="browser.sessionstore.max_concurrent_tabs" + onsyncfrompreference="var val = document.getElementById(this.getAttribute('preference')).value; return val > 0 ? 3 : val;" + onsynctopreference="return document.getElementById('navigator_pane').WriteConcurrentTabs();"> + <radio value="-1" + label="&restoreImmediately.label;" + accesskey="&restoreImmediately.accesskey;"/> + <hbox align="center"> + <radio id="restoreTabs" + value="3" + onclick="this.nextSibling.focus();" + label="&restoreTabs.label;" + accesskey="&restoreTabs.accesskey;"/> + <textbox id="maxConcurrentTabs" + type="number" + size="2" + min="1" + value="3" + aria-labelledby="restoreTabs maxConcurrentTabs restoreTabsAtATime" + preference="browser.sessionstore.max_concurrent_tabs" + onsyncfrompreference="var pref = document.getElementById(this.getAttribute('preference')); var val = pref.value; var valid = val > 0; this.disabled = pref.locked || !valid; return valid ? val : this.value;" + onsynctopreference="return document.getElementById('navigator_pane').WriteConcurrentTabs();"/> + <label id="restoreTabsAtATime" value="&restoreTabsAtATime.label;"> + <observes element="maxConcurrentTabsGroup" attribute="disabled"/> + </label> + </hbox> + <radio value="0" + label="&restoreDeferred.label;" + accesskey="&restoreDeferred.accesskey;"/> + </radiogroup> + </groupbox> + </hbox> + + <groupbox id="siteIconPreferences"> + <caption label="&siteIcons.label;"/> + + <checkbox id="useSiteIcons" + label="&useSiteIcons.label;" + accesskey="&useSiteIcons.accesskey;" + preference="browser.chrome.site_icons"/> + <checkbox id="useFavIcons" + label="&useFavIcons.label;" + accesskey="&useFavIcons.accesskey;" + preference="browser.chrome.favicons"/> + </groupbox> + + <!-- homepage specification --> + <description>&homePageIntro.label;</description> + <hbox> + <textbox id="browserStartupHomepage" class="uri-element" flex="1" + multiline="true" wrap="off" timeout="500" + oninput="UpdateHomePageListFromInput();"/> + <vbox> + <button label="&browseFile.label;" accesskey="&browseFile.accesskey;" + oncommand="SelectFile();" + id="browserChooseFile" + preference="pref.browser.homepage.disable_button.select_file"/> + <button label="&useCurrent.label;" accesskey="&useCurrent.accesskey;" + oncommand="SetHomePageToCurrentPage();" + id="browserUseCurrent" + preference="pref.browser.homepage.disable_button.current_page"/> + <button label="&useCurrentGroup.label;" accesskey="&useCurrentGroup.accesskey;" + oncommand="SetHomePageToCurrentGroup();" + id="browserUseCurrentGroup" + preference="pref.browser.homepage.disable_button.current_group"/> + <button label="&useDefault.label;" accesskey="&useDefault.accesskey;" + oncommand="SetHomePageToDefaultPage();" + id="browserUseDefault" + preference="pref.browser.homepage.disable_button.default_page"/> + </vbox> + </hbox> + </prefpane> +</overlay> diff --git a/comm/suite/components/pref/content/pref-offlineapps.js b/comm/suite/components/pref/content/pref-offlineapps.js new file mode 100644 index 0000000000..db7c44cb81 --- /dev/null +++ b/comm/suite/components/pref/content/pref-offlineapps.js @@ -0,0 +1,178 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const {DownloadUtils} = ChromeUtils.import("resource://gre/modules/DownloadUtils.jsm"); +var {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm"); + +function Startup() +{ + OfflineAppsObserver.init(); + + let always = document.getElementById("offline-apps.allow_by_default").value; + UpdateNotifyBox(always); +} + +var OfflineAppsObserver = { + + init: function offlineAppsInit() { + this.update(); + Services.obs.addObserver(this, "perm-changed"); + window.addEventListener("unload", this); + }, + + update: function offlineAppsUpdate() { + UpdateActualCacheSize(); + UpdateOfflineApps(); + }, + + observe: function offlineAppsObserve(aSubject, aTopic, aData) { + if (aTopic == "perm-changed") + this.update(); + }, + + handleEvent: function offlineAppsEvent(aEvent) { + if (aEvent.type == "unload") { + window.removeEventListener("unload", this); + Services.obs.removeObserver(this, "perm-changed"); + } + } +} + +function UpdateActualCacheSize() +{ + var visitor = { + onCacheStorageInfo: function(aEntryCount, aTotalSize) + { + let actualSizeLabel = document.getElementById("offlineAppSizeInfo"); + let sizeStrings = DownloadUtils.convertByteUnits(aTotalSize); + let bundle = document.getElementById("bundle_prefutilities"); + let sizeStr = bundle.getFormattedString("offlineAppSizeInfo", + sizeStrings); + actualSizeLabel.textContent = sizeStr; + }, + + onCacheEntryInfo: function(entryInfo) + { + }, + + onCacheEntryVisitCompleted: function() + { + } + }; + + Services.cache2.appCacheStorage(Services.loadContextInfo.default, null) + .asyncVisitStorage(visitor, false); +} + +/** + * Clears the application cache. + */ +var callback = { + onCacheEntryDoomed: function(aResult) { + UpdateActualCacheSize(); + UpdateOfflineApps(); + } +}; + +function ClearOfflineAppCache() +{ + try { + Services.cache2.appCacheStorage(Services.loadContextInfo.default, null) + .asyncEvictStorage(callback); + } catch(ex) {} +} + +function UpdateNotifyBox(aValue) +{ + EnableElementById("offlineNotifyAsk", !aValue); + + // remove this once bug 934457 and bug 1024832 are fixed + document.getElementById("offlineNotifyPermissions").disabled = aValue; +} + +function _getOfflineAppUsage(aPermission) +{ + var appCache = Cc["@mozilla.org/network/application-cache-service;1"] + .getService(Ci.nsIApplicationCacheService); + var groups = appCache.getGroups(); + + var usage = 0; + for (let i = 0; i < groups.length; i++) { + let uri = Services.io.newURI(groups[i]); + if (aPermission.matchesURI(uri, true)) + usage += appCache.getActiveCache(groups[i]).usage; + } + return usage; +} + +/** + * Updates the list of offline applications. + */ +function UpdateOfflineApps() +{ + var list = document.getElementById("offlineAppsList"); + while (list.hasChildNodes()) + list.lastChild.remove(); + + var bundle = document.getElementById("bundle_prefutilities"); + var pm = Services.perms; + var enumerator = pm.enumerator; + + while (enumerator.hasMoreElements()) { + let perm = enumerator.getNext() + .QueryInterface(Ci.nsIPermission); + if (perm.type != "offline-app" || + perm.capability != pm.ALLOW_ACTION) + continue; + + let usage = _getOfflineAppUsage(perm); + let row = document.createElement("listitem"); + row.setAttribute("host", perm.principal.URI.host); + let converted = DownloadUtils.convertByteUnits(usage); + row.setAttribute("usage", bundle.getFormattedString("offlineAppUsage", + converted)); + list.appendChild(row); + } +} + +function OfflineAppSelected(aList) +{ + document.getElementById("offlineAppsListRemove") + .setAttribute("disabled", !aList.selectedItem); +} + +function RemoveOfflineApp() +{ + var list = document.getElementById("offlineAppsList"); + var item = list.selectedItem; + var host = item.getAttribute("host"); + + var flags = Services.prompt.BUTTON_TITLE_IS_STRING * Services.prompt.BUTTON_POS_0 + + Services.prompt.BUTTON_TITLE_CANCEL * Services.prompt.BUTTON_POS_1; + + var bundle = document.getElementById("bundle_prefutilities"); + var title = bundle.getString("offlineAppRemoveTitle"); + var prompt = bundle.getFormattedString("offlineAppRemovePrompt", [host]); + var confirm = bundle.getString("offlineAppRemoveConfirm"); + if (Services.prompt.confirmEx(window, title, prompt, flags, confirm, + null, null, null, {})) + return; + + // clear offline cache entries + var appCache = Cc["@mozilla.org/network/application-cache-service;1"] + .getService(Ci.nsIApplicationCacheService); + var groups = appCache.getGroups(); + for (let i = 0; i < groups.length; i++) { + var uri = Services.io.newURI(groups[i]); + if (uri.asciiHost == host) + appCache.getActiveCache(groups[i]).discard(); + } + + // remove the permission + // Services.perms.remove(host, "offline-app"); + + UpdateOfflineApps(); + OfflineAppSelected(list); + UpdateActualCacheSize(); +} diff --git a/comm/suite/components/pref/content/pref-offlineapps.xul b/comm/suite/components/pref/content/pref-offlineapps.xul new file mode 100644 index 0000000000..d12a26c808 --- /dev/null +++ b/comm/suite/components/pref/content/pref-offlineapps.xul @@ -0,0 +1,81 @@ +<?xml version="1.0"?> +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this file, + - You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<!DOCTYPE overlay [ + <!ENTITY % prefOfflineCacheDTD SYSTEM "chrome://communicator/locale/pref/pref-offlineapps.dtd"> + %prefOfflineCacheDTD; +]> + +<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <prefpane id="offlineapps_pane" + label="&pref.offlineapps.title;" + script="chrome://communicator/content/pref/pref-offlineapps.js"> + + <preferences> + <preference id="offline-apps.allow_by_default" + name="offline-apps.allow_by_default" + type="bool" + onchange="UpdateNotifyBox(this.value);"/> + <preference id="browser.offline-apps.notify" + name="browser.offline-apps.notify" + type="bool"/> + </preferences> + + <groupbox id="offlineGroup" flex="1"> + <caption label="&pref.offlineCache.caption;"/> + + <hbox align="center"> + <label id="offlineAppSizeInfo" flex="1"/> + <button id="clearOfflineAppCache" + icon="clear" + label="&clearOfflineAppCache.label;" + accesskey="&clearOfflineAppCache.accesskey;" + oncommand="ClearOfflineAppCache();"/> + </hbox> + <radiogroup id="offlineDefault" + preference="offline-apps.allow_by_default"> + <radio id="offlineAlwaysAllow" + value="true" + label="&offlineAlwaysAllow.label;" + accesskey="&offlineAlwaysAllow.accesskey;"/> + <hbox align="center"> + <radio id="offlineExplicit" + flex="1" + value="false" + label="&offlineExplicit.label;" + accesskey="&offlineExplicit.accesskey;"/> + <button id="offlineNotifyPermissions" + label="&offlineNotifyPermissions.label;" + accesskey="&offlineNotifyPermissions.accesskey;" + oncommand="toDataManager('|permissions');"/> + </hbox> + </radiogroup> + <checkbox id="offlineNotifyAsk" + class="indent" + label="&offlineNotifyAsk.label;" + accesskey="&offlineNotifyAsk.accesskey;" + preference="browser.offline-apps.notify"/> + <separator class="thin"/> + <hbox flex="1"> + <vbox flex="1"> + <label id="offlineAppsListLabel">&offlineAppsUsage.label;</label> + <listbox id="offlineAppsList" + flex="1" + aria-labelledby="offlineAppsListLabel" + onselect="OfflineAppSelected(this);"> + </listbox> + </vbox> + <vbox pack="end"> + <button id="offlineAppsListRemove" + disabled="true" + label="&offlineAppsListRemove.label;" + accesskey="&offlineAppsListRemove.accesskey;" + oncommand="RemoveOfflineApp();"/> + </vbox> + </hbox> + </groupbox> + + </prefpane> +</overlay> diff --git a/comm/suite/components/pref/content/pref-popups.js b/comm/suite/components/pref/content/pref-popups.js new file mode 100644 index 0000000000..dc8a2b42c2 --- /dev/null +++ b/comm/suite/components/pref/content/pref-popups.js @@ -0,0 +1,95 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public +* License, v. 2.0. If a copy of the MPL was not distributed with this +* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +var gSoundUrlPref; + +function Startup() +{ + gSoundUrlPref = document.getElementById("privacy.popups.sound_url"); + + SetLists(); + + SetButtons(); +} + +function SetLists() +{ + const kPopupType = "popup"; + + var pref = document.getElementById("privacy.popups.remove_blacklist"); + if (pref.value) + { + var enumerator = Services.perms.enumerator; + var uris = []; + + while (enumerator.hasMoreElements()) + { + var permission = enumerator.getNext(); + if (permission instanceof Ci.nsIPermission) + { + if ((permission.type == kPopupType) && + (permission.capability == Ci.nsIPermissionManager.DENY_ACTION)) + uris.push(permission.principal.URI); + } + } + + for (var i in uris) + Services.perms.remove(uris[i], kPopupType); + + pref.value = false; + } + + pref = document.getElementById("privacy.popups.prefill_whitelist"); + if (pref.value) + { + try + { + var whitelist = document.getElementById("privacy.popups.default_whitelist").value; + var hosts = whitelist.split(","); + + for (var i in hosts) + { + var host = "http://" + hosts[i]; + var uri = Services.io.newURI(host); + Services.perms.add(uri, kPopupType, true); + } + } + catch (ex) {} + + pref.value = false; + } +} + +function SetButtons() +{ + var prefString = document.getElementById("popupPolicy") + .getAttribute("preference"); + var enable = document.getElementById(prefString).value; + EnableElementById("exceptionsButton", enable, false); + EnableElementById("displayIcon", enable, false); + EnableElementById("displayPopupsNotification", enable, false); + + var element = document.getElementById("playSound"); + EnableElement(element, enable, false); + + prefString = element.getAttribute("preference"); + EnableSoundRadio(enable && document.getElementById(prefString).value); +} + +function EnableSoundRadio(aSoundChecked) +{ + const kCustomSound = 1; + + var element = document.getElementById("popupSoundType"); + EnableElement(element, aSoundChecked, false); + var pref = document.getElementById(element.getAttribute("preference")); + EnableSoundUrl(aSoundChecked && (pref.value == kCustomSound)); +} + +function EnableSoundUrl(aCustomSelected) +{ + EnableElementById("playSoundUrl", aCustomSelected, false); + EnableElementById("selectSound", aCustomSelected, false); + EnableElementById("playSoundButton", aCustomSelected, false); +} diff --git a/comm/suite/components/pref/content/pref-popups.xul b/comm/suite/components/pref/content/pref-popups.xul new file mode 100644 index 0000000000..78f7a75e57 --- /dev/null +++ b/comm/suite/components/pref/content/pref-popups.xul @@ -0,0 +1,132 @@ +<?xml version="1.0"?> + +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<!DOCTYPE overlay [ +<!ENTITY % prefPopupsDTD SYSTEM "chrome://communicator/locale/pref/pref-popups.dtd"> +%prefPopupsDTD; +]> + +<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <prefpane id="popups_pane" + label="&pref.popups.title;" + script="chrome://communicator/content/pref/pref-popups.js"> + <preferences id="popups_preferences"> + <preference id="dom.disable_open_during_load" + name="dom.disable_open_during_load" + type="bool" + onchange="SetButtons();"/> + <preference id="pref.advanced.popups.disable_button.view_popups" + name="pref.advanced.popups.disable_button.view_popups" + type="bool"/> + <preference id="privacy.popups.sound_enabled" + name="privacy.popups.sound_enabled" + type="bool" + onchange="EnableSoundRadio(this.value);"/> + <preference id="privacy.popups.sound_type" + name="privacy.popups.sound_type" + type="int" + onchange="EnableSoundUrl(this.value == 1);"/> + <preference id="privacy.popups.sound_url" + name="privacy.popups.sound_url" + type="string" + onchange="EnableElementById('previewSound', true, false);"/> + <preference id="pref.advanced.popups.disable_button.select_sound" + name="pref.advanced.popups.disable_button.select_sound" + type="bool"/> + <preference id="pref.advanced.popups.disable_button.preview_sound" + name="pref.advanced.popups.disable_button.preview_sound" + type="bool"/> + <preference id="privacy.popups.statusbar_icon_enabled" + name="privacy.popups.statusbar_icon_enabled" + type="bool"/> + <preference id="privacy.popups.showBrowserMessage" + name="privacy.popups.showBrowserMessage" + type="bool"/> + <preference id="privacy.popups.prefill_whitelist" + name="privacy.popups.prefill_whitelist" + type="bool"/> + <preference id="privacy.popups.remove_blacklist" + name="privacy.popups.remove_blacklist" + type="bool"/> + <preference id="privacy.popups.default_whitelist" + name="privacy.popups.default_whitelist" + type="string"/> + </preferences> + + <groupbox id="popupsArea"> + <caption label="&pref.popups.caption;"/> + + <hbox> + <checkbox id="popupPolicy" + label="&popupBlock.label;" + accesskey="&popupBlock.accesskey;" + preference="dom.disable_open_during_load"/> + <spacer flex="1"/> + <button id="exceptionsButton" + label="&viewPermissions.label;" + accesskey="&viewPermissions.accesskey;" + preference="pref.advanced.popups.disable_button.view_popups" + oncommand="toDataManager('|permissions');"/> + </hbox> + <separator class="thin"/> + <description id="whenBlock">&whenBlock.description;</description> + <hbox> + <checkbox id="playSound" + label="&playSound.label;" + accesskey="&playSound.accesskey;" + preference="privacy.popups.sound_enabled"/> + </hbox> + <hbox class="indent"> + <radiogroup id="popupSoundType" + preference="privacy.popups.sound_type" + aria-labelledby="playSound"> + <radio id="popupSystemSound" + class="iconic" + value="0" + label="&systemSound.label;" + accesskey="&systemSound.accesskey;"/> + <radio id="popupCustomSound" + class="iconic" + value="1" + label="&customSound.label;" + accesskey="&customSound.accesskey;"/> + </radiogroup> + </hbox> + <hbox class="indent"> + <filefield id="playSoundUrl" + flex="1" + preference="privacy.popups.sound_url" + preference-editable="true" + onsyncfrompreference="return WriteSoundField(this, document.getElementById('popups_pane').gSoundUrlPref.value);" + aria-labelledby="popupCustomSound"/> + <button id="selectSound" + label="&selectSound.label;" + accesskey="&selectSound.accesskey;" + preference="pref.advanced.popups.disable_button.select_sound" + oncommand="SelectSound(gSoundUrlPref);"/> + <button id="playSoundButton" + label="&playSoundButton.label;" + accesskey="&playSoundButton.accesskey;" + preference="pref.advanced.popups.disable_button.preview_sound" + oncommand="PlaySound(gSoundUrlPref.value, false);"/> + </hbox> + <hbox> + <checkbox id="displayIcon" + label="&displayIcon.label;" + accesskey="&displayIcon.accesskey;" + preference="privacy.popups.statusbar_icon_enabled"/> + </hbox> + <hbox> + <checkbox id="displayPopupsNotification" + label="&displayNotification.label;" + accesskey="&displayNotification.accesskey;" + preference="privacy.popups.showBrowserMessage"/> + </hbox> + <separator class="thin"/> + <description>&popupNote.description;</description> + </groupbox> + </prefpane> +</overlay> diff --git a/comm/suite/components/pref/content/pref-privatedata.js b/comm/suite/components/pref/content/pref-privatedata.js new file mode 100644 index 0000000000..ba7305bc41 --- /dev/null +++ b/comm/suite/components/pref/content/pref-privatedata.js @@ -0,0 +1,30 @@ +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +function Startup() { + let pref = document.getElementById("privacy.sanitize.sanitizeOnShutdown"); + updateClearOnShutdownBox(pref.valueFromPreferences); +} + +/** + * Disable/enable clear on shutdown items in dialog depending on general pref + * to clear on shutdown. + */ +function updateClearOnShutdownBox(aDisable) { + let clearOnShutdownBox = document.getElementById("clearOnShutdownBox"); + for (let childNode of clearOnShutdownBox.childNodes) { + childNode.disabled = !aDisable; + } +} + +/** + * Displays a dialog from which individual parts of private data may be + * cleared. + */ +function clearPrivateDataNow() { + Cc["@mozilla.org/suite/suiteglue;1"] + .getService(Ci.nsISuiteGlue) + .sanitize(window); +} diff --git a/comm/suite/components/pref/content/pref-privatedata.xul b/comm/suite/components/pref/content/pref-privatedata.xul new file mode 100644 index 0000000000..97e236def8 --- /dev/null +++ b/comm/suite/components/pref/content/pref-privatedata.xul @@ -0,0 +1,181 @@ +<?xml version="1.0"?> + +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<!DOCTYPE overlay [ + <!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd"> + %brandDTD; + <!ENTITY % prefPrivateDataDTD SYSTEM "chrome://communicator/locale/pref/pref-privatedata.dtd"> + %prefPrivateDataDTD; + <!ENTITY % prefSanitizeDTD SYSTEM "chrome://communicator/locale/sanitize.dtd"> + %prefSanitizeDTD; +]> + +<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <prefpane id="privatedata_pane" label="&pref.privatedata.title;" + script="chrome://communicator/content/pref/pref-privatedata.js"> + <preferences id="privatedata_preferences"> + <!-- Clear Private Data --> + <preference id="privacy.sanitize.sanitizeOnShutdown" + name="privacy.sanitize.sanitizeOnShutdown" + type="bool" + onchange="updateClearOnShutdownBox(this.value);"/> + <!-- Clear Private Data on shutdown --> + <preference id="privacy.clearOnShutdown.history" + name="privacy.clearOnShutdown.history" + type="bool"/> + <preference id="privacy.clearOnShutdown.urlbar" + name="privacy.clearOnShutdown.urlbar" + type="bool"/> + <preference id="privacy.clearOnShutdown.formdata" + name="privacy.clearOnShutdown.formdata" + type="bool"/> + <preference id="privacy.clearOnShutdown.passwords" + name="privacy.clearOnShutdown.passwords" + type="bool"/> + <preference id="privacy.clearOnShutdown.downloads" + name="privacy.clearOnShutdown.downloads" + type="bool"/> + <preference id="privacy.clearOnShutdown.cookies" + name="privacy.clearOnShutdown.cookies" + type="bool"/> + <preference id="privacy.clearOnShutdown.cache" + name="privacy.clearOnShutdown.cache" + type="bool"/> + <preference id="privacy.clearOnShutdown.offlineApps" + name="privacy.clearOnShutdown.offlineApps" + type="bool"/> + <preference id="privacy.clearOnShutdown.sessions" + name="privacy.clearOnShutdown.sessions" + type="bool"/> + <preference id="privacy.clearOnShutdown.siteSettings" + name="privacy.clearOnShutdown.siteSettings" + type="bool"/> + + <!-- Clear Private Data manually --> + <preference id="privacy.cpd.history" + name="privacy.cpd.history" + type="bool"/> + <preference id="privacy.cpd.urlbar" + name="privacy.cpd.urlbar" + type="bool"/> + <preference id="privacy.cpd.formdata" + name="privacy.cpd.formdata" + type="bool"/> + <preference id="privacy.cpd.passwords" + name="privacy.cpd.passwords" + type="bool"/> + <preference id="privacy.cpd.downloads" + name="privacy.cpd.downloads" + type="bool"/> + <preference id="privacy.cpd.cookies" + name="privacy.cpd.cookies" + type="bool"/> + <preference id="privacy.cpd.cache" + name="privacy.cpd.cache" + type="bool"/> + <preference id="privacy.cpd.offlineApps" + name="privacy.cpd.offlineApps" + type="bool"/> + <preference id="privacy.cpd.sessions" + name="privacy.cpd.sessions" + type="bool"/> + <preference id="privacy.cpd.siteSettings" + name="privacy.cpd.siteSettings" + type="bool"/> + </preferences> + + <!-- Clear Private Data --> + <groupbox id="clearPrivateDataGroup"> + <caption label="&clearPrivateData.label;"/> + <button id="clearDataNow" icon="clear" + label="&clearDataDialog.label;" + accesskey="&clearDataDialog.accesskey;" + oncommand="clearPrivateDataNow();"/> + <separator class="thin" /> + <hbox id="clearDataBox" align="center"> + <checkbox id="alwaysClear" flex="1" + label="&alwaysClear.label;" + accesskey="&alwaysClear.accesskey;" + preference="privacy.sanitize.sanitizeOnShutdown"/> + </hbox> + + <separator class="thin"/> + + <label id="clearDataSettings" + value="&clearData.label;"/> + + <hbox> + <groupbox id="clearCpdBox" flex="1"> + <caption label="&clearData.cpd.label;"/> + <checkbox label="&itemHistory.label;" + accesskey="&itemHistory.accesskey;" + preference="privacy.cpd.history"/> + <checkbox label="&itemUrlBar.label;" + accesskey="&itemUrlBar.accesskey;" + preference="privacy.cpd.urlbar"/> + <checkbox label="&itemDownloads.label;" + accesskey="&itemDownloads.accesskey;" + preference="privacy.cpd.downloads"/> + <checkbox label="&itemFormSearchHistory.label;" + accesskey="&itemFormSearchHistory.accesskey;" + preference="privacy.cpd.formdata"/> + <checkbox label="&itemCache.label;" + accesskey="&itemCache.accesskey;" + preference="privacy.cpd.cache"/> + <checkbox label="&itemCookies.label;" + accesskey="&itemCookies.accesskey;" + preference="privacy.cpd.cookies"/> + <checkbox label="&itemOfflineApps.label;" + accesskey="&itemOfflineApps.accesskey;" + preference="privacy.cpd.offlineApps"/> + <checkbox label="&itemPasswords.label;" + accesskey="&itemPasswords.accesskey;" + preference="privacy.cpd.passwords"/> + <checkbox label="&itemSessions.label;" + accesskey="&itemSessions.accesskey;" + preference="privacy.cpd.sessions"/> + <checkbox label="&itemSitePreferences.label;" + accesskey="&itemSitePreferences.accesskey;" + preference="privacy.cpd.siteSettings"/> + </groupbox> + + <groupbox id="clearOnShutdownBox" flex="1"> + <caption label="&clearData.onShutdown.label;"/> + <checkbox label="&itemHistory.label;" + accesskey="&itemHistoryS.accesskey;" + preference="privacy.clearOnShutdown.history"/> + <checkbox label="&itemUrlBar.label;" + accesskey="&itemUrlBarS.accesskey;" + preference="privacy.clearOnShutdown.urlbar"/> + <checkbox label="&itemDownloads.label;" + accesskey="&itemDownloadsS.accesskey;" + preference="privacy.clearOnShutdown.downloads"/> + <checkbox label="&itemFormSearchHistory.label;" + accesskey="&itemFormSearchHistoryS.accesskey;" + preference="privacy.clearOnShutdown.formdata"/> + <checkbox label="&itemCache.label;" + accesskey="&itemCacheS.accesskey;" + preference="privacy.clearOnShutdown.cache"/> + <checkbox label="&itemCookies.label;" + accesskey="&itemCookiesS.accesskey;" + preference="privacy.clearOnShutdown.cookies"/> + <checkbox label="&itemOfflineApps.label;" + accesskey="&itemOfflineAppsS.accesskey;" + preference="privacy.clearOnShutdown.offlineApps"/> + <checkbox label="&itemPasswords.label;" + accesskey="&itemPasswordsS.accesskey;" + preference="privacy.clearOnShutdown.passwords"/> + <checkbox label="&itemSessions.label;" + accesskey="&itemSessionsS.accesskey;" + preference="privacy.clearOnShutdown.sessions"/> + <checkbox label="&itemSitePreferences.label;" + accesskey="&itemSitePreferencesS.accesskey;" + preference="privacy.clearOnShutdown.siteSettings"/> + </groupbox> + </hbox> + </groupbox> + </prefpane> +</overlay> diff --git a/comm/suite/components/pref/content/pref-proxies-advanced.xul b/comm/suite/components/pref/content/pref-proxies-advanced.xul new file mode 100644 index 0000000000..69313f80e7 --- /dev/null +++ b/comm/suite/components/pref/content/pref-proxies-advanced.xul @@ -0,0 +1,194 @@ +<?xml version="1.0"?> +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<?xml-stylesheet href="chrome://communicator/skin/" type="text/css"?> + +<!DOCTYPE prefwindow SYSTEM "chrome://communicator/locale/pref/pref-proxies-advanced.dtd" > + +<prefwindow xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + id="advancedProxyPreferences" + type="child" + onload="AdvancedInit();" + title="&pref.proxies.advanced.title;" + persist="screenX screenY"> + + <script src="chrome://communicator/content/pref/pref-proxies.js"/> + <script src="chrome://communicator/content/pref/preferences.js"/> + + <prefpane helpTopic="nav-prefs-advanced-proxy-advanced" + helpURI="chrome://communicator/locale/help/suitehelp.rdf"> + <preferences> + <preference id="network.proxy.http" + name="network.proxy.http" + type="string" + onchange="DoProxyHostCopy(this.value);"/> + <preference id="network.proxy.http_port" + name="network.proxy.http_port" + type="int" + onchange="DoProxyPortCopy(this.value);"/> + <preference id="network.proxy.ssl" + name="network.proxy.ssl" + type="string"/> + <preference id="network.proxy.ssl_port" + name="network.proxy.ssl_port" + type="int"/> + <preference id="network.proxy.ftp" + name="network.proxy.ftp" + type="string"/> + <preference id="network.proxy.ftp_port" + name="network.proxy.ftp_port" + type="int"/> + <preference id="network.proxy.share_proxy_settings" + name="network.proxy.share_proxy_settings" + type="bool" + onchange="DoProxyCopy(this.value);"/> + <preference id="network.proxy.socks" + name="network.proxy.socks" + type="string"/> + <preference id="network.proxy.socks_port" + name="network.proxy.socks_port" + type="int"/> + <preference id="network.proxy.socks_version" + name="network.proxy.socks_version" + type="int"/> + <preference id="network.proxy.socks_remote_dns" + name="network.proxy.socks_remote_dns" + type="bool"/> + </preferences> + + <groupbox> + <caption label="&protocols.caption;"/> + <description style="width: 1px;">&protocols.description;</description> + + <grid> + <columns> + <column/> + <column flex="1"/> + </columns> + + <rows> + <row> + <hbox align="center" pack="end"> + <label value="&http.label;" + accesskey="&http.accesskey;" + control="networkProxyHTTP"/> + </hbox> + <hbox align="center"> + <textbox id="networkProxyHTTP" + preference="network.proxy.http" + flex="1" + class="uri-element"/> + <label value="&port.label;" + accesskey="&HTTPPort.accesskey;" + control="networkProxyHTTP_Port"/> + <textbox id="networkProxyHTTP_Port" + preference="network.proxy.http_port" + type="number" + max="65535" + size="5"/> + </hbox> + </row> + + <row> + <spacer/> + <hbox> + <checkbox id="networkProxyShareSettings" + label="&reuseProxy.label;" + accesskey="&reuseProxy.accesskey;" + preference="network.proxy.share_proxy_settings"/> + </hbox> + </row> + + <row> + <hbox align="center" pack="end"> + <label value="&ssl.label;" + accesskey="&ssl.accesskey;" + control="networkProxySSL"/> + </hbox> + <hbox align="center"> + <textbox id="networkProxySSL" + preference="network.proxy.ssl" + flex="1" + class="uri-element"/> + <label value="&port.label;" + accesskey="&SSLPort.accesskey;" + control="networkProxySSL_Port"/> + <textbox id="networkProxySSL_Port" + preference="network.proxy.ssl_port" + type="number" + max="65535" + size="5"/> + </hbox> + </row> + + <row> + <hbox align="center" pack="end"> + <label value="&ftp.label;" accesskey="&ftp.accesskey;" + control="networkProxyFTP"/> + </hbox> + <hbox align="center"> + <textbox id="networkProxyFTP" + preference="network.proxy.ftp" + flex="1" + class="uri-element"/> + <label value="&port.label;" + accesskey="&FTPPort.accesskey;" + control="networkProxyFTP_Port"/> + <textbox id="networkProxyFTP_Port" + preference="network.proxy.ftp_port" + type="number" + max="65535" + size="5"/> + </hbox> + </row> + + </rows> + </grid> + </groupbox> + + <groupbox> + <caption label="&socks.caption;"/> + <description style="width: 1px;">&socks.description;</description> + + <hbox align="center" pack="end"> + <label value="&socks.label;" + accesskey="&socks.accesskey;" + control="networkProxySOCKS"/> + <textbox id="networkProxySOCKS" + preference="network.proxy.socks" + flex="1" + class="uri-element"/> + <label value="&port.label;" + accesskey="&SOCKSport.accesskey;" + control="networkProxySOCKS_Port"/> + <textbox id="networkProxySOCKS_Port" + type="number" + preference="network.proxy.socks_port" + max="65535" + size="5"/> + </hbox> + + <radiogroup id="networkProxySOCKSVersion" + orient="horizontal" + preference="network.proxy.socks_version"> + <radio id="networkProxySOCKSVersion4" + value="4" + label="&socks4.label;" + accesskey="&socks4.accesskey;"/> + <radio id="networkProxySOCKSVersion5" + value="5" + label="&socks5.label;" + accesskey="&socks5.accesskey;"/> + </radiogroup> + + <hbox align="left"> + <checkbox id="networkProxySOCKSRemoteDNS" + label="&socksRemoteDNS.label;" + accesskey="&socksRemoteDNS.accesskey;" + preference="network.proxy.socks_remote_dns"/> + </hbox> + + </groupbox> + </prefpane> +</prefwindow> diff --git a/comm/suite/components/pref/content/pref-proxies.js b/comm/suite/components/pref/content/pref-proxies.js new file mode 100644 index 0000000000..5120c3f5d0 --- /dev/null +++ b/comm/suite/components/pref/content/pref-proxies.js @@ -0,0 +1,188 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public +* License, v. 2.0. If a copy of the MPL was not distributed with this +* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const kNoProxy = 0; +const kManualProxy = 1; +const kAutoConfigProxy = 2; +const kObsoleteProxy = 3; +const kAutoDiscoverProxy = 4; +const kSystemProxy = 5; + +var gInstantApply; +var gHTTP; +var gHTTPPort; +var gSSL; +var gSSLPort; +var gFTP; +var gFTPPort; +var gAutoURL; +var gProxyType; +var gShareSettings; + +// Only used by main prefwindow +function Startup() +{ + InitCommonGlobals(); + gAutoURL = document.getElementById("network.proxy.autoconfig_url"); + gProxyType = document.getElementById("network.proxy.type"); + + // Check for system proxy settings class and unhide UI if present + if ("@mozilla.org/system-proxy-settings;1" in Cc) + document.getElementById("systemPref").hidden = false; + + // Calculate a sane default for network.proxy.share_proxy_settings. + if (gShareSettings.value == null) + gShareSettings.value = DefaultForShareSettingsPref(); + + // The pref value 3 (kObsoleteProxy) for network.proxy.type is unused to + // maintain backwards compatibility. Treat 3 (kObsoleteProxy) equally to + // 0 (kNoProxy). See bug 115720. + if (gProxyType.value == kObsoleteProxy) + gProxyType.value = kNoProxy; + + DoEnabling(); +} + +// Only used by child prefwindow +function AdvancedInit() +{ + InitCommonGlobals(); + DoProxyCopy(gShareSettings.value); +} + +function InitCommonGlobals() +{ + gInstantApply = document.documentElement.instantApply; + gHTTP = document.getElementById("network.proxy.http"); + gHTTPPort = document.getElementById("network.proxy.http_port"); + gSSL = document.getElementById("network.proxy.ssl"); + gSSLPort = document.getElementById("network.proxy.ssl_port"); + gFTP = document.getElementById("network.proxy.ftp"); + gFTPPort = document.getElementById("network.proxy.ftp_port"); + gShareSettings = document.getElementById("network.proxy.share_proxy_settings"); +} + +// Returns true if all protocol specific proxies and all their +// ports are set to the same value, false otherwise. +function DefaultForShareSettingsPref() +{ + return gHTTP.value == gSSL.value && + gHTTP.value == gFTP.value && + gHTTPPort.value == gSSLPort.value && + gHTTPPort.value == gFTPPort.value; +} + +function DoEnabling() +{ + // convenience arrays + var manual = ["networkProxyHTTP", "networkProxyHTTP_Port", + "networkProxyNone", "advancedButton"]; + var auto = ["networkProxyAutoconfigURL", "autoReload"]; + + switch (gProxyType.value) + { + case kNoProxy: + case kAutoDiscoverProxy: + case kSystemProxy: + Disable(manual); + Disable(auto); + break; + case kManualProxy: + Disable(auto); + if (!gProxyType.locked) + EnableUnlockedElements(manual, true); + break; + case kAutoConfigProxy: + default: + Disable(manual); + if (!gProxyType.locked) + { + EnableElementById("networkProxyAutoconfigURL", true, false); + EnableUnlockedButton(gAutoURL); + } + break; + } +} + +function Disable(aElementIds) +{ + for (var i = 0; i < aElementIds.length; i++) + document.getElementById(aElementIds[i]).setAttribute("disabled", "true"); +} + +function EnableUnlockedElements(aElementIds, aEnable) +{ + for (var i = 0; i < aElementIds.length; i++) + EnableElementById(aElementIds[i], aEnable, false); +} + +function EnableUnlockedButton(aElement) +{ + var enable = gInstantApply || + (aElement.valueFromPreferences == aElement.value); + EnableElementById("autoReload", enable, false); +} + +function ReloadPAC() { + // This reloads the PAC URL stored in preferences. + // When not in instant apply mode, the button that calls this gets + // disabled if the preference and what is showing in the UI differ. + Cc["@mozilla.org/network/protocol-proxy-service;1"] + .getService().reloadPAC(); +} + +function FixProxyURL(aURL) +{ + try + { + aURL.value = + Services.uriFixup.createFixupURI(aURL.value, + Ci.nsIURIFixup.FIXUP_FLAG_NONE).spec; + } + catch (e) {} + + if (!gInstantApply) + EnableUnlockedButton(aURL); +} + +function OpenAdvancedDialog() +{ + document.documentElement.openSubDialog("chrome://communicator/content/pref/pref-proxies-advanced.xul", + "AdvancedProxyPreferences", null); +} + +function DoProxyCopy(aChecked) +{ + DoProxyHostCopy(gHTTP.value); + DoProxyPortCopy(gHTTPPort.value); + var nonshare = ["networkProxySSL", "networkProxySSL_Port", + "networkProxyFTP", "networkProxyFTP_Port"]; + EnableUnlockedElements(nonshare, !aChecked); +} + +function DoProxyHostCopy(aValue) +{ + if (!gShareSettings.value) + return; + + gSSL.value = aValue; + gFTP.value = aValue; +} + +function DoProxyPortCopy(aValue) +{ + if (!gShareSettings.value) + return; + + gSSLPort.value = aValue; + gFTPPort.value = aValue; +} + +function UpdateProxies() +{ + var noProxiesPref = document.getElementById("network.proxy.no_proxies_on"); + + noProxiesPref.value = noProxiesPref.value.replace(/[;, \n]+/g, ", ") + .replace(/^, |, $/g, ""); +} diff --git a/comm/suite/components/pref/content/pref-proxies.xul b/comm/suite/components/pref/content/pref-proxies.xul new file mode 100644 index 0000000000..acd1a1f053 --- /dev/null +++ b/comm/suite/components/pref/content/pref-proxies.xul @@ -0,0 +1,156 @@ +<?xml version="1.0"?> +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<!DOCTYPE overlay SYSTEM "chrome://communicator/locale/pref/pref-proxies.dtd"> +<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <prefpane id="proxies_pane" + label="&pref.proxies.title;" + script="chrome://communicator/content/pref/pref-proxies.js"> + <preferences id="proxies_preferences"> + <preference id="network.proxy.type" + name="network.proxy.type" + type="int" + onchange="DoEnabling();"/> + <preference id="network.proxy.autoconfig_url" + name="network.proxy.autoconfig_url" + type="string"/> + <preference id="pref.advanced.proxies.disable_button.reload" + name="pref.advanced.proxies.disable_button.reload" + type="bool"/> + <preference id="network.proxy.http" + name="network.proxy.http" + type="string" + onchange="DoProxyHostCopy(this.value);"/> + <preference id="network.proxy.http_port" + name="network.proxy.http_port" + type="int" + onchange="DoProxyPortCopy(this.value);"/> + <preference id="pref.advanced.proxies.disable_button.advanced" + name="pref.advanced.proxies.disable_button.advanced" + type="bool"/> + <preference id="network.proxy.no_proxies_on" + name="network.proxy.no_proxies_on" + type="string"/> + <preference id="network.proxy.ssl" + name="network.proxy.ssl" + type="string"/> + <preference id="network.proxy.ssl_port" + name="network.proxy.ssl_port" + type="int"/> + <preference id="network.proxy.ftp" + name="network.proxy.ftp" + type="string"/> + <preference id="network.proxy.ftp_port" + name="network.proxy.ftp_port" + type="int"/> + <preference id="network.proxy.share_proxy_settings" + name="network.proxy.share_proxy_settings" + type="bool"/> + </preferences> + + <description>&pref.proxies.desc;</description> + <groupbox> + <caption label="&proxyTitle.label;"/> + <radiogroup id="networkProxyType" + preference="network.proxy.type" + align="stretch"> + <vbox align="start"> + <radio value="0" + label="&directTypeRadio.label;" + accesskey="&directTypeRadio.accesskey;"/> + <radio value="4" + label="&wpadTypeRadio.label;" + accesskey="&wpadTypeRadio.accesskey;"/> + <radio value="5" + label="&systemTypeRadio.label;" + accesskey="&systemTypeRadio.accesskey;" + id="systemPref" + hidden="true"/> + <radio value="2" + label="&autoTypeRadio.label;" + accesskey="&autoTypeRadio.accesskey;"/> + </vbox> + + <hbox class="indent" align="center"> + <textbox id="networkProxyAutoconfigURL" + flex="1" + class="uri-element" + onchange="FixProxyURL(this);" + preference="network.proxy.autoconfig_url"/> + <button id="autoReload" + label="&reload.label;" + accesskey="&reload.accesskey;" + oncommand="ReloadPAC();" + preference="pref.advanced.proxies.disable_button.reload"/> + </hbox> + + <vbox align="start"> + <radio value="1" + label="&manualTypeRadio.label;" + accesskey="&manualTypeRadio.accesskey;"/> + </vbox> + + <grid class="indent"> + <columns> + <column/> + <column flex="1"/> + </columns> + + <rows> + <row align="center"> + <hbox align="center" pack="end"> + <label value="&http.label;" + accesskey="&http.accesskey;" + control="networkProxyHTTP"/> + </hbox> + <textbox id="networkProxyHTTP" + preference="network.proxy.http" + class="uri-element"/> + </row> + + <row> + <hbox align="center" pack="end"> + <label value="&port.label;" + accesskey="&HTTPPort.accesskey;" + control="networkProxyHTTP_Port"/> + </hbox> + <hbox align="center"> + <textbox id="networkProxyHTTP_Port" + preference="network.proxy.http_port" + type="number" + max="65535" + size="5"/> + <spacer flex="1"/> + <button id="advancedButton" + label="&advanced.label;" + accesskey="&advanced.accesskey;" + align="end" + oncommand="OpenAdvancedDialog();" + preference="pref.advanced.proxies.disable_button.advanced"/> + </hbox> + </row> + + <row align="baseline"> + <hbox align="center" pack="end"> + <label value="&noproxy.label;" + accesskey="&noproxy.accesskey;" + control="networkProxyNone"/> + </hbox> + <textbox id="networkProxyNone" + multiline="true" + preference="network.proxy.no_proxies_on" + class="uri-element" + onchange="UpdateProxies();"/> + </row> + <row> + <spacer/> + <description control="networkProxyNone">&noproxyExplain.label; + </description> + </row> + </rows> + </grid> + </radiogroup> + </groupbox> + </prefpane> +</overlay> diff --git a/comm/suite/components/pref/content/pref-scripts.js b/comm/suite/components/pref/content/pref-scripts.js new file mode 100644 index 0000000000..eb16b4d62f --- /dev/null +++ b/comm/suite/components/pref/content/pref-scripts.js @@ -0,0 +1,29 @@ +/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +function setDisableState(id, state) { + var component = document.getElementById(id); + var preference = component.getAttribute("preference"); + var isLocked = document.getElementById(preference).locked; + component.disabled = isLocked || state; +} + +function changeDisabledState(state) { + //Set the states of the groupbox children state based on the "javascript enabled" checkbox value + setDisableState("allowWindowMoveResize", state); + setDisableState("allowWindowStatusChange", state); + setDisableState("allowWindowFlip", state); + setDisableState("allowHideStatusBar", state); + setDisableState("allowContextmenuDisable", state); +} + +function javascriptEnabledChange() { + var javascriptDisabled = !document.getElementById('javascript.enabled').value; + changeDisabledState(javascriptDisabled); +} + +function Startup() { + javascriptEnabledChange(); +} diff --git a/comm/suite/components/pref/content/pref-scripts.xul b/comm/suite/components/pref/content/pref-scripts.xul new file mode 100644 index 0000000000..9018f29cc4 --- /dev/null +++ b/comm/suite/components/pref/content/pref-scripts.xul @@ -0,0 +1,92 @@ +<?xml version="1.0"?><!-- -*- Mode: HTML -*- --> +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<!DOCTYPE overlay SYSTEM "chrome://communicator/locale/pref/pref-scripts.dtd"> + +<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <prefpane id="scripts_pane" + label="&pref.scripts2.title;" + script="chrome://communicator/content/pref/pref-scripts.js"> + + <preferences id="scripts_preferences"> + <preference id="javascript.enabled" + name="javascript.enabled" + type="bool" + onchange="javascriptEnabledChange();"/> + <preference id="dom.disable_window_move_resize" + name="dom.disable_window_move_resize" + type="bool" inverted="true"/> + <preference id="dom.disable_window_flip" + name="dom.disable_window_flip" + type="bool" inverted="true"/> + <preference id="dom.disable_window_open_feature.status" + name="dom.disable_window_open_feature.status" + type="bool" inverted="true"/> + <preference id="dom.disable_window_status_change" + name="dom.disable_window_status_change" + type="bool" inverted="true"/> + <preference id="dom.event.contextmenu.enabled" + name="dom.event.contextmenu.enabled" + type="bool"/> + <preference id="browser.dom.window.dump.enabled" + name="browser.dom.window.dump.enabled" + type="bool"/> + <preference id="javascript.options.strict" + name="javascript.options.strict" + type="bool"/> + <preference id="javascript.options.showInConsole" + name="javascript.options.showInConsole" + type="bool"/> + </preferences> + + <groupbox id="javascriptPreferences" flex="1"> + <caption label="&enableJavaScript.label;"/> + + <checkbox id="javascriptAllowNavigator" + label="&navigator.label;" + accesskey="&navigator.accesskey;" + preference="javascript.enabled"/> + + <label control="AllowList" + class="indent" + value="&allowScripts.label;" + accesskey="&allowScripts.accesskey;"/> + + <listbox id="AllowList" class="indent" flex="1"> + <listitem type="checkbox" id="allowWindowMoveResize" + label="&allowWindowMoveResize.label;" + preference="dom.disable_window_move_resize"/> + <listitem type="checkbox" id="allowWindowFlip" + label="&allowWindowFlip.label;" + preference="dom.disable_window_flip"/> + <listitem type="checkbox" id="allowHideStatusBar" + label="&allowHideStatusBar.label;" + preference="dom.disable_window_open_feature.status"/> + <listitem type="checkbox" id="allowWindowStatusChange" + label="&allowWindowStatusChange.label;" + preference="dom.disable_window_status_change"/> + <listitem type="checkbox" id="allowContextmenuDisable" + label="&allowContextmenuDisable.label;" + preference="dom.event.contextmenu.enabled"/> + </listbox> + </groupbox> + + <groupbox id="debugging"> + <caption label="&debugging.label;"/> + <checkbox id="browserDOMWindowDumpEnabled" + label="&debugEnableDump.label;" + accesskey="&debugEnableDump.accesskey;" + preference="browser.dom.window.dump.enabled"/> + <checkbox id="javascriptOptionsStrict" + label="&debugStrictJavascript.label;" + accesskey="&debugStrictJavascript.accesskey;" + preference="javascript.options.strict"/> + <checkbox id="javascriptOptionsShowInConsole" + label="&debugConsoleJavascript.label;" + accesskey="&debugConsoleJavascript.accesskey;" + preference="javascript.options.showInConsole"/> + </groupbox> + </prefpane> +</overlay> diff --git a/comm/suite/components/pref/content/pref-search.js b/comm/suite/components/pref/content/pref-search.js new file mode 100755 index 0000000000..8f17af63d2 --- /dev/null +++ b/comm/suite/components/pref/content/pref-search.js @@ -0,0 +1,60 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +var {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm"); + +function Startup() { + MakeList(); + SearchObserver.init(); +} + +var SearchObserver = { + init: function searchEngineListObserver_init() { + Services.obs.addObserver(this, "browser-search-engine-modified"); + window.addEventListener("unload", this); + }, + + observe: function searchEngineListObj_observe(aEngine, aTopic, aVerb) { + if (aTopic != "browser-search-engine-modified") + return; + MakeList(); + }, + + handleEvent: function searchEngineListEvent(aEvent) { + if (aEvent.type == "unload") { + window.removeEventListener("unload", this); + Services.obs.removeObserver(this, "browser-search-engine-modified"); + } + } +}; + +function MakeList() { + var menulist = document.getElementById("engineList"); + var currentEngineName = Services.search.currentEngine.name; + + // Make sure the popup is empty. + menulist.removeAllItems(); + + var engines = Services.search.getVisibleEngines(); + for (let engine of engines) { + let name = engine.name; + let menuitem = menulist.appendItem(name, name); + menuitem.setAttribute("class", "menuitem-iconic"); + if (engine.iconURI) + menuitem.setAttribute("image", engine.iconURI.spec); + menuitem.engine = engine; + if (engine.name == currentEngineName) { + // Set selection to the current default engine. + menulist.selectedItem = menuitem; + } + } + // If the current engine isn't in the list any more, select the first item. + if (menulist.selectedIndex < 0) + menulist.selectedIndex = 0; +} + +function UpdateDefaultEngine(selectedItem) { + Services.search.currentEngine = selectedItem.engine; + Services.obs.notifyObservers(null, "browser-search-engine-modified", "engine-current"); +} diff --git a/comm/suite/components/pref/content/pref-search.xul b/comm/suite/components/pref/content/pref-search.xul new file mode 100755 index 0000000000..e3eaa61701 --- /dev/null +++ b/comm/suite/components/pref/content/pref-search.xul @@ -0,0 +1,50 @@ +<?xml version="1.0"?> +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<!DOCTYPE overlay SYSTEM "chrome://communicator/locale/pref/pref-search.dtd"> +<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <prefpane id="search_pane" + label="&pref.search.title;" + script="chrome://communicator/content/pref/pref-search.js"> + + <preferences id="search_preferences"> + <preference id="browser.search.openintab" + name="browser.search.openintab" + type="bool"/> + <preference id="browser.search.opentabforcontextsearch" + name="browser.search.opentabforcontextsearch" + type="bool"/> + </preferences> + + <groupbox> + <caption label="&legendHeader;"/> + + <hbox align="center"> + <label value="&defaultSearchEngine.label;" + accesskey="&defaultSearchEngine.accesskey;" + control="engineList"/> + <menulist id="engineList" + oncommand="UpdateDefaultEngine(this.selectedItem)"/> + </hbox> + <hbox pack="end"> + <button id="managerButton" + label="&engineManager.label;" + oncommand="OpenSearchEngineManager();"/> + </hbox> + </groupbox> + + <groupbox> + <caption label="&searchResults.label;"/> + <checkbox id="openSearchTab" + label="&openInTab.label;" + accesskey="&openInTab.accesskey;" + preference="browser.search.openintab"/> + <checkbox id="openContextSearchTab" + label="&openContextSearchTab.label;" + accesskey="&openContextSearchTab.accesskey;" + preference="browser.search.opentabforcontextsearch"/> + </groupbox> + </prefpane> +</overlay> diff --git a/comm/suite/components/pref/content/pref-security.js b/comm/suite/components/pref/content/pref-security.js new file mode 100644 index 0000000000..31dba56b7a --- /dev/null +++ b/comm/suite/components/pref/content/pref-security.js @@ -0,0 +1,15 @@ +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +function Startup() +{ + var prefTrackProtect = document.getElementById("privacy.trackingprotection.enabled"); + SetWarnTrackEnabled(prefTrackProtect.value); +} + +function SetWarnTrackEnabled(aEnable) +{ + EnableElementById("warnTrackContent", aEnable, false); +} diff --git a/comm/suite/components/pref/content/pref-security.xul b/comm/suite/components/pref/content/pref-security.xul new file mode 100644 index 0000000000..6823df7f9e --- /dev/null +++ b/comm/suite/components/pref/content/pref-security.xul @@ -0,0 +1,108 @@ +<?xml version="1.0"?> + +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<!DOCTYPE overlay [ +<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd"> +%brandDTD; +<!ENTITY % prefSecurityDTD SYSTEM "chrome://communicator/locale/pref/pref-security.dtd"> +%prefSecurityDTD; +]> + +<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <prefpane id="security_pane" label="&pref.security.title;" + script="chrome://communicator/content/pref/pref-security.js"> + <preferences id="security_preferences"> + <!-- User Tracking --> + <preference id="privacy.donottrackheader.enabled" + name="privacy.donottrackheader.enabled" + type="bool"/> + <preference id="privacy.trackingprotection.enabled" + name="privacy.trackingprotection.enabled" + type="bool" + onchange="SetWarnTrackEnabled(this.value);"/> + <preference id="privacy.warn_tracking_content" + name="privacy.warn_tracking_content" + type="bool"/> + + <!-- Location Aware Browsing --> + <preference id="geo.enabled" + name="geo.enabled" + type="bool"/> + + <!-- Safe Browsing --> + <preference id="browser.safebrowsing.malware.enabled" + name="browser.safebrowsing.malware.enabled" + type="bool"/> + <preference id="browser.safebrowsing.phishing.enabled" + name="browser.safebrowsing.phishing.enabled" + type="bool"/> + + <preference id="accessibility.blockautorefresh" + name="accessibility.blockautorefresh" + type="bool"/> + </preferences> + + <!-- User Tracking --> + <groupbox id="trackingGroup"> + <caption label="&tracking.label;"/> + + <description>&trackingIntro.label;</description> + <checkbox id="doNotTrack" + label="&doNotTrack.label;" + accesskey="&doNotTrack.accesskey;" + preference="privacy.donottrackheader.enabled"/> + <checkbox id="trackProtect" + label="&trackProtect.label;" + accesskey="&trackProtect.accesskey;" + preference="privacy.trackingprotection.enabled"/> + <checkbox id="warnTrackContent" + class="indent" + label="&warnTrackContent.label;" + accesskey="&warnTrackContent.accesskey;" + preference="privacy.warn_tracking_content"/> + </groupbox> + + <!-- Location Aware Browsing --> + <groupbox id="geoLocationGroup"> + <caption label="&geoLocation.label;"/> + + <description>&geoIntro.label;</description> + <radiogroup id="geoSelection" + preference="geo.enabled"> + <radio id="geoEnabled" + value="true" + label="&geoEnabled.label;" + accesskey="&geoEnabled.accesskey;"/> + <radio id="geoDisabled" + value="false" + label="&geoDisabled.label;" + accesskey="&geoDisabled.accesskey;"/> + </radiogroup> + </groupbox> + + <!-- Safe Browsing --> + <groupbox id="safeBrowsingGroup"> + <caption label="&safeBrowsing.label;"/> + + <description>&safeBrowsingIntro.label;</description> + <checkbox id="blockAttackSites" + label="&blockAttackSites.label;" + accesskey="&blockAttackSites.accesskey;" + preference="browser.safebrowsing.malware.enabled"/> + <checkbox id="blockWebForgeries" + label="&blockWebForgeries.label;" + accesskey="&blockWebForgeries.accesskey;" + preference="browser.safebrowsing.phishing.enabled"/> + </groupbox> + + <vbox class="box-padded" align="start"> + <checkbox id="blockAutoRefresh" + label="&blockAutoRefresh.label;" + accesskey="&blockAutoRefresh.accesskey;" + preference="accessibility.blockautorefresh"/> + </vbox> + </prefpane> +</overlay> diff --git a/comm/suite/components/pref/content/pref-smartupdate.js b/comm/suite/components/pref/content/pref-smartupdate.js new file mode 100644 index 0000000000..8e9712a936 --- /dev/null +++ b/comm/suite/components/pref/content/pref-smartupdate.js @@ -0,0 +1,87 @@ +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +var gCanCheckForUpdates; + +function Startup() +{ + var hasUpdater = "nsIApplicationUpdateService" in Ci; + + if (hasUpdater) + { + var aus = Cc["@mozilla.org/updates/update-service;1"] + .getService(Ci.nsIApplicationUpdateService); + gCanCheckForUpdates = aus.canCheckForUpdates; + + UpdateAddonsItems(); + UpdateAppItems(); + } + else + { + var appGroupBox = document.getElementById("appUpdatesGroupBox"); + appGroupBox.hidden = true; + } +} + +/* + * Preferences: + * + * app.update.enabled + * - boolean: + * - true if updates to the application are enabled, false otherwise + * extensions.update.enabled + * - boolean: + * - true if updates to extensions and themes are enabled, false otherwise + * app.update.auto + * - true if updates should be automatically downloaded and installed, + * false if the user should be asked what he wants to do when an + * update is available + */ +function UpdateAddonsItems() +{ + var addOnsCheck = !document.getElementById("xpinstall.enabled").value; + + document.getElementById("addOnsUpdatesEnabled").disabled = + addOnsCheck || + document.getElementById("extensions.update.enabled").locked; + + document.getElementById("addOnsUpdateFrequency").disabled = + !document.getElementById("xpinstall.enabled").value || + !document.getElementById("extensions.update.enabled").value || + document.getElementById("extensions.update.interval").locked; + + document.getElementById("allowedSitesLink").disabled = + addOnsCheck; + + document.getElementById("addOnsModeAutoEnabled").disabled = + addOnsCheck || + !document.getElementById("extensions.update.enabled").value || + document.getElementById("extensions.update.enabled").locked; +} + +function UpdateAppItems() +{ + var enabledPref = document.getElementById("app.update.enabled"); + + document.getElementById("appUpdatesEnabled").disabled = + !gCanCheckForUpdates || enabledPref.locked; + + document.getElementById("appUpdateFrequency").disabled = + !enabledPref.value || !gCanCheckForUpdates || + document.getElementById("app.update.interval").locked; + + document.getElementById("appModeAutoEnabled").disabled = + !enabledPref.value || !gCanCheckForUpdates; +} + +/** + * Displays the history of installed updates. + */ +function ShowUpdateHistory() +{ + Cc["@mozilla.org/updates/update-prompt;1"] + .createInstance(Ci.nsIUpdatePrompt) + .showUpdateHistory(window); +} diff --git a/comm/suite/components/pref/content/pref-smartupdate.xul b/comm/suite/components/pref/content/pref-smartupdate.xul new file mode 100644 index 0000000000..a9b9546c31 --- /dev/null +++ b/comm/suite/components/pref/content/pref-smartupdate.xul @@ -0,0 +1,139 @@ +<?xml version="1.0"?> +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<!DOCTYPE overlay [ +<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd"> +%brandDTD; +<!ENTITY % prefSmartUpdateDTD SYSTEM "chrome://communicator/locale/pref/pref-smartupdate.dtd"> +%prefSmartUpdateDTD; +]> + +<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <prefpane id="smartupdate_pane" + label="&pref.smartUpdate.title;" + script="chrome://communicator/content/pref/pref-smartupdate.js"> + + <preferences id="smartupdate_preferences"> + <preference id="xpinstall.enabled" + name="xpinstall.enabled" + type="bool" + onchange="UpdateAddonsItems();"/> + <preference id="extensions.update.enabled" + name="extensions.update.enabled" + type="bool" + onchange="UpdateAddonsItems();"/> + <preference id="extensions.update.interval" + name="extensions.update.interval" + type="int"/> + <preference id="extensions.update.autoUpdateDefault" + name="extensions.update.autoUpdateDefault" + type="bool"/> + <preference id="extensions.getAddons.cache.enabled" + name="extensions.getAddons.cache.enabled" + type="bool"/> + <preference id="app.update.enabled" + name="app.update.enabled" + type="bool" + onchange="UpdateAppItems();"/> + <preference id="app.update.auto" + name="app.update.auto" + type="bool" + onchange="UpdateAppItems();"/> + <preference id="app.update.interval" + name="app.update.interval" + type="int"/> + <preference id="app.update.disable_button.showUpdateHistory" + name="app.update.disable_button.showUpdateHistory" + type="bool"/> + </preferences> + + <groupbox> + <caption label="&addOnsTitle.label;"/> + <hbox align="center"> + <checkbox id="XPInstallEnabled" + label="&addOnsAllow.label;" + flex="1" + accesskey="&addOnsAllow.accesskey;" + preference="xpinstall.enabled"/> + <label id="allowedSitesLink" + class="text-link" + value="&allowedSitesLink.label;" + onclick="toDataManager('|permissions');"/> + </hbox> + <hbox class="indent"> + <checkbox id="addOnsUpdatesEnabled" + label="&autoAddOnsUpdates.label;" + accesskey="&autoAddOnsUpdates.accesskey;" + preference="extensions.update.enabled"/> + <radiogroup id="addOnsUpdateFrequency" + orient="horizontal" + preference="extensions.update.interval"> + <radio id="addOnsFreqDaily" + label="&daily.label;" + accesskey="&addOnsDaily.accesskey;" + value="86400"/> + <radio id="addOnsFreqWeekly" + label="&weekly.label;" + accesskey="&addOnsWeekly.accesskey;" + value="604800"/> + </radiogroup> + </hbox> + <hbox class="indent"> + <checkbox id="addOnsModeAutoEnabled" + class="indent" + label="&addOnsModeAutomatic.label;" + flex="1" + accesskey="&addOnsModeAutomatic.accesskey;" + preference="extensions.update.autoUpdateDefault"/> + </hbox> + <hbox align="center"> + <checkbox id="enablePersonalized" + flex="1" + label="&enablePersonalized.label;" + accesskey="&enablePersonalized.accesskey;" + preference="extensions.getAddons.cache.enabled"/> + <label id="addonManagerLink" + class="text-link" + onclick="toEM('addons://list/extension');" + value="&addonManagerLink.label;"/> + </hbox> + </groupbox> + + <groupbox id="appUpdatesGroupBox"> + <caption label="&appUpdates.caption;"/> + <hbox> + <checkbox id="appUpdatesEnabled" + label="&autoAppUpdates.label;" + accesskey="&autoAppUpdates.accesskey;" + preference="app.update.enabled"/> + <radiogroup id="appUpdateFrequency" + orient="horizontal" + preference="app.update.interval"> + <radio id="appFreqDaily" + label="&daily.label;" + accesskey="&appDaily.accesskey;" + value="86400"/> + <radio id="appFreqWeekly" + label="&weekly.label;" + accesskey="&appWeekly.accesskey;" + value="604800"/> + </radiogroup> + </hbox> + <checkbox id="appModeAutoEnabled" + class="indent" + label="&appModeAutomatic.label;" + flex="1" + accesskey="&appModeAutomatic.accesskey;" + preference="app.update.auto"/> + <hbox pack="end"> + <button id="showUpdateHistory" + label="&updateHistoryButton.label;" + accesskey="&updateHistoryButton.accesskey;" + preference="app.update.disable_button.showUpdateHistory" + oncommand="ShowUpdateHistory();"/> + </hbox> + </groupbox> + </prefpane> +</overlay> diff --git a/comm/suite/components/pref/content/pref-spelling.js b/comm/suite/components/pref/content/pref-spelling.js new file mode 100644 index 0000000000..6c214af3fc --- /dev/null +++ b/comm/suite/components/pref/content/pref-spelling.js @@ -0,0 +1,119 @@ +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +var gDictCount = 0; +var gLastSelectedLang; + +function Startup() { + if ("@mozilla.org/spellchecker;1" in Cc) + InitLanguageMenu(); + else + { + document.getElementById("generalSpelling").hidden = true; + document.getElementById("mailSpelling").hidden = true; + document.getElementById("noSpellCheckLabel").hidden = false; + } +} + +function InitLanguageMenu() { + var spellChecker = Cc["@mozilla.org/spellchecker/engine;1"] + .getService(Ci.mozISpellCheckingEngine); + + // Get the list of dictionaries from the spellchecker. + var dictList = spellChecker.getDictionaryList(); + var count = dictList.length; + + // If dictionary count hasn't changed then no need to update the menu. + if (gDictCount == count) + return; + + // Store current dictionary count. + gDictCount = count; + + // Load the string bundles that will help us map + // RFC 1766 strings to UI strings. + + // Load the language string bundle. + var languageBundle = document.getElementById("languageNamesBundle"); + var regionBundle = null; + // If we have a language string bundle, load the region string bundle. + if (languageBundle) + regionBundle = document.getElementById("regionNamesBundle"); + + var menuStr2; + var isoStrArray; + var langId; + var langLabel; + + for (let i = 0; i < count; i++) { + try { + langId = dictList[i]; + isoStrArray = dictList[i].split(/[-_]/); + + if (languageBundle && isoStrArray[0]) + langLabel = languageBundle.getString(isoStrArray[0].toLowerCase()); + + if (regionBundle && langLabel && isoStrArray.length > 1 && isoStrArray[1]) { + menuStr2 = regionBundle.getString(isoStrArray[1].toLowerCase()); + if (menuStr2) + langLabel += "/" + menuStr2; + } + + if (langLabel && isoStrArray.length > 2 && isoStrArray[2]) + langLabel += " (" + isoStrArray[2] + ")"; + + if (!langLabel) + langLabel = langId; + } catch (ex) { + // getString throws an exception when a key is not found in the + // bundle. In that case, just use the original dictList string. + langLabel = langId; + } + dictList[i] = [langLabel, langId]; + } + + // sort by locale-aware collation + dictList.sort( + function compareFn(a, b) { + return a[0].localeCompare(b[0]); + } + ); + + var languageMenuList = document.getElementById("languageMenuList"); + // Remove any languages from the list. + var languageMenuPopup = languageMenuList.menupopup; + while (languageMenuPopup.firstChild.localName != "menuseparator") + languageMenuPopup.firstChild.remove(); + + var curLang = languageMenuList.value; + var defaultItem = null; + + for (let i = 0; i < count; i++) { + let item = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "menuitem"); + item.setAttribute("label", dictList[i][0]); + item.setAttribute("value", dictList[i][1]); + let beforeItem = gDialog.LanguageMenulist.getItemAtIndex(i); + languageMenuPopup.insertBefore(item, beforeItem); + + if (curLang && dictList[i][1] == curLang) + defaultItem = item; + } + + // Now make sure the correct item in the menu list is selected. + if (defaultItem) { + languageMenuList.selectedItem = defaultItem; + gLastSelectedLang = defaultItem; + } +} + +function SelectLanguage(aTarget) { + if (aTarget.value != "more-cmd") + gLastSelectedLang = aTarget; + else { + openDictionaryList(); + if (gLastSelectedLang) + document.getElementById("languageMenuList").selectedItem = gLastSelectedLang; + } +} diff --git a/comm/suite/components/pref/content/pref-spelling.xul b/comm/suite/components/pref/content/pref-spelling.xul new file mode 100644 index 0000000000..93fa605fb5 --- /dev/null +++ b/comm/suite/components/pref/content/pref-spelling.xul @@ -0,0 +1,80 @@ +<?xml version="1.0"?> + +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this file, + - You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<!DOCTYPE overlay SYSTEM "chrome://communicator/locale/pref/pref-spelling.dtd"> + +<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <prefpane id="spelling_pane" + label="&prefSpelling.title;" + script="chrome://communicator/content/pref/pref-spelling.js"> + + <preferences id="spelling_preferences"> + <preference id="mail.SpellCheckBeforeSend" + name="mail.SpellCheckBeforeSend" + type="bool"/> + <preference id="mail.spellcheck.inline" + name="mail.spellcheck.inline" + type="bool"/> + <preference id="spellchecker.dictionary" + name="spellchecker.dictionary" + type="string" + onchange="SelectLanguage(event.target)"/> + <preference id="layout.spellcheckDefault" + name="layout.spellcheckDefault" + type="int"/> + </preferences> + + <label id="noSpellCheckLabel" + value="&noSpellCheckAvailable.label;" + hidden="true"/> + + <groupbox id="generalSpelling" align="start"> + <caption label="&generalSpelling.label;"/> + <hbox align="center" pack="start"> + <label value="&languagePopup.label;" + accesskey="&languagePopup.accessKey;" + control="languageMenuList"/> + <menulist id="languageMenuList" + preference="spellchecker.dictionary"> + <menupopup onpopupshowing="InitLanguageMenu();"> + <!-- dynamic content populated by JS --> + <menuseparator/> + <menuitem value="more-cmd" label="&moreDictionaries.label;"/> + </menupopup> + </menulist> + <spring flex="1"/> + </hbox> + <separator class="thin"/> + <hbox align="center"> + <label value="&checkSpellingWhenTyping.label;" + accesskey="&checkSpellingWhenTyping.accesskey;" + control="spellcheckDefault"/> + <menulist id="spellcheckDefault" + preference="layout.spellcheckDefault"> + <menupopup> + <menuitem value="0" label="&dontCheckSpelling.label;"/> + <menuitem value="1" label="&multilineCheckSpelling.label;"/> + <menuitem value="2" label="&alwaysCheckSpelling.label;"/> + </menupopup> + </menulist> + </hbox> + </groupbox> + + <groupbox id="mailSpelling" align="start"> + <caption label="&spellForMailAndNews.label;"/> + <vbox align="start"> + <checkbox id="spellCheckBeforeSend" + label="&checkSpellingBeforeSend.label;" + accesskey="&checkSpellingBeforeSend.accesskey;" + preference="mail.SpellCheckBeforeSend"/> + <checkbox id="inlineSpellCheck" + label="&spellCheckInline.label;" + accesskey="&spellCheckInline.accesskey;" + preference="mail.spellcheck.inline"/> + </vbox> + </groupbox> + </prefpane> +</overlay> diff --git a/comm/suite/components/pref/content/pref-sync.js b/comm/suite/components/pref/content/pref-sync.js new file mode 100644 index 0000000000..06d1825a70 --- /dev/null +++ b/comm/suite/components/pref/content/pref-sync.js @@ -0,0 +1,143 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const {Weave} = ChromeUtils.import("resource://services-sync/main.js"); + +const PAGE_NO_ACCOUNT = 0; +const PAGE_HAS_ACCOUNT = 1; +const PAGE_NEEDS_UPDATE = 2; + +var gSyncPane = { + get page() { + return document.getElementById("weavePrefsDeck").selectedIndex; + }, + + set page(val) { + document.getElementById("weavePrefsDeck").selectedIndex = val; + }, + + get _usingCustomServer() { + return Weave.Svc.Prefs.isSet("serverURL"); + }, + + needsUpdate: function () { + this.page = PAGE_NEEDS_UPDATE; + let label = document.getElementById("loginError"); + label.value = Weave.Utils.getErrorString(Weave.Status.login); + label.className = "error"; + }, + + topics: [ "weave:service:ready", + "weave:service:login:error", + "weave:service:login:finish", + "weave:service:start-over", + "weave:service:setup-complete", + "weave:service:logout:finish"], + + init: function () { + for (var topic of this.topics) + Services.obs.addObserver(this, topic); + + window.addEventListener("unload", this); + + var xps = Cc["@mozilla.org/weave/service;1"] + .getService().wrappedJSObject; + if (xps.ready) + this.observe(null, "weave:service:ready", null); + else + xps.ensureLoaded(); + }, + + handleEvent: function (aEvent) { + window.removeEventListener("unload", this); + + for (var topic of this.topics) + Services.obs.removeObserver(this, topic); + }, + + observe: function (aSubject, aTopic, aData) { + if (Weave.Status.service == Weave.CLIENT_NOT_CONFIGURED || + Weave.Svc.Prefs.get("firstSync", "") == "notReady") { + this.page = PAGE_NO_ACCOUNT; + } else if (Weave.Status.login == Weave.LOGIN_FAILED_INVALID_PASSPHRASE || + Weave.Status.login == Weave.LOGIN_FAILED_LOGIN_REJECTED) { + this.needsUpdate(); + } else { + this.page = PAGE_HAS_ACCOUNT; + document.getElementById("accountName").value = Weave.Service.identity.account; + document.getElementById("syncComputerName").value = Weave.Service.clientsEngine.localName; + document.getElementById("tosPP").hidden = this._usingCustomServer; + } + }, + + startOver: function (showDialog) { + if (showDialog) { + let flags = Services.prompt.BUTTON_POS_0 * Services.prompt.BUTTON_TITLE_IS_STRING + + Services.prompt.BUTTON_POS_1 * Services.prompt.BUTTON_TITLE_CANCEL; + let prefutilitiesBundle = document.getElementById("bundle_prefutilities"); + let buttonChoice = + Services.prompt.confirmEx(window, + prefutilitiesBundle.getString("syncUnlink.title"), + prefutilitiesBundle.getString("syncUnlink.label"), + flags, + prefutilitiesBundle.getString("syncUnlinkConfirm.label"), + null, null, null, {}); + + // If the user selects cancel, just bail + if (buttonChoice == 1) + return; + } + + Weave.Service.startOver(); + this.updateWeavePrefs(); + }, + + updatePass: function () { + if (Weave.Status.login == Weave.LOGIN_FAILED_LOGIN_REJECTED) + gSyncUtils.changePassword(); + else + gSyncUtils.updatePassphrase(); + }, + + resetPass: function () { + if (Weave.Status.login == Weave.LOGIN_FAILED_LOGIN_REJECTED) + gSyncUtils.resetPassword(); + else + gSyncUtils.resetPassphrase(); + }, + + openSetup: function (resetSync) { + var win = Services.wm.getMostRecentWindow("Weave:AccountSetup"); + if (win) + win.focus(); + else { + window.openDialog("chrome://communicator/content/sync/syncSetup.xul", + "weaveSetup", "centerscreen,chrome,resizable=no", resetSync); + } + }, + + openQuotaDialog: function () { + let win = Services.wm.getMostRecentWindow("Sync:ViewQuota"); + if (win) + win.focus(); + else + window.openDialog("chrome://communicator/content/sync/syncQuota.xul", "", + "centerscreen,chrome,dialog,modal"); + }, + + openAddDevice: function () { + if (!Weave.Utils.ensureMPUnlocked()) + return; + let win = Services.wm.getMostRecentWindow("Sync:AddDevice"); + if (win) + win.focus(); + else + window.openDialog("chrome://communicator/content/sync/syncAddDevice.xul", + "syncAddDevice", "centerscreen,chrome,resizable=no"); + }, + + resetSync: function () { + this.openSetup(true); + } +}; diff --git a/comm/suite/components/pref/content/pref-sync.xul b/comm/suite/components/pref/content/pref-sync.xul new file mode 100644 index 0000000000..4163c0de70 --- /dev/null +++ b/comm/suite/components/pref/content/pref-sync.xul @@ -0,0 +1,158 @@ +<?xml version="1.0"?> + +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<!DOCTYPE overlay [ +<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd"> +<!ENTITY % syncBrandDTD SYSTEM "chrome://communicator/locale/sync/syncBrand.dtd"> +<!ENTITY % syncDTD SYSTEM "chrome://communicator/locale/pref/pref-sync.dtd"> +%brandDTD; +%syncBrandDTD; +%syncDTD; +]> + +<overlay id="SyncPaneOverlay" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + xmlns:html="http://www.w3.org/1999/xhtml"> + + <prefpane id="sync_pane" + helpTopic="sync_prefs" + onpaneload="gSyncPane.init();"> + + <preferences> + <preference id="engine.addons" name="services.sync.engine.addons" type="bool"/> + <preference id="engine.bookmarks" name="services.sync.engine.bookmarks" type="bool"/> + <preference id="engine.history" name="services.sync.engine.history" type="bool"/> + <preference id="engine.passwords" name="services.sync.engine.passwords" type="bool"/> + <preference id="engine.prefs" name="services.sync.engine.prefs" type="bool"/> + <preference id="engine.tabs" name="services.sync.engine.tabs" type="bool"/> + </preferences> + + <script src="chrome://communicator/content/pref/pref-sync.js"/> + <script src="chrome://communicator/content/sync/syncUtils.js"/> + + <deck id="weavePrefsDeck"> + <vbox id="noAccount" align="center"> + <spacer flex="1"/> + <description id="syncDesc" flex="1"> + &weaveDesc.label; + </description> + <button id="setupButton" + label="&setupButton.label;" + accesskey="&setupButton.accesskey;" + oncommand="gSyncPane.openSetup();"/> + <separator/> + <spacer flex="3"/> + </vbox> + <vbox id="hasAccount"> + <groupbox> + <caption label="&accountGroupboxCaption.label;"/> + <hbox align="center"> + <label value="&accountName.label;" control="accountName"/> + <textbox id="accountName" flex="1" readonly="true"/> + <button type="menu" + label="&manageAccount.label;" + accesskey="&manageAccount.accesskey;"> + <menupopup> + <menuitem label="&viewQuota.label;" + accesskey="&viewQuota.accesskey;" + oncommand="gSyncPane.openQuotaDialog();"/> + <menuseparator/> + <menuitem label="&changePassword.label;" + accesskey="&changePassword.accesskey;" + oncommand="gSyncUtils.changePassword();"/> + <menuitem label="&myRecoveryKey.label;" + accesskey="&myRecoveryKey.accesskey;" + oncommand="gSyncUtils.resetPassphrase();"/> + <menuseparator/> + <menuitem label="&resetSync.label;" + accesskey="&resetSync.accesskey;" + oncommand="gSyncPane.resetSync();"/> + <menuitem label="&unlinkDevice.label;" + accesskey="&unlinkDevice.accesskey;" + oncommand="gSyncPane.startOver(true);"/> + <menuseparator/> + <menuitem label="&addDevice.label;" + accesskey="&addDevice.accesskey;" + oncommand="gSyncPane.openAddDevice();"/> + </menupopup> + </button> + </hbox> + <vbox> + <label value="&syncMy2.label;"/> + <listbox id="syncEnginesList" flex="1"> + <listitem type="checkbox" + label="&engine.addons.label;" + accesskey="&engine.addons.accesskey;" + preference="engine.addons"/> + <listitem type="checkbox" + label="&engine.bookmarks.label;" + accesskey="&engine.bookmarks.accesskey;" + preference="engine.bookmarks"/> + <listitem type="checkbox" + label="&engine.history.label;" + accesskey="&engine.history.accesskey;" + preference="engine.history"/> + <listitem type="checkbox" + label="&engine.passwords.label;" + accesskey="&engine.passwords.accesskey;" + preference="engine.passwords"/> + <listitem type="checkbox" + label="&engine.prefs.label;" + accesskey="&engine.prefs.accesskey;" + preference="engine.prefs"/> + <listitem type="checkbox" + label="&engine.tabs.label;" + accesskey="&engine.tabs.accesskey;" + preference="engine.tabs"/> + </listbox> + </vbox> + </groupbox> + <groupbox> + <grid> + <columns> + <column/> + <column flex="1"/> + </columns> + <rows> + <row align="center"> + <label value="&syncComputerName.label;" + accesskey="&syncComputerName.accesskey;" + control="syncComputerName"/> + <textbox id="syncComputerName" + onchange="gSyncUtils.changeName(this);"/> + </row> + </rows> + </grid> + </groupbox> + <hbox id="tosPP" pack="center"> + <label class="text-link" + onclick="event.stopPropagation(); gSyncUtils.openToS();" + value="&prefs.tosLink.label;"/> + <label class="text-link" + onclick="event.stopPropagation(); gSyncUtils.openPrivacyPolicy();" + value="&prefs.ppLink.label;"/> + </hbox> + </vbox> + <vbox id="needsUpdate" align="center" pack="center"> + <hbox> + <label id="loginError" value=""/> + <button label="&updatePass.label;" + accesskey="&updatePass.accesskey;" + oncommand="gSyncPane.updatePass(); return false;" + id="updatePassButton"/> + <button label="&resetPass.label;" + accesskey="&resetPass.accesskey;" + oncommand="gSyncPane.resetPass(); return false;" + id="resetPassButton"/> + </hbox> + <button label="&unlinkDevice.label;" + accesskey="&unlinkDevice.accesskey;" + oncommand="gSyncPane.startOver(true); return false;" + id="unlinkDeviceButton"/> + </vbox> + </deck> + </prefpane> +</overlay> diff --git a/comm/suite/components/pref/content/pref-tabs.xul b/comm/suite/components/pref/content/pref-tabs.xul new file mode 100644 index 0000000000..24361fba85 --- /dev/null +++ b/comm/suite/components/pref/content/pref-tabs.xul @@ -0,0 +1,113 @@ +<?xml version="1.0"?> +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<!DOCTYPE overlay SYSTEM "chrome://communicator/locale/pref/pref-tabs.dtd"> + +<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + + <prefpane id="tabs_pane" + label="&tabHeader.label;"> + + <preferences id="tabs_preferences"> + <preference id="browser.tabs.autoHide" + name="browser.tabs.autoHide" + type="bool"/> + <preference id="browser.tabs.loadInBackground" + name="browser.tabs.loadInBackground" + type="bool" + inverted="true"/> + <preference id="browser.tabs.loadDivertedInBackground" + name="browser.tabs.loadDivertedInBackground" + type="bool" + inverted="true"/> + <preference id="browser.tabs.avoidBrowserFocus" + name="browser.tabs.avoidBrowserFocus" + type="bool" + inverted="true"/> + <preference id="browser.tabs.warnOnClose" + name="browser.tabs.warnOnClose" + type="bool"/> + <preference id="browser.tabs.insertRelatedAfterCurrent" + name="browser.tabs.insertRelatedAfterCurrent" + type="bool"/> + <preference id="browser.tabs.opentabfor.middleclick" + name="browser.tabs.opentabfor.middleclick" + type="bool"/> + <preference id="browser.tabs.opentabfor.urlbar" + name="browser.tabs.opentabfor.urlbar" + type="bool"/> + <preference id="suite.manager.dataman.openAsDialog" + name="suite.manager.dataman.openAsDialog" + inverted="true" + type="bool"/> + <preference id="suite.manager.addons.openAsDialog" + name="suite.manager.addons.openAsDialog" + inverted="true" + type="bool"/> + </preferences> + + <groupbox id="generalTabPreferences" align="start"> + <caption label="&tabDisplay.label;"/> + <checkbox id="tabStrip" + label="&autoHide.label;" + accesskey="&autoHide.accesskey2;" + preference="browser.tabs.autoHide"/> + <checkbox id="tabBackground" + label="&background.label;" + accesskey="&background.accesskey;" + preference="browser.tabs.loadInBackground"/> + <checkbox id="tabDivertedBackground" + label="&diverted.label;" + accesskey="&diverted.accesskey;" + preference="browser.tabs.loadDivertedInBackground"/> + <checkbox id="tabAvoidBrowserFocus" + label="&browserFocus.label;" + accesskey="&browserFocus.accesskey;" + preference="browser.tabs.avoidBrowserFocus"/> + <checkbox id="tabWarnOnClose" + label="&warnOnClose.label;" + accesskey="&warnOnClose.accesskey;" + preference="browser.tabs.warnOnClose"/> + <checkbox id="tabRelatedAfterCurrent" + label="&relatedAfterCurrent.label;" + accesskey="&relatedAfterCurrent.accesskey;" + preference="browser.tabs.insertRelatedAfterCurrent"/> + </groupbox> + + <groupbox id="useTabPreferences" align="start"> + <caption label="&openTabs.label;"/> + <checkbox id="middleClick" +#ifndef XP_MACOSX + label="&middleClick.label;" + accesskey="&middleClick.accesskey;" +#else + label="&middleClickMac.label;" + accesskey="&middleClickMac.accesskey;" +#endif + preference="browser.tabs.opentabfor.middleclick"/> + <checkbox id="urlBar" +#ifndef XP_MACOSX + label="&urlbar.label;" + accesskey="&urlbar.accesskey;" +#else + label="&urlbarMac.label;" + accesskey="&urlbarMac.accesskey;" +#endif + preference="browser.tabs.opentabfor.urlbar"/> + </groupbox> + + <groupbox id="useManagersPreferences" align="start"> + <caption label="&openManagers.label;"/> + <checkbox id="openDataManager" + label="&openDataManager.label;" + accesskey="&openDataManager.accesskey;" + preference="suite.manager.dataman.openAsDialog"/> + <checkbox id="openAddOnsManager" + label="&openAddOnsManager.label;" + accesskey="&openAddOnsManager.accesskey;" + preference="suite.manager.addons.openAsDialog"/> + </groupbox> + </prefpane> +</overlay> diff --git a/comm/suite/components/pref/content/preferences.js b/comm/suite/components/pref/content/preferences.js new file mode 100644 index 0000000000..091a3904fc --- /dev/null +++ b/comm/suite/components/pref/content/preferences.js @@ -0,0 +1,99 @@ +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// The content of this file is loaded into the scope of the +// prefwindow and will be available to all prefpanes! + +const {AppConstants} = ChromeUtils.import("resource://gre/modules/AppConstants.jsm"); + +function OnLoad() +{ + // Make sure that the preferences window fits the screen. + let dialog = document.documentElement; + let curHeight = dialog.scrollHeight; + let curWidth = dialog.scrollWidth; + + // Leave some space for desktop toolbar and window decoration. + let maxHeight = window.screen.availHeight - 48; + let maxWidth = window.screen.availWidth - 24; + + // Trigger overflow situation within 40px for bug 868495 expansions. + let setHeight = curHeight > maxHeight - 40 ? maxHeight : curHeight; + let setWidth = curWidth > maxWidth ? maxWidth : curWidth; + + if (setHeight == curHeight && setWidth == curWidth) + dialog.setAttribute("overflow", "visible"); + + window.innerHeight = setHeight; + window.innerWidth = setWidth; +} + +function EnableElementById(aElementId, aEnable, aFocus) +{ + EnableElement(document.getElementById(aElementId), aEnable, aFocus); +} + +function EnableElement(aElement, aEnable, aFocus) +{ + let pref = document.getElementById(aElement.getAttribute("preference")); + let enabled = aEnable && !pref.locked; + + aElement.disabled = !enabled; + + if (enabled && aFocus) + aElement.focus(); +} + +function WriteSoundField(aField, aValue) +{ + var file = GetFileFromString(aValue); + if (file) + { + aField.file = file; + aField.label = (AppConstants.platform == "macosx") ? file.leafName : file.path; + } +} + +function SelectSound(aSoundUrlPref) +{ + var soundUrlPref = aSoundUrlPref; + let fp = Cc["@mozilla.org/filepicker;1"] + .createInstance(Ci.nsIFilePicker); + var prefutilitiesBundle = document.getElementById("bundle_prefutilities"); + fp.init(window, prefutilitiesBundle.getString("choosesound"), + Ci.nsIFilePicker.modeOpen); + + let file = GetFileFromString(soundUrlPref.value); + if (file && file.parent && file.parent.exists()) + fp.displayDirectory = file.parent; + + let filterExts = "*.wav; *.wave"; + // On Mac, allow AIFF and CAF files too. + if (AppConstants.platform == "macosx") { + filterExts += "; *.aif; *.aiff; *.caf"; + } + fp.appendFilter(prefutilitiesBundle.getString("SoundFiles"), filterExts); + fp.appendFilters(Ci.nsIFilePicker.filterAll); + fp.open(rv => { + if (rv == Ci.nsIFilePicker.returnOK && fp.fileURL.spec && + fp.fileURL.spec.length > 0) { + soundUrlPref.value = fp.fileURL.spec; + } + }); +} + +function PlaySound(aValue, aMail) +{ + const nsISound = Ci.nsISound; + var sound = Cc["@mozilla.org/sound;1"] + .createInstance(nsISound); + + if (aValue) + sound.play(Services.io.newURI(aValue)); + else if (aMail && (AppConstants.platform != "macosx")) + sound.playEventSound(nsISound.EVENT_NEW_MAIL_RECEIVED); + else + sound.beep(); +} diff --git a/comm/suite/components/pref/content/preferences.xul b/comm/suite/components/pref/content/preferences.xul new file mode 100644 index 0000000000..787d086af5 --- /dev/null +++ b/comm/suite/components/pref/content/preferences.xul @@ -0,0 +1,264 @@ +<?xml version="1.0"?> + +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<?xml-stylesheet type="text/css" href="chrome://communicator/skin/"?> +<?xml-stylesheet type="text/css" href="chrome://communicator/content/communicator.css"?> +<?xml-stylesheet type="text/css" href="chrome://communicator/content/pref/prefpanels.css"?> +<?xml-stylesheet type="text/css" href="chrome://communicator/skin/prefpanels.css"?> +<?xml-stylesheet type="text/css" href="chrome://communicator/skin/preferences.css"?> + +<!DOCTYPE prefwindow SYSTEM "chrome://communicator/locale/pref/preferences.dtd"> + +<prefwindow id="prefDialog" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + title="&prefWindow.title;" +#ifndef XP_WIN +#ifndef XP_MACOSX + style="&prefWindow.size;" +#else + style="&prefWindowMac2.size;" +#endif +#else + style="&prefWindowWin2.size;" +#endif + overflow="auto" + onload="OnLoad();" + windowtype="mozilla:preferences" + buttons="accept,cancel,help" + autopanes="true"> + + <script src="chrome://communicator/content/pref/preferences.js"/> + <!-- Used by pref-smartupdate, pref-privatedata, pref-cookies, pref-images, pref-popups and pref-passwords, as well as pref-sync (gSyncUtils.*open* -> openUILinkIn) --> + <script src="chrome://communicator/content/utilityOverlay.js"/> + <script src="chrome://communicator/content/tasksOverlay.js"/> + + <stringbundleset id="prefBundleset"> + <stringbundle id="bundle_prefutilities" + src="chrome://communicator/locale/pref/prefutilities.properties"/> + <stringbundle id="languageNamesBundle" + src="chrome://global/locale/languageNames.properties"/> + <stringbundle id="regionNamesBundle" + src="chrome://global/locale/regionNames.properties"/> + </stringbundleset> + + <tree id="prefsTree" + style="width: 13em;" + seltype="single" + hidecolumnpicker="true" + hidden="true" + flex="1"> + <treecols> + <treecol id="categoryCol" + label="&categoryHeader;" + primary="true" + flex="1"/> + </treecols> + + <treechildren id="prefsPanelChildren"> + <!-- Appearance items --> + <treeitem container="true" + id="appearanceItem" + label="&appear.label;" + prefpane="appearance_pane" + helpTopic="appearance_pref" + url="chrome://communicator/content/pref/pref-appearance.xul"> + <treechildren id="appearanceChildren"> + <treeitem id="contentItem" + label="&content.label;" + prefpane="content_pane" + helpTopic="appearance_pref_content" + url="chrome://communicator/content/pref/pref-content.xul"/> + <treeitem id="fontsItem" + label="&fonts.label;" + prefpane="fonts_pane" + helpTopic="appearance_pref_fonts" + url="chrome://communicator/content/pref/pref-fonts.xul"/> + <treeitem id="colorsItem" + label="&colors.label;" + prefpane="colors_pane" + helpTopic="appearance_pref_colors" + url="chrome://communicator/content/pref/pref-colors.xul"/> + <treeitem id="mediaItem" + label="&media.label;" + prefpane="media_pane" + helpTopic="appearance_pref_media" + url="chrome://communicator/content/pref/pref-media.xul"/> + <treeitem id="spellingItem" + label="&spellingPane.label;" + prefpane="spelling_pane" + helpTopic="appearance_pref_spelling" + url="chrome://communicator/content/pref/pref-spelling.xul"/> + </treechildren> + </treeitem> + + <!-- Browser items --> + <treeitem container="true" + id="navigatorItem" + label="&navigator.label;" + prefpane="navigator_pane" + helpTopic="navigator_pref_navigator" + url="chrome://communicator/content/pref/pref-navigator.xul"> + <treechildren id="navigatorChildren"> + <treeitem id="historyItem" + label="&history.label;" + prefpane="history_pane" + helpTopic="navigator_pref_history" + url="chrome://communicator/content/pref/pref-history.xul"/> + <treeitem id="languagesItem" + label="&languages.label;" + prefpane="languages_pane" + helpTopic="navigator_pref_languages" + url="chrome://communicator/content/pref/pref-languages.xul"/> + <treeitem id="applicationsItem" + label="&applications.label;" + prefpane="applications_pane" + helpTopic="navigator_pref_helper_applications" + url="chrome://communicator/content/pref/pref-applications.xul"/> + <treeitem id="locationBarItem" + label="&locationBar.label;" + prefpane="locationBar_pane" + helpTopic="navigator_pref_location_bar" + url="chrome://communicator/content/pref/pref-locationbar.xul"/> + <treeitem id="searchItem" + label="&search.label;" + prefpane="search_pane" + helpTopic="navigator_pref_internet_searching" + url="chrome://communicator/content/pref/pref-search.xul"/> + <treeitem id="tabsItem" + label="&tabWindows.label;" + prefpane="tabs_pane" + helpTopic="navigator_pref_tabbed_browsing" + url="chrome://communicator/content/pref/pref-tabs.xul"/> + <treeitem id="linksItem" + label="&links.label;" + prefpane="links_pane" + helpTopic="navigator_pref_link_behavior" + url="chrome://communicator/content/pref/pref-links.xul"/> + <treeitem id="downloadItem" + label="&download.label;" + prefpane="download_pane" + helpTopic="navigator_pref_downloads" + url="chrome://communicator/content/pref/pref-download.xul"/> + </treechildren> + </treeitem> + + <!-- Privacy & Security items --> + <treeitem container="true" + id="securityItem" + prefpane="security_pane" + label="&security.label;" + helpTopic="sec_gen" + url="chrome://communicator/content/pref/pref-security.xul"> + <treechildren id="securityChildren"> + <treeitem id="privatedataItem" + label="&privatedata.label;" + prefpane="privatedata_pane" + helpTopic="privatedata_prefs" + url="chrome://communicator/content/pref/pref-privatedata.xul"/> + <treeitem id="cookiesItem" + label="&cookies.label;" + prefpane="cookies_pane" + helpTopic="cookies_prefs" + url="chrome://communicator/content/pref/pref-cookies.xul"/> + <treeitem id="imagesItem" + label="&images.label;" + prefpane="images_pane" + helpTopic="images_prefs" + url="chrome://communicator/content/pref/pref-images.xul"/> + <treeitem id="popupsItem" + label="&popups.label;" + prefpane="popups_pane" + helpTopic="pop_up_blocking_prefs" + url="chrome://communicator/content/pref/pref-popups.xul"/> + <treeitem id="passwordsItem" + label="&passwords.label;" + prefpane="passwords_pane" + url="chrome://pippki/content/pref-passwords.xul" + helpTopic="passwords_prefs"/> + <treeitem id="sslItem" + label="&ssltls.label;" + prefpane="ssl_pane" + url="chrome://pippki/content/pref-ssl.xul" + helpTopic="ssl_prefs"/> + <treeitem id="certItem" + label="&certs.label;" + prefpane="certs_pane" + url="chrome://pippki/content/pref-certs.xul" + helpTopic="certs_prefs"/> + </treechildren> + </treeitem> + + <!-- Sync + <treeitem id="syncItem" + label="&sync.label;" + prefpane="sync_pane" + url="chrome://communicator/content/pref/pref-sync.xul" + helpTopic="sync_prefs"/> --> + + <!-- Advanced items --> + <treeitem container="true" + id="advancedItem" + label="&advance.label;" + prefpane="advanced_pane" + helpTopic="advanced_pref_advanced" + url="chrome://communicator/content/pref/pref-advanced.xul"> + <treechildren id="advancedChildren"> + <treeitem id="scriptsItem" + label="&scriptsAndWindows2.label;" + prefpane="scripts_pane" + helpTopic="advanced_pref_scripts" + url="chrome://communicator/content/pref/pref-scripts.xul"/> + <treeitem id="keynavItem" + label="&keynav.label;" + prefpane="keynav_pane" + helpTopic="advanced_pref_keyboard_nav" + url="chrome://communicator/content/pref/pref-keynav.xul"/> + <treeitem id="findasyoutypeItem" + label="&findAsYouType.label;" + prefpane="findasyoutype_pane" + helpTopic="advanced_pref_find_as_you_type" + url="chrome://communicator/content/pref/pref-findasyoutype.xul"/> + <treeitem id="cacheItem" + label="&cache.label;" + prefpane="cache_pane" + helpTopic="advanced_pref_cache" + url="chrome://communicator/content/pref/pref-cache.xul"/> + <treeitem id="offlineAppsItem" + label="&offlineApps.label;" + prefpane="offlineapps_pane" + helpTopic="advanced_pref_offlineapps" + url="chrome://communicator/content/pref/pref-offlineapps.xul"/> + <treeitem id="proxiesItem" + label="&proxies.label;" + prefpane="proxies_pane" + helpTopic="advanced_pref_proxies" + url="chrome://communicator/content/pref/pref-proxies.xul"/> + <treeitem id="httpItem" + label="&httpnetworking.label;" + prefpane="http_pane" + helpTopic="advanced_http_networking" + url="chrome://communicator/content/pref/pref-http.xul"/> + <treeitem id="smartupdateItem" + label="&smart.label;" + prefpane="smartupdate_pane" + helpTopic="advanced_pref_installation" + url="chrome://communicator/content/pref/pref-smartupdate.xul"/> + <treeitem id="mousewheelItem" + label="&mousewheel.label;" + prefpane="mousewheel_pane" + helpTopic="advanced_pref_mouse_wheel" + url="chrome://communicator/content/pref/pref-mousewheel.xul"/> + <treeitem id="debuggingItem" + label="&debugging.label;" + prefpane="debugging_pane" + helpTopic="advanced_pref_debugging" + url="chrome://communicator/content/pref/pref-debugging.xul"/> + </treechildren> + </treeitem> + </treechildren> + </tree> + +</prefwindow> diff --git a/comm/suite/components/pref/content/prefpanels.css b/comm/suite/components/pref/content/prefpanels.css new file mode 100755 index 0000000000..c38509d590 --- /dev/null +++ b/comm/suite/components/pref/content/prefpanels.css @@ -0,0 +1,33 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#handlersView > listitem { + -moz-binding: url("chrome://communicator/content/pref/prefpanels.xml#handler"); +} + +.listcell-iconic.handler-action[selected="true"] { + -moz-binding: url("chrome://communicator/content/pref/prefpanels.xml#handler-action-selected"); +} + +#offlineAppsList > listitem { + -moz-binding: url("chrome://communicator/content/pref/prefpanels.xml#offlineapp"); +} + +/* + * Font dialog menulist fixes + */ +#defaultFontType, +#serif, +#sans-serif, +#monospace { + min-width: 30ch; +} + +/* + * Calendar Event/Tasks menulist fix + */ + +#defaults-itemtype-menulist { + min-width: 20ch; +} diff --git a/comm/suite/components/pref/content/prefpanels.xml b/comm/suite/components/pref/content/prefpanels.xml new file mode 100644 index 0000000000..347eac9755 --- /dev/null +++ b/comm/suite/components/pref/content/prefpanels.xml @@ -0,0 +1,59 @@ +<?xml version="1.0"?> + +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + +<!DOCTYPE bindings [ + <!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd"> + %brandDTD; + <!ENTITY % applicationsDTD SYSTEM "chrome://communicator/locale/pref/pref-applications.dtd"> + %applicationsDTD; +]> + +<bindings id="handlerBindings" + xmlns="http://www.mozilla.org/xbl" + xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + xmlns:xbl="http://www.mozilla.org/xbl"> + + <binding id="handler" extends="chrome://global/content/bindings/listbox.xml#listitem"> + <implementation> + <constructor> + this.doCommand(); + </constructor> + <property name="type" readonly="true"> + <getter> + return this.getAttribute("type"); + </getter> + </property> + </implementation> + <content> + <xul:listcell class="listcell-iconic handler-type" align="center" crop="end" + xbl:inherits="tooltiptext=typeDescription,label=typeDescription,image=typeIcon,typeClass"/> + <xul:listcell anonid="action-cell" class="listcell-iconic handler-action" align="center" crop="end" + xbl:inherits="tooltiptext=actionDescription,label=actionDescription,image=actionIcon,appHandlerIcon,selected"/> + </content> + </binding> + + <binding id="handler-action-selected" extends="chrome://global/content/bindings/listbox.xml#listcell"> + <content> + <xul:menulist anonid="action-menu" class="actionsMenu" flex="1" crop="end" selectedIndex="1"> + <xul:menupopup/> + </xul:menulist> + </content> + + <implementation> + <constructor> + this.doCommand(); + </constructor> + </implementation> + </binding> + + <binding id="offlineapp" extends="chrome://global/content/bindings/listbox.xml#listitem"> + <content> + <xul:listcell xbl:inherits="label=host"/> + <xul:listcell xbl:inherits="label=usage"/> + </content> + </binding> + +</bindings> |