diff --git a/firefox-25-kde.patch b/firefox-25-kde.patch
index cad45cb..5a4bc1a 100644
--- a/firefox-25-kde.patch
+++ b/firefox-25-kde.patch
@@ -1,3 +1,1774 @@
-
- Authentication required
-
+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,1161 @@
++#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
++
++
++
++#ifdef CAN_DRAW_IN_TITLEBAR
++
++
++#ifdef MENUBAR_CAN_AUTOHIDE
++
++#endif
++
++
++
++
++
++
++
++
++
++
++#endif
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++#ifdef MENUBAR_CAN_AUTOHIDE
++#ifndef CAN_DRAW_IN_TITLEBAR
++#define APPMENU_ON_TABBAR
++#endif
++#endif
++
++
++
++
++#ifdef APPMENU_ON_TABBAR
++
++#endif
++
++
++
++
++
++
++
++
++
++
++
++
++
++#ifdef CAN_DRAW_IN_TITLEBAR
++
++
++#endif
++
++
++
++
++# Update primaryToolbarButtons in browser/themes/shared/browser.inc when adding
++# or removing default items with the toolbarbutton-1 class.
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++#ifdef MOZ_SERVICES_SYNC
++
++#endif
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++#ifndef XP_UNIX
++
++
++#else
++
++
++#endif
++
++
++
++
++
++
++
++
++
++
++#ifdef XP_MACOSX
++
++#endif
++
++
++
++
++
++#ifndef XP_MACOSX
++
++#endif
++
++
++
++
++
++
++
++
++#ifndef XP_UNIX
++
++
++
++
++
++
++
++
++#endif
++#ifdef XP_MACOSX
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++#endif
++
++
++#
++
++
+diff --git a/browser/base/jar.mn b/browser/base/jar.mn
+--- a/browser/base/jar.mn
++++ b/browser/base/jar.mn
+@@ -52,16 +52,18 @@ browser.jar:
+ content/browser/abouthealthreport/abouthealth.css (content/abouthealthreport/abouthealth.css)
+ #endif
+ content/browser/aboutRobots-icon.png (content/aboutRobots-icon.png)
+ content/browser/aboutRobots-widget-left.png (content/aboutRobots-widget-left.png)
+ content/browser/aboutSocialError.xhtml (content/aboutSocialError.xhtml)
+ * 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-tabPreviews.xml (content/browser-tabPreviews.xml)
+ * content/browser/chatWindow.xul (content/chatWindow.xul)
+ content/browser/content.js (content/content.js)
+ content/browser/newtab/newTab.xul (content/newtab/newTab.xul)
+ * content/browser/newtab/newTab.js (content/newtab/newTab.js)
+ content/browser/newtab/newTab.css (content/newtab/newTab.css)
+ * content/browser/pageinfo/pageInfo.xul (content/pageinfo/pageInfo.xul)
+ content/browser/pageinfo/pageInfo.js (content/pageinfo/pageInfo.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, NULL, DirectoryProviderConstructor },
+ #if defined(XP_WIN)
+ { &kNS_SHELLSERVICE_CID, false, NULL, nsWindowsShellServiceConstructor },
+ #elif defined(MOZ_WIDGET_GTK)
+- { &kNS_SHELLSERVICE_CID, false, NULL, nsGNOMEShellServiceConstructor },
++ { &kNS_SHELLSERVICE_CID, false, NULL, nsUnixShellServiceConstructor },
+ #endif
+ { &kNS_FEEDSNIFFER_CID, false, NULL, nsFeedSnifferConstructor },
+ { &kNS_BROWSER_ABOUT_REDIRECTOR_CID, false, NULL, AboutRedirector::Create },
+ #if defined(XP_WIN)
+ { &kNS_WINIEHISTORYENUMERATOR_CID, false, NULL, nsIEHistoryEnumeratorConstructor },
+ #elif defined(XP_MACOSX)
+ { &kNS_SHELLSERVICE_CID, false, NULL, nsMacShellServiceConstructor },
+ #endif
+diff --git a/browser/components/preferences/advanced.js b/browser/components/preferences/advanced.js
+--- a/browser/components/preferences/advanced.js
++++ b/browser/components/preferences/advanced.js
+@@ -23,16 +23,22 @@ var gAdvancedPane = {
+ if (extraArgs && extraArgs["advancedTab"]){
+ advancedPrefs.selectedTab = document.getElementById(extraArgs["advancedTab"]);
+ } else {
+ var preference = document.getElementById("browser.preferences.advanced.selectedTabIndex");
+ if (preference.value !== null)
+ advancedPrefs.selectedIndex = preference.value;
+ }
+
++ 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.
+@@ -860,14 +866,25 @@ var gAdvancedPane = {
+ * Set browser as the operating system default browser.
+ */
+ setDefaultBrowser: function()
+ {
+ let shellSvc = getShellService();
+ if (!shellSvc)
+ return;
+ 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", "MozillaFirefox"];
++ process.run(false, args, args.length);
++ }
+ let selectedIndex =
+ shellSvc.isDefaultBrowser(false, true) ? 1 : 0;
+ document.getElementById("setDefaultPane").selectedIndex = selectedIndex;
+ }
+ #endif
+ };
+diff --git a/browser/components/shell/src/Makefile.in b/browser/components/shell/src/Makefile.in
+--- a/browser/components/shell/src/Makefile.in
++++ b/browser/components/shell/src/Makefile.in
+@@ -16,10 +16,12 @@ USE_STATIC_LIBS = 1
+
+ include $(topsrcdir)/config/rules.mk
+
+ DEFINES += -DMOZ_APP_NAME=\"$(MOZ_APP_NAME)\" \
+ -DMOZ_APP_VERSION=\"$(MOZ_APP_VERSION)\"
+
+ CXXFLAGS += $(TK_CFLAGS)
+
++LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre
++
+ clobber::
+ rm -f $(DIST)/lib/$(LIBRARY_NAME).lib
+diff --git a/browser/components/shell/src/moz.build b/browser/components/shell/src/moz.build
+--- a/browser/components/shell/src/moz.build
++++ b/browser/components/shell/src/moz.build
+@@ -11,17 +11,19 @@ if CONFIG['OS_ARCH'] == 'WINNT':
+ 'nsWindowsShellService.cpp',
+ ]
+ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
+ CPP_SOURCES += [
+ 'nsMacShellService.cpp',
+ ]
+ elif CONFIG['MOZ_WIDGET_GTK']:
+ CPP_SOURCES += [
++ 'nsUnixShellService.cpp',
+ 'nsGNOMEShellService.cpp',
++ 'nsKDEShellService.cpp'
+ ]
+
+ if CPP_SOURCES:
+ LIBRARY_NAME = 'shellservice_s'
+
+ EXTRA_COMPONENTS += [
+ 'nsSetDefaultBrowser.js',
+ 'nsSetDefaultBrowser.manifest',
+diff --git a/browser/components/shell/src/nsKDEShellService.cpp b/browser/components/shell/src/nsKDEShellService.cpp
+new file mode 100644
+--- /dev/null
++++ b/browser/components/shell/src/nsKDEShellService.cpp
+@@ -0,0 +1,234 @@
++/* -*- 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 "nsKDEShellService.h"
++#include "nsShellService.h"
++#include "nsKDEUtils.h"
++#include "nsCOMPtr.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"
++
++nsresult
++nsKDEShellService::Init()
++ {
++ if( !nsKDEUtils::kdeSupport())
++ return NS_ERROR_NOT_AVAILABLE;
++ return NS_OK;
++ }
++
++NS_IMPL_ISUPPORTS1(nsKDEShellService, 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::GetShouldCheckDefaultBrowser(bool* aResult)
++{
++ // If we've already checked, the browser has been started and this is a
++ // new window open, and we don't want to check again.
++ if (mCheckedThisSession) {
++ *aResult = false;
++ return NS_OK;
++ }
++
++ nsCOMPtr prefs;
++ nsCOMPtr pserve(do_GetService(NS_PREFSERVICE_CONTRACTID));
++ if (pserve)
++ pserve->GetBranch("", getter_AddRefs(prefs));
++
++ if (prefs)
++ prefs->GetBoolPref(PREF_CHECKDEFAULTBROWSER, aResult);
++
++ return NS_OK;
++}
++
++NS_IMETHODIMP
++nsKDEShellService::SetShouldCheckDefaultBrowser(bool aShouldCheck)
++{
++ nsCOMPtr prefs;
++ nsCOMPtr pserve(do_GetService(NS_PREFSERVICE_CONTRACTID));
++ if (pserve)
++ pserve->GetBranch("", getter_AddRefs(prefs));
++
++ if (prefs)
++ prefs->SetBoolPref(PREF_CHECKDEFAULTBROWSER, aShouldCheck);
++
++ return NS_OK;
++}
++
++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/src/nsKDEShellService.h b/browser/components/shell/src/nsKDEShellService.h
+new file mode 100644
+--- /dev/null
++++ b/browser/components/shell/src/nsKDEShellService.h
+@@ -0,0 +1,59 @@
++/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
++/* ***** BEGIN LICENSE BLOCK *****
++ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
++ *
++ * The contents of this file are subject to the Mozilla Public License Version
++ * 1.1 (the "License"); you may not use this file except in compliance with
++ * the License. You may obtain a copy of the License at
++ * http://www.mozilla.org/MPL/
++ *
++ * Software distributed under the License is distributed on an "AS IS" basis,
++ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
++ * for the specific language governing rights and limitations under the
++ * License.
++ *
++ * The Original Code is Shell Service.
++ *
++ * The Initial Developer of the Original Code is mozilla.org.
++ * Portions created by the Initial Developer are Copyright (C) 2004
++ * the Initial Developer. All Rights Reserved.
++ *
++ * Contributor(s):
++ *
++ * Alternatively, the contents of this file may be used under the terms of
++ * either the GNU General Public License Version 2 or later (the "GPL"), or
++ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
++ * in which case the provisions of the GPL or the LGPL are applicable instead
++ * of those above. If you wish to allow use of your version of this file only
++ * under the terms of either the GPL or the LGPL, and not to allow others to
++ * use your version of this file under the terms of the MPL, indicate your
++ * decision by deleting the provisions above and replace them with the notice
++ * and other provisions required by the GPL or the LGPL. If you do not delete
++ * the provisions above, a recipient may use your version of this file under
++ * the terms of any one of the MPL, the GPL or the LGPL.
++ *
++ * ***** END LICENSE BLOCK ***** */
++
++#ifndef nskdeshellservice_h____
++#define nskdeshellservice_h____
++
++#include "nsIShellService.h"
++#include "nsStringAPI.h"
++
++class nsKDEShellService : public nsIShellService
++{
++public:
++ nsKDEShellService() : mCheckedThisSession(PR_FALSE) { }
++
++ NS_DECL_ISUPPORTS
++ NS_DECL_NSISHELLSERVICE
++
++ nsresult Init() NS_HIDDEN;
++
++private:
++ ~nsKDEShellService() {}
++
++ PRPackedBool mCheckedThisSession;
++};
++
++#endif // nskdeshellservice_h____
+diff --git a/browser/components/shell/src/nsUnixShellService.cpp b/browser/components/shell/src/nsUnixShellService.cpp
+new file mode 100644
+--- /dev/null
++++ b/browser/components/shell/src/nsUnixShellService.cpp
+@@ -0,0 +1,52 @@
++/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
++/* ***** BEGIN LICENSE BLOCK *****
++ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
++ *
++ * The contents of this file are subject to the Mozilla Public License Version
++ * 1.1 (the "License"); you may not use this file except in compliance with
++ * the License. You may obtain a copy of the License at
++ * http://www.mozilla.org/MPL/
++ *
++ * Software distributed under the License is distributed on an "AS IS" basis,
++ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
++ * for the specific language governing rights and limitations under the
++ * License.
++ *
++ * The Original Code is Shell Service.
++ *
++ * The Initial Developer of the Original Code is mozilla.org.
++ * Portions created by the Initial Developer are Copyright (C) 2004
++ * the Initial Developer. All Rights Reserved.
++ *
++ * Contributor(s):
++ *
++ * Alternatively, the contents of this file may be used under the terms of
++ * either the GNU General Public License Version 2 or later (the "GPL"), or
++ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
++ * in which case the provisions of the GPL or the LGPL are applicable instead
++ * of those above. If you wish to allow use of your version of this file only
++ * under the terms of either the GPL or the LGPL, and not to allow others to
++ * use your version of this file under the terms of the MPL, indicate your
++ * decision by deleting the provisions above and replace them with the notice
++ * and other provisions required by the GPL or the LGPL. If you do not delete
++ * the provisions above, a recipient may use your version of this file under
++ * the terms of any one of the MPL, the GPL or the LGPL.
++ *
++ * ***** END LICENSE BLOCK ***** */
++
++#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/src/nsUnixShellService.h b/browser/components/shell/src/nsUnixShellService.h
+new file mode 100644
+--- /dev/null
++++ b/browser/components/shell/src/nsUnixShellService.h
+@@ -0,0 +1,45 @@
++/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
++/* ***** BEGIN LICENSE BLOCK *****
++ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
++ *
++ * The contents of this file are subject to the Mozilla Public License Version
++ * 1.1 (the "License"); you may not use this file except in compliance with
++ * the License. You may obtain a copy of the License at
++ * http://www.mozilla.org/MPL/
++ *
++ * Software distributed under the License is distributed on an "AS IS" basis,
++ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
++ * for the specific language governing rights and limitations under the
++ * License.
++ *
++ * The Original Code is Shell Service.
++ *
++ * The Initial Developer of the Original Code is mozilla.org.
++ * Portions created by the Initial Developer are Copyright (C) 2004
++ * the Initial Developer. All Rights Reserved.
++ *
++ * Contributor(s):
++ *
++ * Alternatively, the contents of this file may be used under the terms of
++ * either the GNU General Public License Version 2 or later (the "GPL"), or
++ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
++ * in which case the provisions of the GPL or the LGPL are applicable instead
++ * of those above. If you wish to allow use of your version of this file only
++ * under the terms of either the GPL or the LGPL, and not to allow others to
++ * use your version of this file under the terms of the MPL, indicate your
++ * decision by deleting the provisions above and replace them with the notice
++ * and other provisions required by the GPL or the LGPL. If you do not delete
++ * the provisions above, a recipient may use your version of this file under
++ * the terms of any one of the MPL, the GPL or the LGPL.
++ *
++ * ***** END LICENSE BLOCK ***** */
++
++#ifndef nsunixshellservice_h____
++#define nsunixshellservice_h____
++
++#include "nsIShellService.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
+@@ -606,19 +606,21 @@
+ @BINPATH@/defaults/autoconfig/prefcalls.js
+ @BINPATH@/browser/defaults/profile/prefs.js
+
+ #ifndef LIBXUL_SDK
+ ; 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.
+ @BINPATH@/defaults/pref/channel-prefs.js
++@BINPATH@/defaults/pref/kde.js
+ #else
+ ; For Fx-on-xr, channel-prefs lives with the app preferences. (Bug 762588)
+ @BINPATH@/@PREF_DIR@/channel-prefs.js
++@BINPATH@/@PREF_DIR@/kde.js
+ #endif
+
+ ; Services (gre) prefs
+ #ifdef MOZ_SERVICES_NOTIFICATIONS
+ @BINPATH@/defaults/pref/services-notifications.js
+ #endif
+ #ifdef MOZ_SERVICES_SYNC
+ @BINPATH@/defaults/pref/services-sync.js
diff --git a/mozilla-25-kde.patch b/mozilla-25-kde.patch
index cad45cb..e2eb942 100644
--- a/mozilla-25-kde.patch
+++ b/mozilla-25-kde.patch
@@ -1,3 +1,3731 @@
-
- Authentication required
-
+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/src/Makefile.in b/modules/libpref/src/Makefile.in
+--- a/modules/libpref/src/Makefile.in
++++ b/modules/libpref/src/Makefile.in
+@@ -49,14 +49,15 @@ endif
+ # Optimizer bug with GCC 3.2.2 on OS/2
+ ifeq ($(OS_ARCH), OS2)
+ nsPrefService.$(OBJ_SUFFIX): nsPrefService.cpp
+ $(REPORT_BUILD)
+ @$(MAKE_DEPS_AUTO_CXX)
+ $(ELOG) $(CCC) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS:-O2=-O1) $(_VPATH_SRCS)
+ endif
+
++LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre
+
+ greprefs.js: $(grepref_files)
+ $(PYTHON) $(topsrcdir)/config/Preprocessor.py $(PREF_PPFLAGS) $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) $^ > $@
+
+ libs:: greprefs.js
+ $(INSTALL) $^ $(DIST)/bin/
+diff --git a/modules/libpref/src/Preferences.cpp b/modules/libpref/src/Preferences.cpp
+--- a/modules/libpref/src/Preferences.cpp
++++ b/modules/libpref/src/Preferences.cpp
+@@ -24,16 +24,17 @@
+ #include "nsIStringEnumerator.h"
+ #include "nsIZipReader.h"
+ #include "nsPrefBranch.h"
+ #include "nsXPIDLString.h"
+ #include "nsCRT.h"
+ #include "nsCOMArray.h"
+ #include "nsXPCOMCID.h"
+ #include "nsAutoPtr.h"
++#include "nsKDEUtils.h"
+
+ #include "nsQuickSort.h"
+ #include "pldhash.h"
+
+ #include "prefapi.h"
+ #include "prefread.h"
+ #include "prefapi_private_data.h"
+
+@@ -973,16 +974,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 < NS_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;
+@@ -998,17 +1017,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).Equals(NS_LITERAL_CSTRING(".xpi")))
+ ReadExtensionPrefs(path);
+ else
+- pref_LoadPrefsInDir(path, nullptr, 0);
++ pref_LoadPrefsInDir(path, specialFiles, NS_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);
+@@ -1102,28 +1121,40 @@ 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(VMS)
+ , "openvms.js"
+ #elif defined(_AIX)
+ , "aix.js"
+ #endif
+ #elif defined(XP_OS2)
+ "os2pref.js"
+ #elif defined(XP_BEOS)
+ "beos.js"
+ #endif
+ };
+
++ if(nsKDEUtils::kdeSession()) { // TODO what if some setup actually requires the helper?
++ for(int i = 0;
++ i < NS_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.
+ nsRefPtr appJarReader = mozilla::Omnijar::GetReader(mozilla::Omnijar::APP);
+ // GetReader(mozilla::Omnijar::APP) returns null when $app == $gre, in which
+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
+@@ -208,16 +208,17 @@ class Flags(OrderedDict):
+ 'platformversion': VersionFlag,
+ 'contentaccessible': Flag,
+ 'os': StringFlag,
+ 'osversion': VersionFlag,
+ 'abi': StringFlag,
+ 'platform': Flag,
+ 'xpcnativewrappers': Flag,
+ 'tablet': Flag,
++ '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
+@@ -30,16 +30,17 @@ class ManifestEntry(object):
+ allowed_flags = [
+ 'application',
+ 'platformversion',
+ 'os',
+ 'osversion',
+ 'abi',
+ 'xpcnativewrappers',
+ 'tablet',
++ '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/Makefile.in b/toolkit/components/downloads/Makefile.in
+--- a/toolkit/components/downloads/Makefile.in
++++ b/toolkit/components/downloads/Makefile.in
+@@ -11,13 +11,15 @@ VPATH = @srcdir@
+ include $(DEPTH)/config/autoconf.mk
+
+ LIBRARY_NAME = download_s
+ LIBXUL_LIBRARY = 1
+ FAIL_ON_WARNINGS = 1
+
+ include $(topsrcdir)/config/rules.mk
+
++
+ CXXFLAGS += $(TK_CFLAGS) -DGOOGLE_PROTOBUF_NO_RTTI
+
+ LOCAL_INCLUDES += \
+ -I$(srcdir)/../protobuf \
++ -I$(topsrcdir)/toolkit/xre \
+ $(NULL)
+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
+@@ -38,16 +38,20 @@
+
+ #ifdef XP_WIN
+ #include
+ #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 "AndroidBridge.h"
+ #endif
+
+@@ -2609,16 +2613,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;
+
+@@ -2645,19 +2658,20 @@ nsDownload::SetState(DownloadState aStat
+ // retention policy, there's no reason to make the text clickable
+ // because if it is, they'll click open the download manager and
+ // the items they downloaded will have been removed.
+ alerts->ShowAlertNotification(
+ 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());
+- }
++ }
+ }
+ }
++ }
+
+ #if defined(XP_WIN) || defined(XP_MACOSX) || defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GTK2)
+ 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
+@@ -50,29 +50,33 @@ toolkit.jar:
+ content/global/viewZoomOverlay.js (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,451 @@
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++#elif XP_UNIX
++ pack="end">
++
++
++
++
++
++
++
++#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,1339 @@
++
++
++
++ %preferencesDTD;
++
++ %globalKeysDTD;
++]>
++
++
++
++#
++# = Preferences Window Framework
++#
++# The syntax for use looks something like:
++#
++#
++#
++#
++#
++#
++#
++#
++#
++#
++#
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++ 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);
++
++
++
++
++ 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
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++#elif XP_UNIX
++ pack="end">
++
++
++
++
++
++
++
++#else
++ pack="end">
++
++
++
++
++
++
++
++#endif
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++ 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"));
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++ 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
+@@ -14,16 +14,18 @@
+ #include "prenv.h"
+ #include "nsPrintfCString.h"
+ #include "nsNetUtil.h"
+ #include "nsISupportsPrimitives.h"
+ #include "nsIGSettingsService.h"
+ #include "nsInterfaceHashtable.h"
+ #include "mozilla/Attributes.h"
+ #include "nsIURI.h"
++#include "nsVoidArray.h"
++#include "nsKDEUtils.h"
+
+ class nsUnixSystemProxySettings MOZ_FINAL : public nsISystemProxySettings {
+ public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISYSTEMPROXYSETTINGS
+
+ nsUnixSystemProxySettings() {}
+ nsresult Init();
+@@ -35,16 +37,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_ISUPPORTS1(nsUnixSystemProxySettings, nsISystemProxySettings)
+
+ NS_IMETHODIMP
+ nsUnixSystemProxySettings::GetMainThreadOnly(bool *aMainThreadOnly)
+ {
+ // dbus prevents us from being threadsafe, but this routine should not block anyhow
+@@ -496,16 +499,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);
+
+@@ -531,8 +537,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
+@@ -38,18 +38,20 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'qt
+ 'nsNativeAppSupportQt.cpp',
+ 'nsQAppInstance.cpp',
+ ]
+ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'os2':
+ CPP_SOURCES += [
+ 'nsNativeAppSupportOS2.cpp',
+ ]
+ elif CONFIG['MOZ_ENABLE_GTK']:
++ EXPORTS += ['nsKDEUtils.h']
+ CPP_SOURCES += [
+ 'nsNativeAppSupportUnix.cpp',
++ 'nsKDEUtils.cpp'
+ ]
+ else:
+ CPP_SOURCES += [
+ 'nsNativeAppSupportDefault.cpp',
+ ]
+
+ if CONFIG['MOZ_X11']:
+ CPP_SOURCES += [
+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, const GtkWindow* parent, nsTArray* output )
++ {
++ return self()->internalCommand( command, parent, true, output );
++ }
++
++bool nsKDEUtils::internalCommand( const nsTArray& command, const 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 && parent->group )
++ gtk_window_group_add_window( parent->group, 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, const 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, const GtkWindow* parent, bool isParent,
++ nsTArray* output );
++ FILE* commandFile;
++ FILE* replyFile;
++ };
++
++#endif // nsKDEUtils
+diff --git a/uriloader/exthandler/Makefile.in b/uriloader/exthandler/Makefile.in
+--- a/uriloader/exthandler/Makefile.in
++++ b/uriloader/exthandler/Makefile.in
+@@ -77,9 +77,10 @@ endif
+ endif
+
+ include $(topsrcdir)/config/config.mk
+ include $(topsrcdir)/config/rules.mk
+ include $(topsrcdir)/ipc/chromium/chromium-config.mk
+
+ ifneq (,$(filter qt gtk2 gtk3, $(MOZ_WIDGET_TOOLKIT)))
+ CXXFLAGS += $(TK_CFLAGS) $(MOZ_DBUS_GLIB_CFLAGS)
++LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre
+ endif
+diff --git a/uriloader/exthandler/moz.build b/uriloader/exthandler/moz.build
+--- a/uriloader/exthandler/moz.build
++++ b/uriloader/exthandler/moz.build
+@@ -68,16 +68,18 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'coco
+ pass
+ else:
+ CPP_SOURCES += [
+ 'nsOSHelperAppService.cpp',
+ ]
+
+ if CONFIG['MOZ_ENABLE_GTK']:
+ CPP_SOURCES += [
++ 'nsCommonRegistry.cpp',
++ 'nsKDERegistry.cpp',
+ 'nsGNOMERegistry.cpp',
+ 'nsMIMEInfoUnix.cpp',
+ ]
+ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
+ CPP_SOURCES += [
+ 'nsMIMEInfoAndroid.cpp',
+ 'nsAndroidHandlerApp.cpp',
+ 'nsExternalSharingAppService.cpp',
+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,54 @@
++/* -*- 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 "nsVoidArray.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,23 @@
++/* 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 "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);
++};
+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 ];
++ nsRefPtr 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,29 @@
++/* 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 "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);
++
++};
+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
+@@ -16,30 +16,33 @@
+ #include
+ #if (MOZ_ENABLE_CONTENTACTION)
+ #include
+ #include "nsContentHandlerApp.h"
+ #endif
+ #endif
+
+ #include "nsMIMEInfoUnix.h"
+-#include "nsGNOMERegistry.h"
++#include "nsCommonRegistry.h"
+ #include "nsIGIOService.h"
+ #include "nsNetCID.h"
+ #include "nsIIOService.h"
+ #include "nsIGnomeVFSService.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)
+ {
+- nsresult rv = nsGNOMERegistry::LoadURL(aURI);
++ nsresult rv = nsCommonRegistry::LoadURL(aURI);
+
+ #if (MOZ_PLATFORM_MAEMO == 5) && defined (MOZ_ENABLE_GNOMEVFS)
+ if (NS_FAILED(rv)){
+ HildonURIAction *action = hildon_uri_get_default_action(mSchemeOrType.get(), nullptr);
+ if (action) {
+ nsAutoCString spec;
+ aURI->GetAsciiSpec(spec);
+ if (hildon_uri_open(spec.get(), action, nullptr))
+@@ -67,22 +70,22 @@ nsMIMEInfoUnix::GetHasDefaultHandler(boo
+ {
+ // 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;
+- nsRefPtr mimeInfo = nsGNOMERegistry::GetFromType(mSchemeOrType);
++ nsRefPtr 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;
+
+@@ -130,16 +133,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);
+ nsAutoCString uriSpec;
+ if (giovfs) {
+ // nsGIOMimeApp->Launch wants a URI string instead of local file
+ nsresult rv;
+ nsCOMPtr ioservice = do_GetService(NS_IOSERVICE_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+ nsCOMPtr uri;
+@@ -157,17 +177,17 @@ nsMIMEInfoUnix::LaunchDefaultWithFile(ns
+ /* Fallback to GnomeVFS */
+ nsCOMPtr app;
+ if (NS_SUCCEEDED(gnomevfs->GetAppForMimeType(mSchemeOrType, getter_AddRefs(app))) && app)
+ return app->Launch(nativePath);
+ }
+
+ // If we haven't got an app we try to get a valid one by searching for the
+ // extension mapped type
+- nsRefPtr mimeInfo = nsGNOMERegistry::GetFromExtension(nativePath);
++ nsRefPtr mimeInfo = nsCommonRegistry::GetFromExtension(nativePath);
+ if (mimeInfo) {
+ nsAutoCString type;
+ mimeInfo->GetType(type);
+ if (giovfs) {
+ nsCOMPtr app;
+ if (NS_SUCCEEDED(giovfs->GetAppForMimeType(type, getter_AddRefs(app))) && app)
+ return app->Launch(uriSpec);
+ } else if (gnomevfs) {
+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"
+@@ -1157,29 +1157,29 @@ nsresult nsOSHelperAppService::OSProtoco
+ ContentAction::Action::defaultActionForScheme(QString(aProtocolScheme) + ':');
+
+ if (action.isValid())
+ *aHandlerExists = true;
+ #endif
+
+ #ifdef MOZ_WIDGET_GTK
+ // Check the GConf registry for a protocol handler
+- *aHandlerExists = nsGNOMERegistry::HandlerExists(aProtocolScheme);
++ *aHandlerExists = nsCommonRegistry::HandlerExists(aProtocolScheme);
+ #if (MOZ_PLATFORM_MAEMO == 5) && defined (MOZ_ENABLE_GNOMEVFS)
+ *aHandlerExists = nsMIMEInfoUnix::HandlerExists(aProtocolScheme);
+ #endif
+ #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 PRUnichar * platformAppPath, nsIFile ** aFile)
+ {
+@@ -1266,17 +1266,17 @@ nsOSHelperAppService::GetFromExtension(c
+ mime_types_description,
+ true);
+
+ if (NS_FAILED(rv) || majorType.IsEmpty()) {
+
+ #ifdef MOZ_WIDGET_GTK
+ LOG(("Looking in GNOME registry\n"));
+ nsRefPtr 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,
+@@ -1389,17 +1389,17 @@ nsOSHelperAppService::GetFromType(const
+ #ifdef MOZ_WIDGET_GTK
+ nsRefPtr gnomeInfo;
+ if (handler.IsEmpty()) {
+ // No useful data yet. Check the GNOME registry. Unfortunately, newer
+ // GNOME versions no longer have type-to-extension mappings, so we might
+ // get back a MIMEInfo without any extensions set. In that case we'll have
+ // to look in our mime.types files for the extensions.
+ LOG(("Looking in GNOME registry\n"));
+- gnomeInfo = nsGNOMERegistry::GetFromType(aMIMEType);
++ gnomeInfo = nsCommonRegistry::GetFromType(aMIMEType);
+ if (gnomeInfo && gnomeInfo->HasExtensions()) {
+ LOG(("Got MIMEInfo from GNOME registry, and it has extensions set\n"));
+ return gnomeInfo.forget();
+ }
+ }
+ #endif
+
+ // Now look up our extensions
+diff --git a/widget/gtk2/Makefile.in b/widget/gtk2/Makefile.in
+--- a/widget/gtk2/Makefile.in
++++ b/widget/gtk2/Makefile.in
+@@ -68,11 +68,14 @@ DEFINES += -DCAIRO_GFX -DMOZ_APP_NAME='
+
+ INCLUDES += \
+ -I$(srcdir)/../xpwidgets \
+ -I$(srcdir)/../shared \
+ -I$(topsrcdir)/layout/generic \
+ -I$(topsrcdir)/layout/xul/base/src \
+ -I$(topsrcdir)/other-licenses/atk-1.0 \
+ $(NULL)
++
++LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre
++
+ ifdef MOZ_X11
+ INCLUDES += -I$(srcdir)/../shared/x11
+ endif
+diff --git a/widget/gtk2/nsFilePicker.cpp b/widget/gtk2/nsFilePicker.cpp
+--- a/widget/gtk2/nsFilePicker.cpp
++++ b/widget/gtk2/nsFilePicker.cpp
+@@ -1,32 +1,34 @@
+ /* -*- 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/Util.h"
+
+ #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"
+
+ #if (MOZ_PLATFORM_MAEMO == 5)
+ #include
+ #endif
+
+ using namespace mozilla;
+
+ #define MAX_PREVIEW_SIZE 180
+@@ -232,17 +234,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);
+@@ -356,16 +360,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);
+ const gchar *accept_button = (action == GTK_FILE_CHOOSER_ACTION_SAVE)
+@@ -553,8 +573,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/gtk2/nsFilePicker.h b/widget/gtk2/nsFilePicker.h
+--- a/widget/gtk2/nsFilePicker.h
++++ b/widget/gtk2/nsFilePicker.h
+@@ -67,11 +67,17 @@ protected:
+ nsString mDefault;
+ 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 );
+ };
+
+ #endif
+diff --git a/xpcom/components/Makefile.in b/xpcom/components/Makefile.in
+--- a/xpcom/components/Makefile.in
++++ b/xpcom/components/Makefile.in
+@@ -23,9 +23,10 @@ LOCAL_INCLUDES = \
+ -I$(topsrcdir)/chrome/src \
+ -I$(topsrcdir)/modules/libjar \
+ $(NULL)
+
+ include $(topsrcdir)/config/rules.mk
+
+ ifdef MOZ_WIDGET_GTK
+ CXXFLAGS += $(TK_CFLAGS)
++LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre
+ endif
+diff --git a/xpcom/components/ManifestParser.cpp b/xpcom/components/ManifestParser.cpp
+--- a/xpcom/components/ManifestParser.cpp
++++ b/xpcom/components/ManifestParser.cpp
+@@ -30,16 +30,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;
+
+@@ -397,16 +398,17 @@ ParseManifest(NSLocationType type, FileL
+ NS_NAMED_LITERAL_STRING(kPlatform, "platform");
+ NS_NAMED_LITERAL_STRING(kContentAccessible, "contentaccessible");
+ 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");
+ #if defined(MOZ_WIDGET_ANDROID)
+ NS_NAMED_LITERAL_STRING(kTablet, "tablet");
+ #endif
+
+ // Obsolete
+ NS_NAMED_LITERAL_STRING(kXPCNativeWrappers, "xpcnativewrappers");
+
+ nsAutoString appID;
+@@ -444,41 +446,46 @@ ParseManifest(NSLocationType type, FileL
+ CopyUTF8toUTF16(s, abi);
+ abi.Insert(PRUnichar('_'), 0);
+ abi.Insert(osTarget, 0);
+ }
+ }
+ }
+
+ nsAutoString osVersion;
++ nsAutoString desktop;
+ #if defined(XP_WIN)
+ OSVERSIONINFO info = { sizeof(OSVERSIONINFO) };
+ if (GetVersionEx(&info)) {
+ nsTextFormatter::ssprintf(osVersion, NS_LITERAL_STRING("%ld.%ld").get(),
+ info.dwMajorVersion,
+ info.dwMinorVersion);
+ }
++ desktop = NS_LITERAL_STRING("win");
+ #elif defined(MOZ_WIDGET_COCOA)
+ SInt32 majorVersion, minorVersion;
+ if ((Gestalt(gestaltSystemVersionMajor, &majorVersion) == noErr) &&
+ (Gestalt(gestaltSystemVersionMinor, &minorVersion) == noErr)) {
+ nsTextFormatter::ssprintf(osVersion, NS_LITERAL_STRING("%ld.%ld").get(),
+ majorVersion,
+ minorVersion);
+ }
++ desktop = NS_LITERAL_STRING("macosx");
+ #elif defined(MOZ_WIDGET_GTK)
+ nsTextFormatter::ssprintf(osVersion, NS_LITERAL_STRING("%ld.%ld").get(),
+ 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 = mozilla::AndroidBridge::Bridge()->IsTablet();
+ }
++ desktop = NS_LITERAL_STRING("android");
+ #endif
+
+ // Because contracts must be registered after CIDs, we save and process them
+ // at the end.
+ nsTArray contracts;
+
+ char *token;
+ char *newline = buf;
+@@ -560,24 +567,26 @@ ParseManifest(NSLocationType type, FileL
+ TriState stOsVersion = eUnspecified;
+ TriState stOs = eUnspecified;
+ TriState stABI = eUnspecified;
+ #if defined(MOZ_WIDGET_ANDROID)
+ TriState stTablet = eUnspecified;
+ #endif
+ bool platform = false;
+ bool contentAccessible = false;
++ TriState stDesktop = eUnspecified;
+
+ while (NULL != (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) ||
+ CheckVersionFlag(kOsVersion, wtoken, osVersion, stOsVersion) ||
+ CheckVersionFlag(kAppVersion, wtoken, appVersion, stAppVersion) ||
+ CheckVersionFlag(kGeckoVersion, wtoken, geckoVersion, stGeckoVersion))
+ continue;
+
+ #if defined(MOZ_WIDGET_ANDROID)
+ bool tablet = false;
+ if (CheckFlag(kTablet, wtoken, tablet)) {
+@@ -606,16 +615,17 @@ ParseManifest(NSLocationType type, FileL
+ }
+
+ if (!ok ||
+ stApp == eBad ||
+ stAppVersion == eBad ||
+ stGeckoVersion == eBad ||
+ stOs == eBad ||
+ stOsVersion == eBad ||
++ stDesktop == eBad ||
+ #ifdef MOZ_WIDGET_ANDROID
+ stTablet == eBad ||
+ #endif
+ stABI == eBad)
+ continue;
+
+ if (directive->regfunc) {
+ if (GeckoProcessType_Default != XRE_GetProcessType())
+diff --git a/xpcom/io/Makefile.in b/xpcom/io/Makefile.in
+--- a/xpcom/io/Makefile.in
++++ b/xpcom/io/Makefile.in
+@@ -26,17 +26,17 @@ include $(topsrcdir)/config/rules.mk
+ include $(topsrcdir)/ipc/chromium/chromium-config.mk
+
+ ifeq ($(OS_ARCH),Linux)
+ ifneq (,$(findstring lib64,$(libdir)))
+ DEFINES += -DHAVE_USR_LIB64_DIR
+ endif
+ endif
+
+-LOCAL_INCLUDES += -I..
++LOCAL_INCLUDES += -I.. -I$(topsrcdir)/toolkit/xre
+
+ ifeq ($(MOZ_PLATFORM_MAEMO),5)
+ CFLAGS += $(MOZ_DBUS_CFLAGS)
+ CXXFLAGS += $(MOZ_DBUS_CFLAGS)
+ endif
+
+ ifdef MOZ_PLATFORM_MAEMO
+ CFLAGS += $(MOZ_PLATFORM_MAEMO_CFLAGS) $(MOZ_QT_CFLAGS)
+diff --git a/xpcom/io/nsLocalFileUnix.cpp b/xpcom/io/nsLocalFileUnix.cpp
+--- a/xpcom/io/nsLocalFileUnix.cpp
++++ b/xpcom/io/nsLocalFileUnix.cpp
+@@ -50,16 +50,17 @@
+ #include "prproces.h"
+ #include "nsIDirectoryEnumerator.h"
+ #include "nsISimpleEnumerator.h"
+ #include "private/pprio.h"
+
+ #ifdef MOZ_WIDGET_GTK
+ #include "nsIGIOService.h"
+ #include "nsIGnomeVFSService.h"
++#include "nsKDEUtils.h"
+ #endif
+
+ #ifdef MOZ_WIDGET_COCOA
+ #include
+ #include "CocoaFileUtils.h"
+ #include "prmem.h"
+ #include "plbase64.h"
+
+@@ -1753,44 +1754,51 @@ nsLocalFile::SetPersistentDescriptor(con
+ return InitWithNativePath(aPersistentDescriptor);
+ #endif
+ }
+
+ NS_IMETHODIMP
+ nsLocalFile::Reveal()
+ {
+ #ifdef MOZ_WIDGET_GTK
+- nsCOMPtr giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID);
+- nsCOMPtr gnomevfs = do_GetService(NS_GNOMEVFSSERVICE_CONTRACTID);
+- if (!giovfs && !gnomevfs)
+- return NS_ERROR_FAILURE;
+-
++ nsAutoCString url;
+ bool isDirectory;
+ if (NS_FAILED(IsDirectory(&isDirectory)))
+ return NS_ERROR_FAILURE;
+
+ if (isDirectory) {
+- if (giovfs)
+- return giovfs->ShowURIForInput(mPath);
+- else
+- /* Fallback to GnomeVFS */
+- return gnomevfs->ShowURIForInput(mPath);
++ url = mPath;
+ } 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;
+
+- if (giovfs)
+- return giovfs->ShowURIForInput(dirPath);
+- else
+- return gnomevfs->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;
++ }
++
++ nsCOMPtr giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID);
++ nsCOMPtr gnomevfs = do_GetService(NS_GNOMEVFSSERVICE_CONTRACTID);
++ if (!giovfs && !gnomevfs)
++ return NS_ERROR_FAILURE;
++
++ if (giovfs)
++ return giovfs->ShowURIForInput(url);
++ else
++ return gnomevfs->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;
+@@ -1816,16 +1824,23 @@ nsLocalFile::Launch()
+
+ if (nullptr == connection)
+ return NS_ERROR_FAILURE;
+
+ if (hildon_mime_open_file(connection, mPath.get()) != kHILDON_SUCCESS)
+ return NS_ERROR_FAILURE;
+ return NS_OK;
+ #else
++ 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);
+ nsCOMPtr gnomevfs = do_GetService(NS_GNOMEVFSSERVICE_CONTRACTID);
+ if (giovfs) {
+ return giovfs->ShowURIForInput(mPath);
+ } else if (gnomevfs) {
+ /* GnomeVFS fallback */
+ return gnomevfs->ShowURIForInput(mPath);
+ }