summarylogtreecommitdiffstats
path: root/waterfoxproject-kde-56.2.0.patch
diff options
context:
space:
mode:
authorhawkeye1164772019-06-07 20:17:09 +0200
committerhawkeye1164772019-06-07 20:17:09 +0200
commit930acd3c74eed5029f0ee151b85bd469dc987a0b (patch)
treebd0531caf7291567ef7c3cf231484e325b702e63 /waterfoxproject-kde-56.2.0.patch
parent723a7af0bc0249cc27af991f514920abec3ca8e0 (diff)
downloadaur-930acd3c74eed5029f0ee151b85bd469dc987a0b.tar.gz
Update
Diffstat (limited to 'waterfoxproject-kde-56.2.0.patch')
-rw-r--r--waterfoxproject-kde-56.2.0.patch3819
1 files changed, 0 insertions, 3819 deletions
diff --git a/waterfoxproject-kde-56.2.0.patch b/waterfoxproject-kde-56.2.0.patch
deleted file mode 100644
index 536b6471966a..000000000000
--- a/waterfoxproject-kde-56.2.0.patch
+++ /dev/null
@@ -1,3819 +0,0 @@
-# HG changeset patch
-# Parent a930d4c1c3fba77f61071becdc51e3232e0b72ca
-Description: Add KDE integration to Waterfox (toolkit parts). Fixed for Waterfox 56.2.0 by hawkeye116477.
-Author: Wolfgang Rosenauer <wolfgang@rosenauer.org>
-Author: Lubos Lunak <lunak@suse.com>
-Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=140751
- https://bugzilla.novell.com/show_bug.cgi?id=170055
-
-diff --git a/modules/libpref/Preferences.cpp b/modules/libpref/Preferences.cpp
---- a/modules/libpref/Preferences.cpp
-+++ b/modules/libpref/Preferences.cpp
-@@ -33,16 +33,17 @@
- #include "nsIZipReader.h"
- #include "nsPrefBranch.h"
- #include "nsXPIDLString.h"
- #include "nsCRT.h"
- #include "nsCOMArray.h"
- #include "nsXPCOMCID.h"
- #include "nsAutoPtr.h"
- #include "nsPrintfCString.h"
-+#include "nsKDEUtils.h"
-
- #include "nsQuickSort.h"
- #include "PLDHashTable.h"
-
- #include "prefapi.h"
- #include "prefread.h"
- #include "prefapi_private_data.h"
-
-@@ -1435,16 +1436,34 @@ pref_LoadPrefsInDir(nsIFile* aDir, char
-
- static nsresult pref_LoadPrefsInDirList(const char *listId)
- {
- nsresult rv;
- nsCOMPtr<nsIProperties> dirSvc(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv));
- if (NS_FAILED(rv))
- return rv;
-
-+ // make sure we load these special files after all the others
-+ static const char* specialFiles[] = {
-+#if defined(XP_UNIX)
-+ ""
-+#endif
-+ };
-+
-+ if (nsKDEUtils::kdeSession()) {
-+ for(int i = 0;
-+ i < MOZ_ARRAY_LENGTH(specialFiles);
-+ ++i ) {
-+ if (*specialFiles[ i ] == '\0') {
-+ specialFiles[ i ] = "kde.js";
-+ break;
-+ }
-+ }
-+ }
-+
- nsCOMPtr<nsISimpleEnumerator> list;
- dirSvc->Get(listId,
- NS_GET_IID(nsISimpleEnumerator),
- getter_AddRefs(list));
- if (!list)
- return NS_OK;
-
- bool hasMore;
-@@ -1460,17 +1479,17 @@ static nsresult pref_LoadPrefsInDirList(
-
- nsAutoCString leaf;
- path->GetNativeLeafName(leaf);
-
- // Do we care if a file provided by this process fails to load?
- if (Substring(leaf, leaf.Length() - 4).EqualsLiteral(".xpi"))
- ReadExtensionPrefs(path);
- else
-- pref_LoadPrefsInDir(path, nullptr, 0);
-+ pref_LoadPrefsInDir(path, specialFiles, MOZ_ARRAY_LENGTH(specialFiles));
- }
- return NS_OK;
- }
-
- static nsresult pref_ReadPrefFromJar(nsZipArchive* jarReader, const char *name)
- {
- nsZipItemPtr<char> manifest(jarReader, name, true);
- NS_ENSURE_TRUE(manifest.Buffer(), NS_ERROR_NOT_AVAILABLE);
-@@ -1566,24 +1585,36 @@ pref_InitInitialObjects()
- /* these pref file names should not be used: we process them after all other application pref files for backwards compatibility */
- static const char* specialFiles[] = {
- #if defined(XP_MACOSX)
- "macprefs.js"
- #elif defined(XP_WIN)
- "winpref.js"
- #elif defined(XP_UNIX)
- "unix.js"
-+ , "" // placeholder for KDE (empty is otherwise harmless)
- #if defined(_AIX)
- , "aix.js"
- #endif
- #elif defined(XP_BEOS)
- "beos.js"
- #endif
- };
-
-+ if(nsKDEUtils::kdeSession()) { // TODO what if some setup actually requires the helper?
-+ for(int i = 0;
-+ i < MOZ_ARRAY_LENGTH(specialFiles);
-+ ++i ) {
-+ if( *specialFiles[ i ] == '\0' ) {
-+ specialFiles[ i ] = "kde.js";
-+ break;
-+ }
-+ }
-+ }
-+
- rv = pref_LoadPrefsInDir(defaultPrefDir, specialFiles, ArrayLength(specialFiles));
- if (NS_FAILED(rv))
- NS_WARNING("Error parsing application default preferences.");
-
- // Load jar:$app/omni.jar!/defaults/preferences/*.js
- // or jar:$gre/omni.jar!/defaults/preferences/*.js.
- RefPtr<nsZipArchive> appJarReader = mozilla::Omnijar::GetReader(mozilla::Omnijar::APP);
- // GetReader(mozilla::Omnijar::APP) returns null when $app == $gre, in which
-diff --git a/modules/libpref/moz.build b/modules/libpref/moz.build
---- a/modules/libpref/moz.build
-+++ b/modules/libpref/moz.build
-@@ -33,16 +33,20 @@ EXPORTS.mozilla += [
- UNIFIED_SOURCES += [
- 'nsPrefBranch.cpp',
- 'nsPrefsFactory.cpp',
- 'prefapi.cpp',
- 'Preferences.cpp',
- 'prefread.cpp',
- ]
-
-+LOCAL_INCLUDES += [
-+ '/toolkit/xre'
-+]
-+
- include('/ipc/chromium/chromium-config.mozbuild')
-
- FINAL_LIBRARY = 'xul'
-
- DEFINES['OS_ARCH'] = CONFIG['OS_ARCH']
- DEFINES['MOZ_WIDGET_TOOLKIT'] = CONFIG['MOZ_WIDGET_TOOLKIT']
- if CONFIG['MOZ_ENABLE_WEBRENDER']:
- DEFINES['MOZ_ENABLE_WEBRENDER'] = True
-diff --git a/python/mozbuild/mozpack/chrome/flags.py b/python/mozbuild/mozpack/chrome/flags.py
---- a/python/mozbuild/mozpack/chrome/flags.py
-+++ b/python/mozbuild/mozpack/chrome/flags.py
-@@ -220,16 +220,17 @@ class Flags(OrderedDict):
- 'contentaccessible': Flag,
- 'os': StringFlag,
- 'osversion': VersionFlag,
- 'abi': StringFlag,
- 'platform': Flag,
- 'xpcnativewrappers': Flag,
- 'tablet': Flag,
- 'process': StringFlag,
-+ 'desktop': StringFlag,
- }
- RE = re.compile(r'([!<>=]+)')
-
- def __init__(self, *flags):
- '''
- Initialize a set of flags given in string form.
- flags = Flags('contentaccessible=yes', 'appversion>=3.5')
- '''
-diff --git a/python/mozbuild/mozpack/chrome/manifest.py b/python/mozbuild/mozpack/chrome/manifest.py
-index 5c5b51f9949c..31a9f54b9260 100644
---- a/python/mozbuild/mozpack/chrome/manifest.py
-+++ b/python/mozbuild/mozpack/chrome/manifest.py
-@@ -39,6 +39,7 @@ class ManifestEntry(object):
- 'tablet',
- 'process',
- 'contentaccessible',
-+ 'desktop',
- ]
-
- def __init__(self, base, *flags):
-diff --git a/toolkit/components/downloads/moz.build b/toolkit/components/downloads/moz.build
---- a/toolkit/components/downloads/moz.build
-+++ b/toolkit/components/downloads/moz.build
-@@ -37,16 +37,17 @@ UNIFIED_SOURCES += [
- 'nsDownloadManager.cpp'
- ]
-
- FINAL_LIBRARY = 'xul'
-
- LOCAL_INCLUDES += [
- '../protobuf',
- '/ipc/chromium/src',
-+ '/toolkit/xre',
- 'chromium'
- ]
-
- DEFINES['GOOGLE_PROTOBUF_NO_RTTI'] = True
- DEFINES['GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER'] = True
-
- CXXFLAGS += CONFIG['TK_CFLAGS']
-
-diff --git a/toolkit/content/jar.mn b/toolkit/content/jar.mn
---- a/toolkit/content/jar.mn
-+++ b/toolkit/content/jar.mn
-@@ -75,29 +75,33 @@ toolkit.jar:
- content/global/bindings/colorpicker.xml (widgets/colorpicker.xml)
- content/global/bindings/datekeeper.js (widgets/datekeeper.js)
- content/global/bindings/datepicker.js (widgets/datepicker.js)
- content/global/bindings/datetimepicker.xml (widgets/datetimepicker.xml)
- content/global/bindings/datetimepopup.xml (widgets/datetimepopup.xml)
- content/global/bindings/datetimebox.xml (widgets/datetimebox.xml)
- content/global/bindings/datetimebox.css (widgets/datetimebox.css)
- * content/global/bindings/dialog.xml (widgets/dialog.xml)
-+* content/global/bindings/dialog-kde.xml (widgets/dialog-kde.xml)
-+% override chrome://global/content/bindings/dialog.xml chrome://global/content/bindings/dialog-kde.xml desktop=kde
- content/global/bindings/editor.xml (widgets/editor.xml)
- content/global/bindings/expander.xml (widgets/expander.xml)
- content/global/bindings/filefield.xml (widgets/filefield.xml)
- * content/global/bindings/findbar.xml (widgets/findbar.xml)
- content/global/bindings/general.xml (widgets/general.xml)
- content/global/bindings/groupbox.xml (widgets/groupbox.xml)
- content/global/bindings/listbox.xml (widgets/listbox.xml)
- content/global/bindings/menu.xml (widgets/menu.xml)
- content/global/bindings/menulist.xml (widgets/menulist.xml)
- content/global/bindings/notification.xml (widgets/notification.xml)
- content/global/bindings/numberbox.xml (widgets/numberbox.xml)
- content/global/bindings/popup.xml (widgets/popup.xml)
- * content/global/bindings/preferences.xml (widgets/preferences.xml)
-+* content/global/bindings/preferences-kde.xml (widgets/preferences-kde.xml)
-+% override chrome://global/content/bindings/preferences.xml chrome://global/content/bindings/preferences-kde.xml desktop=kde
- content/global/bindings/progressmeter.xml (widgets/progressmeter.xml)
- content/global/bindings/radio.xml (widgets/radio.xml)
- content/global/bindings/remote-browser.xml (widgets/remote-browser.xml)
- content/global/bindings/resizer.xml (widgets/resizer.xml)
- content/global/bindings/richlistbox.xml (widgets/richlistbox.xml)
- content/global/bindings/scale.xml (widgets/scale.xml)
- content/global/bindings/scrollbar.xml (widgets/scrollbar.xml)
- content/global/bindings/scrollbox.xml (widgets/scrollbox.xml)
-diff --git a/toolkit/content/widgets/dialog-kde.xml b/toolkit/content/widgets/dialog-kde.xml
-new file mode 100644
---- /dev/null
-+++ b/toolkit/content/widgets/dialog-kde.xml
-@@ -0,0 +1,455 @@
-+<?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/. -->
-+
-+
-+<bindings id="dialogBindings"
-+ 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="dialog" extends="chrome://global/content/bindings/general.xml#root-element">
-+ <resources>
-+ <stylesheet src="chrome://global/skin/dialog.css"/>
-+ </resources>
-+ <content>
-+ <xul:vbox class="box-inherit dialog-content-box" flex="1">
-+ <children/>
-+ </xul:vbox>
-+
-+ <xul:hbox class="dialog-button-box" anonid="buttons"
-+ xbl:inherits="pack=buttonpack,align=buttonalign,dir=buttondir,orient=buttonorient"
-+#ifdef XP_UNIX_GNOME
-+ >
-+ <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/>
-+ <xul:button dlgtype="help" class="dialog-button" hidden="true"/>
-+ <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/>
-+ <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/>
-+ <xul:spacer anonid="spacer" flex="1"/>
-+ <xul:button dlgtype="cancel" class="dialog-button"/>
-+ <xul:button dlgtype="accept" class="dialog-button" xbl:inherits="disabled=buttondisabledaccept"/>
-+#elif XP_UNIX
-+ >
-+ <xul:button dlgtype="help" class="dialog-button" hidden="true"/>
-+ <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/>
-+ <xul:spacer anonid="spacer" flex="1"/>
-+ <xul:button dlgtype="accept" class="dialog-button" xbl:inherits="disabled=buttondisabledaccept"/>
-+ <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/>
-+ <xul:button dlgtype="cancel" class="dialog-button"/>
-+ <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/>
-+#else
-+ pack="end">
-+ <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/>
-+ <xul:spacer anonid="spacer" flex="1" hidden="true"/>
-+ <xul:button dlgtype="accept" class="dialog-button" xbl:inherits="disabled=buttondisabledaccept"/>
-+ <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/>
-+ <xul:button dlgtype="cancel" class="dialog-button"/>
-+ <xul:button dlgtype="help" class="dialog-button" hidden="true"/>
-+ <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/>
-+#endif
-+ </xul:hbox>
-+ </content>
-+
-+ <implementation>
-+ <field name="_mStrBundle">null</field>
-+ <field name="_closeHandler">(function(event) {
-+ if (!document.documentElement.cancelDialog())
-+ event.preventDefault();
-+ })</field>
-+
-+ <property name="buttons"
-+ onget="return this.getAttribute('buttons');"
-+ onset="this._configureButtons(val); return val;"/>
-+
-+ <property name="defaultButton">
-+ <getter>
-+ <![CDATA[
-+ if (this.hasAttribute("defaultButton"))
-+ return this.getAttribute("defaultButton");
-+ return "accept"; // default to the accept button
-+ ]]>
-+ </getter>
-+ <setter>
-+ <![CDATA[
-+ this._setDefaultButton(val);
-+ return val;
-+ ]]>
-+ </setter>
-+ </property>
-+
-+ <method name="acceptDialog">
-+ <body>
-+ <![CDATA[
-+ return this._doButtonCommand("accept");
-+ ]]>
-+ </body>
-+ </method>
-+
-+ <method name="cancelDialog">
-+ <body>
-+ <![CDATA[
-+ return this._doButtonCommand("cancel");
-+ ]]>
-+ </body>
-+ </method>
-+
-+ <method name="getButton">
-+ <parameter name="aDlgType"/>
-+ <body>
-+ <![CDATA[
-+ return this._buttons[aDlgType];
-+ ]]>
-+ </body>
-+ </method>
-+
-+ <method name="moveToAlertPosition">
-+ <body>
-+ <![CDATA[
-+ // hack. we need this so the window has something like its final size
-+ if (window.outerWidth == 1) {
-+ dump("Trying to position a sizeless window; caller should have called sizeToContent() or sizeTo(). See bug 75649.\n");
-+ sizeToContent();
-+ }
-+
-+ if (opener) {
-+ var xOffset = (opener.outerWidth - window.outerWidth) / 2;
-+ var yOffset = opener.outerHeight / 5;
-+
-+ var newX = opener.screenX + xOffset;
-+ var newY = opener.screenY + yOffset;
-+ } else {
-+ newX = (screen.availWidth - window.outerWidth) / 2;
-+ newY = (screen.availHeight - window.outerHeight) / 2;
-+ }
-+
-+ // ensure the window is fully onscreen (if smaller than the screen)
-+ if (newX < screen.availLeft)
-+ newX = screen.availLeft + 20;
-+ if ((newX + window.outerWidth) > (screen.availLeft + screen.availWidth))
-+ newX = (screen.availLeft + screen.availWidth) - window.outerWidth - 20;
-+
-+ if (newY < screen.availTop)
-+ newY = screen.availTop + 20;
-+ if ((newY + window.outerHeight) > (screen.availTop + screen.availHeight))
-+ newY = (screen.availTop + screen.availHeight) - window.outerHeight - 60;
-+
-+ window.moveTo( newX, newY );
-+ ]]>
-+ </body>
-+ </method>
-+
-+ <method name="centerWindowOnScreen">
-+ <body>
-+ <![CDATA[
-+ var xOffset = screen.availWidth / 2 - window.outerWidth / 2;
-+ var yOffset = screen.availHeight / 2 - window.outerHeight / 2;
-+
-+ xOffset = xOffset > 0 ? xOffset : 0;
-+ yOffset = yOffset > 0 ? yOffset : 0;
-+ window.moveTo(xOffset, yOffset);
-+ ]]>
-+ </body>
-+ </method>
-+
-+ <constructor>
-+ <![CDATA[
-+ this._configureButtons(this.buttons);
-+
-+ // listen for when window is closed via native close buttons
-+ window.addEventListener("close", this._closeHandler);
-+
-+ // for things that we need to initialize after onload fires
-+ window.addEventListener("load", this.postLoadInit);
-+
-+ window.moveToAlertPosition = this.moveToAlertPosition;
-+ window.centerWindowOnScreen = this.centerWindowOnScreen;
-+ ]]>
-+ </constructor>
-+
-+ <method name="postLoadInit">
-+ <parameter name="aEvent"/>
-+ <body>
-+ <![CDATA[
-+ function focusInit() {
-+ const dialog = document.documentElement;
-+ const defaultButton = dialog.getButton(dialog.defaultButton);
-+ // give focus to the first focusable element in the dialog
-+ if (!document.commandDispatcher.focusedElement) {
-+ document.commandDispatcher.advanceFocusIntoSubtree(dialog);
-+
-+ var focusedElt = document.commandDispatcher.focusedElement;
-+ if (focusedElt) {
-+ var initialFocusedElt = focusedElt;
-+ while (focusedElt.localName == "tab" ||
-+ focusedElt.getAttribute("noinitialfocus") == "true") {
-+ document.commandDispatcher.advanceFocusIntoSubtree(focusedElt);
-+ focusedElt = document.commandDispatcher.focusedElement;
-+ if (focusedElt == initialFocusedElt)
-+ break;
-+ }
-+
-+ if (initialFocusedElt.localName == "tab") {
-+ if (focusedElt.hasAttribute("dlgtype")) {
-+ // We don't want to focus on anonymous OK, Cancel, etc. buttons,
-+ // so return focus to the tab itself
-+ initialFocusedElt.focus();
-+ }
-+ } else if (!/Mac/.test(navigator.platform) &&
-+ focusedElt.hasAttribute("dlgtype") && focusedElt != defaultButton) {
-+ defaultButton.focus();
-+ }
-+ }
-+ }
-+
-+ try {
-+ if (defaultButton)
-+ window.notifyDefaultButtonLoaded(defaultButton);
-+ } catch (e) { }
-+ }
-+
-+ // Give focus after onload completes, see bug 103197.
-+ setTimeout(focusInit, 0);
-+ ]]>
-+ </body>
-+ </method>
-+
-+ <property name="mStrBundle">
-+ <getter>
-+ <![CDATA[
-+ if (!this._mStrBundle) {
-+ // need to create string bundle manually instead of using <xul:stringbundle/>
-+ // see bug 63370 for details
-+ this._mStrBundle = Components.classes["@mozilla.org/intl/stringbundle;1"]
-+ .getService(Components.interfaces.nsIStringBundleService)
-+ .createBundle("chrome://global/locale/dialog.properties");
-+ }
-+ return this._mStrBundle;
-+ ]]></getter>
-+ </property>
-+
-+ <method name="_configureButtons">
-+ <parameter name="aButtons"/>
-+ <body>
-+ <![CDATA[
-+ // by default, get all the anonymous button elements
-+ var buttons = {};
-+ this._buttons = buttons;
-+ buttons.accept = document.getAnonymousElementByAttribute(this, "dlgtype", "accept");
-+ buttons.cancel = document.getAnonymousElementByAttribute(this, "dlgtype", "cancel");
-+ buttons.extra1 = document.getAnonymousElementByAttribute(this, "dlgtype", "extra1");
-+ buttons.extra2 = document.getAnonymousElementByAttribute(this, "dlgtype", "extra2");
-+ buttons.help = document.getAnonymousElementByAttribute(this, "dlgtype", "help");
-+ buttons.disclosure = document.getAnonymousElementByAttribute(this, "dlgtype", "disclosure");
-+
-+ // look for any overriding explicit button elements
-+ var exBtns = this.getElementsByAttribute("dlgtype", "*");
-+ var dlgtype;
-+ var i;
-+ for (i = 0; i < exBtns.length; ++i) {
-+ dlgtype = exBtns[i].getAttribute("dlgtype");
-+ buttons[dlgtype].hidden = true; // hide the anonymous button
-+ buttons[dlgtype] = exBtns[i];
-+ }
-+
-+ // add the label and oncommand handler to each button
-+ for (dlgtype in buttons) {
-+ var button = buttons[dlgtype];
-+ button.addEventListener("command", this._handleButtonCommand, true);
-+
-+ // don't override custom labels with pre-defined labels on explicit buttons
-+ if (!button.hasAttribute("label")) {
-+ // dialog attributes override the default labels in dialog.properties
-+ if (this.hasAttribute("buttonlabel" + dlgtype)) {
-+ button.setAttribute("label", this.getAttribute("buttonlabel" + dlgtype));
-+ if (this.hasAttribute("buttonaccesskey" + dlgtype))
-+ button.setAttribute("accesskey", this.getAttribute("buttonaccesskey" + dlgtype));
-+ } else if (dlgtype != "extra1" && dlgtype != "extra2") {
-+ button.setAttribute("label", this.mStrBundle.GetStringFromName("button-" + dlgtype));
-+ var accessKey = this.mStrBundle.GetStringFromName("accesskey-" + dlgtype);
-+ if (accessKey)
-+ button.setAttribute("accesskey", accessKey);
-+ }
-+ }
-+ // allow specifying alternate icons in the dialog header
-+ if (!button.hasAttribute("icon")) {
-+ // if there's an icon specified, use that
-+ if (this.hasAttribute("buttonicon" + dlgtype))
-+ button.setAttribute("icon", this.getAttribute("buttonicon" + dlgtype));
-+ // otherwise set defaults
-+ else
-+ switch (dlgtype) {
-+ case "accept":
-+ button.setAttribute("icon", "accept");
-+ break;
-+ case "cancel":
-+ button.setAttribute("icon", "cancel");
-+ break;
-+ case "disclosure":
-+ button.setAttribute("icon", "properties");
-+ break;
-+ case "help":
-+ button.setAttribute("icon", "help");
-+ break;
-+ default:
-+ break;
-+ }
-+ }
-+ }
-+
-+ // ensure that hitting enter triggers the default button command
-+ this.defaultButton = this.defaultButton;
-+
-+ // if there is a special button configuration, use it
-+ if (aButtons) {
-+ // expect a comma delimited list of dlgtype values
-+ var list = aButtons.split(",");
-+
-+ // mark shown dlgtypes as true
-+ var shown = { accept: false, cancel: false, help: false,
-+ disclosure: false, extra1: false, extra2: false };
-+ for (i = 0; i < list.length; ++i)
-+ shown[list[i].replace(/ /g, "")] = true;
-+
-+ // hide/show the buttons we want
-+ for (dlgtype in buttons)
-+ buttons[dlgtype].hidden = !shown[dlgtype];
-+
-+ // show the spacer on Windows only when the extra2 button is present
-+ if (/Win/.test(navigator.platform)) {
-+ var spacer = document.getAnonymousElementByAttribute(this, "anonid", "spacer");
-+ spacer.removeAttribute("hidden");
-+ spacer.setAttribute("flex", shown["extra2"] ? "1" : "0");
-+ }
-+ }
-+ ]]>
-+ </body>
-+ </method>
-+
-+ <method name="_setDefaultButton">
-+ <parameter name="aNewDefault"/>
-+ <body>
-+ <![CDATA[
-+ // remove the default attribute from the previous default button, if any
-+ var oldDefaultButton = this.getButton(this.defaultButton);
-+ if (oldDefaultButton)
-+ oldDefaultButton.removeAttribute("default");
-+
-+ var newDefaultButton = this.getButton(aNewDefault);
-+ if (newDefaultButton) {
-+ this.setAttribute("defaultButton", aNewDefault);
-+ newDefaultButton.setAttribute("default", "true");
-+ } else {
-+ this.setAttribute("defaultButton", "none");
-+ if (aNewDefault != "none")
-+ dump("invalid new default button: " + aNewDefault + ", assuming: none\n");
-+ }
-+ ]]>
-+ </body>
-+ </method>
-+
-+ <method name="_handleButtonCommand">
-+ <parameter name="aEvent"/>
-+ <body>
-+ <![CDATA[
-+ return document.documentElement._doButtonCommand(
-+ aEvent.target.getAttribute("dlgtype"));
-+ ]]>
-+ </body>
-+ </method>
-+
-+ <method name="_doButtonCommand">
-+ <parameter name="aDlgType"/>
-+ <body>
-+ <![CDATA[
-+ var button = this.getButton(aDlgType);
-+ if (!button.disabled) {
-+ var noCancel = this._fireButtonEvent(aDlgType);
-+ if (noCancel) {
-+ if (aDlgType == "accept" || aDlgType == "cancel") {
-+ var closingEvent = new CustomEvent("dialogclosing", {
-+ bubbles: true,
-+ detail: { button: aDlgType },
-+ });
-+ this.dispatchEvent(closingEvent);
-+ window.close();
-+ }
-+ }
-+ return noCancel;
-+ }
-+ return true;
-+ ]]>
-+ </body>
-+ </method>
-+
-+ <method name="_fireButtonEvent">
-+ <parameter name="aDlgType"/>
-+ <body>
-+ <![CDATA[
-+ var event = document.createEvent("Events");
-+ event.initEvent("dialog" + aDlgType, true, true);
-+
-+ // handle dom event handlers
-+ var noCancel = this.dispatchEvent(event);
-+
-+ // handle any xml attribute event handlers
-+ var handler = this.getAttribute("ondialog" + aDlgType);
-+ if (handler != "") {
-+ var fn = new Function("event", handler);
-+ var returned = fn(event);
-+ if (returned == false)
-+ noCancel = false;
-+ }
-+
-+ return noCancel;
-+ ]]>
-+ </body>
-+ </method>
-+
-+ <method name="_hitEnter">
-+ <parameter name="evt"/>
-+ <body>
-+ <![CDATA[
-+ if (evt.defaultPrevented)
-+ return;
-+
-+ var btn = this.getButton(this.defaultButton);
-+ if (btn)
-+ this._doButtonCommand(this.defaultButton);
-+ ]]>
-+ </body>
-+ </method>
-+
-+ </implementation>
-+
-+ <handlers>
-+ <handler event="keypress" keycode="VK_RETURN"
-+ group="system" action="this._hitEnter(event);"/>
-+ <handler event="keypress" keycode="VK_ESCAPE" group="system">
-+ if (!event.defaultPrevented)
-+ this.cancelDialog();
-+ </handler>
-+#ifdef XP_MACOSX
-+ <handler event="keypress" key="." modifiers="meta" phase="capturing" action="this.cancelDialog();"/>
-+#else
-+ <handler event="focus" phase="capturing">
-+ var btn = this.getButton(this.defaultButton);
-+ if (btn)
-+ btn.setAttribute("default", event.originalTarget == btn || !(event.originalTarget instanceof Components.interfaces.nsIDOMXULButtonElement));
-+ </handler>
-+#endif
-+ </handlers>
-+
-+ </binding>
-+
-+ <binding id="dialogheader">
-+ <resources>
-+ <stylesheet src="chrome://global/skin/dialog.css"/>
-+ </resources>
-+ <content>
-+ <xul:label class="dialogheader-title" xbl:inherits="value=title,crop" crop="right" flex="1"/>
-+ <xul:label class="dialogheader-description" xbl:inherits="value=description"/>
-+ </content>
-+ </binding>
-+
-+</bindings>
-diff --git a/toolkit/content/widgets/preferences-kde.xml b/toolkit/content/widgets/preferences-kde.xml
-new file mode 100644
---- /dev/null
-+++ b/toolkit/content/widgets/preferences-kde.xml
-@@ -0,0 +1,1409 @@
-+<?xml version="1.0"?>
-+
-+<!DOCTYPE bindings [
-+ <!ENTITY % preferencesDTD SYSTEM "chrome://global/locale/preferences.dtd">
-+ %preferencesDTD;
-+ <!ENTITY % globalKeysDTD SYSTEM "chrome://global/locale/globalKeys.dtd">
-+ %globalKeysDTD;
-+]>
-+
-+<bindings id="preferencesBindings"
-+ xmlns="http://www.mozilla.org/xbl"
-+ xmlns:xbl="http://www.mozilla.org/xbl"
-+ xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-+
-+#
-+# = Preferences Window Framework
-+#
-+# The syntax for use looks something like:
-+#
-+# <prefwindow>
-+# <prefpane id="prefPaneA">
-+# <preferences>
-+# <preference id="preference1" name="app.preference1" type="bool" onchange="foo();"/>
-+# <preference id="preference2" name="app.preference2" type="bool" useDefault="true"/>
-+# </preferences>
-+# <checkbox label="Preference" preference="preference1"/>
-+# </prefpane>
-+# </prefwindow>
-+#
-+
-+ <binding id="preferences">
-+ <implementation implements="nsIObserver">
-+ <method name="_constructAfterChildren">
-+ <body>
-+ <![CDATA[
-+ // This method will be called after the last of the child
-+ // <preference> elements is constructed. Its purpose is to propagate
-+ // the values to the associated form elements. Sometimes the code for
-+ // some <preference> initializers depend on other <preference> elements
-+ // being initialized so we wait and call updateElements on all of them
-+ // once the last one has been constructed. See bugs 997570 and 992185.
-+
-+ var elements = this.getElementsByTagName("preference");
-+ for (let element of elements) {
-+ element.updateElements();
-+ }
-+
-+ this._constructAfterChildrenCalled = true;
-+ ]]>
-+ </body>
-+ </method>
-+ <method name="observe">
-+ <parameter name="aSubject"/>
-+ <parameter name="aTopic"/>
-+ <parameter name="aData"/>
-+ <body>
-+ <![CDATA[
-+ for (var i = 0; i < this.childNodes.length; ++i) {
-+ var preference = this.childNodes[i];
-+ if (preference.name == aData) {
-+ preference.value = preference.valueFromPreferences;
-+ }
-+ }
-+ ]]>
-+ </body>
-+ </method>
-+
-+ <method name="fireChangedEvent">
-+ <parameter name="aPreference"/>
-+ <body>
-+ <![CDATA[
-+ // Value changed, synthesize an event
-+ try {
-+ var event = document.createEvent("Events");
-+ event.initEvent("change", true, true);
-+ aPreference.dispatchEvent(event);
-+ } catch (e) {
-+ Components.utils.reportError(e);
-+ }
-+ ]]>
-+ </body>
-+ </method>
-+
-+ <field name="service">
-+ Components.classes["@mozilla.org/preferences-service;1"]
-+ .getService(Components.interfaces.nsIPrefService);
-+ </field>
-+ <field name="rootBranch">
-+ Components.classes["@mozilla.org/preferences-service;1"]
-+ .getService(Components.interfaces.nsIPrefBranch);
-+ </field>
-+ <field name="defaultBranch">
-+ this.service.getDefaultBranch("");
-+ </field>
-+ <field name="rootBranchInternal">
-+ Components.classes["@mozilla.org/preferences-service;1"]
-+ .getService(Components.interfaces.nsIPrefBranchInternal);
-+ </field>
-+ <property name="type" readonly="true">
-+ <getter>
-+ <![CDATA[
-+ return document.documentElement.type || "";
-+ ]]>
-+ </getter>
-+ </property>
-+ <property name="instantApply" readonly="true">
-+ <getter>
-+ <![CDATA[
-+ var doc = document.documentElement;
-+ return this.type == "child" ? doc.instantApply
-+ : doc.instantApply || this.rootBranch.getBoolPref("browser.preferences.instantApply");
-+ ]]>
-+ </getter>
-+ </property>
-+
-+ <!-- We want to call _constructAfterChildren after all child
-+ <preference> elements have been constructed. To do this, we get
-+ and store the node list of all child <preference> elements in the
-+ constructor, and maintain a count which is incremented in the
-+ constructor of <preference>. _constructAfterChildren is called
-+ when the count matches the length of the list. -->
-+ <field name="_constructedChildrenCount">0</field>
-+ <field name="_preferenceChildren">null</field>
-+ <!-- Some <preference> elements are added dynamically after
-+ _constructAfterChildren has already been called - we want to
-+ avoid looping over all of them again in this case so we remember
-+ if we already called it. -->
-+ <field name="_constructAfterChildrenCalled">false</field>
-+ <constructor>
-+ <![CDATA[
-+ this._preferenceChildren = this.getElementsByTagName("preference");
-+ ]]>
-+ </constructor>
-+ </implementation>
-+ </binding>
-+
-+ <binding id="preference">
-+ <implementation>
-+ <constructor>
-+ <![CDATA[
-+ // if the element has been inserted without the name attribute set,
-+ // we have nothing to do here
-+ if (!this.name)
-+ return;
-+
-+ this.preferences.rootBranchInternal
-+ .addObserver(this.name, this.preferences);
-+ // In non-instant apply mode, we must try and use the last saved state
-+ // from any previous opens of a child dialog instead of the value from
-+ // preferences, to pick up any edits a user may have made.
-+
-+ var secMan = Components.classes["@mozilla.org/scriptsecuritymanager;1"]
-+ .getService(Components.interfaces.nsIScriptSecurityManager);
-+ if (this.preferences.type == "child" &&
-+ !this.instantApply && window.opener &&
-+ secMan.isSystemPrincipal(window.opener.document.nodePrincipal)) {
-+ var pdoc = window.opener.document;
-+
-+ // Try to find a preference element for the same preference.
-+ var preference = null;
-+ var parentPreferences = pdoc.getElementsByTagName("preferences");
-+ for (var k = 0; (k < parentPreferences.length && !preference); ++k) {
-+ var parentPrefs = parentPreferences[k]
-+ .getElementsByAttribute("name", this.name);
-+ for (var l = 0; (l < parentPrefs.length && !preference); ++l) {
-+ if (parentPrefs[l].localName == "preference")
-+ preference = parentPrefs[l];
-+ }
-+ }
-+
-+ // Don't use the value setter here, we don't want updateElements to be prematurely fired.
-+ this._value = preference ? preference.value : this.valueFromPreferences;
-+ } else {
-+ this._value = this.valueFromPreferences;
-+ }
-+ if (this.preferences._constructAfterChildrenCalled) {
-+ // This <preference> was added after _constructAfterChildren() was already called.
-+ // We can directly call updateElements().
-+ this.updateElements();
-+ return;
-+ }
-+ this.preferences._constructedChildrenCount++;
-+ if (this.preferences._constructedChildrenCount ==
-+ this.preferences._preferenceChildren.length) {
-+ // This is the last <preference>, time to updateElements() on all of them.
-+ this.preferences._constructAfterChildren();
-+ }
-+ ]]>
-+ </constructor>
-+ <destructor>
-+ this.preferences.rootBranchInternal
-+ .removeObserver(this.name, this.preferences);
-+ </destructor>
-+ <field name="_constructed">false</field>
-+ <property name="instantApply">
-+ <getter>
-+ if (this.getAttribute("instantApply") == "false")
-+ return false;
-+ return this.getAttribute("instantApply") == "true" || this.preferences.instantApply;
-+ </getter>
-+ </property>
-+
-+ <property name="preferences" onget="return this.parentNode"/>
-+ <property name="name" onget="return this.getAttribute('name');">
-+ <setter>
-+ if (val == this.name)
-+ return val;
-+
-+ this.preferences.rootBranchInternal
-+ .removeObserver(this.name, this.preferences);
-+ this.setAttribute("name", val);
-+ this.preferences.rootBranchInternal
-+ .addObserver(val, this.preferences);
-+
-+ return val;
-+ </setter>
-+ </property>
-+ <property name="type" onget="return this.getAttribute('type');"
-+ onset="this.setAttribute('type', val); return val;"/>
-+ <property name="inverted" onget="return this.getAttribute('inverted') == 'true';"
-+ onset="this.setAttribute('inverted', val); return val;"/>
-+ <property name="readonly" onget="return this.getAttribute('readonly') == 'true';"
-+ onset="this.setAttribute('readonly', val); return val;"/>
-+
-+ <field name="_value">null</field>
-+ <method name="_setValue">
-+ <parameter name="aValue"/>
-+ <body>
-+ <![CDATA[
-+ if (this.value !== aValue) {
-+ this._value = aValue;
-+ if (this.instantApply)
-+ this.valueFromPreferences = aValue;
-+ this.preferences.fireChangedEvent(this);
-+ }
-+ return aValue;
-+ ]]>
-+ </body>
-+ </method>
-+ <property name="value" onget="return this._value" onset="return this._setValue(val);"/>
-+
-+ <property name="locked">
-+ <getter>
-+ return this.preferences.rootBranch.prefIsLocked(this.name);
-+ </getter>
-+ </property>
-+
-+ <property name="disabled">
-+ <getter>
-+ return this.getAttribute("disabled") == "true";
-+ </getter>
-+ <setter>
-+ <![CDATA[
-+ if (val)
-+ this.setAttribute("disabled", "true");
-+ else
-+ this.removeAttribute("disabled");
-+
-+ if (!this.id)
-+ return val;
-+
-+ var elements = document.getElementsByAttribute("preference", this.id);
-+ for (var i = 0; i < elements.length; ++i) {
-+ elements[i].disabled = val;
-+
-+ var labels = document.getElementsByAttribute("control", elements[i].id);
-+ for (var j = 0; j < labels.length; ++j)
-+ labels[j].disabled = val;
-+ }
-+
-+ return val;
-+ ]]>
-+ </setter>
-+ </property>
-+
-+ <property name="tabIndex">
-+ <getter>
-+ return parseInt(this.getAttribute("tabindex"));
-+ </getter>
-+ <setter>
-+ <![CDATA[
-+ if (val)
-+ this.setAttribute("tabindex", val);
-+ else
-+ this.removeAttribute("tabindex");
-+
-+ if (!this.id)
-+ return val;
-+
-+ var elements = document.getElementsByAttribute("preference", this.id);
-+ for (var i = 0; i < elements.length; ++i) {
-+ elements[i].tabIndex = val;
-+
-+ var labels = document.getElementsByAttribute("control", elements[i].id);
-+ for (var j = 0; j < labels.length; ++j)
-+ labels[j].tabIndex = val;
-+ }
-+
-+ return val;
-+ ]]>
-+ </setter>
-+ </property>
-+
-+ <property name="hasUserValue">
-+ <getter>
-+ <![CDATA[
-+ return this.preferences.rootBranch.prefHasUserValue(this.name) &&
-+ this.value !== undefined;
-+ ]]>
-+ </getter>
-+ </property>
-+
-+ <method name="reset">
-+ <body>
-+ // defer reset until preference update
-+ this.value = undefined;
-+ </body>
-+ </method>
-+
-+ <field name="_useDefault">false</field>
-+ <property name="defaultValue">
-+ <getter>
-+ <![CDATA[
-+ this._useDefault = true;
-+ var val = this.valueFromPreferences;
-+ this._useDefault = false;
-+ return val;
-+ ]]>
-+ </getter>
-+ </property>
-+
-+ <property name="_branch">
-+ <getter>
-+ return this._useDefault ? this.preferences.defaultBranch : this.preferences.rootBranch;
-+ </getter>
-+ </property>
-+
-+ <field name="batching">false</field>
-+
-+ <method name="_reportUnknownType">
-+ <body>
-+ <![CDATA[
-+ var consoleService = Components.classes["@mozilla.org/consoleservice;1"]
-+ .getService(Components.interfaces.nsIConsoleService);
-+ var msg = "<preference> with id='" + this.id + "' and name='" +
-+ this.name + "' has unknown type '" + this.type + "'.";
-+ consoleService.logStringMessage(msg);
-+ ]]>
-+ </body>
-+ </method>
-+
-+ <property name="valueFromPreferences">
-+ <getter>
-+ <![CDATA[
-+ try {
-+ // Force a resync of value with preferences.
-+ switch (this.type) {
-+ case "int":
-+ return this._branch.getIntPref(this.name);
-+ case "bool":
-+ var val = this._branch.getBoolPref(this.name);
-+ return this.inverted ? !val : val;
-+ case "wstring":
-+ return this._branch
-+ .getComplexValue(this.name, Components.interfaces.nsIPrefLocalizedString)
-+ .data;
-+ case "string":
-+ case "unichar":
-+ return this._branch.getStringPref(this.name);
-+ case "fontname":
-+ var family = this._branch.getStringPref(this.name);
-+ var fontEnumerator = Components.classes["@mozilla.org/gfx/fontenumerator;1"]
-+ .createInstance(Components.interfaces.nsIFontEnumerator);
-+ return fontEnumerator.getStandardFamilyName(family);
-+ case "file":
-+ var f = this._branch
-+ .getComplexValue(this.name, Components.interfaces.nsILocalFile);
-+ return f;
-+ default:
-+ this._reportUnknownType();
-+ }
-+ } catch (e) { }
-+ return null;
-+ ]]>
-+ </getter>
-+ <setter>
-+ <![CDATA[
-+ // Exit early if nothing to do.
-+ if (this.readonly || this.valueFromPreferences == val)
-+ return val;
-+
-+ // The special value undefined means 'reset preference to default'.
-+ if (val === undefined) {
-+ this.preferences.rootBranch.clearUserPref(this.name);
-+ return val;
-+ }
-+
-+ // Force a resync of preferences with value.
-+ switch (this.type) {
-+ case "int":
-+ this.preferences.rootBranch.setIntPref(this.name, val);
-+ break;
-+ case "bool":
-+ this.preferences.rootBranch.setBoolPref(this.name, this.inverted ? !val : val);
-+ break;
-+ case "wstring":
-+ var pls = Components.classes["@mozilla.org/pref-localizedstring;1"]
-+ .createInstance(Components.interfaces.nsIPrefLocalizedString);
-+ pls.data = val;
-+ this.preferences.rootBranch
-+ .setComplexValue(this.name, Components.interfaces.nsIPrefLocalizedString, pls);
-+ break;
-+ case "string":
-+ case "unichar":
-+ case "fontname":
-+ this.preferences.rootBranch.setStringPref(this.name, val);
-+ break;
-+ case "file":
-+ var lf;
-+ if (typeof(val) == "string") {
-+ lf = Components.classes["@mozilla.org/file/local;1"]
-+ .createInstance(Components.interfaces.nsILocalFile);
-+ lf.persistentDescriptor = val;
-+ if (!lf.exists())
-+ lf.initWithPath(val);
-+ } else
-+ lf = val.QueryInterface(Components.interfaces.nsILocalFile);
-+ this.preferences.rootBranch
-+ .setComplexValue(this.name, Components.interfaces.nsILocalFile, lf);
-+ break;
-+ default:
-+ this._reportUnknownType();
-+ }
-+ if (!this.batching)
-+ this.preferences.service.savePrefFile(null);
-+ return val;
-+ ]]>
-+ </setter>
-+ </property>
-+
-+ <method name="setElementValue">
-+ <parameter name="aElement"/>
-+ <body>
-+ <![CDATA[
-+ if (this.locked)
-+ aElement.disabled = true;
-+
-+ if (!this.isElementEditable(aElement))
-+ return;
-+
-+ var rv = undefined;
-+ if (aElement.hasAttribute("onsyncfrompreference")) {
-+ // Value changed, synthesize an event
-+ try {
-+ var event = document.createEvent("Events");
-+ event.initEvent("syncfrompreference", true, true);
-+ var f = new Function("event",
-+ aElement.getAttribute("onsyncfrompreference"));
-+ rv = f.call(aElement, event);
-+ } catch (e) {
-+ Components.utils.reportError(e);
-+ }
-+ }
-+ var val = rv;
-+ if (val === undefined)
-+ val = this.instantApply ? this.valueFromPreferences : this.value;
-+ // if the preference is marked for reset, show default value in UI
-+ if (val === undefined)
-+ val = this.defaultValue;
-+
-+ /**
-+ * Initialize a UI element property with a value. Handles the case
-+ * where an element has not yet had a XBL binding attached for it and
-+ * the property setter does not yet exist by setting the same attribute
-+ * on the XUL element using DOM apis and assuming the element's
-+ * constructor or property getters appropriately handle this state.
-+ */
-+ function setValue(element, attribute, value) {
-+ if (attribute in element)
-+ element[attribute] = value;
-+ else
-+ element.setAttribute(attribute, value);
-+ }
-+ if (aElement.localName == "checkbox" ||
-+ aElement.localName == "listitem")
-+ setValue(aElement, "checked", val);
-+ else if (aElement.localName == "colorpicker")
-+ setValue(aElement, "color", val);
-+ else if (aElement.localName == "textbox") {
-+ // XXXmano Bug 303998: Avoid a caret placement issue if either the
-+ // preference observer or its setter calls updateElements as a result
-+ // of the input event handler.
-+ if (aElement.value !== val)
-+ setValue(aElement, "value", val);
-+ } else
-+ setValue(aElement, "value", val);
-+ ]]>
-+ </body>
-+ </method>
-+
-+ <method name="getElementValue">
-+ <parameter name="aElement"/>
-+ <body>
-+ <![CDATA[
-+ if (aElement.hasAttribute("onsynctopreference")) {
-+ // Value changed, synthesize an event
-+ try {
-+ var event = document.createEvent("Events");
-+ event.initEvent("synctopreference", true, true);
-+ var f = new Function("event",
-+ aElement.getAttribute("onsynctopreference"));
-+ var rv = f.call(aElement, event);
-+ if (rv !== undefined)
-+ return rv;
-+ } catch (e) {
-+ Components.utils.reportError(e);
-+ }
-+ }
-+
-+ /**
-+ * Read the value of an attribute from an element, assuming the
-+ * attribute is a property on the element's node API. If the property
-+ * is not present in the API, then assume its value is contained in
-+ * an attribute, as is the case before a binding has been attached.
-+ */
-+ function getValue(element, attribute) {
-+ if (attribute in element)
-+ return element[attribute];
-+ return element.getAttribute(attribute);
-+ }
-+ if (aElement.localName == "checkbox" ||
-+ aElement.localName == "listitem")
-+ var value = getValue(aElement, "checked");
-+ else if (aElement.localName == "colorpicker")
-+ value = getValue(aElement, "color");
-+ else
-+ value = getValue(aElement, "value");
-+
-+ switch (this.type) {
-+ case "int":
-+ return parseInt(value, 10) || 0;
-+ case "bool":
-+ return typeof(value) == "boolean" ? value : value == "true";
-+ }
-+ return value;
-+ ]]>
-+ </body>
-+ </method>
-+
-+ <method name="isElementEditable">
-+ <parameter name="aElement"/>
-+ <body>
-+ <![CDATA[
-+ switch (aElement.localName) {
-+ case "checkbox":
-+ case "colorpicker":
-+ case "radiogroup":
-+ case "textbox":
-+ case "listitem":
-+ case "listbox":
-+ case "menulist":
-+ return true;
-+ }
-+ return aElement.getAttribute("preference-editable") == "true";
-+ ]]>
-+ </body>
-+ </method>
-+
-+ <method name="updateElements">
-+ <body>
-+ <![CDATA[
-+ if (!this.id)
-+ return;
-+
-+ // This "change" event handler tracks changes made to preferences by
-+ // sources other than the user in this window.
-+ var elements = document.getElementsByAttribute("preference", this.id);
-+ for (var i = 0; i < elements.length; ++i)
-+ this.setElementValue(elements[i]);
-+ ]]>
-+ </body>
-+ </method>
-+ </implementation>
-+
-+ <handlers>
-+ <handler event="change">
-+ this.updateElements();
-+ </handler>
-+ </handlers>
-+ </binding>
-+
-+ <binding id="prefwindow"
-+ extends="chrome://global/content/bindings/dialog.xml#dialog">
-+ <resources>
-+ <stylesheet src="chrome://global/skin/preferences.css"/>
-+ </resources>
-+ <content dlgbuttons="accept,cancel" persist="lastSelected screenX screenY"
-+ closebuttonlabel="&preferencesCloseButton.label;"
-+ closebuttonaccesskey="&preferencesCloseButton.accesskey;"
-+ role="dialog"
-+#ifdef XP_WIN
-+ title="&preferencesDefaultTitleWin.title;">
-+#else
-+ title="&preferencesDefaultTitleMac.title;">
-+#endif
-+ <xul:windowdragbox orient="vertical">
-+ <xul:radiogroup anonid="selector" orient="horizontal" class="paneSelector chromeclass-toolbar"
-+ role="listbox"/> <!-- Expose to accessibility APIs as a listbox -->
-+ </xul:windowdragbox>
-+ <xul:hbox flex="1" class="paneDeckContainer">
-+ <xul:deck anonid="paneDeck" flex="1">
-+ <children includes="prefpane"/>
-+ </xul:deck>
-+ </xul:hbox>
-+ <xul:hbox anonid="dlg-buttons" class="prefWindow-dlgbuttons" pack="end">
-+#ifndef XP_UNIX
-+ <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/>
-+ <xul:button dlgtype="help" class="dialog-button" hidden="true" icon="help"/>
-+ <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/>
-+ <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/>
-+ <xul:spacer anonid="spacer" flex="1"/>
-+ <xul:button dlgtype="cancel" class="dialog-button" icon="cancel"/>
-+ <xul:button dlgtype="accept" class="dialog-button" icon="accept"/>
-+#else
-+ <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/>
-+ <xul:spacer anonid="spacer" flex="1"/>
-+ <xul:button dlgtype="accept" class="dialog-button" icon="accept"/>
-+ <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/>
-+ <xul:button dlgtype="cancel" class="dialog-button" icon="cancel"/>
-+ <xul:button dlgtype="help" class="dialog-button" hidden="true" icon="help"/>
-+ <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/>
-+#endif
-+ </xul:hbox>
-+ <xul:hbox>
-+ <children/>
-+ </xul:hbox>
-+ </content>
-+ <implementation implements="nsITimerCallback">
-+ <constructor>
-+ <![CDATA[
-+ if (this.type != "child") {
-+ if (!this._instantApplyInitialized) {
-+ let psvc = Components.classes["@mozilla.org/preferences-service;1"]
-+ .getService(Components.interfaces.nsIPrefBranch);
-+ this.instantApply = psvc.getBoolPref("browser.preferences.instantApply");
-+ }
-+ if (this.instantApply) {
-+ var docElt = document.documentElement;
-+ var acceptButton = docElt.getButton("accept");
-+ acceptButton.hidden = true;
-+ var cancelButton = docElt.getButton("cancel");
-+ if (/Mac/.test(navigator.platform)) {
-+ // no buttons on Mac except Help
-+ cancelButton.hidden = true;
-+ // Move Help button to the end
-+ document.getAnonymousElementByAttribute(this, "anonid", "spacer").hidden = true;
-+ // Also, don't fire onDialogAccept on enter
-+ acceptButton.disabled = true;
-+ } else {
-+ // morph the Cancel button into the Close button
-+ cancelButton.setAttribute("icon", "close");
-+ cancelButton.label = docElt.getAttribute("closebuttonlabel");
-+ cancelButton.accesskey = docElt.getAttribute("closebuttonaccesskey");
-+ }
-+ }
-+ }
-+ this.setAttribute("animated", this._shouldAnimate ? "true" : "false");
-+ var panes = this.preferencePanes;
-+
-+ var lastPane = null;
-+ if (this.lastSelected) {
-+ lastPane = document.getElementById(this.lastSelected);
-+ if (!lastPane) {
-+ this.lastSelected = "";
-+ }
-+ }
-+
-+ var paneToLoad;
-+ if ("arguments" in window && window.arguments[0] && document.getElementById(window.arguments[0]) && document.getElementById(window.arguments[0]).nodeName == "prefpane") {
-+ paneToLoad = document.getElementById(window.arguments[0]);
-+ this.lastSelected = paneToLoad.id;
-+ } else if (lastPane)
-+ paneToLoad = lastPane;
-+ else
-+ paneToLoad = panes[0];
-+
-+ for (var i = 0; i < panes.length; ++i) {
-+ this._makePaneButton(panes[i]);
-+ if (panes[i].loaded) {
-+ // Inline pane content, fire load event to force initialization.
-+ this._fireEvent("paneload", panes[i]);
-+ }
-+ }
-+ this.showPane(paneToLoad);
-+
-+ if (panes.length == 1)
-+ this._selector.setAttribute("collapsed", "true");
-+ ]]>
-+ </constructor>
-+
-+ <destructor>
-+ <![CDATA[
-+ // Release timers to avoid reference cycles.
-+ if (this._animateTimer) {
-+ this._animateTimer.cancel();
-+ this._animateTimer = null;
-+ }
-+ if (this._fadeTimer) {
-+ this._fadeTimer.cancel();
-+ this._fadeTimer = null;
-+ }
-+ ]]>
-+ </destructor>
-+
-+ <!-- Derived bindings can set this to true to cause us to skip
-+ reading the browser.preferences.instantApply pref in the constructor.
-+ Then they can set instantApply to their wished value. -->
-+ <field name="_instantApplyInitialized">false</field>
-+ <!-- Controls whether changed pref values take effect immediately. -->
-+ <field name="instantApply">false</field>
-+
-+ <property name="preferencePanes"
-+ onget="return this.getElementsByTagName('prefpane');"/>
-+
-+ <property name="type" onget="return this.getAttribute('type');"/>
-+ <property name="_paneDeck"
-+ onget="return document.getAnonymousElementByAttribute(this, 'anonid', 'paneDeck');"/>
-+ <property name="_paneDeckContainer"
-+ onget="return document.getAnonymousElementByAttribute(this, 'class', 'paneDeckContainer');"/>
-+ <property name="_selector"
-+ onget="return document.getAnonymousElementByAttribute(this, 'anonid', 'selector');"/>
-+ <property name="lastSelected"
-+ onget="return this.getAttribute('lastSelected');">
-+ <setter>
-+ this.setAttribute("lastSelected", val);
-+ document.persist(this.id, "lastSelected");
-+ return val;
-+ </setter>
-+ </property>
-+ <property name="currentPane"
-+ onset="return this._currentPane = val;">
-+ <getter>
-+ if (!this._currentPane)
-+ this._currentPane = this.preferencePanes[0];
-+
-+ return this._currentPane;
-+ </getter>
-+ </property>
-+ <field name="_currentPane">null</field>
-+
-+
-+ <method name="_makePaneButton">
-+ <parameter name="aPaneElement"/>
-+ <body>
-+ <![CDATA[
-+ var radio = document.createElement("radio");
-+ radio.setAttribute("pane", aPaneElement.id);
-+ radio.setAttribute("label", aPaneElement.label);
-+ // Expose preference group choice to accessibility APIs as an unchecked list item
-+ // The parent group is exposed to accessibility APIs as a list
-+ if (aPaneElement.image)
-+ radio.setAttribute("src", aPaneElement.image);
-+ radio.style.listStyleImage = aPaneElement.style.listStyleImage;
-+ this._selector.appendChild(radio);
-+ return radio;
-+ ]]>
-+ </body>
-+ </method>
-+
-+ <method name="showPane">
-+ <parameter name="aPaneElement"/>
-+ <body>
-+ <![CDATA[
-+ if (!aPaneElement)
-+ return;
-+
-+ this._selector.selectedItem = document.getAnonymousElementByAttribute(this, "pane", aPaneElement.id);
-+ if (!aPaneElement.loaded) {
-+ let OverlayLoadObserver = function(aPane) {
-+ this._pane = aPane;
-+ }
-+ OverlayLoadObserver.prototype = {
-+ _outer: this,
-+ observe(aSubject, aTopic, aData) {
-+ this._pane.loaded = true;
-+ this._outer._fireEvent("paneload", this._pane);
-+ this._outer._selectPane(this._pane);
-+ }
-+ };
-+
-+ var obs = new OverlayLoadObserver(aPaneElement);
-+ document.loadOverlay(aPaneElement.src, obs);
-+ } else
-+ this._selectPane(aPaneElement);
-+ ]]>
-+ </body>
-+ </method>
-+
-+ <method name="_fireEvent">
-+ <parameter name="aEventName"/>
-+ <parameter name="aTarget"/>
-+ <body>
-+ <![CDATA[
-+ // Panel loaded, synthesize a load event.
-+ try {
-+ var event = document.createEvent("Events");
-+ event.initEvent(aEventName, true, true);
-+ var cancel = !aTarget.dispatchEvent(event);
-+ if (aTarget.hasAttribute("on" + aEventName)) {
-+ var fn = new Function("event", aTarget.getAttribute("on" + aEventName));
-+ var rv = fn.call(aTarget, event);
-+ if (rv == false)
-+ cancel = true;
-+ }
-+ return !cancel;
-+ } catch (e) {
-+ Components.utils.reportError(e);
-+ }
-+ return false;
-+ ]]>
-+ </body>
-+ </method>
-+
-+ <field name="_initialized">false</field>
-+ <method name="_selectPane">
-+ <parameter name="aPaneElement"/>
-+ <body>
-+ <![CDATA[
-+ if (/Mac/.test(navigator.platform)) {
-+ var paneTitle = aPaneElement.label;
-+ if (paneTitle != "")
-+ document.title = paneTitle;
-+ }
-+ var helpButton = document.documentElement.getButton("help");
-+ if (aPaneElement.helpTopic)
-+ helpButton.hidden = false;
-+ else
-+ helpButton.hidden = true;
-+
-+ // Find this pane's index in the deck and set the deck's
-+ // selectedIndex to that value to switch to it.
-+ var prefpanes = this.preferencePanes;
-+ for (var i = 0; i < prefpanes.length; ++i) {
-+ if (prefpanes[i] == aPaneElement) {
-+ this._paneDeck.selectedIndex = i;
-+
-+ if (this.type != "child") {
-+ if (aPaneElement.hasAttribute("flex") && this._shouldAnimate &&
-+ prefpanes.length > 1)
-+ aPaneElement.removeAttribute("flex");
-+ // Calling sizeToContent after the first prefpane is loaded
-+ // will size the windows contents so style information is
-+ // available to calculate correct sizing.
-+ if (!this._initialized && prefpanes.length > 1) {
-+ if (this._shouldAnimate)
-+ this.style.minHeight = 0;
-+ window.sizeToContent();
-+ }
-+
-+ var oldPane = this.lastSelected ? document.getElementById(this.lastSelected) : this.preferencePanes[0];
-+ oldPane.selected = !(aPaneElement.selected = true);
-+ this.lastSelected = aPaneElement.id;
-+ this.currentPane = aPaneElement;
-+ this._initialized = true;
-+
-+ // Only animate if we've switched between prefpanes
-+ if (this._shouldAnimate && oldPane.id != aPaneElement.id) {
-+ aPaneElement.style.opacity = 0.0;
-+ this.animate(oldPane, aPaneElement);
-+ } else if (!this._shouldAnimate && prefpanes.length > 1) {
-+ var targetHeight = parseInt(window.getComputedStyle(this._paneDeckContainer).height);
-+ var verticalPadding = parseInt(window.getComputedStyle(aPaneElement).paddingTop);
-+ verticalPadding += parseInt(window.getComputedStyle(aPaneElement).paddingBottom);
-+ if (aPaneElement.contentHeight > targetHeight - verticalPadding) {
-+ // To workaround the bottom border of a groupbox from being
-+ // cutoff an hbox with a class of bottomBox may enclose it.
-+ // This needs to include its padding to resize properly.
-+ // See bug 394433
-+ var bottomPadding = 0;
-+ var bottomBox = aPaneElement.getElementsByAttribute("class", "bottomBox")[0];
-+ if (bottomBox)
-+ bottomPadding = parseInt(window.getComputedStyle(bottomBox).paddingBottom);
-+ window.innerHeight += bottomPadding + verticalPadding + aPaneElement.contentHeight - targetHeight;
-+ }
-+
-+ // XXX rstrong - extend the contents of the prefpane to
-+ // prevent elements from being cutoff (see bug 349098).
-+ if (aPaneElement.contentHeight + verticalPadding < targetHeight)
-+ aPaneElement._content.style.height = targetHeight - verticalPadding + "px";
-+ }
-+ }
-+ break;
-+ }
-+ }
-+ ]]>
-+ </body>
-+ </method>
-+
-+ <property name="_shouldAnimate">
-+ <getter>
-+ <![CDATA[
-+ var psvc = Components.classes["@mozilla.org/preferences-service;1"]
-+ .getService(Components.interfaces.nsIPrefBranch);
-+ return psvc.getBoolPref("browser.preferences.animateFadeIn",
-+ /Mac/.test(navigator.platform));
-+ ]]>
-+ </getter>
-+ </property>
-+
-+ <method name="animate">
-+ <parameter name="aOldPane"/>
-+ <parameter name="aNewPane"/>
-+ <body>
-+ <![CDATA[
-+ // if we are already resizing, use currentHeight
-+ var oldHeight = this._currentHeight ? this._currentHeight : aOldPane.contentHeight;
-+
-+ this._multiplier = aNewPane.contentHeight > oldHeight ? 1 : -1;
-+ var sizeDelta = Math.abs(oldHeight - aNewPane.contentHeight);
-+ this._animateRemainder = sizeDelta % this._animateIncrement;
-+
-+ this._setUpAnimationTimer(oldHeight);
-+ ]]>
-+ </body>
-+ </method>
-+
-+ <property name="_sizeIncrement">
-+ <getter>
-+ <![CDATA[
-+ var lastSelectedPane = document.getElementById(this.lastSelected);
-+ var increment = this._animateIncrement * this._multiplier;
-+ var newHeight = this._currentHeight + increment;
-+ if ((this._multiplier > 0 && this._currentHeight >= lastSelectedPane.contentHeight) ||
-+ (this._multiplier < 0 && this._currentHeight <= lastSelectedPane.contentHeight))
-+ return 0;
-+
-+ if ((this._multiplier > 0 && newHeight > lastSelectedPane.contentHeight) ||
-+ (this._multiplier < 0 && newHeight < lastSelectedPane.contentHeight))
-+ increment = this._animateRemainder * this._multiplier;
-+ return increment;
-+ ]]>
-+ </getter>
-+ </property>
-+
-+ <method name="notify">
-+ <parameter name="aTimer"/>
-+ <body>
-+ <![CDATA[
-+ if (!document)
-+ aTimer.cancel();
-+
-+ if (aTimer == this._animateTimer) {
-+ var increment = this._sizeIncrement;
-+ if (increment != 0) {
-+ window.innerHeight += increment;
-+ this._currentHeight += increment;
-+ } else {
-+ aTimer.cancel();
-+ this._setUpFadeTimer();
-+ }
-+ } else if (aTimer == this._fadeTimer) {
-+ var elt = document.getElementById(this.lastSelected);
-+ var newOpacity = parseFloat(window.getComputedStyle(elt).opacity) + this._fadeIncrement;
-+ if (newOpacity < 1.0)
-+ elt.style.opacity = newOpacity;
-+ else {
-+ aTimer.cancel();
-+ elt.style.opacity = 1.0;
-+ }
-+ }
-+ ]]>
-+ </body>
-+ </method>
-+
-+ <method name="_setUpAnimationTimer">
-+ <parameter name="aStartHeight"/>
-+ <body>
-+ <![CDATA[
-+ if (!this._animateTimer)
-+ this._animateTimer = Components.classes["@mozilla.org/timer;1"]
-+ .createInstance(Components.interfaces.nsITimer);
-+ else
-+ this._animateTimer.cancel();
-+ this._currentHeight = aStartHeight;
-+
-+ this._animateTimer.initWithCallback(this, this._animateDelay,
-+ Components.interfaces.nsITimer.TYPE_REPEATING_SLACK);
-+ ]]>
-+ </body>
-+ </method>
-+
-+ <method name="_setUpFadeTimer">
-+ <body>
-+ <![CDATA[
-+ if (!this._fadeTimer)
-+ this._fadeTimer = Components.classes["@mozilla.org/timer;1"]
-+ .createInstance(Components.interfaces.nsITimer);
-+ else
-+ this._fadeTimer.cancel();
-+
-+ this._fadeTimer.initWithCallback(this, this._fadeDelay,
-+ Components.interfaces.nsITimer.TYPE_REPEATING_SLACK);
-+ ]]>
-+ </body>
-+ </method>
-+
-+ <field name="_animateTimer">null</field>
-+ <field name="_fadeTimer">null</field>
-+ <field name="_animateDelay">15</field>
-+ <field name="_animateIncrement">40</field>
-+ <field name="_fadeDelay">5</field>
-+ <field name="_fadeIncrement">0.40</field>
-+ <field name="_animateRemainder">0</field>
-+ <field name="_currentHeight">0</field>
-+ <field name="_multiplier">0</field>
-+
-+ <method name="addPane">
-+ <parameter name="aPaneElement"/>
-+ <body>
-+ <![CDATA[
-+ this.appendChild(aPaneElement);
-+
-+ // Set up pane button
-+ this._makePaneButton(aPaneElement);
-+ ]]>
-+ </body>
-+ </method>
-+
-+ <method name="openSubDialog">
-+ <parameter name="aURL"/>
-+ <parameter name="aFeatures"/>
-+ <parameter name="aParams"/>
-+ <body>
-+ return openDialog(aURL, "", "modal,centerscreen,resizable=no" + (aFeatures != "" ? ("," + aFeatures) : ""), aParams);
-+ </body>
-+ </method>
-+
-+ <method name="openWindow">
-+ <parameter name="aWindowType"/>
-+ <parameter name="aURL"/>
-+ <parameter name="aFeatures"/>
-+ <parameter name="aParams"/>
-+ <body>
-+ <![CDATA[
-+ var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
-+ .getService(Components.interfaces.nsIWindowMediator);
-+ var win = aWindowType ? wm.getMostRecentWindow(aWindowType) : null;
-+ if (win) {
-+ if ("initWithParams" in win)
-+ win.initWithParams(aParams);
-+ win.focus();
-+ } else {
-+ var features = "resizable,dialog=no,centerscreen" + (aFeatures != "" ? ("," + aFeatures) : "");
-+ var parentWindow = (this.instantApply || !window.opener || window.opener.closed) ? window : window.opener;
-+ win = parentWindow.openDialog(aURL, "_blank", features, aParams);
-+ }
-+ return win;
-+ ]]>
-+ </body>
-+ </method>
-+ </implementation>
-+ <handlers>
-+ <handler event="dialogaccept">
-+ <![CDATA[
-+ if (!this._fireEvent("beforeaccept", this)) {
-+ return false;
-+ }
-+
-+ var secMan = Components.classes["@mozilla.org/scriptsecuritymanager;1"]
-+ .getService(Components.interfaces.nsIScriptSecurityManager);
-+ if (this.type == "child" && window.opener &&
-+ secMan.isSystemPrincipal(window.opener.document.nodePrincipal)) {
-+ var pdocEl = window.opener.document.documentElement;
-+ if (pdocEl.instantApply) {
-+ let panes = this.preferencePanes;
-+ for (let i = 0; i < panes.length; ++i)
-+ panes[i].writePreferences(true);
-+ } else {
-+ // Clone all the preferences elements from the child document and
-+ // insert them into the pane collection of the parent.
-+ var pdoc = window.opener.document;
-+ if (pdoc.documentElement.localName == "prefwindow") {
-+ var currentPane = pdoc.documentElement.currentPane;
-+ var id = window.location.href + "#childprefs";
-+ var childPrefs = pdoc.getElementById(id);
-+ if (!childPrefs) {
-+ childPrefs = pdoc.createElement("preferences");
-+ currentPane.appendChild(childPrefs);
-+ childPrefs.id = id;
-+ }
-+ let panes = this.preferencePanes;
-+ for (let i = 0; i < panes.length; ++i) {
-+ var preferences = panes[i].preferences;
-+ for (var j = 0; j < preferences.length; ++j) {
-+ // Try to find a preference element for the same preference.
-+ var preference = null;
-+ var parentPreferences = pdoc.getElementsByTagName("preferences");
-+ for (var k = 0; (k < parentPreferences.length && !preference); ++k) {
-+ var parentPrefs = parentPreferences[k]
-+ .getElementsByAttribute("name", preferences[j].name);
-+ for (var l = 0; (l < parentPrefs.length && !preference); ++l) {
-+ if (parentPrefs[l].localName == "preference")
-+ preference = parentPrefs[l];
-+ }
-+ }
-+ if (!preference) {
-+ // No matching preference in the parent window.
-+ preference = pdoc.createElement("preference");
-+ childPrefs.appendChild(preference);
-+ preference.name = preferences[j].name;
-+ preference.type = preferences[j].type;
-+ preference.inverted = preferences[j].inverted;
-+ preference.readonly = preferences[j].readonly;
-+ preference.disabled = preferences[j].disabled;
-+ }
-+ preference.value = preferences[j].value;
-+ }
-+ }
-+ }
-+ }
-+ } else {
-+ let panes = this.preferencePanes;
-+ for (var i = 0; i < panes.length; ++i)
-+ panes[i].writePreferences(false);
-+
-+ let psvc = Components.classes["@mozilla.org/preferences-service;1"]
-+ .getService(Components.interfaces.nsIPrefService);
-+ psvc.savePrefFile(null);
-+ }
-+
-+ return true;
-+ ]]>
-+ </handler>
-+ <handler event="command">
-+ if (event.originalTarget.hasAttribute("pane")) {
-+ var pane = document.getElementById(event.originalTarget.getAttribute("pane"));
-+ this.showPane(pane);
-+ }
-+ </handler>
-+
-+ <handler event="keypress" key="&windowClose.key;" modifiers="accel" phase="capturing">
-+ <![CDATA[
-+ if (this.instantApply)
-+ window.close();
-+ event.stopPropagation();
-+ event.preventDefault();
-+ ]]>
-+ </handler>
-+
-+ <handler event="keypress"
-+#ifdef XP_MACOSX
-+ key="&openHelpMac.commandkey;" modifiers="accel"
-+#else
-+ keycode="&openHelp.commandkey;"
-+#endif
-+ phase="capturing">
-+ <![CDATA[
-+ var helpButton = this.getButton("help");
-+ if (helpButton.disabled || helpButton.hidden)
-+ return;
-+ this._fireEvent("dialoghelp", this);
-+ event.stopPropagation();
-+ event.preventDefault();
-+ ]]>
-+ </handler>
-+ </handlers>
-+ </binding>
-+
-+ <binding id="prefpane">
-+ <resources>
-+ <stylesheet src="chrome://global/skin/preferences.css"/>
-+ </resources>
-+ <content>
-+ <xul:vbox class="content-box" xbl:inherits="flex">
-+ <children/>
-+ </xul:vbox>
-+ </content>
-+ <implementation>
-+ <method name="writePreferences">
-+ <parameter name="aFlushToDisk"/>
-+ <body>
-+ <![CDATA[
-+ // Write all values to preferences.
-+ if (this._deferredValueUpdateElements.size) {
-+ this._finalizeDeferredElements();
-+ }
-+
-+ var preferences = this.preferences;
-+ for (var i = 0; i < preferences.length; ++i) {
-+ var preference = preferences[i];
-+ preference.batching = true;
-+ preference.valueFromPreferences = preference.value;
-+ preference.batching = false;
-+ }
-+ if (aFlushToDisk) {
-+ var psvc = Components.classes["@mozilla.org/preferences-service;1"]
-+ .getService(Components.interfaces.nsIPrefService);
-+ psvc.savePrefFile(null);
-+ }
-+ ]]>
-+ </body>
-+ </method>
-+
-+ <property name="src"
-+ onget="return this.getAttribute('src');"
-+ onset="this.setAttribute('src', val); return val;"/>
-+ <property name="selected"
-+ onget="return this.getAttribute('selected') == 'true';"
-+ onset="this.setAttribute('selected', val); return val;"/>
-+ <property name="image"
-+ onget="return this.getAttribute('image');"
-+ onset="this.setAttribute('image', val); return val;"/>
-+ <property name="label"
-+ onget="return this.getAttribute('label');"
-+ onset="this.setAttribute('label', val); return val;"/>
-+
-+ <property name="preferenceElements"
-+ onget="return this.getElementsByAttribute('preference', '*');"/>
-+ <property name="preferences"
-+ onget="return this.getElementsByTagName('preference');"/>
-+
-+ <property name="helpTopic">
-+ <getter>
-+ <![CDATA[
-+ // if there are tabs, and the selected tab provides a helpTopic, return that
-+ var box = this.getElementsByTagName("tabbox");
-+ if (box[0]) {
-+ var tab = box[0].selectedTab;
-+ if (tab && tab.hasAttribute("helpTopic"))
-+ return tab.getAttribute("helpTopic");
-+ }
-+
-+ // otherwise, return the helpTopic of the current panel
-+ return this.getAttribute("helpTopic");
-+ ]]>
-+ </getter>
-+ </property>
-+
-+ <field name="_loaded">false</field>
-+ <property name="loaded"
-+ onget="return !this.src ? true : this._loaded;"
-+ onset="this._loaded = val; return val;"/>
-+
-+ <method name="preferenceForElement">
-+ <parameter name="aElement"/>
-+ <body>
-+ return document.getElementById(aElement.getAttribute("preference"));
-+ </body>
-+ </method>
-+
-+ <method name="getPreferenceElement">
-+ <parameter name="aStartElement"/>
-+ <body>
-+ <![CDATA[
-+ var temp = aStartElement;
-+ while (temp && temp.nodeType == Node.ELEMENT_NODE &&
-+ !temp.hasAttribute("preference"))
-+ temp = temp.parentNode;
-+ return temp && temp.nodeType == Node.ELEMENT_NODE ?
-+ temp : aStartElement;
-+ ]]>
-+ </body>
-+ </method>
-+
-+ <property name="DeferredTask" readonly="true">
-+ <getter><![CDATA[
-+ let module = {};
-+ Components.utils.import("resource://gre/modules/DeferredTask.jsm", module);
-+ Object.defineProperty(this, "DeferredTask", {
-+ configurable: true,
-+ enumerable: true,
-+ writable: true,
-+ value: module.DeferredTask
-+ });
-+ return module.DeferredTask;
-+ ]]></getter>
-+ </property>
-+ <method name="_deferredValueUpdate">
-+ <parameter name="aElement"/>
-+ <body>
-+ <![CDATA[
-+ delete aElement._deferredValueUpdateTask;
-+ let preference = document.getElementById(aElement.getAttribute("preference"));
-+ let prefVal = preference.getElementValue(aElement);
-+ preference.value = prefVal;
-+ this._deferredValueUpdateElements.delete(aElement);
-+ ]]>
-+ </body>
-+ </method>
-+ <field name="_deferredValueUpdateElements">
-+ new Set();
-+ </field>
-+ <method name="_finalizeDeferredElements">
-+ <body>
-+ <![CDATA[
-+ for (let el of this._deferredValueUpdateElements) {
-+ if (el._deferredValueUpdateTask) {
-+ el._deferredValueUpdateTask.finalize();
-+ }
-+ }
-+ ]]>
-+ </body>
-+ </method>
-+ <method name="userChangedValue">
-+ <parameter name="aElement"/>
-+ <body>
-+ <![CDATA[
-+ let element = this.getPreferenceElement(aElement);
-+ if (element.hasAttribute("preference")) {
-+ if (element.getAttribute("delayprefsave") != "true") {
-+ var preference = document.getElementById(element.getAttribute("preference"));
-+ var prefVal = preference.getElementValue(element);
-+ preference.value = prefVal;
-+ } else {
-+ if (!element._deferredValueUpdateTask) {
-+ element._deferredValueUpdateTask = new this.DeferredTask(this._deferredValueUpdate.bind(this, element), 1000);
-+ this._deferredValueUpdateElements.add(element);
-+ } else {
-+ // Each time the preference is changed, restart the delay.
-+ element._deferredValueUpdateTask.disarm();
-+ }
-+ element._deferredValueUpdateTask.arm();
-+ }
-+ }
-+ ]]>
-+ </body>
-+ </method>
-+
-+ <property name="contentHeight">
-+ <getter>
-+ var targetHeight = parseInt(window.getComputedStyle(this._content).height);
-+ targetHeight += parseInt(window.getComputedStyle(this._content).marginTop);
-+ targetHeight += parseInt(window.getComputedStyle(this._content).marginBottom);
-+ return targetHeight;
-+ </getter>
-+ </property>
-+ <field name="_content">
-+ document.getAnonymousElementByAttribute(this, "class", "content-box");
-+ </field>
-+ </implementation>
-+ <handlers>
-+ <handler event="command">
-+ // This "command" event handler tracks changes made to preferences by
-+ // the user in this window.
-+ if (event.sourceEvent)
-+ event = event.sourceEvent;
-+ this.userChangedValue(event.target);
-+ </handler>
-+ <handler event="select">
-+ // This "select" event handler tracks changes made to colorpicker
-+ // preferences by the user in this window.
-+ if (event.target.localName == "colorpicker")
-+ this.userChangedValue(event.target);
-+ </handler>
-+ <handler event="change">
-+ // This "change" event handler tracks changes made to preferences by
-+ // the user in this window.
-+ this.userChangedValue(event.target);
-+ </handler>
-+ <handler event="input">
-+ // This "input" event handler tracks changes made to preferences by
-+ // the user in this window.
-+ this.userChangedValue(event.target);
-+ </handler>
-+ <handler event="paneload">
-+ <![CDATA[
-+ // Initialize all values from preferences.
-+ var elements = this.preferenceElements;
-+ for (var i = 0; i < elements.length; ++i) {
-+ try {
-+ var preference = this.preferenceForElement(elements[i]);
-+ preference.setElementValue(elements[i]);
-+ } catch (e) {
-+ dump("*** No preference found for " + elements[i].getAttribute("preference") + "\n");
-+ }
-+ }
-+ ]]>
-+ </handler>
-+ </handlers>
-+ </binding>
-+
-+ <binding id="panebutton" role="xul:listitem"
-+ extends="chrome://global/content/bindings/radio.xml#radio">
-+ <resources>
-+ <stylesheet src="chrome://global/skin/preferences.css"/>
-+ </resources>
-+ <content>
-+ <xul:image class="paneButtonIcon" xbl:inherits="src"/>
-+ <xul:label class="paneButtonLabel" xbl:inherits="value=label"/>
-+ </content>
-+ </binding>
-+
-+</bindings>
-+
-+# -*- 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/.
-+
-+#
-+# This is PrefWindow 6. The Code Could Well Be Ready, Are You?
-+#
-+# Historical References:
-+# PrefWindow V (February 1, 2003)
-+# PrefWindow IV (April 24, 2000)
-+# PrefWindow III (January 6, 2000)
-+# PrefWindow II (???)
-+# PrefWindow I (June 4, 1999)
-+#
-diff --git a/toolkit/mozapps/downloads/nsHelperAppDlg.js b/toolkit/mozapps/downloads/nsHelperAppDlg.js
---- a/toolkit/mozapps/downloads/nsHelperAppDlg.js
-+++ b/toolkit/mozapps/downloads/nsHelperAppDlg.js
-@@ -628,17 +628,17 @@ nsUnknownContentTypeDialog.prototype = {
- else
- typeString = mimeInfo.MIMEType;
- }
- // When the length is unknown, contentLength would be -1
- if (this.mLauncher.contentLength >= 0) {
- let [size, unit] = DownloadUtils.
- convertByteUnits(this.mLauncher.contentLength);
- type.value = this.dialogElement("strings")
-- .getFormattedString("orderedFileSizeWithType",
-+ .getFormattedString("orderedFileSizeWithType",
- [typeString, size, unit]);
- }
- else {
- type.value = typeString;
- }
- },
-
- // Returns true if opening the default application makes sense.
-@@ -802,17 +802,17 @@ nsUnknownContentTypeDialog.prototype = {
- switch (this.dialogElement("openHandler").selectedIndex) {
- case 0:
- // No app need be specified in this case.
- ok = true;
- break;
- case 1:
- // only enable the OK button if we have a default app to use or if
- // the user chose an app....
-- ok = this.chosenApp || /\S/.test(this.dialogElement("otherHandler").getAttribute("path"));
-+ ok = this.chosenApp || /\S/.test(this.dialogElement("otherHandler").getAttribute("path"));
- break;
- }
- }
-
- // Enable Ok button if ok to press.
- this.mDialog.document.documentElement.getButton("accept").disabled = !ok;
- },
-
-@@ -1067,30 +1067,57 @@ nsUnknownContentTypeDialog.prototype = {
-
- if (params.handlerApp &&
- params.handlerApp.executable &&
- params.handlerApp.executable.isFile()) {
- // Remember the file they chose to run.
- this.chosenApp = params.handlerApp;
- }
- } else if ("@mozilla.org/applicationchooser;1" in Components.classes) {
-- var nsIApplicationChooser = Components.interfaces.nsIApplicationChooser;
-- var appChooser = Components.classes["@mozilla.org/applicationchooser;1"]
-- .createInstance(nsIApplicationChooser);
-- appChooser.init(this.mDialog, this.dialogElement("strings").getString("chooseAppFilePickerTitle"));
-- var contentTypeDialogObj = this;
-- let appChooserCallback = function appChooserCallback_done(aResult) {
-- if (aResult) {
-- contentTypeDialogObj.chosenApp = aResult.QueryInterface(Components.interfaces.nsILocalHandlerApp);
-+ // handle the KDE case which is implemented in the filepicker
-+ // therefore falling back to Gtk2 like behaviour if KDE is running
-+ // FIXME this should be better handled in the nsIApplicationChooser
-+ // interface
-+ var env = Components.classes["@mozilla.org/process/environment;1"]
-+ .getService(Components.interfaces.nsIEnvironment);
-+ if (env.get('KDE_FULL_SESSION') == "true")
-+ {
-+ var nsIFilePicker = Components.interfaces.nsIFilePicker;
-+ var fp = Components.classes["@mozilla.org/filepicker;1"]
-+ .createInstance(nsIFilePicker);
-+ fp.init(this.mDialog,
-+ this.dialogElement("strings").getString("chooseAppFilePickerTitle"),
-+ nsIFilePicker.modeOpen);
-+
-+ fp.appendFilters(nsIFilePicker.filterApps);
-+
-+ if (fp.show() == nsIFilePicker.returnOK && fp.file) {
-+ // Remember the file they chose to run.
-+ var localHandlerApp =
-+ Components.classes["@mozilla.org/uriloader/local-handler-app;1"].
-+ createInstance(Components.interfaces.nsILocalHandlerApp);
-+ localHandlerApp.executable = fp.file;
-+ this.chosenApp = localHandlerApp;
- }
-- contentTypeDialogObj.finishChooseApp();
-- };
-- appChooser.open(this.mLauncher.MIMEInfo.MIMEType, appChooserCallback);
-- // The finishChooseApp is called from appChooserCallback
-- return;
-+ } else {
-+ var nsIApplicationChooser = Components.interfaces.nsIApplicationChooser;
-+ var appChooser = Components.classes["@mozilla.org/applicationchooser;1"]
-+ .createInstance(nsIApplicationChooser);
-+ appChooser.init(this.mDialog, this.dialogElement("strings").getString("chooseAppFilePickerTitle"));
-+ var contentTypeDialogObj = this;
-+ let appChooserCallback = function appChooserCallback_done(aResult) {
-+ if (aResult) {
-+ contentTypeDialogObj.chosenApp = aResult.QueryInterface(Components.interfaces.nsILocalHandlerApp);
-+ }
-+ contentTypeDialogObj.finishChooseApp();
-+ };
-+ appChooser.open(this.mLauncher.MIMEInfo.MIMEType, appChooserCallback);
-+ // The finishChooseApp is called from appChooserCallback
-+ return;
-+ }
- } else {
- var nsIFilePicker = Components.interfaces.nsIFilePicker;
- var fp = Components.classes["@mozilla.org/filepicker;1"]
- .createInstance(nsIFilePicker);
- fp.init(this.mDialog,
- this.dialogElement("strings").getString("chooseAppFilePickerTitle"),
- nsIFilePicker.modeOpen);
-
-diff --git a/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp b/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp
---- a/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp
-+++ b/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp
-@@ -15,16 +15,17 @@
- #include "nsPrintfCString.h"
- #include "nsNetCID.h"
- #include "nsNetUtil.h"
- #include "nsISupportsPrimitives.h"
- #include "nsIGSettingsService.h"
- #include "nsInterfaceHashtable.h"
- #include "mozilla/Attributes.h"
- #include "nsIURI.h"
-+#include "nsKDEUtils.h"
-
- class nsUnixSystemProxySettings final : public nsISystemProxySettings {
- public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSISYSTEMPROXYSETTINGS
-
- nsUnixSystemProxySettings()
- : mSchemeProxySettings(4)
-@@ -39,16 +40,17 @@ private:
- nsCOMPtr<nsIGSettingsService> mGSettings;
- nsCOMPtr<nsIGSettingsCollection> mProxySettings;
- nsInterfaceHashtable<nsCStringHashKey, nsIGSettingsCollection> mSchemeProxySettings;
- bool IsProxyMode(const char* aMode);
- nsresult SetProxyResultFromGConf(const char* aKeyBase, const char* aType, nsACString& aResult);
- nsresult GetProxyFromGConf(const nsACString& aScheme, const nsACString& aHost, int32_t aPort, nsACString& aResult);
- nsresult GetProxyFromGSettings(const nsACString& aScheme, const nsACString& aHost, int32_t aPort, nsACString& aResult);
- nsresult SetProxyResultFromGSettings(const char* aKeyBase, const char* aType, nsACString& aResult);
-+ nsresult GetProxyFromKDE(const nsACString& aScheme, const nsACString& aHost, PRInt32 aPort, nsACString& aResult);
- };
-
- NS_IMPL_ISUPPORTS(nsUnixSystemProxySettings, nsISystemProxySettings)
-
- NS_IMETHODIMP
- nsUnixSystemProxySettings::GetMainThreadOnly(bool *aMainThreadOnly)
- {
- // dbus prevents us from being threadsafe, but this routine should not block anyhow
-@@ -505,16 +507,19 @@ nsUnixSystemProxySettings::GetProxyFromG
-
- nsresult
- nsUnixSystemProxySettings::GetProxyForURI(const nsACString & aSpec,
- const nsACString & aScheme,
- const nsACString & aHost,
- const int32_t aPort,
- nsACString & aResult)
- {
-+ if (nsKDEUtils::kdeSupport())
-+ return GetProxyFromKDE(aScheme, aHost, aPort, aResult);
-+
- if (mProxySettings) {
- nsresult rv = GetProxyFromGSettings(aScheme, aHost, aPort, aResult);
- if (NS_SUCCEEDED(rv))
- return rv;
- }
- if (mGConf)
- return GetProxyFromGConf(aScheme, aHost, aPort, aResult);
-
-@@ -540,8 +545,34 @@ static const mozilla::Module::ContractID
-
- static const mozilla::Module kUnixProxyModule = {
- mozilla::Module::kVersion,
- kUnixProxyCIDs,
- kUnixProxyContracts
- };
-
- NSMODULE_DEFN(nsUnixProxyModule) = &kUnixProxyModule;
-+
-+nsresult
-+nsUnixSystemProxySettings::GetProxyFromKDE(const nsACString& aScheme,
-+ const nsACString& aHost,
-+ PRInt32 aPort,
-+ nsACString& aResult)
-+{
-+ nsAutoCString url;
-+ url = aScheme;
-+ url += "://";
-+ url += aHost;
-+ if( aPort >= 0 )
-+ {
-+ url += ":";
-+ url += nsPrintfCString("%d", aPort);
-+ }
-+ nsTArray<nsCString> command;
-+ command.AppendElement( NS_LITERAL_CSTRING( "GETPROXY" ));
-+ command.AppendElement( url );
-+ nsTArray<nsCString> result;
-+ if( !nsKDEUtils::command( command, &result ) || result.Length() != 1 )
-+ return NS_ERROR_FAILURE;
-+ aResult = result[0];
-+ return NS_OK;
-+}
-+
-diff --git a/toolkit/xre/moz.build b/toolkit/xre/moz.build
---- a/toolkit/xre/moz.build
-+++ b/toolkit/xre/moz.build
-@@ -61,17 +61,19 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'co
- '../components/printingui/mac',
- ]
- elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'uikit':
- UNIFIED_SOURCES += [
- 'nsNativeAppSupportDefault.cpp',
- 'UIKitDirProvider.mm',
- ]
- elif 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
-+ EXPORTS += ['nsKDEUtils.h']
- UNIFIED_SOURCES += [
-+ 'nsKDEUtils.cpp',
- 'nsNativeAppSupportUnix.cpp',
- ]
- else:
- UNIFIED_SOURCES += [
- 'nsNativeAppSupportDefault.cpp',
- ]
-
- if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk3':
-diff --git a/toolkit/xre/nsKDEUtils.cpp b/toolkit/xre/nsKDEUtils.cpp
-new file mode 100644
---- /dev/null
-+++ b/toolkit/xre/nsKDEUtils.cpp
-@@ -0,0 +1,344 @@
-+/* -*- Mode: C++; 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/. */
-+
-+#include "nsKDEUtils.h"
-+#include "nsIWidget.h"
-+#include "nsISupportsPrimitives.h"
-+#include "nsIMutableArray.h"
-+#include "nsComponentManagerUtils.h"
-+#include "nsArrayUtils.h"
-+
-+#include <gtk/gtk.h>
-+
-+#include <limits.h>
-+#include <stdio.h>
-+#include <sys/wait.h>
-+#include <sys/resource.h>
-+#include <unistd.h>
-+#include <X11/Xlib.h>
-+// copied from X11/X.h as a hack since for an unknown
-+// reason it's not picked up from X11/X.h
-+#ifndef None
-+#define None 0L /* universal null resource or null atom */
-+#endif
-+
-+//#define DEBUG_KDE
-+#ifdef DEBUG_KDE
-+#define KWATERFOXHELPER "kwaterfoxhelper"
-+#else
-+// not need for lib64, it's a binary
-+#define KWATERFOXHELPER "/opt/waterfox/kwaterfoxhelper"
-+#endif
-+
-+#define KWATERFOXHELPER_VERSION 6
-+#define MAKE_STR2( n ) #n
-+#define MAKE_STR( n ) MAKE_STR2( n )
-+
-+static bool getKdeSession()
-+ {
-+ Display* dpy = XOpenDisplay( NULL );
-+ if( dpy == NULL )
-+ return false;
-+ Atom kde_full_session = XInternAtom( dpy, "KDE_FULL_SESSION", True );
-+ bool kde = false;
-+ if( kde_full_session != None )
-+ {
-+ int cnt;
-+ if( Atom* props = XListProperties( dpy, DefaultRootWindow( dpy ), &cnt ))
-+ {
-+ for( int i = 0;
-+ i < cnt;
-+ ++i )
-+ {
-+ if( props[ i ] == kde_full_session )
-+ {
-+ kde = true;
-+#ifdef DEBUG_KDE
-+ fprintf( stderr, "KDE SESSION %d\n", kde );
-+#endif
-+ break;
-+ }
-+ }
-+ XFree( props );
-+ }
-+ }
-+ XCloseDisplay( dpy );
-+ return kde;
-+ }
-+
-+static bool getKdeSupport()
-+ {
-+ nsTArray<nsCString> command;
-+ command.AppendElement( NS_LITERAL_CSTRING( "CHECK" ));
-+ command.AppendElement( NS_LITERAL_CSTRING( MAKE_STR( KWATERFOXHELPER_VERSION )));
-+ bool kde = nsKDEUtils::command( command );
-+#ifdef DEBUG_KDE
-+ fprintf( stderr, "KDE RUNNING %d\n", kde );
-+#endif
-+ return kde;
-+ }
-+
-+nsKDEUtils::nsKDEUtils()
-+ : commandFile( NULL )
-+ , replyFile( NULL )
-+ {
-+ }
-+
-+nsKDEUtils::~nsKDEUtils()
-+ {
-+// closeHelper(); not actually useful, exiting will close the fd too
-+ }
-+
-+nsKDEUtils* nsKDEUtils::self()
-+ {
-+ static nsKDEUtils s;
-+ return &s;
-+ }
-+
-+static bool helperRunning = false;
-+static bool helperFailed = false;
-+
-+bool nsKDEUtils::kdeSession()
-+ {
-+ static bool session = getKdeSession();
-+ return session;
-+ }
-+
-+bool nsKDEUtils::kdeSupport()
-+ {
-+ static bool support = kdeSession() && getKdeSupport();
-+ return support && helperRunning;
-+ }
-+
-+struct nsKDECommandData
-+ {
-+ FILE* file;
-+ nsTArray<nsCString>* output;
-+ GMainLoop* loop;
-+ bool success;
-+ };
-+
-+static gboolean kdeReadFunc( GIOChannel*, GIOCondition, gpointer data )
-+ {
-+ nsKDECommandData* p = static_cast< nsKDECommandData* >( data );
-+ char buf[ 8192 ]; // TODO big enough
-+ bool command_done = false;
-+ bool command_failed = false;
-+ while( !command_done && !command_failed && fgets( buf, 8192, p->file ) != NULL )
-+ { // TODO what if the kernel splits a line into two chunks?
-+//#ifdef DEBUG_KDE
-+// fprintf( stderr, "READ: %s %d\n", buf, feof( p->file ));
-+//#endif
-+ if( char* eol = strchr( buf, '\n' ))
-+ *eol = '\0';
-+ command_done = ( strcmp( buf, "\\1" ) == 0 );
-+ command_failed = ( strcmp( buf, "\\0" ) == 0 );
-+ nsAutoCString line( buf );
-+ line.ReplaceSubstring( "\\n", "\n" );
-+ line.ReplaceSubstring( "\\" "\\", "\\" ); // \\ -> \ , i.e. unescape
-+ if( p->output && !( command_done || command_failed ))
-+ p->output->AppendElement( nsCString( buf )); // TODO utf8?
-+ }
-+ bool quit = false;
-+ if( feof( p->file ) || command_failed )
-+ {
-+ quit = true;
-+ p->success = false;
-+ }
-+ if( command_done )
-+ { // reading one reply finished
-+ quit = true;
-+ p->success = true;
-+ }
-+ if( quit )
-+ {
-+ if( p->loop )
-+ g_main_loop_quit( p->loop );
-+ return FALSE;
-+ }
-+ return TRUE;
-+ }
-+
-+bool nsKDEUtils::command( const nsTArray<nsCString>& command, nsTArray<nsCString>* output )
-+ {
-+ return self()->internalCommand( command, NULL, false, output );
-+ }
-+
-+bool nsKDEUtils::command( nsIArray* command, nsIArray** output)
-+ {
-+ nsTArray<nsCString> in;
-+ PRUint32 length;
-+ command->GetLength( &length );
-+ for ( PRUint32 i = 0; i < length; i++ )
-+ {
-+ nsCOMPtr<nsISupportsCString> str = do_QueryElementAt( command, i );
-+ if( str )
-+ {
-+ nsAutoCString s;
-+ str->GetData( s );
-+ in.AppendElement( s );
-+ }
-+ }
-+
-+ nsTArray<nsCString> out;
-+ bool ret = self()->internalCommand( in, NULL, false, &out );
-+
-+ if ( !output ) return ret;
-+
-+ nsCOMPtr<nsIMutableArray> result = do_CreateInstance( NS_ARRAY_CONTRACTID );
-+ if ( !result ) return false;
-+
-+ for ( PRUint32 i = 0; i < out.Length(); i++ )
-+ {
-+ nsCOMPtr<nsISupportsCString> rstr = do_CreateInstance( NS_SUPPORTS_CSTRING_CONTRACTID );
-+ if ( !rstr ) return false;
-+
-+ rstr->SetData( out[i] );
-+ result->AppendElement( rstr, false );
-+ }
-+
-+ NS_ADDREF( *output = result);
-+ return ret;
-+ }
-+
-+
-+bool nsKDEUtils::commandBlockUi( const nsTArray<nsCString>& command, GtkWindow* parent, nsTArray<nsCString>* output )
-+ {
-+ return self()->internalCommand( command, parent, true, output );
-+ }
-+
-+bool nsKDEUtils::internalCommand( const nsTArray<nsCString>& command, GtkWindow* parent, bool blockUi,
-+ nsTArray<nsCString>* output )
-+ {
-+ if( !startHelper())
-+ return false;
-+ feedCommand( command );
-+ // do not store the data in 'this' but in extra structure, just in case there
-+ // is reentrancy (can there be? the event loop is re-entered)
-+ nsKDECommandData data;
-+ data.file = replyFile;
-+ data.output = output;
-+ data.success = false;
-+ if( blockUi )
-+ {
-+ data.loop = g_main_loop_new( NULL, FALSE );
-+ GtkWidget* window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
-+ if( parent && gtk_window_get_group(parent) )
-+ gtk_window_group_add_window( gtk_window_get_group(parent), GTK_WINDOW( window ));
-+ gtk_widget_realize( window );
-+ gtk_widget_set_sensitive( window, TRUE );
-+ gtk_grab_add( window );
-+ GIOChannel* channel = g_io_channel_unix_new( fileno( data.file ));
-+ g_io_add_watch( channel, static_cast< GIOCondition >( G_IO_IN | G_IO_ERR | G_IO_HUP ), kdeReadFunc, &data );
-+ g_io_channel_unref( channel );
-+ g_main_loop_run( data.loop );
-+ g_main_loop_unref( data.loop );
-+ gtk_grab_remove( window );
-+ gtk_widget_destroy( window );
-+ }
-+ else
-+ {
-+ data.loop = NULL;
-+ while( kdeReadFunc( NULL, static_cast< GIOCondition >( 0 ), &data ))
-+ ;
-+ }
-+ return data.success;
-+ }
-+
-+bool nsKDEUtils::startHelper()
-+ {
-+ if( helperRunning )
-+ return true;
-+ if( helperFailed )
-+ return false;
-+ helperFailed = true;
-+ int fdcommand[ 2 ];
-+ int fdreply[ 2 ];
-+ if( pipe( fdcommand ) < 0 )
-+ return false;
-+ if( pipe( fdreply ) < 0 )
-+ {
-+ close( fdcommand[ 0 ] );
-+ close( fdcommand[ 1 ] );
-+ return false;
-+ }
-+ char* args[ 2 ] = { const_cast< char* >( KWATERFOXHELPER ), NULL };
-+ switch( fork())
-+ {
-+ case -1:
-+ {
-+ close( fdcommand[ 0 ] );
-+ close( fdcommand[ 1 ] );
-+ close( fdreply[ 0 ] );
-+ close( fdreply[ 1 ] );
-+ return false;
-+ }
-+ case 0: // child
-+ {
-+ if( dup2( fdcommand[ 0 ], STDIN_FILENO ) < 0 )
-+ _exit( 1 );
-+ if( dup2( fdreply[ 1 ], STDOUT_FILENO ) < 0 )
-+ _exit( 1 );
-+ int maxfd = 1024; // close all other fds
-+ struct rlimit rl;
-+ if( getrlimit( RLIMIT_NOFILE, &rl ) == 0 )
-+ maxfd = rl.rlim_max;
-+ for( int i = 3;
-+ i < maxfd;
-+ ++i )
-+ close( i );
-+#ifdef DEBUG_KDE
-+ execvp( KWATERFOXHELPER, args );
-+#else
-+ execv( KWATERFOXHELPER, args );
-+#endif
-+ _exit( 1 ); // failed
-+ }
-+ default: // parent
-+ {
-+ commandFile = fdopen( fdcommand[ 1 ], "w" );
-+ replyFile = fdopen( fdreply[ 0 ], "r" );
-+ close( fdcommand[ 0 ] );
-+ close( fdreply[ 1 ] );
-+ if( commandFile == NULL || replyFile == NULL )
-+ {
-+ closeHelper();
-+ return false;
-+ }
-+ // ok, helper ready, getKdeRunning() will check if it works
-+ }
-+ }
-+ helperFailed = false;
-+ helperRunning = true;
-+ return true;
-+ }
-+
-+void nsKDEUtils::closeHelper()
-+ {
-+ if( commandFile != NULL )
-+ fclose( commandFile ); // this will also make the helper quit
-+ if( replyFile != NULL )
-+ fclose( replyFile );
-+ helperRunning = false;
-+ }
-+
-+void nsKDEUtils::feedCommand( const nsTArray<nsCString>& command )
-+ {
-+ for( int i = 0;
-+ i < command.Length();
-+ ++i )
-+ {
-+ nsCString line = command[ i ];
-+ line.ReplaceSubstring( "\\", "\\" "\\" ); // \ -> \\ , i.e. escape
-+ line.ReplaceSubstring( "\n", "\\n" );
-+#ifdef DEBUG_KDE
-+ fprintf( stderr, "COMM: %s\n", line.get());
-+#endif
-+ fputs( line.get(), commandFile );
-+ fputs( "\n", commandFile );
-+ }
-+ fputs( "\\E\n", commandFile ); // done as \E, so it cannot happen in normal data
-+ fflush( commandFile );
-+ }
-diff --git a/toolkit/xre/nsKDEUtils.h b/toolkit/xre/nsKDEUtils.h
-new file mode 100644
---- /dev/null
-+++ b/toolkit/xre/nsKDEUtils.h
-@@ -0,0 +1,48 @@
-+/* -*- Mode: C++; 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/. */
-+
-+#ifndef nsKDEUtils_h__
-+#define nsKDEUtils_h__
-+
-+#include "nsStringGlue.h"
-+#include "nsTArray.h"
-+#include <stdio.h>
-+
-+typedef struct _GtkWindow GtkWindow;
-+
-+class nsIArray;
-+
-+class NS_EXPORT nsKDEUtils
-+ {
-+ public:
-+ /* Returns true if running inside a KDE session (regardless of whether there is KDE
-+ support available for Waterfox). This should be used e.g. when determining
-+ dialog button order but not for code that requires the KDE support. */
-+ static bool kdeSession();
-+ /* Returns true if running inside a KDE session and KDE support is available
-+ for Waterfox. This should be used everywhere where the external helper is needed. */
-+ static bool kdeSupport();
-+ /* Executes the given helper command, returns true if helper returned success. */
-+ static bool command( const nsTArray<nsCString>& command, nsTArray<nsCString>* output = NULL );
-+ static bool command( nsIArray* command, nsIArray** output = NULL );
-+ /* Like command(), but additionally blocks the parent widget like if there was
-+ a modal dialog shown and enters the event loop (i.e. there are still paint updates,
-+ this is for commands that take long). */
-+ static bool commandBlockUi( const nsTArray<nsCString>& command, GtkWindow* parent, nsTArray<nsCString>* output = NULL );
-+
-+ private:
-+ nsKDEUtils();
-+ ~nsKDEUtils();
-+ static nsKDEUtils* self();
-+ bool startHelper();
-+ void closeHelper();
-+ void feedCommand( const nsTArray<nsCString>& command );
-+ bool internalCommand( const nsTArray<nsCString>& command, GtkWindow* parent, bool isParent,
-+ nsTArray<nsCString>* output );
-+ FILE* commandFile;
-+ FILE* replyFile;
-+ };
-+
-+#endif // nsKDEUtils
-diff --git a/uriloader/exthandler/moz.build b/uriloader/exthandler/moz.build
---- a/uriloader/exthandler/moz.build
-+++ b/uriloader/exthandler/moz.build
-@@ -77,17 +77,19 @@ else:
- SOURCES += [
- osdir + '/nsOSHelperAppService.cpp',
- ]
- if CONFIG['GNU_CXX']:
- CXXFLAGS += ['-Wno-error=shadow']
-
- if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
- UNIFIED_SOURCES += [
-+ 'unix/nsCommonRegistry.cpp',
- 'unix/nsGNOMERegistry.cpp',
-+ 'unix/nsKDERegistry.cpp',
- 'unix/nsMIMEInfoUnix.cpp',
- ]
- elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
- UNIFIED_SOURCES += [
- 'android/nsAndroidHandlerApp.cpp',
- 'android/nsExternalSharingAppService.cpp',
- 'android/nsExternalURLHandlerService.cpp',
- 'android/nsMIMEInfoAndroid.cpp',
-@@ -125,16 +127,17 @@ include('/ipc/chromium/chromium-config.m
-
- FINAL_LIBRARY = 'xul'
-
- LOCAL_INCLUDES += [
- '/dom/base',
- '/dom/ipc',
- '/netwerk/base',
- '/netwerk/protocol/http',
-+ '/toolkit/xre',
- ]
-
- if CONFIG['MOZ_ENABLE_DBUS']:
- CXXFLAGS += CONFIG['TK_CFLAGS']
- CXXFLAGS += CONFIG['MOZ_DBUS_CFLAGS']
-
- if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('gtk2', 'gtk3'):
- CXXFLAGS += CONFIG['TK_CFLAGS']
-diff --git a/uriloader/exthandler/unix/nsCommonRegistry.cpp b/uriloader/exthandler/unix/nsCommonRegistry.cpp
-new file mode 100644
---- /dev/null
-+++ b/uriloader/exthandler/unix/nsCommonRegistry.cpp
-@@ -0,0 +1,53 @@
-+/* -*- Mode: C++; 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/. */
-+
-+#include "nsCommonRegistry.h"
-+
-+#include "nsGNOMERegistry.h"
-+#include "nsKDERegistry.h"
-+#include "nsString.h"
-+#include "nsKDEUtils.h"
-+
-+/* static */ bool
-+nsCommonRegistry::HandlerExists(const char *aProtocolScheme)
-+{
-+ if( nsKDEUtils::kdeSupport())
-+ return nsKDERegistry::HandlerExists( aProtocolScheme );
-+ return nsGNOMERegistry::HandlerExists( aProtocolScheme );
-+}
-+
-+/* static */ nsresult
-+nsCommonRegistry::LoadURL(nsIURI *aURL)
-+{
-+ if( nsKDEUtils::kdeSupport())
-+ return nsKDERegistry::LoadURL( aURL );
-+ return nsGNOMERegistry::LoadURL( aURL );
-+}
-+
-+/* static */ void
-+nsCommonRegistry::GetAppDescForScheme(const nsACString& aScheme,
-+ nsAString& aDesc)
-+{
-+ if( nsKDEUtils::kdeSupport())
-+ return nsKDERegistry::GetAppDescForScheme( aScheme, aDesc );
-+ return nsGNOMERegistry::GetAppDescForScheme( aScheme, aDesc );
-+}
-+
-+
-+/* static */ already_AddRefed<nsMIMEInfoBase>
-+nsCommonRegistry::GetFromExtension(const nsACString& aFileExt)
-+{
-+ if( nsKDEUtils::kdeSupport())
-+ return nsKDERegistry::GetFromExtension( aFileExt );
-+ return nsGNOMERegistry::GetFromExtension( aFileExt );
-+}
-+
-+/* static */ already_AddRefed<nsMIMEInfoBase>
-+nsCommonRegistry::GetFromType(const nsACString& aMIMEType)
-+{
-+ if( nsKDEUtils::kdeSupport())
-+ return nsKDERegistry::GetFromType( aMIMEType );
-+ return nsGNOMERegistry::GetFromType( aMIMEType );
-+}
-diff --git a/uriloader/exthandler/unix/nsCommonRegistry.h b/uriloader/exthandler/unix/nsCommonRegistry.h
-new file mode 100644
---- /dev/null
-+++ b/uriloader/exthandler/unix/nsCommonRegistry.h
-@@ -0,0 +1,28 @@
-+/* 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/. */
-+
-+#ifndef nsCommonRegistry_h__
-+#define nsCommonRegistry_h__
-+
-+#include "nsIURI.h"
-+#include "nsCOMPtr.h"
-+
-+class nsMIMEInfoBase;
-+
-+class nsCommonRegistry
-+{
-+ public:
-+ static bool HandlerExists(const char *aProtocolScheme);
-+
-+ static nsresult LoadURL(nsIURI *aURL);
-+
-+ static void GetAppDescForScheme(const nsACString& aScheme,
-+ nsAString& aDesc);
-+
-+ static already_AddRefed<nsMIMEInfoBase> GetFromExtension(const nsACString& aFileExt);
-+
-+ static already_AddRefed<nsMIMEInfoBase> GetFromType(const nsACString& aMIMEType);
-+};
-+
-+#endif
-diff --git a/uriloader/exthandler/unix/nsKDERegistry.cpp b/uriloader/exthandler/unix/nsKDERegistry.cpp
-new file mode 100644
---- /dev/null
-+++ b/uriloader/exthandler/unix/nsKDERegistry.cpp
-@@ -0,0 +1,88 @@
-+/* -*- Mode: C++; 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/. */
-+
-+#include "nsKDERegistry.h"
-+#include "prlink.h"
-+#include "prmem.h"
-+#include "nsString.h"
-+#include "nsILocalFile.h"
-+#include "nsMIMEInfoUnix.h"
-+#include "nsAutoPtr.h"
-+#include "nsKDEUtils.h"
-+
-+/* static */ bool
-+nsKDERegistry::HandlerExists(const char *aProtocolScheme)
-+{
-+ nsTArray<nsCString> command;
-+ command.AppendElement( NS_LITERAL_CSTRING( "HANDLEREXISTS" ));
-+ command.AppendElement( nsAutoCString( aProtocolScheme ));
-+ return nsKDEUtils::command( command );
-+}
-+
-+/* static */ nsresult
-+nsKDERegistry::LoadURL(nsIURI *aURL)
-+{
-+ nsTArray<nsCString> command;
-+ command.AppendElement( NS_LITERAL_CSTRING( "OPEN" ));
-+ nsCString url;
-+ aURL->GetSpec( url );
-+ command.AppendElement( url );
-+ bool rv = nsKDEUtils::command( command );
-+ if (!rv)
-+ return NS_ERROR_FAILURE;
-+
-+ return NS_OK;
-+}
-+
-+/* static */ void
-+nsKDERegistry::GetAppDescForScheme(const nsACString& aScheme,
-+ nsAString& aDesc)
-+{
-+ nsTArray<nsCString> command;
-+ command.AppendElement( NS_LITERAL_CSTRING( "GETAPPDESCFORSCHEME" ));
-+ command.AppendElement( aScheme );
-+ nsTArray<nsCString> output;
-+ if( nsKDEUtils::command( command, &output ) && output.Length() == 1 )
-+ CopyUTF8toUTF16( output[ 0 ], aDesc );
-+}
-+
-+
-+/* static */ already_AddRefed<nsMIMEInfoBase>
-+nsKDERegistry::GetFromExtension(const nsACString& aFileExt)
-+{
-+ NS_ASSERTION(aFileExt[0] != '.', "aFileExt shouldn't start with a dot");
-+ nsTArray<nsCString> command;
-+ command.AppendElement( NS_LITERAL_CSTRING( "GETFROMEXTENSION" ));
-+ command.AppendElement( aFileExt );
-+ return GetFromHelper( command );
-+}
-+
-+/* static */ already_AddRefed<nsMIMEInfoBase>
-+nsKDERegistry::GetFromType(const nsACString& aMIMEType)
-+{
-+ nsTArray<nsCString> command;
-+ command.AppendElement( NS_LITERAL_CSTRING( "GETFROMTYPE" ));
-+ command.AppendElement( aMIMEType );
-+ return GetFromHelper( command );
-+}
-+
-+/* static */ already_AddRefed<nsMIMEInfoBase>
-+nsKDERegistry::GetFromHelper(const nsTArray<nsCString>& command)
-+{
-+ nsTArray<nsCString> output;
-+ if( nsKDEUtils::command( command, &output ) && output.Length() == 3 )
-+ {
-+ nsCString mimetype = output[ 0 ];
-+ RefPtr<nsMIMEInfoUnix> mimeInfo = new nsMIMEInfoUnix( mimetype );
-+ NS_ENSURE_TRUE(mimeInfo, nullptr);
-+ nsCString description = output[ 1 ];
-+ mimeInfo->SetDescription(NS_ConvertUTF8toUTF16(description));
-+ nsCString handlerAppName = output[ 2 ];
-+ mimeInfo->SetDefaultDescription(NS_ConvertUTF8toUTF16(handlerAppName));
-+ mimeInfo->SetPreferredAction(nsIMIMEInfo::useSystemDefault);
-+ return mimeInfo.forget();
-+ }
-+ return nullptr;
-+}
-diff --git a/uriloader/exthandler/unix/nsKDERegistry.h b/uriloader/exthandler/unix/nsKDERegistry.h
-new file mode 100644
---- /dev/null
-+++ b/uriloader/exthandler/unix/nsKDERegistry.h
-@@ -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/. */
-+
-+#ifndef nsKDERegistry_h__
-+#define nsKDERegistry_h__
-+
-+#include "nsIURI.h"
-+#include "nsCOMPtr.h"
-+#include "nsTArray.h"
-+
-+class nsMIMEInfoBase;
-+class nsAutoCString;
-+class nsCString;
-+
-+class nsKDERegistry
-+{
-+ public:
-+ static bool HandlerExists(const char *aProtocolScheme);
-+
-+ static nsresult LoadURL(nsIURI *aURL);
-+
-+ static void GetAppDescForScheme(const nsACString& aScheme,
-+ nsAString& aDesc);
-+
-+ static already_AddRefed<nsMIMEInfoBase> GetFromExtension(const nsACString& aFileExt);
-+
-+ static already_AddRefed<nsMIMEInfoBase> GetFromType(const nsACString& aMIMEType);
-+ private:
-+ static already_AddRefed<nsMIMEInfoBase> GetFromHelper(const nsTArray<nsCString>& command);
-+
-+};
-+
-+#endif //nsKDERegistry_h__
-diff --git a/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp b/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp
---- a/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp
-+++ b/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp
-@@ -1,50 +1,53 @@
- /* -*- Mode: C++; tab-width: 3; 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/. */
-
- #include "nsMIMEInfoUnix.h"
--#include "nsGNOMERegistry.h"
-+#include "nsCommonRegistry.h"
- #include "nsIGIOService.h"
- #include "nsNetCID.h"
- #include "nsIIOService.h"
- #include "nsAutoPtr.h"
- #ifdef MOZ_ENABLE_DBUS
- #include "nsDBusHandlerApp.h"
- #endif
-+#if defined(XP_UNIX) && !defined(XP_MACOSX)
-+#include "nsKDEUtils.h"
-+#endif
-
- nsresult
- nsMIMEInfoUnix::LoadUriInternal(nsIURI * aURI)
- {
-- return nsGNOMERegistry::LoadURL(aURI);
-+ return nsCommonRegistry::LoadURL(aURI);
- }
-
- NS_IMETHODIMP
- nsMIMEInfoUnix::GetHasDefaultHandler(bool *_retval)
- {
- // if mDefaultApplication is set, it means the application has been set from
- // either /etc/mailcap or ${HOME}/.mailcap, in which case we don't want to
- // give the GNOME answer.
- if (mDefaultApplication)
- return nsMIMEInfoImpl::GetHasDefaultHandler(_retval);
-
- *_retval = false;
-
- if (mClass == eProtocolInfo) {
-- *_retval = nsGNOMERegistry::HandlerExists(mSchemeOrType.get());
-+ *_retval = nsCommonRegistry::HandlerExists(mSchemeOrType.get());
- } else {
-- RefPtr<nsMIMEInfoBase> mimeInfo = nsGNOMERegistry::GetFromType(mSchemeOrType);
-+ RefPtr<nsMIMEInfoBase> mimeInfo = nsCommonRegistry::GetFromType(mSchemeOrType);
- if (!mimeInfo) {
- nsAutoCString ext;
- nsresult rv = GetPrimaryExtension(ext);
- if (NS_SUCCEEDED(rv)) {
-- mimeInfo = nsGNOMERegistry::GetFromExtension(ext);
-+ mimeInfo = nsCommonRegistry::GetFromExtension(ext);
- }
- }
- if (mimeInfo)
- *_retval = true;
- }
-
- if (*_retval)
- return NS_OK;
-@@ -79,16 +82,33 @@ nsMIMEInfoUnix::LaunchDefaultWithFile(ns
- ContentAction::Action::defaultActionForFile(uri, QString(mSchemeOrType.get()));
- if (action.isValid()) {
- action.trigger();
- return NS_OK;
- }
- return NS_ERROR_FAILURE;
- #endif
-
-+ if( nsKDEUtils::kdeSupport()) {
-+ bool supports;
-+ if( NS_SUCCEEDED( GetHasDefaultHandler( &supports )) && supports ) {
-+ nsTArray<nsCString> command;
-+ command.AppendElement( NS_LITERAL_CSTRING( "OPEN" ));
-+ command.AppendElement( nativePath );
-+ command.AppendElement( NS_LITERAL_CSTRING( "MIMETYPE" ));
-+ command.AppendElement( mSchemeOrType );
-+ if( nsKDEUtils::command( command ))
-+ return NS_OK;
-+ }
-+ if (!mDefaultApplication)
-+ return NS_ERROR_FILE_NOT_FOUND;
-+
-+ return LaunchWithIProcess(mDefaultApplication, nativePath);
-+ }
-+
- nsCOMPtr<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID);
- if (!giovfs) {
- return NS_ERROR_FAILURE;
- }
-
- // nsGIOMimeApp->Launch wants a URI string instead of local file
- nsresult rv;
- nsCOMPtr<nsIIOService> ioservice = do_GetService(NS_IOSERVICE_CONTRACTID, &rv);
-diff --git a/uriloader/exthandler/unix/nsOSHelperAppService.cpp b/uriloader/exthandler/unix/nsOSHelperAppService.cpp
---- a/uriloader/exthandler/unix/nsOSHelperAppService.cpp
-+++ b/uriloader/exthandler/unix/nsOSHelperAppService.cpp
-@@ -10,17 +10,17 @@
- #if defined(MOZ_ENABLE_CONTENTACTION)
- #include <contentaction/contentaction.h>
- #include <QString>
- #endif
-
- #include "nsOSHelperAppService.h"
- #include "nsMIMEInfoUnix.h"
- #ifdef MOZ_WIDGET_GTK
--#include "nsGNOMERegistry.h"
-+#include "nsCommonRegistry.h"
- #endif
- #include "nsISupports.h"
- #include "nsString.h"
- #include "nsReadableUtils.h"
- #include "nsUnicharUtils.h"
- #include "nsXPIDLString.h"
- #include "nsIURL.h"
- #include "nsIFileStreams.h"
-@@ -1143,26 +1143,26 @@ nsresult nsOSHelperAppService::OSProtoco
- ContentAction::Action::defaultActionForScheme(QString(aProtocolScheme) + ':');
-
- if (action.isValid())
- *aHandlerExists = true;
- #endif
-
- #ifdef MOZ_WIDGET_GTK
- // Check the GNOME registry for a protocol handler
-- *aHandlerExists = nsGNOMERegistry::HandlerExists(aProtocolScheme);
-+ *aHandlerExists = nsCommonRegistry::HandlerExists(aProtocolScheme);
- #endif
-
- return NS_OK;
- }
-
- NS_IMETHODIMP nsOSHelperAppService::GetApplicationDescription(const nsACString& aScheme, nsAString& _retval)
- {
- #ifdef MOZ_WIDGET_GTK
-- nsGNOMERegistry::GetAppDescForScheme(aScheme, _retval);
-+ nsCommonRegistry::GetAppDescForScheme(aScheme, _retval);
- return _retval.IsEmpty() ? NS_ERROR_NOT_AVAILABLE : NS_OK;
- #else
- return NS_ERROR_NOT_AVAILABLE;
- #endif
- }
-
- nsresult nsOSHelperAppService::GetFileTokenForPath(const char16_t * platformAppPath, nsIFile ** aFile)
- {
-@@ -1249,17 +1249,17 @@ nsOSHelperAppService::GetFromExtension(c
- mime_types_description,
- true);
-
- if (NS_FAILED(rv) || majorType.IsEmpty()) {
-
- #ifdef MOZ_WIDGET_GTK
- LOG(("Looking in GNOME registry\n"));
- RefPtr<nsMIMEInfoBase> gnomeInfo =
-- nsGNOMERegistry::GetFromExtension(aFileExt);
-+ nsCommonRegistry::GetFromExtension(aFileExt);
- if (gnomeInfo) {
- LOG(("Got MIMEInfo from GNOME registry\n"));
- return gnomeInfo.forget();
- }
- #endif
-
- rv = LookUpTypeAndDescription(NS_ConvertUTF8toUTF16(aFileExt),
- majorType,
-@@ -1370,17 +1370,17 @@ nsOSHelperAppService::GetFromType(const
- nsAutoString extensions, mime_types_description;
- LookUpExtensionsAndDescription(majorType,
- minorType,
- extensions,
- mime_types_description);
-
- #ifdef MOZ_WIDGET_GTK
- if (handler.IsEmpty()) {
-- RefPtr<nsMIMEInfoBase> gnomeInfo = nsGNOMERegistry::GetFromType(aMIMEType);
-+ RefPtr<nsMIMEInfoBase> gnomeInfo = nsCommonRegistry::GetFromType(aMIMEType);
- if (gnomeInfo) {
- LOG(("Got MIMEInfo from GNOME registry without extensions; setting them "
- "to %s\n", NS_LossyConvertUTF16toASCII(extensions).get()));
-
- NS_ASSERTION(!gnomeInfo->HasExtensions(), "How'd that happen?");
- gnomeInfo->SetFileExtensions(NS_ConvertUTF16toUTF8(extensions));
- return gnomeInfo.forget();
- }
-diff --git a/widget/gtk/moz.build b/widget/gtk/moz.build
---- a/widget/gtk/moz.build
-+++ b/widget/gtk/moz.build
-@@ -109,16 +109,17 @@ else:
- include('/ipc/chromium/chromium-config.mozbuild')
-
- FINAL_LIBRARY = 'xul'
-
- LOCAL_INCLUDES += [
- '/layout/generic',
- '/layout/xul',
- '/other-licenses/atk-1.0',
-+ '/toolkit/xre',
- '/widget',
- '/widget/headless',
- ]
-
- if CONFIG['MOZ_X11']:
- LOCAL_INCLUDES += [
- '/widget/x11',
- ]
-diff --git a/widget/gtk/nsFilePicker.cpp b/widget/gtk/nsFilePicker.cpp
---- a/widget/gtk/nsFilePicker.cpp
-+++ b/widget/gtk/nsFilePicker.cpp
-@@ -4,32 +4,34 @@
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
- #include "mozilla/Types.h"
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <unistd.h>
-
- #include <gtk/gtk.h>
-+#include <gdk/gdkx.h>
-
- #include "nsGtkUtils.h"
- #include "nsIFileURL.h"
- #include "nsIURI.h"
- #include "nsIWidget.h"
- #include "nsIFile.h"
- #include "nsIStringBundle.h"
-
- #include "nsArrayEnumerator.h"
- #include "nsMemory.h"
- #include "nsEnumeratorUtils.h"
- #include "nsNetUtil.h"
- #include "nsReadableUtils.h"
- #include "mozcontainer.h"
-
- #include "nsFilePicker.h"
-+#include "nsKDEUtils.h"
-
- using namespace mozilla;
-
- #define MAX_PREVIEW_SIZE 180
- // bug 1184009
- #define MAX_PREVIEW_SOURCE_SIZE 4096
-
- nsIFile *nsFilePicker::mPrevDisplayDirectory = nullptr;
-@@ -246,17 +248,19 @@ nsFilePicker::AppendFilters(int32_t aFil
- return nsBaseFilePicker::AppendFilters(aFilterMask);
- }
-
- NS_IMETHODIMP
- nsFilePicker::AppendFilter(const nsAString& aTitle, const nsAString& aFilter)
- {
- if (aFilter.EqualsLiteral("..apps")) {
- // No platform specific thing we can do here, really....
-- return NS_OK;
-+ // Unless it's KDE.
-+ if( mMode != modeOpen || !nsKDEUtils::kdeSupport())
-+ return NS_OK;
- }
-
- nsAutoCString filter, name;
- CopyUTF16toUTF8(aFilter, filter);
- CopyUTF16toUTF8(aTitle, name);
-
- mFilters.AppendElement(filter);
- mFilterNames.AppendElement(name);
-@@ -371,16 +375,37 @@ nsFilePicker::Show(int16_t *aReturn)
-
- NS_IMETHODIMP
- nsFilePicker::Open(nsIFilePickerShownCallback *aCallback)
- {
- // Can't show two dialogs concurrently with the same filepicker
- if (mRunning)
- return NS_ERROR_NOT_AVAILABLE;
-
-+ // KDE file picker is not handled via callback
-+ if( nsKDEUtils::kdeSupport()) {
-+ mCallback = aCallback;
-+ mRunning = true;
-+ g_idle_add([](gpointer data) -> gboolean {
-+ nsFilePicker* queuedPicker = (nsFilePicker*) data;
-+ int16_t result;
-+ queuedPicker->kdeFileDialog(&result);
-+ if (queuedPicker->mCallback) {
-+ queuedPicker->mCallback->Done(result);
-+ queuedPicker->mCallback = nullptr;
-+ } else {
-+ queuedPicker->mResult = result;
-+ }
-+ queuedPicker->mRunning = false;
-+ return G_SOURCE_REMOVE;
-+ }, this);
-+
-+ return NS_OK;
-+ }
-+
- nsXPIDLCString title;
- title.Adopt(ToNewUTF8String(mTitle));
-
- GtkWindow *parent_widget =
- GTK_WINDOW(mParentWidget->GetNativeData(NS_NATIVE_SHELLWIDGET));
-
- GtkFileChooserAction action = GetGtkFileChooserAction(mMode);
-
-@@ -603,8 +628,233 @@ nsFilePicker::Done(GtkWidget* file_choos
- if (mCallback) {
- mCallback->Done(result);
- mCallback = nullptr;
- } else {
- mResult = result;
- }
- NS_RELEASE_THIS();
- }
-+
-+nsCString nsFilePicker::kdeMakeFilter( int index )
-+ {
-+ nsCString buf = mFilters[ index ];
-+ for( PRUint32 i = 0;
-+ i < buf.Length();
-+ ++i )
-+ if( buf[ i ] == ';' ) // KDE separates just using spaces
-+ buf.SetCharAt( ' ', i );
-+ if (!mFilterNames[index].IsEmpty())
-+ {
-+ buf += "|";
-+ buf += mFilterNames[index].get();
-+ }
-+ return buf;
-+ }
-+
-+static PRInt32 windowToXid( nsIWidget* widget )
-+ {
-+ GtkWindow *parent_widget = GTK_WINDOW(widget->GetNativeData(NS_NATIVE_SHELLWIDGET));
-+ GdkWindow* gdk_window = gtk_widget_get_window( gtk_widget_get_toplevel( GTK_WIDGET( parent_widget )));
-+ return GDK_WINDOW_XID( gdk_window );
-+ }
-+
-+NS_IMETHODIMP nsFilePicker::kdeFileDialog(PRInt16 *aReturn)
-+ {
-+ NS_ENSURE_ARG_POINTER(aReturn);
-+
-+ if( mMode == modeOpen && mFilters.Length() == 1 && mFilters[ 0 ].EqualsLiteral( "..apps" ))
-+ return kdeAppsDialog( aReturn );
-+
-+ nsXPIDLCString title;
-+ title.Adopt(ToNewUTF8String(mTitle));
-+
-+ const char* arg = NULL;
-+ if( mAllowURLs )
-+ {
-+ switch( mMode )
-+ {
-+ case nsIFilePicker::modeOpen:
-+ case nsIFilePicker::modeOpenMultiple:
-+ arg = "GETOPENURL";
-+ break;
-+ case nsIFilePicker::modeSave:
-+ arg = "GETSAVEURL";
-+ break;
-+ case nsIFilePicker::modeGetFolder:
-+ arg = "GETDIRECTORYURL";
-+ break;
-+ }
-+ }
-+ else
-+ {
-+ switch( mMode )
-+ {
-+ case nsIFilePicker::modeOpen:
-+ case nsIFilePicker::modeOpenMultiple:
-+ arg = "GETOPENFILENAME";
-+ break;
-+ case nsIFilePicker::modeSave:
-+ arg = "GETSAVEFILENAME";
-+ break;
-+ case nsIFilePicker::modeGetFolder:
-+ arg = "GETDIRECTORYFILENAME";
-+ break;
-+ }
-+ }
-+
-+ nsAutoCString directory;
-+ if (mDisplayDirectory) {
-+ mDisplayDirectory->GetNativePath(directory);
-+ } else if (mPrevDisplayDirectory) {
-+ mPrevDisplayDirectory->GetNativePath(directory);
-+ }
-+
-+ nsAutoCString startdir;
-+ if (!directory.IsEmpty()) {
-+ startdir = directory;
-+ }
-+ if (mMode == nsIFilePicker::modeSave) {
-+ if( !startdir.IsEmpty())
-+ {
-+ startdir += "/";
-+ startdir += ToNewUTF8String(mDefault);
-+ }
-+ else
-+ startdir = ToNewUTF8String(mDefault);
-+ }
-+
-+ nsAutoCString filters;
-+ PRInt32 count = mFilters.Length();
-+ if( count == 0 ) //just in case
-+ filters = "*";
-+ else
-+ {
-+ filters = kdeMakeFilter( 0 );
-+ for (PRInt32 i = 1; i < count; ++i)
-+ {
-+ filters += "\n";
-+ filters += kdeMakeFilter( i );
-+ }
-+ }
-+
-+ nsTArray<nsCString> command;
-+ command.AppendElement( nsAutoCString( arg ));
-+ command.AppendElement( startdir );
-+ if( mMode != nsIFilePicker::modeGetFolder )
-+ {
-+ command.AppendElement( filters );
-+ nsAutoCString selected;
-+ selected.AppendInt( mSelectedType );
-+ command.AppendElement( selected );
-+ }
-+ command.AppendElement( title );
-+ if( mMode == nsIFilePicker::modeOpenMultiple )
-+ command.AppendElement( NS_LITERAL_CSTRING( "MULTIPLE" ));
-+ if( PRInt32 xid = windowToXid( mParentWidget ))
-+ {
-+ command.AppendElement( NS_LITERAL_CSTRING( "PARENT" ));
-+ nsAutoCString parent;
-+ parent.AppendInt( xid );
-+ command.AppendElement( parent );
-+ }
-+
-+ nsTArray<nsCString> output;
-+ if( nsKDEUtils::commandBlockUi( command, GTK_WINDOW(mParentWidget->GetNativeData(NS_NATIVE_SHELLWIDGET)), &output ))
-+ {
-+ *aReturn = nsIFilePicker::returnOK;
-+ mFiles.Clear();
-+ if( mMode != nsIFilePicker::modeGetFolder )
-+ {
-+ mSelectedType = atoi( output[ 0 ].get());
-+ output.RemoveElementAt( 0 );
-+ }
-+ if (mMode == nsIFilePicker::modeOpenMultiple)
-+ {
-+ mFileURL.Truncate();
-+ PRUint32 count = output.Length();
-+ for( PRUint32 i = 0;
-+ i < count;
-+ ++i )
-+ {
-+ nsCOMPtr<nsIFile> localfile;
-+ nsresult rv = NS_NewNativeLocalFile( output[ i ],
-+ PR_FALSE,
-+ getter_AddRefs(localfile));
-+ if (NS_SUCCEEDED(rv))
-+ mFiles.AppendObject(localfile);
-+ }
-+ }
-+ else
-+ {
-+ if( output.Length() == 0 )
-+ mFileURL = nsCString();
-+ else if( mAllowURLs )
-+ mFileURL = output[ 0 ];
-+ else // GetFile() actually requires it to be url even for local files :-/
-+ {
-+ mFileURL = nsCString( "file://" );
-+ mFileURL.Append( output[ 0 ] );
-+ }
-+ }
-+ // Remember last used directory.
-+ nsCOMPtr<nsIFile> file;
-+ GetFile(getter_AddRefs(file));
-+ if (file) {
-+ nsCOMPtr<nsIFile> dir;
-+ file->GetParent(getter_AddRefs(dir));
-+ nsCOMPtr<nsIFile> localDir(do_QueryInterface(dir));
-+ if (localDir) {
-+ localDir.swap(mPrevDisplayDirectory);
-+ }
-+ }
-+ if (mMode == nsIFilePicker::modeSave)
-+ {
-+ nsCOMPtr<nsIFile> file;
-+ GetFile(getter_AddRefs(file));
-+ if (file)
-+ {
-+ bool exists = false;
-+ file->Exists(&exists);
-+ if (exists) // TODO do overwrite check in the helper app
-+ *aReturn = nsIFilePicker::returnReplace;
-+ }
-+ }
-+ }
-+ else
-+ {
-+ *aReturn = nsIFilePicker::returnCancel;
-+ }
-+ return NS_OK;
-+ }
-+
-+
-+NS_IMETHODIMP nsFilePicker::kdeAppsDialog(PRInt16 *aReturn)
-+ {
-+ NS_ENSURE_ARG_POINTER(aReturn);
-+
-+ nsXPIDLCString title;
-+ title.Adopt(ToNewUTF8String(mTitle));
-+
-+ nsTArray<nsCString> command;
-+ command.AppendElement( NS_LITERAL_CSTRING( "APPSDIALOG" ));
-+ command.AppendElement( title );
-+ if( PRInt32 xid = windowToXid( mParentWidget ))
-+ {
-+ command.AppendElement( NS_LITERAL_CSTRING( "PARENT" ));
-+ nsAutoCString parent;
-+ parent.AppendInt( xid );
-+ command.AppendElement( parent );
-+ }
-+
-+ nsTArray<nsCString> output;
-+ if( nsKDEUtils::commandBlockUi( command, GTK_WINDOW(mParentWidget->GetNativeData(NS_NATIVE_SHELLWIDGET)), &output ))
-+ {
-+ *aReturn = nsIFilePicker::returnOK;
-+ mFileURL = output.Length() > 0 ? output[ 0 ] : nsCString();
-+ }
-+ else
-+ {
-+ *aReturn = nsIFilePicker::returnCancel;
-+ }
-+ return NS_OK;
-+ }
-+
-diff --git a/widget/gtk/nsFilePicker.h b/widget/gtk/nsFilePicker.h
---- a/widget/gtk/nsFilePicker.h
-+++ b/widget/gtk/nsFilePicker.h
-@@ -69,14 +69,20 @@ protected:
- nsString mDefaultExtension;
-
- nsTArray<nsCString> mFilters;
- nsTArray<nsCString> mFilterNames;
-
- private:
- static nsIFile *mPrevDisplayDirectory;
-
-+ bool kdeRunning();
-+ bool getKdeRunning();
-+ NS_IMETHODIMP kdeFileDialog(PRInt16 *aReturn);
-+ NS_IMETHODIMP kdeAppsDialog(PRInt16 *aReturn);
-+ nsCString kdeMakeFilter( int index );
-+
- #if (MOZ_WIDGET_GTK == 3)
- GtkFileChooserWidget *mFileChooserDelegate;
- #endif
- };
-
- #endif
-diff --git a/xpcom/components/ManifestParser.cpp b/xpcom/components/ManifestParser.cpp
---- a/xpcom/components/ManifestParser.cpp
-+++ b/xpcom/components/ManifestParser.cpp
-@@ -33,16 +33,17 @@
- #include "nsTextFormatter.h"
- #include "nsVersionComparator.h"
- #include "nsXPCOMCIDInternal.h"
-
- #include "nsIConsoleService.h"
- #include "nsIScriptError.h"
- #include "nsIXULAppInfo.h"
- #include "nsIXULRuntime.h"
-+#include "nsKDEUtils.h"
-
- using namespace mozilla;
-
- struct ManifestDirective
- {
- const char* directive;
- int argc;
-
-@@ -466,16 +467,17 @@ ParseManifest(NSLocationType aType, File
- NS_NAMED_LITERAL_STRING(kRemoteEnabled, "remoteenabled");
- NS_NAMED_LITERAL_STRING(kRemoteRequired, "remoterequired");
- NS_NAMED_LITERAL_STRING(kApplication, "application");
- NS_NAMED_LITERAL_STRING(kAppVersion, "appversion");
- NS_NAMED_LITERAL_STRING(kGeckoVersion, "platformversion");
- NS_NAMED_LITERAL_STRING(kOs, "os");
- NS_NAMED_LITERAL_STRING(kOsVersion, "osversion");
- NS_NAMED_LITERAL_STRING(kABI, "abi");
-+ NS_NAMED_LITERAL_STRING(kDesktop, "desktop");
- NS_NAMED_LITERAL_STRING(kProcess, "process");
- #if defined(MOZ_WIDGET_ANDROID)
- NS_NAMED_LITERAL_STRING(kTablet, "tablet");
- #endif
-
- NS_NAMED_LITERAL_STRING(kMain, "main");
- NS_NAMED_LITERAL_STRING(kContent, "content");
-
-@@ -526,44 +528,49 @@ ParseManifest(NSLocationType aType, File
- CopyUTF8toUTF16(s, abi);
- abi.Insert(char16_t('_'), 0);
- abi.Insert(osTarget, 0);
- }
- }
- }
-
- nsAutoString osVersion;
-+ nsAutoString desktop;
- #if defined(XP_WIN)
- #pragma warning(push)
- #pragma warning(disable:4996) // VC12+ deprecates GetVersionEx
- OSVERSIONINFO info = { sizeof(OSVERSIONINFO) };
- if (GetVersionEx(&info)) {
- nsTextFormatter::ssprintf(osVersion, u"%ld.%ld",
- info.dwMajorVersion,
- info.dwMinorVersion);
- }
-+ desktop = NS_LITERAL_STRING("win");
- #pragma warning(pop)
- #elif defined(MOZ_WIDGET_COCOA)
- SInt32 majorVersion = nsCocoaFeatures::OSXVersionMajor();
- SInt32 minorVersion = nsCocoaFeatures::OSXVersionMinor();
- nsTextFormatter::ssprintf(osVersion, u"%ld.%ld",
- majorVersion,
- minorVersion);
-+ desktop = NS_LITERAL_STRING("macosx");
- #elif defined(MOZ_WIDGET_GTK)
- nsTextFormatter::ssprintf(osVersion, u"%ld.%ld",
- gtk_major_version,
- gtk_minor_version);
-+ desktop = nsKDEUtils::kdeSession() ? NS_LITERAL_STRING("kde") : NS_LITERAL_STRING("gnome");
- #elif defined(MOZ_WIDGET_ANDROID)
- bool isTablet = false;
- if (mozilla::AndroidBridge::Bridge()) {
- mozilla::AndroidBridge::Bridge()->GetStaticStringField("android/os/Build$VERSION",
- "RELEASE",
- osVersion);
- isTablet = java::GeckoAppShell::IsTablet();
- }
-+ desktop = NS_LITERAL_STRING("android");
- #endif
-
- if (XRE_IsContentProcess()) {
- process = kContent;
- } else {
- process = kMain;
- }
-
-@@ -666,25 +673,27 @@ ParseManifest(NSLocationType aType, File
- TriState stOsVersion = eUnspecified;
- TriState stOs = eUnspecified;
- TriState stABI = eUnspecified;
- TriState stProcess = eUnspecified;
- #if defined(MOZ_WIDGET_ANDROID)
- TriState stTablet = eUnspecified;
- #endif
- int flags = 0;
-+ TriState stDesktop = eUnspecified;
-
- while ((token = nsCRT::strtok(whitespace, kWhitespace, &whitespace)) &&
- ok) {
- ToLowerCase(token);
- NS_ConvertASCIItoUTF16 wtoken(token);
-
- if (CheckStringFlag(kApplication, wtoken, appID, stApp) ||
- CheckOsFlag(kOs, wtoken, osTarget, stOs) ||
- CheckStringFlag(kABI, wtoken, abi, stABI) ||
-+ CheckStringFlag(kDesktop, wtoken, desktop, stDesktop) ||
- CheckStringFlag(kProcess, wtoken, process, stProcess) ||
- CheckVersionFlag(kOsVersion, wtoken, osVersion, stOsVersion) ||
- CheckVersionFlag(kAppVersion, wtoken, appVersion, stAppVersion) ||
- CheckVersionFlag(kGeckoVersion, wtoken, geckoVersion, stGeckoVersion)) {
- continue;
- }
-
- #if defined(MOZ_WIDGET_ANDROID)
-@@ -729,16 +738,17 @@ ParseManifest(NSLocationType aType, File
- }
-
- if (!ok ||
- stApp == eBad ||
- stAppVersion == eBad ||
- stGeckoVersion == eBad ||
- stOs == eBad ||
- stOsVersion == eBad ||
-+ stDesktop == eBad ||
- #ifdef MOZ_WIDGET_ANDROID
- stTablet == eBad ||
- #endif
- stABI == eBad ||
- stProcess == eBad) {
- continue;
- }
-
-diff --git a/xpcom/components/moz.build b/xpcom/components/moz.build
---- a/xpcom/components/moz.build
-+++ b/xpcom/components/moz.build
-@@ -44,12 +44,13 @@ FINAL_LIBRARY = 'xul'
- LOCAL_INCLUDES += [
- '!..',
- '../base',
- '../build',
- '../ds',
- '../reflect/xptinfo',
- '/chrome',
- '/modules/libjar',
-+ '/toolkit/xre'
- ]
-
- if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
- CXXFLAGS += CONFIG['TK_CFLAGS']
-diff --git a/xpcom/io/nsLocalFileUnix.cpp b/xpcom/io/nsLocalFileUnix.cpp
---- a/xpcom/io/nsLocalFileUnix.cpp
-+++ b/xpcom/io/nsLocalFileUnix.cpp
-@@ -46,16 +46,17 @@
- #include "prproces.h"
- #include "nsIDirectoryEnumerator.h"
- #include "nsISimpleEnumerator.h"
- #include "private/pprio.h"
- #include "prlink.h"
-
- #ifdef MOZ_WIDGET_GTK
- #include "nsIGIOService.h"
-+#include "nsKDEUtils.h"
- #endif
-
- #ifdef MOZ_WIDGET_COCOA
- #include <Carbon/Carbon.h>
- #include "CocoaFileUtils.h"
- #include "prmem.h"
- #include "plbase64.h"
-
-@@ -1941,59 +1942,74 @@ nsLocalFile::SetPersistentDescriptor(con
- return InitWithNativePath(aPersistentDescriptor);
- #endif
- }
-
- NS_IMETHODIMP
- nsLocalFile::Reveal()
- {
- #ifdef MOZ_WIDGET_GTK
-- nsCOMPtr<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID);
-- if (!giovfs) {
-- return NS_ERROR_FAILURE;
-- }
-+ nsAutoCString url;
-
- bool isDirectory;
- if (NS_FAILED(IsDirectory(&isDirectory))) {
- return NS_ERROR_FAILURE;
- }
-
-+ nsCOMPtr<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID);
- if (isDirectory) {
-- return giovfs->ShowURIForInput(mPath);
-+ url = mPath;
- }
- if (NS_SUCCEEDED(giovfs->OrgFreedesktopFileManager1ShowItems(mPath))) {
- return NS_OK;
- }
- nsCOMPtr<nsIFile> parentDir;
- nsAutoCString dirPath;
- if (NS_FAILED(GetParent(getter_AddRefs(parentDir)))) {
- return NS_ERROR_FAILURE;
- }
- if (NS_FAILED(parentDir->GetNativePath(dirPath))) {
- return NS_ERROR_FAILURE;
- }
-
-- return giovfs->ShowURIForInput(dirPath);
-+ url = dirPath;
- #elif defined(MOZ_WIDGET_COCOA)
- CFURLRef url;
- if (NS_SUCCEEDED(GetCFURL(&url))) {
- nsresult rv = CocoaFileUtils::RevealFileInFinder(url);
- ::CFRelease(url);
- return rv;
- }
- return NS_ERROR_FAILURE;
- #else
- return NS_ERROR_FAILURE;
- #endif
-+ if(nsKDEUtils::kdeSupport()) {
-+ nsTArray<nsCString> command;
-+ command.AppendElement( NS_LITERAL_CSTRING("REVEAL") );
-+ command.AppendElement( mPath );
-+ return nsKDEUtils::command( command ) ? NS_OK : NS_ERROR_FAILURE;
-+ }
-+
-+ if (!giovfs)
-+ return NS_ERROR_FAILURE;
-+
-+ return giovfs->ShowURIForInput(url);
- }
-
- NS_IMETHODIMP
- nsLocalFile::Launch()
- {
- #ifdef MOZ_WIDGET_GTK
-+ if( nsKDEUtils::kdeSupport()) {
-+ nsTArray<nsCString> command;
-+ command.AppendElement( NS_LITERAL_CSTRING("OPEN") );
-+ command.AppendElement( mPath );
-+ return nsKDEUtils::command( command ) ? NS_OK : NS_ERROR_FAILURE;
-+ }
- nsCOMPtr<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID);
- if (!giovfs) {
- return NS_ERROR_FAILURE;
- }
-
- return giovfs->ShowURIForInput(mPath);
- #elif defined(MOZ_ENABLE_CONTENTACTION)
- QUrl uri = QUrl::fromLocalFile(QString::fromUtf8(mPath.get()));