diff --git a/firefox-kde.patch b/firefox-kde.patch
new file mode 100644
index 0000000..d2a94cb
--- /dev/null
+++ b/firefox-kde.patch
@@ -0,0 +1,1677 @@
+# HG changeset patch
+# Parent 2cb2f829aabd7e3efaa973a0a8cf99aca9605bdc
+
+diff --git a/browser/base/content/browser-kde.xul b/browser/base/content/browser-kde.xul
+new file mode 100644
+--- /dev/null
++++ b/browser/base/content/browser-kde.xul
+@@ -0,0 +1,1200 @@
++#filter substitution
++
++# -*- Mode: HTML -*-
++#
++# This Source Code Form is subject to the terms of the Mozilla Public
++# License, v. 2.0. If a copy of the MPL was not distributed with this
++# file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++# All DTD information is stored in a separate file so that it can be shared by
++# hiddenWindow.xul.
++#include browser-doctype.inc
++
++
++
++# All JS files which are not content (only) dependent that browser.xul
++# wishes to include *must* go into the global-scripts.inc file
++# so that they can be shared by macBrowserOverlay.xul.
++#include global-scripts.inc
++
++
++
++
++
++
++
++
++# All sets except for popupsets (commands, keys, stringbundles and broadcasters) *must* go into the
++# browser-sets.inc file for sharing with hiddenWindow.xul.
++#define FULL_BROWSER_WINDOW
++#include browser-sets.inc
++#undef FULL_BROWSER_WINDOW
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++#ifdef XP_UNIX
++
++
++#else
++
++
++#endif
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++#ifdef XP_MACOSX
++
++#else
++
++#endif
++
++
++
++
++#ifdef XP_MACOSX
++
++#else
++
++#endif
++
++
++
++
++
++
++
++#include popup-notifications.inc
++
++#include ../../components/customizableui/content/panelUI.inc.xul
++#include ../../components/controlcenter/content/panel.inc.xul
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++#ifdef CAN_DRAW_IN_TITLEBAR
++
++
++
++
++#ifdef XP_WIN
++
++
++
++#endif
++
++
++
++
++
++
++#ifdef XP_MACOSX
++
++
++
++
++
++#endif
++
++
++#endif
++
++
++
++
++
++
++
++
++
++
++#if defined(MOZ_WIDGET_GTK)
++
++#endif
++
++
++
++
++
++
++
++
++
++
++
++#if !defined(MOZ_WIDGET_GTK)
++
++#endif
++#ifdef CAN_DRAW_IN_TITLEBAR
++
++
++#ifdef XP_MACOSX
++
++#endif
++#endif
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++# Update primaryToolbarButtons in browser/themes/shared/browser.inc when adding
++# or removing default items with the toolbarbutton-1 class.
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++#include ../../components/customizableui/content/customizeMode.inc.xul
++
++
++
++
++ &fullscreenWarning.beforeDomain.label;
++
++ &fullscreenWarning.afterDomain.label;
++
++
++ &fullscreenWarning.generic.label;
++
++
++#ifdef XP_MACOSX
++ &exitDOMFullscreenMac.button;
++#else
++ &exitDOMFullscreen.button;
++#endif
++
++
++
++
++
++ &pointerlockWarning.beforeDomain.label;
++
++ &pointerlockWarning.afterDomain.label;
++
++
++ &pointerlockWarning.generic.label;
++
++
++
++
++
++
++
++
++#include tab-shape.inc.svg
++
++#ifndef XP_MACOSX
++
++#else
++
++#endif
++
++#ifdef XP_WIN
++
++
++
++#endif
++
++
++
++#
++
++
+diff --git a/browser/base/jar.mn b/browser/base/jar.mn
+--- a/browser/base/jar.mn
++++ b/browser/base/jar.mn
+@@ -68,16 +68,18 @@ browser.jar:
+ content/browser/aboutTabCrashed.css (content/aboutTabCrashed.css)
+ content/browser/aboutTabCrashed.js (content/aboutTabCrashed.js)
+ content/browser/aboutTabCrashed.xhtml (content/aboutTabCrashed.xhtml)
+ * content/browser/aboutTabGroupsMigration.xhtml (content/aboutTabGroupsMigration.xhtml)
+ content/browser/aboutTabGroupsMigration.js (content/aboutTabGroupsMigration.js)
+ * content/browser/browser.css (content/browser.css)
+ content/browser/browser.js (content/browser.js)
+ * content/browser/browser.xul (content/browser.xul)
++* content/browser/browser-kde.xul (content/browser-kde.xul)
++% override chrome://browser/content/browser.xul chrome://browser/content/browser-kde.xul desktop=kde
+ content/browser/browser-addons.js (content/browser-addons.js)
+ content/browser/browser-ctrlTab.js (content/browser-ctrlTab.js)
+ content/browser/browser-customization.js (content/browser-customization.js)
+ content/browser/browser-data-submission-info-bar.js (content/browser-data-submission-info-bar.js)
+ content/browser/browser-devedition.js (content/browser-devedition.js)
+ content/browser/browser-feeds.js (content/browser-feeds.js)
+ content/browser/browser-fullScreenAndPointerLock.js (content/browser-fullScreenAndPointerLock.js)
+ content/browser/browser-fullZoom.js (content/browser-fullZoom.js)
+diff --git a/browser/components/build/nsModule.cpp b/browser/components/build/nsModule.cpp
+--- a/browser/components/build/nsModule.cpp
++++ b/browser/components/build/nsModule.cpp
+@@ -8,17 +8,17 @@
+ #include "nsBrowserCompsCID.h"
+ #include "DirectoryProvider.h"
+
+ #if defined(XP_WIN)
+ #include "nsWindowsShellService.h"
+ #elif defined(XP_MACOSX)
+ #include "nsMacShellService.h"
+ #elif defined(MOZ_WIDGET_GTK)
+-#include "nsGNOMEShellService.h"
++#include "nsUnixShellService.h"
+ #endif
+
+ #if defined(XP_WIN)
+ #include "nsIEHistoryEnumerator.h"
+ #endif
+
+ #include "rdf.h"
+ #include "nsFeedSniffer.h"
+@@ -31,18 +31,16 @@ using namespace mozilla::browser;
+
+ /////////////////////////////////////////////////////////////////////////////
+
+ NS_GENERIC_FACTORY_CONSTRUCTOR(DirectoryProvider)
+ #if defined(XP_WIN)
+ NS_GENERIC_FACTORY_CONSTRUCTOR(nsWindowsShellService)
+ #elif defined(XP_MACOSX)
+ NS_GENERIC_FACTORY_CONSTRUCTOR(nsMacShellService)
+-#elif defined(MOZ_WIDGET_GTK)
+-NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsGNOMEShellService, Init)
+ #endif
+
+ #if defined(XP_WIN)
+ NS_GENERIC_FACTORY_CONSTRUCTOR(nsIEHistoryEnumerator)
+ #endif
+
+ NS_GENERIC_FACTORY_CONSTRUCTOR(nsFeedSniffer)
+
+@@ -60,17 +58,17 @@ NS_DEFINE_NAMED_CID(NS_WINIEHISTORYENUME
+ NS_DEFINE_NAMED_CID(NS_SHELLSERVICE_CID);
+ #endif
+
+ static const mozilla::Module::CIDEntry kBrowserCIDs[] = {
+ { &kNS_BROWSERDIRECTORYPROVIDER_CID, false, nullptr, DirectoryProviderConstructor },
+ #if defined(XP_WIN)
+ { &kNS_SHELLSERVICE_CID, false, nullptr, nsWindowsShellServiceConstructor },
+ #elif defined(MOZ_WIDGET_GTK)
+- { &kNS_SHELLSERVICE_CID, false, nullptr, nsGNOMEShellServiceConstructor },
++ { &kNS_SHELLSERVICE_CID, false, nullptr, nsUnixShellServiceConstructor },
+ #endif
+ { &kNS_FEEDSNIFFER_CID, false, nullptr, nsFeedSnifferConstructor },
+ { &kNS_BROWSER_ABOUT_REDIRECTOR_CID, false, nullptr, AboutRedirector::Create },
+ #if defined(XP_WIN)
+ { &kNS_WINIEHISTORYENUMERATOR_CID, false, nullptr, nsIEHistoryEnumeratorConstructor },
+ #elif defined(XP_MACOSX)
+ { &kNS_SHELLSERVICE_CID, false, nullptr, nsMacShellServiceConstructor },
+ #endif
+diff --git a/browser/components/preferences/in-content/main.js b/browser/components/preferences/in-content/main.js
+--- a/browser/components/preferences/in-content/main.js
++++ b/browser/components/preferences/in-content/main.js
+@@ -23,16 +23,22 @@ var gMainPane = {
+ init: function ()
+ {
+ function setEventListener(aId, aEventType, aCallback)
+ {
+ document.getElementById(aId)
+ .addEventListener(aEventType, aCallback.bind(gMainPane));
+ }
+
++ var env = Components.classes["@mozilla.org/process/environment;1"]
++ .getService(Components.interfaces.nsIEnvironment);
++ var kde_session = 0;
++ if (env.get('KDE_FULL_SESSION') == "true")
++ kde_session = 1;
++
+ #ifdef HAVE_SHELL_SERVICE
+ this.updateSetDefaultBrowser();
+ #ifdef XP_WIN
+ // In Windows 8 we launch the control panel since it's the only
+ // way to get all file type association prefs. So we don't know
+ // when the user will select the default. We refresh here periodically
+ // in case the default changes. On other Windows OS's defaults can also
+ // be set while the prefs are open.
+@@ -703,16 +709,27 @@ var gMainPane = {
+ let alwaysCheckPref = document.getElementById("browser.shell.checkDefaultBrowser");
+ alwaysCheckPref.value = true;
+
+ let shellSvc = getShellService();
+ if (!shellSvc)
+ return;
+ try {
+ shellSvc.setDefaultBrowser(true, false);
++ if (kde_session == 1) {
++ var shellObj = Components.classes["@mozilla.org/file/local;1"]
++ .createInstance(Components.interfaces.nsILocalFile);
++ shellObj.initWithPath("/usr/bin/kwriteconfig");
++ var process = Components.classes["@mozilla.org/process/util;1"]
++ .createInstance(Components.interfaces.nsIProcess);
++ process.init(shellObj);
++ var args = ["--file", "kdeglobals", "--group", "General", "--key",
++ "BrowserApplication", "firefox"];
++ process.run(false, args, args.length);
++ }
+ } catch (ex) {
+ Cu.reportError(ex);
+ return;
+ }
+
+ let selectedIndex = shellSvc.isDefaultBrowser(false, true) ? 1 : 0;
+ document.getElementById("setDefaultPane").selectedIndex = selectedIndex;
+ }
+diff --git a/browser/components/shell/moz.build b/browser/components/shell/moz.build
+--- a/browser/components/shell/moz.build
++++ b/browser/components/shell/moz.build
+@@ -34,16 +34,18 @@ if CONFIG['OS_ARCH'] == 'WINNT':
+ ]
+ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
+ SOURCES += [
+ 'nsMacShellService.cpp',
+ ]
+ elif 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
+ SOURCES += [
+ 'nsGNOMEShellService.cpp',
++ 'nsKDEShellService.cpp',
++ 'nsUnixShellService.cpp',
+ ]
+
+ if SOURCES:
+ FINAL_LIBRARY = 'browsercomps'
+
+ EXTRA_COMPONENTS += [
+ 'nsSetDefaultBrowser.js',
+ 'nsSetDefaultBrowser.manifest',
+diff --git a/browser/components/shell/nsKDEShellService.cpp b/browser/components/shell/nsKDEShellService.cpp
+new file mode 100644
+--- /dev/null
++++ b/browser/components/shell/nsKDEShellService.cpp
+@@ -0,0 +1,203 @@
++/* -*- 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 "mozilla/ArrayUtils.h"
++
++#include "nsCOMPtr.h"
++#include "nsKDEShellService.h"
++#include "nsShellService.h"
++#include "nsKDEUtils.h"
++#include "nsIPrefService.h"
++#include "nsIProcess.h"
++#include "nsIFile.h"
++#include "nsServiceManagerUtils.h"
++#include "nsComponentManagerUtils.h"
++#include "nsIMutableArray.h"
++#include "nsISupportsPrimitives.h"
++#include "nsArrayUtils.h"
++
++using namespace mozilla;
++
++nsresult
++nsKDEShellService::Init()
++{
++ if( !nsKDEUtils::kdeSupport())
++ return NS_ERROR_NOT_AVAILABLE;
++ return NS_OK;
++}
++
++NS_IMPL_ISUPPORTS(nsKDEShellService, nsIGNOMEShellService, nsIShellService)
++
++NS_IMETHODIMP
++nsKDEShellService::IsDefaultBrowser(bool aStartupCheck,
++ bool aForAllTypes,
++ bool* aIsDefaultBrowser)
++{
++ *aIsDefaultBrowser = false;
++ if (aStartupCheck)
++ mCheckedThisSession = true;
++
++ nsCOMPtr command = do_CreateInstance( NS_ARRAY_CONTRACTID );
++ if (!command)
++ return NS_ERROR_FAILURE;
++
++ nsCOMPtr str = do_CreateInstance( NS_SUPPORTS_CSTRING_CONTRACTID );
++ if (!str)
++ return NS_ERROR_FAILURE;
++
++ str->SetData( NS_LITERAL_CSTRING( "ISDEFAULTBROWSER" ));
++ command->AppendElement( str, false );
++
++ if( nsKDEUtils::command( command ))
++ *aIsDefaultBrowser = true;
++ return NS_OK;
++}
++
++NS_IMETHODIMP
++nsKDEShellService::SetDefaultBrowser(bool aClaimAllTypes,
++ bool aForAllUsers)
++{
++ nsCOMPtr command = do_CreateInstance( NS_ARRAY_CONTRACTID );
++ if (!command)
++ return NS_ERROR_FAILURE;
++
++ nsCOMPtr cmdstr = do_CreateInstance( NS_SUPPORTS_CSTRING_CONTRACTID );
++ nsCOMPtr paramstr = do_CreateInstance( NS_SUPPORTS_CSTRING_CONTRACTID );
++ if (!cmdstr || !paramstr)
++ return NS_ERROR_FAILURE;
++
++ cmdstr->SetData( NS_LITERAL_CSTRING( "SETDEFAULTBROWSER" ));
++ command->AppendElement( cmdstr, false );
++
++ paramstr->SetData( aClaimAllTypes ? NS_LITERAL_CSTRING( "ALLTYPES" ) : NS_LITERAL_CSTRING( "NORMAL" ));
++ command->AppendElement( paramstr, false );
++
++ return nsKDEUtils::command( command ) ? NS_OK : NS_ERROR_FAILURE;
++}
++
++NS_IMETHODIMP
++nsKDEShellService::GetCanSetDesktopBackground(bool* aResult)
++{
++ *aResult = true;
++ return NS_OK;
++}
++
++NS_IMETHODIMP
++nsKDEShellService::SetDesktopBackground(nsIDOMElement* aElement,
++ PRInt32 aPosition)
++{
++ return NS_ERROR_NOT_IMPLEMENTED;
++}
++
++NS_IMETHODIMP
++nsKDEShellService::GetDesktopBackgroundColor(PRUint32 *aColor)
++{
++ return NS_ERROR_NOT_IMPLEMENTED;
++}
++
++NS_IMETHODIMP
++nsKDEShellService::SetDesktopBackgroundColor(PRUint32 aColor)
++{
++ return NS_ERROR_NOT_IMPLEMENTED;
++}
++
++NS_IMETHODIMP
++nsKDEShellService::OpenApplication(PRInt32 aApplication)
++{
++ nsCOMPtr command = do_CreateInstance( NS_ARRAY_CONTRACTID );
++ if (!command)
++ return NS_ERROR_FAILURE;
++
++ nsCOMPtr str = do_CreateInstance( NS_SUPPORTS_CSTRING_CONTRACTID );
++ if (!str)
++ return NS_ERROR_FAILURE;
++
++ if( aApplication == APPLICATION_MAIL )
++ str->SetData( NS_LITERAL_CSTRING( "OPENMAIL" ));
++ else if( aApplication == APPLICATION_NEWS )
++ str->SetData( NS_LITERAL_CSTRING( "OPENNEWS" ));
++ else
++ return NS_ERROR_NOT_IMPLEMENTED;
++
++ command->AppendElement( str, false );
++ return nsKDEUtils::command( command ) ? NS_OK : NS_ERROR_FAILURE;
++}
++
++NS_IMETHODIMP
++nsKDEShellService::OpenApplicationWithURI(nsIFile* aApplication, const nsACString& aURI)
++{
++ nsCOMPtr command = do_CreateInstance( NS_ARRAY_CONTRACTID );
++ if (!command)
++ return NS_ERROR_FAILURE;
++
++ nsCOMPtr cmdstr = do_CreateInstance( NS_SUPPORTS_CSTRING_CONTRACTID );
++ nsCOMPtr appstr = do_CreateInstance( NS_SUPPORTS_CSTRING_CONTRACTID );
++ nsCOMPtr uristr = do_CreateInstance( NS_SUPPORTS_CSTRING_CONTRACTID );
++ if (!cmdstr || !appstr || !uristr)
++ return NS_ERROR_FAILURE;
++
++ cmdstr->SetData( NS_LITERAL_CSTRING( "RUN" ));
++ command->AppendElement( cmdstr, false );
++ nsAutoCString app;
++ nsresult rv = aApplication->GetNativePath( app );
++ NS_ENSURE_SUCCESS( rv, rv );
++ appstr->SetData( app );
++ command->AppendElement( appstr, false );
++ uristr->SetData( aURI );
++ command->AppendElement( uristr, false );
++ return nsKDEUtils::command( command ) ? NS_OK : NS_ERROR_FAILURE;
++}
++
++NS_IMETHODIMP
++nsKDEShellService::GetDefaultFeedReader(nsIFile** _retval)
++{
++ *_retval = nullptr;
++
++ nsCOMPtr command = do_CreateInstance( NS_ARRAY_CONTRACTID );
++ if( !command )
++ return NS_ERROR_FAILURE;
++
++ nsCOMPtr str = do_CreateInstance( NS_SUPPORTS_CSTRING_CONTRACTID );
++ if( !str )
++ return NS_ERROR_FAILURE;
++
++ str->SetData( NS_LITERAL_CSTRING( "GETDEFAULTFEEDREADER" ));
++ command->AppendElement( str, false );
++
++ nsCOMPtr output;
++ if( !nsKDEUtils::command( command, getter_AddRefs( output ) ) )
++ return NS_ERROR_FAILURE;
++
++ PRUint32 length;
++ output->GetLength( &length );
++ if( length != 1 )
++ return NS_ERROR_FAILURE;
++
++ nsCOMPtr resstr = do_QueryElementAt( output, 0 );
++ if( !resstr )
++ return NS_ERROR_FAILURE;
++
++ nsAutoCString path;
++ resstr->GetData( path );
++ if (path.IsEmpty())
++ return NS_ERROR_FAILURE;
++
++ nsresult rv;
++ nsCOMPtr defaultReader =
++ do_CreateInstance("@mozilla.org/file/local;1", &rv);
++ NS_ENSURE_SUCCESS(rv, rv);
++
++ rv = defaultReader->InitWithNativePath(path);
++ NS_ENSURE_SUCCESS(rv, rv);
++
++ bool exists;
++ rv = defaultReader->Exists(&exists);
++ NS_ENSURE_SUCCESS(rv, rv);
++ if (!exists)
++ return NS_ERROR_FAILURE;
++
++ NS_ADDREF(*_retval = defaultReader);
++ return NS_OK;
++}
+diff --git a/browser/components/shell/nsKDEShellService.h b/browser/components/shell/nsKDEShellService.h
+new file mode 100644
+--- /dev/null
++++ b/browser/components/shell/nsKDEShellService.h
+@@ -0,0 +1,30 @@
++/* -*- 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 nskdeshellservice_h____
++#define nskdeshellservice_h____
++
++#include "nsIGNOMEShellService.h"
++#include "nsStringAPI.h"
++#include "mozilla/Attributes.h"
++
++class nsKDEShellService final : public nsIGNOMEShellService
++{
++public:
++ nsKDEShellService() : mCheckedThisSession(false) { }
++
++ NS_DECL_ISUPPORTS
++ NS_DECL_NSIGNOMESHELLSERVICE
++ NS_DECL_NSISHELLSERVICE
++
++ nsresult Init();
++
++private:
++ ~nsKDEShellService() {}
++
++ bool mCheckedThisSession;
++};
++
++#endif // nskdeshellservice_h____
+diff --git a/browser/components/shell/nsUnixShellService.cpp b/browser/components/shell/nsUnixShellService.cpp
+new file mode 100644
+--- /dev/null
++++ b/browser/components/shell/nsUnixShellService.cpp
+@@ -0,0 +1,22 @@
++/* -*- 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 "nsUnixShellService.h"
++#include "nsGNOMEShellService.h"
++#include "nsKDEShellService.h"
++#include "nsKDEUtils.h"
++#include "mozilla/ModuleUtils.h"
++
++NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsGNOMEShellService, Init)
++NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsKDEShellService, Init)
++
++NS_METHOD
++nsUnixShellServiceConstructor(nsISupports *aOuter, REFNSIID aIID, void **aResult)
++{
++ if( nsKDEUtils::kdeSupport())
++ return nsKDEShellServiceConstructor( aOuter, aIID, aResult );
++ return nsGNOMEShellServiceConstructor( aOuter, aIID, aResult );
++}
+diff --git a/browser/components/shell/nsUnixShellService.h b/browser/components/shell/nsUnixShellService.h
+new file mode 100644
+--- /dev/null
++++ b/browser/components/shell/nsUnixShellService.h
+@@ -0,0 +1,15 @@
++/* -*- 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 nsunixshellservice_h____
++#define nsunixshellservice_h____
++
++#include "nsIGNOMEShellService.h"
++
++NS_METHOD
++nsUnixShellServiceConstructor(nsISupports *aOuter, REFNSIID aIID, void **aResult);
++
++#endif // nsunixshellservice_h____
+diff --git a/browser/installer/package-manifest.in b/browser/installer/package-manifest.in
+--- a/browser/installer/package-manifest.in
++++ b/browser/installer/package-manifest.in
+@@ -674,16 +674,17 @@
+ @RESPATH@/greprefs.js
+ @RESPATH@/defaults/autoconfig/prefcalls.js
+ @RESPATH@/browser/defaults/permissions
+
+ ; Warning: changing the path to channel-prefs.js can cause bugs (Bug 756325)
+ ; Technically this is an app pref file, but we are keeping it in the original
+ ; gre location for now.
+ @RESPATH@/defaults/pref/channel-prefs.js
++@BINPATH@/defaults/pref/kde.js
+
+ ; Services (gre) prefs
+ @RESPATH@/defaults/pref/services-sync.js
+
+ ; [Layout Engine Resources]
+ ; Style Sheets, Graphics and other Resources used by the layout engine.
+ @RESPATH@/res/EditorOverride.css
+ @RESPATH@/res/contenteditable.css
diff --git a/firefox.spec b/firefox.spec
index 4d44935..2e8497d 100644
--- a/firefox.spec
+++ b/firefox.spec
@@ -32,7 +32,7 @@ Summary: Next generation web browser
Name: firefox
Version: %{major}
Epoch: %{ff_epoch}
-Release: 1
+Release: 2
License: MPLv1+
Group: Networking/WWW
Url: http://www.mozilla.com/firefox/
@@ -45,6 +45,11 @@ Source0: https://archive.mozilla.org/pub/firefox/releases/%{realver}/source/%{na
Source4: %{name}.desktop
Source9: kde.js
Source1000: README.urpmi
+# Patches for kde integration of FF
+# http://www.rosenauer.org/hg/mozilla/summary
+Patch11: firefox-kde.patch
+Patch12: mozilla-kde.patch
+#Patch13: mozilla-kde-background.patch
Patch34: xulrunner_nojit.patch
Patch35: firefox-37-build-with-time-independent-uuids.patch
Patch36: firefox-38.0-enable-NTLMv1.patch
@@ -159,6 +164,12 @@ Files and macros mainly for building Firefox extensions.
%prep
%setup -q
+## KDE INTEGRATION
+# Disable kde integration , need refactoring
+%patch11 -p1 -b .kdepatch
+%patch12 -p1 -b .kdemoz
+#patch13 -p1 -b .kdebackground
+
%ifarch %arm
%if "%{_target_cpu}" != "armv7l"
%patch34 -p1
diff --git a/mozilla-kde.patch b/mozilla-kde.patch
new file mode 100644
index 0000000..833ba72
--- /dev/null
+++ b/mozilla-kde.patch
@@ -0,0 +1,3788 @@
+# HG changeset patch
+# Parent 6ff55468281e12a84adefb46b17acb60d9cea608
+Description: Add KDE integration to Firefox (toolkit parts)
+Author: Wolfgang Rosenauer
+Author: Lubos Lunak
+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
+@@ -31,16 +31,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"
+
+@@ -1180,16 +1181,34 @@ pref_LoadPrefsInDir(nsIFile* aDir, char
+
+ static nsresult pref_LoadPrefsInDirList(const char *listId)
+ {
+ nsresult rv;
+ nsCOMPtr 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 list;
+ dirSvc->Get(listId,
+ NS_GET_IID(nsISimpleEnumerator),
+ getter_AddRefs(list));
+ if (!list)
+ return NS_OK;
+
+ bool hasMore;
+@@ -1205,17 +1224,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 manifest(jarReader, name, true);
+ NS_ENSURE_TRUE(manifest.Buffer(), NS_ERROR_NOT_AVAILABLE);
+@@ -1309,24 +1328,36 @@ static nsresult 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 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
+@@ -31,16 +31,20 @@ UNIFIED_SOURCES += [
+ 'prefread.cpp',
+ ]
+
+ # prefapi.cpp cannot be built in unified mode because it uses plarena.h
+ SOURCES += [
+ 'prefapi.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']
+
+ FINAL_TARGET_PP_FILES += [
+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
+@@ -211,16 +211,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
+--- a/python/mozbuild/mozpack/chrome/manifest.py
++++ b/python/mozbuild/mozpack/chrome/manifest.py
+@@ -33,16 +33,17 @@ class ManifestEntry(object):
+ 'application',
+ 'platformversion',
+ 'os',
+ 'osversion',
+ 'abi',
+ 'xpcnativewrappers',
+ 'tablet',
+ 'process',
++ 'desktop',
+ ]
+
+ def __init__(self, base, *flags):
+ '''
+ Initialize a manifest entry with the given base path and flags.
+ '''
+ self.base = base
+ self.flags = Flags(*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
+@@ -60,17 +60,18 @@ if not CONFIG['MOZ_SUITE']:
+ 'nsDownloadManagerUI.js',
+ 'nsDownloadManagerUI.manifest',
+ ]
+
+ FINAL_LIBRARY = 'xul'
+
+ LOCAL_INCLUDES += [
+ '../protobuf',
+- '/ipc/chromium/src'
++ '/ipc/chromium/src',
++ '/toolkit/xre'
+ ]
+
+ DEFINES['GOOGLE_PROTOBUF_NO_RTTI'] = True
+ DEFINES['GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER'] = True
+
+ CXXFLAGS += CONFIG['TK_CFLAGS']
+
+ if CONFIG['GNU_CXX']:
+diff --git a/toolkit/components/downloads/nsDownloadManager.cpp b/toolkit/components/downloads/nsDownloadManager.cpp
+--- a/toolkit/components/downloads/nsDownloadManager.cpp
++++ b/toolkit/components/downloads/nsDownloadManager.cpp
+@@ -51,16 +51,20 @@
+ #ifdef XP_WIN
+ #include
+ #include "nsWindowsHelpers.h"
+ #ifdef DOWNLOAD_SCANNER
+ #include "nsDownloadScanner.h"
+ #endif
+ #endif
+
++#if defined(XP_UNIX) && !defined(XP_MACOSX)
++#include "nsKDEUtils.h"
++#endif
++
+ #ifdef XP_MACOSX
+ #include
+ #endif
+
+ #ifdef MOZ_WIDGET_ANDROID
+ #include "GeneratedJNIWrappers.h"
+ #endif
+
+@@ -2719,16 +2723,25 @@ nsDownload::SetState(DownloadState aStat
+ nsCOMPtr pref(do_GetService(NS_PREFSERVICE_CONTRACTID));
+
+ // Master pref to control this function.
+ bool showTaskbarAlert = true;
+ if (pref)
+ pref->GetBoolPref(PREF_BDM_SHOWALERTONCOMPLETE, &showTaskbarAlert);
+
+ if (showTaskbarAlert) {
++ if( nsKDEUtils::kdeSupport()) {
++ nsTArray command;
++ command.AppendElement( NS_LITERAL_CSTRING( "DOWNLOADFINISHED" ));
++ nsAutoString displayName;
++ GetDisplayName( displayName );
++ command.AppendElement( nsAutoCString( ToNewUTF8String( displayName )));
++ nsKDEUtils::command( command );
++ } else {
++ // begin non-KDE block
+ int32_t alertInterval = 2000;
+ if (pref)
+ pref->GetIntPref(PREF_BDM_SHOWALERTINTERVAL, &alertInterval);
+
+ int64_t alertIntervalUSec = alertInterval * PR_USEC_PER_MSEC;
+ int64_t goat = PR_Now() - mStartTime;
+ showTaskbarAlert = goat > alertIntervalUSec;
+
+@@ -2759,16 +2772,17 @@ nsDownload::SetState(DownloadState aStat
+ NS_LITERAL_STRING(DOWNLOAD_MANAGER_ALERT_ICON), title,
+ message, !removeWhenDone,
+ mPrivate ? NS_LITERAL_STRING("private") : NS_LITERAL_STRING("non-private"),
+ mDownloadManager, EmptyString(), NS_LITERAL_STRING("auto"),
+ EmptyString(), EmptyString(), nullptr, mPrivate);
+ }
+ }
+ }
++ }
+
+ #if defined(XP_WIN) || defined(XP_MACOSX) || defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GTK)
+ nsCOMPtr fileURL = do_QueryInterface(mTarget);
+ nsCOMPtr file;
+ nsAutoString path;
+
+ if (fileURL &&
+ NS_SUCCEEDED(fileURL->GetFile(getter_AddRefs(file))) &&
+diff --git a/toolkit/content/jar.mn b/toolkit/content/jar.mn
+--- a/toolkit/content/jar.mn
++++ b/toolkit/content/jar.mn
+@@ -67,29 +67,33 @@ toolkit.jar:
+ content/global/viewZoomOverlay.js
+ content/global/bindings/autocomplete.xml (widgets/autocomplete.xml)
+ content/global/bindings/browser.xml (widgets/browser.xml)
+ content/global/bindings/button.xml (widgets/button.xml)
+ content/global/bindings/checkbox.xml (widgets/checkbox.xml)
+ content/global/bindings/colorpicker.xml (widgets/colorpicker.xml)
+ content/global/bindings/datetimepicker.xml (widgets/datetimepicker.xml)
+ * 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,463 @@
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++#elif XP_UNIX
++ >
++
++
++
++
++
++
++
++#else
++ pack="end">
++
++
++
++
++
++
++
++#endif
++
++
++
++
++ null
++ (function(event) {
++ if (!document.documentElement.cancelDialog())
++ event.preventDefault();
++ })
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++ (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 );
++ ]]>
++
++
++
++
++
++ 0 ? xOffset : 0;
++ yOffset = yOffset > 0 ? yOffset : 0;
++ window.moveTo(xOffset, yOffset);
++ ]]>
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++ // 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;
++ ]]>
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++ if (!event.defaultPrevented)
++ this.cancelDialog();
++
++#ifdef XP_MACOSX
++
++#else
++
++ var btn = this.getButton(this.defaultButton);
++ if (btn)
++ btn.setAttribute("default", event.originalTarget == btn || !(event.originalTarget instanceof Components.interfaces.nsIDOMXULButtonElement));
++
++#endif
++
++
++
++
++
++
++
+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,1410 @@
++
++
++
++ %preferencesDTD;
++
++ %globalKeysDTD;
++]>
++
++
++
++#
++# = Preferences Window Framework
++#
++# The syntax for use looks something like:
++#
++#
++#
++#
++#
++#
++#
++#
++#
++#
++#
++
++
++
++
++
++ elements is constructed. Its purpose is to propagate
++ // the values to the associated form elements
++
++ var elements = this.getElementsByTagName("preference");
++ for (let element of elements) {
++ if (!element._constructed) {
++ return;
++ }
++ }
++ for (let element of elements) {
++ element.updateElements();
++ }
++ ]]>
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++ Components.classes["@mozilla.org/preferences-service;1"]
++ .getService(Components.interfaces.nsIPrefService);
++
++
++ Components.classes["@mozilla.org/preferences-service;1"]
++ .getService(Components.interfaces.nsIPrefBranch);
++
++
++ this.service.getDefaultBranch("");
++
++
++ Components.classes["@mozilla.org/preferences-service;1"]
++ .getService(Components.interfaces.nsIPrefBranchInternal);
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++ this.preferences.rootBranchInternal
++ .removeObserver(this.name, this.preferences);
++
++ false
++
++
++ if (this.getAttribute("instantApply") == "false")
++ return false;
++ return this.getAttribute("instantApply") == "true" || this.preferences.instantApply;
++
++
++
++
++
++
++ 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, false);
++
++ return val;
++
++
++
++
++
++
++ null
++
++
++
++
++
++
++
++
++
++
++ return this.preferences.rootBranch.prefIsLocked(this.name);
++
++
++
++
++
++ return this.getAttribute("disabled") == "true";
++
++
++
++
++
++
++
++
++ return parseInt(this.getAttribute("tabindex"));
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++ // defer reset until preference update
++ this.value = undefined;
++
++
++
++ false
++
++
++
++
++
++
++
++
++ return this._useDefault ? this.preferences.defaultBranch : this.preferences.rootBranch;
++
++
++
++ false
++
++
++
++ with id='" + this.id + "' and name='" +
++ this.name + "' has unknown type '" + this.type + "'.";
++ consoleService.logStringMessage(msg);
++ ]]>
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++ this.updateElements();
++
++
++
++
++
++
++
++
++
++#else
++ title="&preferencesDefaultTitleMac.title;">
++#endif
++
++
++
++
++
++
++
++
++
++#ifndef XP_UNIX
++
++
++
++
++
++
++
++#else
++
++
++
++
++
++
++
++#endif
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++ false
++
++ false
++
++
++
++
++
++
++
++
++
++ this.setAttribute("lastSelected", val);
++ document.persist(this.id, "lastSelected");
++ return val;
++
++
++
++
++ if (!this._currentPane)
++ this._currentPane = this.preferencePanes[0];
++
++ return this._currentPane;
++
++
++ null
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++ false
++
++
++
++ 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;
++ }
++ }
++ ]]>
++
++
++
++
++
++
++
++
++
++
++
++
++
++ oldHeight ? 1 : -1;
++ var sizeDelta = Math.abs(oldHeight - aNewPane.contentHeight);
++ this._animateRemainder = sizeDelta % this._animateIncrement;
++
++ this._setUpAnimationTimer(oldHeight);
++ ]]>
++
++
++
++
++
++ 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;
++ ]]>
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++ null
++ null
++ 15
++ 40
++ 5
++ 0.40
++ 0
++ 0
++ 0
++
++
++
++
++
++
++
++
++
++
++
++
++
++ return openDialog(aURL, "", "modal,centerscreen,resizable=no" + (aFeatures != "" ? ("," + aFeatures) : ""), aParams);
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++ if (event.originalTarget.hasAttribute("pane")) {
++ var pane = document.getElementById(event.originalTarget.getAttribute("pane"));
++ this.showPane(pane);
++ }
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++ false
++
++
++
++
++
++ return document.getElementById(aElement.getAttribute("preference"));
++
++
++
++
++
++
++
++
++
++
++
++ let targetObj = {};
++ Components.utils.import("resource://gre/modules/DeferredTask.jsm", targetObj);
++ targetObj.DeferredTask;
++
++
++
++
++
++
++
++
++ new Set();
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++ var targetHeight = parseInt(window.getComputedStyle(this._content, "").height);
++ targetHeight += parseInt(window.getComputedStyle(this._content, "").marginTop);
++ targetHeight += parseInt(window.getComputedStyle(this._content, "").marginBottom);
++ return targetHeight;
++
++
++
++ document.getAnonymousElementByAttribute(this, "class", "content-box");
++
++
++
++
++ // 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);
++
++
++ // 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);
++
++
++ // This "change" event handler tracks changes made to preferences by
++ // the user in this window.
++ this.userChangedValue(event.target);
++
++
++ // This "input" event handler tracks changes made to preferences by
++ // the user in this window.
++ this.userChangedValue(event.target);
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++# -*- 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/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 mGSettings;
+ nsCOMPtr mProxySettings;
+ nsInterfaceHashtable 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 command;
++ command.AppendElement( NS_LITERAL_CSTRING( "GETPROXY" ));
++ command.AppendElement( url );
++ nsTArray 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
+@@ -39,17 +39,19 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'co
+ 'updaterfileutils_osx.mm',
+ ]
+ 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,339 @@
++/* -*- 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
++
++#include
++#include
++#include
++#include
++#include
++#include
++
++//#define DEBUG_KDE
++#ifdef DEBUG_KDE
++#define KMOZILLAHELPER "kmozillahelper"
++#else
++// not need for lib64, it's a binary
++#define KMOZILLAHELPER "/usr/lib/mozilla/kmozillahelper"
++#endif
++
++#define KMOZILLAHELPER_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 command;
++ command.AppendElement( NS_LITERAL_CSTRING( "CHECK" ));
++ command.AppendElement( NS_LITERAL_CSTRING( MAKE_STR( KMOZILLAHELPER_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* 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& command, nsTArray* output )
++ {
++ return self()->internalCommand( command, NULL, false, output );
++ }
++
++bool nsKDEUtils::command( nsIArray* command, nsIArray** output)
++ {
++ nsTArray in;
++ PRUint32 length;
++ command->GetLength( &length );
++ for ( PRUint32 i = 0; i < length; i++ )
++ {
++ nsCOMPtr str = do_QueryElementAt( command, i );
++ if( str )
++ {
++ nsAutoCString s;
++ str->GetData( s );
++ in.AppendElement( s );
++ }
++ }
++
++ nsTArray out;
++ bool ret = self()->internalCommand( in, NULL, false, &out );
++
++ if ( !output ) return ret;
++
++ nsCOMPtr result = do_CreateInstance( NS_ARRAY_CONTRACTID );
++ if ( !result ) return false;
++
++ for ( PRUint32 i = 0; i < out.Length(); i++ )
++ {
++ nsCOMPtr 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& command, GtkWindow* parent, nsTArray* output )
++ {
++ return self()->internalCommand( command, parent, true, output );
++ }
++
++bool nsKDEUtils::internalCommand( const nsTArray& command, GtkWindow* parent, bool blockUi,
++ nsTArray* 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* >( KMOZILLAHELPER ), 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( KMOZILLAHELPER, args );
++#else
++ execv( KMOZILLAHELPER, 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& 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
++
++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 Firefox). 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 Firefox. 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& command, nsTArray* 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& command, GtkWindow* parent, nsTArray* output = NULL );
++
++ private:
++ nsKDEUtils();
++ ~nsKDEUtils();
++ static nsKDEUtils* self();
++ bool startHelper();
++ void closeHelper();
++ void feedCommand( const nsTArray& command );
++ bool internalCommand( const nsTArray& command, GtkWindow* parent, bool isParent,
++ nsTArray* 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',
+@@ -123,16 +125,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
++nsCommonRegistry::GetFromExtension(const nsACString& aFileExt)
++{
++ if( nsKDEUtils::kdeSupport())
++ return nsKDERegistry::GetFromExtension( aFileExt );
++ return nsGNOMERegistry::GetFromExtension( aFileExt );
++}
++
++/* static */ already_AddRefed
++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 GetFromExtension(const nsACString& aFileExt);
++
++ static already_AddRefed 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 command;
++ command.AppendElement( NS_LITERAL_CSTRING( "HANDLEREXISTS" ));
++ command.AppendElement( nsAutoCString( aProtocolScheme ));
++ return nsKDEUtils::command( command );
++}
++
++/* static */ nsresult
++nsKDERegistry::LoadURL(nsIURI *aURL)
++{
++ nsTArray 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 command;
++ command.AppendElement( NS_LITERAL_CSTRING( "GETAPPDESCFORSCHEME" ));
++ command.AppendElement( aScheme );
++ nsTArray output;
++ if( nsKDEUtils::command( command, &output ) && output.Length() == 1 )
++ CopyUTF8toUTF16( output[ 0 ], aDesc );
++}
++
++
++/* static */ already_AddRefed
++nsKDERegistry::GetFromExtension(const nsACString& aFileExt)
++{
++ NS_ASSERTION(aFileExt[0] != '.', "aFileExt shouldn't start with a dot");
++ nsTArray command;
++ command.AppendElement( NS_LITERAL_CSTRING( "GETFROMEXTENSION" ));
++ command.AppendElement( aFileExt );
++ return GetFromHelper( command );
++}
++
++/* static */ already_AddRefed
++nsKDERegistry::GetFromType(const nsACString& aMIMEType)
++{
++ nsTArray command;
++ command.AppendElement( NS_LITERAL_CSTRING( "GETFROMTYPE" ));
++ command.AppendElement( aMIMEType );
++ return GetFromHelper( command );
++}
++
++/* static */ already_AddRefed
++nsKDERegistry::GetFromHelper(const nsTArray& command)
++{
++ nsTArray output;
++ if( nsKDEUtils::command( command, &output ) && output.Length() == 3 )
++ {
++ nsCString mimetype = output[ 0 ];
++ RefPtr 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 GetFromExtension(const nsACString& aFileExt);
++
++ static already_AddRefed GetFromType(const nsACString& aMIMEType);
++ private:
++ static already_AddRefed GetFromHelper(const nsTArray& 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 mimeInfo = nsGNOMERegistry::GetFromType(mSchemeOrType);
++ RefPtr 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 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 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 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
+ #include
+ #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"
+@@ -1146,26 +1146,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)
+ {
+@@ -1252,17 +1252,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 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,
+@@ -1373,17 +1373,17 @@ nsOSHelperAppService::GetFromType(const
+ nsAutoString extensions, mime_types_description;
+ LookUpExtensionsAndDescription(majorType,
+ minorType,
+ extensions,
+ mime_types_description);
+
+ #ifdef MOZ_WIDGET_GTK
+ if (handler.IsEmpty()) {
+- RefPtr gnomeInfo = nsGNOMERegistry::GetFromType(aMIMEType);
++ RefPtr 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
+@@ -90,16 +90,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',
+ ]
+
+ 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
+ #include
+ #include
+
+ #include
++#include
+
+ #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,32 @@ 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()) {
++ int16_t result;
++ mCallback = aCallback;
++ mRunning = true;
++ kdeFileDialog(&result);
++ if (mCallback) {
++ mCallback->Done(result);
++ mCallback = nullptr;
++ } else {
++ mResult = result;
++ }
++ mRunning = false;
++ 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 +623,235 @@ 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);
++ }
++ if( startdir.IsEmpty())
++ startdir = ".";
++
++ 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 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 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 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 file;
++ GetFile(getter_AddRefs(file));
++ if (file) {
++ nsCOMPtr dir;
++ file->GetParent(getter_AddRefs(dir));
++ nsCOMPtr localDir(do_QueryInterface(dir));
++ if (localDir) {
++ localDir.swap(mPrevDisplayDirectory);
++ }
++ }
++ if (mMode == nsIFilePicker::modeSave)
++ {
++ nsCOMPtr 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 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 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 mFilters;
+ nsTArray 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
+@@ -35,16 +35,17 @@
+
+ #include "nsIConsoleService.h"
+ #include "nsIScriptError.h"
+ #include "nsIXULAppInfo.h"
+ #include "nsIXULRuntime.h"
+ #ifdef MOZ_B2G_LOADER
+ #include "mozilla/XPTInterfaceInfoManager.h"
+ #endif
++#include "nsKDEUtils.h"
+
+ #ifdef MOZ_B2G_LOADER
+ #define XPTONLY_MANIFEST &nsComponentManagerImpl::XPTOnlyManifestManifest
+ #define XPTONLY_XPT &nsComponentManagerImpl::XPTOnlyManifestXPT
+ #else
+ #define XPTONLY_MANIFEST nullptr
+ #define XPTONLY_XPT nullptr
+ #endif
+@@ -494,16 +495,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");
+
+@@ -554,44 +556,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;
+ }
+
+@@ -694,25 +701,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) ||
+ CheckStringFlag(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)
+@@ -762,16 +771,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
+@@ -44,16 +44,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
+ #include "CocoaFileUtils.h"
+ #include "prmem.h"
+ #include "plbase64.h"
+
+@@ -1948,42 +1949,52 @@ nsLocalFile::SetPersistentDescriptor(con
+ return InitWithNativePath(aPersistentDescriptor);
+ #endif
+ }
+
+ NS_IMETHODIMP
+ nsLocalFile::Reveal()
+ {
+ #ifdef MOZ_WIDGET_GTK
+- nsCOMPtr 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 giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID);
+ if (isDirectory) {
+- return giovfs->ShowURIForInput(mPath);
++ url = mPath;
+ } else if (NS_SUCCEEDED(giovfs->OrgFreedesktopFileManager1ShowItems(mPath))) {
+ return NS_OK;
+ } else {
+ nsCOMPtr 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;
+ }
++
++ if(nsKDEUtils::kdeSupport()) {
++ nsTArray 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);
+ #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;
+@@ -1991,16 +2002,22 @@ nsLocalFile::Reveal()
+ return NS_ERROR_FAILURE;
+ #endif
+ }
+
+ NS_IMETHODIMP
+ nsLocalFile::Launch()
+ {
+ #ifdef MOZ_WIDGET_GTK
++ if( nsKDEUtils::kdeSupport()) {
++ nsTArray command;
++ command.AppendElement( NS_LITERAL_CSTRING("OPEN") );
++ command.AppendElement( mPath );
++ return nsKDEUtils::command( command ) ? NS_OK : NS_ERROR_FAILURE;
++ }
+ nsCOMPtr 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()));