summaryrefslogtreecommitdiffstats
path: root/patches/www-client/firefox/mozilla-kde.patch
diff options
context:
space:
mode:
Diffstat (limited to 'patches/www-client/firefox/mozilla-kde.patch')
-rw-r--r--patches/www-client/firefox/mozilla-kde.patch1940
1 files changed, 0 insertions, 1940 deletions
diff --git a/patches/www-client/firefox/mozilla-kde.patch b/patches/www-client/firefox/mozilla-kde.patch
deleted file mode 100644
index 281f29b..0000000
--- a/patches/www-client/firefox/mozilla-kde.patch
+++ /dev/null
@@ -1,1940 +0,0 @@
-# HG changeset patch
-# User msirringhaus@suse.de
-# Date 1559294891 -7200
-# Fri May 31 11:28:11 2019 +0200
-# Node ID c2aa7198fb925e7fde96abf65b6f68b9b755f112
-# Parent 52a515e07938d75f7c33e7b724845ce6dc315c0c
-Description: Add KDE integration to Firefox (toolkit parts)
-Author: Wolfgang Rosenauer <wolfgang@rosenauer.org>
-Author: Lubos Lunak <lunak@suse.com>
-Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=140751
- https://bugzilla.novell.com/show_bug.cgi?id=170055
-
-diff --git a/modules/libpref/Preferences.cpp b/modules/libpref/Preferences.cpp
---- a/modules/libpref/Preferences.cpp
-+++ b/modules/libpref/Preferences.cpp
-@@ -88,16 +88,17 @@
- #include "nsXPCOM.h"
- #include "nsXULAppAPI.h"
- #include "nsZipArchive.h"
- #include "plbase64.h"
- #include "PLDHashTable.h"
- #include "plstr.h"
- #include "prlink.h"
- #include "xpcpublic.h"
-+#include "nsKDEUtils.h"
-
- #ifdef DEBUG
- # include <map>
- #endif
-
- #ifdef MOZ_MEMORY
- # include "mozmemory.h"
- #endif
-@@ -4543,25 +4544,37 @@ nsresult Preferences::InitInitialObjects
- // application pref files for backwards compatibility.
- static const char* specialFiles[] = {
- #if defined(XP_MACOSX)
- "macprefs.js"
- #elif defined(XP_WIN)
- "winpref.js"
- #elif defined(XP_UNIX)
- "unix.js"
-+ , "" // placeholder for KDE (empty is otherwise harmless)
- # if defined(_AIX)
- ,
- "aix.js"
- # endif
- #elif defined(XP_BEOS)
- "beos.js"
- #endif
- };
-
-+ if(nsKDEUtils::kdeSession()) { // TODO what if some setup actually requires the helper?
-+ for(int i = 0;
-+ i < MOZ_ARRAY_LENGTH(specialFiles);
-+ ++i ) {
-+ if( *specialFiles[ i ] == '\0' ) {
-+ specialFiles[ i ] = "kde.js";
-+ break;
-+ }
-+ }
-+ }
-+
- rv = pref_LoadPrefsInDir(defaultPrefDir, specialFiles,
- ArrayLength(specialFiles));
- if (NS_FAILED(rv)) {
- NS_WARNING("Error parsing application default preferences.");
- }
-
- // Load jar:$app/omni.jar!/defaults/preferences/*.js
- // or jar:$gre/omni.jar!/defaults/preferences/*.js.
-@@ -4607,17 +4620,17 @@ nsresult Preferences::InitInitialObjects
- }
-
- nsCOMPtr<nsIFile> path = do_QueryInterface(elem);
- if (!path) {
- continue;
- }
-
- // Do we care if a file provided by this process fails to load?
-- pref_LoadPrefsInDir(path, nullptr, 0);
-+ pref_LoadPrefsInDir(path, specialFiles, ArrayLength(specialFiles));
- }
- }
-
- if (XRE_IsParentProcess()) {
- SetupTelemetryPref();
- }
-
- NS_CreateServicesFromCategory(NS_PREFSERVICE_APPDEFAULTS_TOPIC_ID, nullptr,
-diff --git a/modules/libpref/moz.build b/modules/libpref/moz.build
---- a/modules/libpref/moz.build
-+++ b/modules/libpref/moz.build
-@@ -113,16 +113,20 @@ EXPORTS.mozilla += [
- ]
- EXPORTS.mozilla += sorted(['!' + g for g in gen_h])
-
- UNIFIED_SOURCES += [
- 'Preferences.cpp',
- 'SharedPrefMap.cpp',
- ]
-
-+LOCAL_INCLUDES += [
-+ '/toolkit/xre'
-+]
-+
- gen_all_tuple = tuple(gen_h + gen_cpp + gen_rs)
-
- GENERATED_FILES += [gen_all_tuple]
-
- static_pref_list = GENERATED_FILES[gen_all_tuple]
- static_pref_list.script = 'init/generate_static_pref_list.py:emit_code'
- static_pref_list.inputs = ['init/StaticPrefList.yaml']
-
-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
-@@ -227,16 +227,17 @@ class Flags(OrderedDict):
- 'contentaccessible': Flag,
- 'os': StringFlag,
- 'osversion': VersionFlag,
- 'abi': StringFlag,
- 'platform': Flag,
- 'xpcnativewrappers': Flag,
- 'tablet': Flag,
- 'process': StringFlag,
-+ 'desktop': StringFlag,
- }
- RE = re.compile(r'([!<>=]+)')
-
- def __init__(self, *flags):
- '''
- Initialize a set of flags given in string form.
- flags = Flags('contentaccessible=yes', 'appversion>=3.5')
- '''
-diff --git a/python/mozbuild/mozpack/chrome/manifest.py b/python/mozbuild/mozpack/chrome/manifest.py
---- a/python/mozbuild/mozpack/chrome/manifest.py
-+++ b/python/mozbuild/mozpack/chrome/manifest.py
-@@ -36,16 +36,17 @@ class ManifestEntry(object):
- 'platformversion',
- 'os',
- 'osversion',
- 'abi',
- 'xpcnativewrappers',
- 'tablet',
- 'process',
- 'contentaccessible',
-+ 'desktop',
- ]
-
- def __init__(self, base, *flags):
- '''
- Initialize a manifest entry with the given base path and flags.
- '''
- self.base = base
- self.flags = Flags(*flags)
-diff --git a/toolkit/components/downloads/moz.build b/toolkit/components/downloads/moz.build
---- a/toolkit/components/downloads/moz.build
-+++ b/toolkit/components/downloads/moz.build
-@@ -41,10 +41,14 @@ XPCOM_MANIFESTS += [
-
- if CONFIG['MOZ_PLACES']:
- EXTRA_JS_MODULES += [
- 'DownloadHistory.jsm',
- ]
-
- FINAL_LIBRARY = 'xul'
-
-+LOCAL_INCLUDES += [
-+ '/toolkit/xre'
-+]
-+
- with Files('**'):
- BUG_COMPONENT = ('Toolkit', 'Downloads API')
-diff --git a/toolkit/mozapps/downloads/HelperAppDlg.jsm b/toolkit/mozapps/downloads/HelperAppDlg.jsm
---- a/toolkit/mozapps/downloads/HelperAppDlg.jsm
-+++ b/toolkit/mozapps/downloads/HelperAppDlg.jsm
-@@ -1199,36 +1199,66 @@ nsUnknownContentTypeDialog.prototype = {
- params.handlerApp &&
- params.handlerApp.executable &&
- params.handlerApp.executable.isFile()
- ) {
- // Remember the file they chose to run.
- this.chosenApp = params.handlerApp;
- }
- } else if ("@mozilla.org/applicationchooser;1" in Cc) {
-- var nsIApplicationChooser = Ci.nsIApplicationChooser;
-- var appChooser = Cc["@mozilla.org/applicationchooser;1"].createInstance(
-- nsIApplicationChooser
-- );
-- appChooser.init(
-- this.mDialog,
-- this.dialogElement("strings").getString("chooseAppFilePickerTitle")
-- );
-- var contentTypeDialogObj = this;
-- let appChooserCallback = function appChooserCallback_done(aResult) {
-- if (aResult) {
-- contentTypeDialogObj.chosenApp = aResult.QueryInterface(
-- Ci.nsILocalHandlerApp
-- );
-- }
-- contentTypeDialogObj.finishChooseApp();
-- };
-- appChooser.open(this.mLauncher.MIMEInfo.MIMEType, appChooserCallback);
-- // The finishChooseApp is called from appChooserCallback
-- return;
-+ // handle the KDE case which is implemented in the filepicker
-+ // therefore falling back to Gtk2 like behaviour if KDE is running
-+ // FIXME this should be better handled in the nsIApplicationChooser
-+ // interface
-+ var env = Components.classes["@mozilla.org/process/environment;1"]
-+ .getService(Components.interfaces.nsIEnvironment);
-+ if (env.get('KDE_FULL_SESSION') == "true")
-+ {
-+ var nsIFilePicker = Ci.nsIFilePicker;
-+ var fp = Cc["@mozilla.org/filepicker;1"]
-+ .createInstance(nsIFilePicker);
-+ fp.init(this.mDialog,
-+ this.dialogElement("strings").getString("chooseAppFilePickerTitle"),
-+ nsIFilePicker.modeOpen);
-+
-+ fp.appendFilters(nsIFilePicker.filterApps);
-+
-+ fp.open(aResult => {
-+ if (aResult == nsIFilePicker.returnOK && fp.file) {
-+ // Remember the file they chose to run.
-+ var localHandlerApp =
-+ Cc["@mozilla.org/uriloader/local-handler-app;1"].
-+ createInstance(Ci.nsILocalHandlerApp);
-+ localHandlerApp.executable = fp.file;
-+ this.chosenApp = localHandlerApp;
-+ }
-+ this.finishChooseApp();
-+ });
-+ } else {
-+ var nsIApplicationChooser = Ci.nsIApplicationChooser;
-+ var appChooser = Cc["@mozilla.org/applicationchooser;1"].createInstance(
-+ nsIApplicationChooser
-+ );
-+ appChooser.init(
-+ this.mDialog,
-+ this.dialogElement("strings").getString("chooseAppFilePickerTitle")
-+ );
-+ var contentTypeDialogObj = this;
-+ let appChooserCallback = function appChooserCallback_done(aResult) {
-+ if (aResult) {
-+ contentTypeDialogObj.chosenApp = aResult.QueryInterface(
-+ Ci.nsILocalHandlerApp
-+ );
-+ }
-+ contentTypeDialogObj.finishChooseApp();
-+ };
-+ appChooser.open(this.mLauncher.MIMEInfo.MIMEType, appChooserCallback);
-+ // The finishChooseApp is called from appChooserCallback
-+ return;
-+ }
- } else {
- var nsIFilePicker = Ci.nsIFilePicker;
- var fp = Cc["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
- fp.init(
- this.mDialog,
- this.dialogElement("strings").getString("chooseAppFilePickerTitle"),
- nsIFilePicker.modeOpen
- );
-diff --git a/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp b/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp
---- a/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp
-+++ b/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp
-@@ -14,16 +14,17 @@
- #include "nsPrintfCString.h"
- #include "nsNetCID.h"
- #include "nsNetUtil.h"
- #include "nsISupportsPrimitives.h"
- #include "nsIGSettingsService.h"
- #include "nsInterfaceHashtable.h"
- #include "mozilla/Attributes.h"
- #include "nsIURI.h"
-+#include "nsKDEUtils.h"
-
- using namespace mozilla;
-
- class nsUnixSystemProxySettings final : public nsISystemProxySettings {
- public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSISYSTEMPROXYSETTINGS
-
-@@ -37,16 +38,18 @@ class nsUnixSystemProxySettings final :
- nsCOMPtr<nsIGSettingsCollection> mProxySettings;
- nsInterfaceHashtable<nsCStringHashKey, nsIGSettingsCollection>
- mSchemeProxySettings;
- nsresult GetProxyFromGSettings(const nsACString& aScheme,
- const nsACString& aHost, int32_t aPort,
- nsACString& aResult);
- nsresult SetProxyResultFromGSettings(const char* aKeyBase, const char* aType,
- nsACString& aResult);
-+ nsresult GetProxyFromKDE(const nsACString& aScheme, const nsACString& aHost,
-+ PRInt32 aPort, nsACString& aResult);
- };
-
- NS_IMPL_ISUPPORTS(nsUnixSystemProxySettings, nsISystemProxySettings)
-
- NS_IMETHODIMP
- nsUnixSystemProxySettings::GetMainThreadOnly(bool* aMainThreadOnly) {
- // dbus prevents us from being threadsafe, but this routine should not block
- // anyhow
-@@ -381,21 +384,50 @@ nsresult nsUnixSystemProxySettings::GetP
- return NS_OK;
- }
-
- 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;
- }
-
- return GetProxyFromEnvironment(aScheme, aHost, aPort, aResult);
- }
-
-+nsresult
-+nsUnixSystemProxySettings::GetProxyFromKDE(const nsACString& aScheme,
-+ const nsACString& aHost,
-+ PRInt32 aPort,
-+ nsACString& aResult)
-+{
-+ nsAutoCString url;
-+ url = aScheme;
-+ url += "://";
-+ url += aHost;
-+ if( aPort >= 0 )
-+ {
-+ url += ":";
-+ url += nsPrintfCString("%d", aPort);
-+ }
-+ nsTArray<nsCString> command;
-+ command.AppendElement( NS_LITERAL_CSTRING( "GETPROXY" ));
-+ command.AppendElement( url );
-+ nsTArray<nsCString> result;
-+ if( !nsKDEUtils::command( command, &result ) || result.Length() != 1 )
-+ return NS_ERROR_FAILURE;
-+ aResult = result[0];
-+ return NS_OK;
-+}
-+
-+
- NS_IMPL_COMPONENT_FACTORY(nsUnixSystemProxySettings) {
- auto result = MakeRefPtr<nsUnixSystemProxySettings>();
- result->Init();
- return result.forget().downcast<nsISupports>();
- }
-diff --git a/toolkit/xre/moz.build b/toolkit/xre/moz.build
---- a/toolkit/xre/moz.build
-+++ b/toolkit/xre/moz.build
-@@ -87,17 +87,19 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'co
- '../components/printingui',
- ]
- elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'uikit':
- UNIFIED_SOURCES += [
- 'nsNativeAppSupportDefault.cpp',
- 'UIKitDirProvider.mm',
- ]
- elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-+ EXPORTS += ['nsKDEUtils.h']
- UNIFIED_SOURCES += [
-+ 'nsKDEUtils.cpp',
- 'nsNativeAppSupportUnix.cpp',
- ]
- else:
- UNIFIED_SOURCES += [
- 'nsNativeAppSupportDefault.cpp',
- ]
-
- if CONFIG['MOZ_HAS_REMOTE']:
-diff --git a/toolkit/xre/nsKDEUtils.cpp b/toolkit/xre/nsKDEUtils.cpp
-new file mode 100644
---- /dev/null
-+++ b/toolkit/xre/nsKDEUtils.cpp
-@@ -0,0 +1,344 @@
-+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-+/* This Source Code Form is subject to the terms of the Mozilla Public
-+ * License, v. 2.0. If a copy of the MPL was not distributed with this
-+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-+
-+#include "nsKDEUtils.h"
-+#include "nsIWidget.h"
-+#include "nsISupportsPrimitives.h"
-+#include "nsIMutableArray.h"
-+#include "nsComponentManagerUtils.h"
-+#include "nsArrayUtils.h"
-+
-+#include <gtk/gtk.h>
-+
-+#include <limits.h>
-+#include <stdio.h>
-+#include <sys/wait.h>
-+#include <sys/resource.h>
-+#include <unistd.h>
-+#include <X11/Xlib.h>
-+// copied from X11/X.h as a hack since for an unknown
-+// reason it's not picked up from X11/X.h
-+#ifndef None
-+#define None 0L /* universal null resource or null atom */
-+#endif
-+
-+//#define DEBUG_KDE
-+#ifdef DEBUG_KDE
-+#define 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<nsCString> 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<nsCString>* output;
-+ GMainLoop* loop;
-+ bool success;
-+ };
-+
-+static gboolean kdeReadFunc( GIOChannel*, GIOCondition, gpointer data )
-+ {
-+ nsKDECommandData* p = static_cast< nsKDECommandData* >( data );
-+ char buf[ 8192 ]; // TODO big enough
-+ bool command_done = false;
-+ bool command_failed = false;
-+ while( !command_done && !command_failed && fgets( buf, 8192, p->file ) != NULL )
-+ { // TODO what if the kernel splits a line into two chunks?
-+//#ifdef DEBUG_KDE
-+// fprintf( stderr, "READ: %s %d\n", buf, feof( p->file ));
-+//#endif
-+ if( char* eol = strchr( buf, '\n' ))
-+ *eol = '\0';
-+ command_done = ( strcmp( buf, "\\1" ) == 0 );
-+ command_failed = ( strcmp( buf, "\\0" ) == 0 );
-+ nsAutoCString line( buf );
-+ line.ReplaceSubstring( "\\n", "\n" );
-+ line.ReplaceSubstring( "\\" "\\", "\\" ); // \\ -> \ , i.e. unescape
-+ if( p->output && !( command_done || command_failed ))
-+ p->output->AppendElement( nsCString( buf )); // TODO utf8?
-+ }
-+ bool quit = false;
-+ if( feof( p->file ) || command_failed )
-+ {
-+ quit = true;
-+ p->success = false;
-+ }
-+ if( command_done )
-+ { // reading one reply finished
-+ quit = true;
-+ p->success = true;
-+ }
-+ if( quit )
-+ {
-+ if( p->loop )
-+ g_main_loop_quit( p->loop );
-+ return FALSE;
-+ }
-+ return TRUE;
-+ }
-+
-+bool nsKDEUtils::command( const nsTArray<nsCString>& command, nsTArray<nsCString>* output )
-+ {
-+ return self()->internalCommand( command, NULL, false, output );
-+ }
-+
-+bool nsKDEUtils::command( nsIArray* command, nsIArray** output)
-+ {
-+ nsTArray<nsCString> in;
-+ PRUint32 length;
-+ command->GetLength( &length );
-+ for ( PRUint32 i = 0; i < length; i++ )
-+ {
-+ nsCOMPtr<nsISupportsCString> str = do_QueryElementAt( command, i );
-+ if( str )
-+ {
-+ nsAutoCString s;
-+ str->GetData( s );
-+ in.AppendElement( s );
-+ }
-+ }
-+
-+ nsTArray<nsCString> out;
-+ bool ret = self()->internalCommand( in, NULL, false, &out );
-+
-+ if ( !output ) return ret;
-+
-+ nsCOMPtr<nsIMutableArray> result = do_CreateInstance( NS_ARRAY_CONTRACTID );
-+ if ( !result ) return false;
-+
-+ for ( PRUint32 i = 0; i < out.Length(); i++ )
-+ {
-+ nsCOMPtr<nsISupportsCString> rstr = do_CreateInstance( NS_SUPPORTS_CSTRING_CONTRACTID );
-+ if ( !rstr ) return false;
-+
-+ rstr->SetData( out[i] );
-+ result->AppendElement( rstr );
-+ }
-+
-+ NS_ADDREF( *output = result);
-+ return ret;
-+ }
-+
-+
-+bool nsKDEUtils::commandBlockUi( const nsTArray<nsCString>& command, GtkWindow* parent, nsTArray<nsCString>* output )
-+ {
-+ return self()->internalCommand( command, parent, true, output );
-+ }
-+
-+bool nsKDEUtils::internalCommand( const nsTArray<nsCString>& command, GtkWindow* parent, bool blockUi,
-+ nsTArray<nsCString>* output )
-+ {
-+ if( !startHelper())
-+ return false;
-+ feedCommand( command );
-+ // do not store the data in 'this' but in extra structure, just in case there
-+ // is reentrancy (can there be? the event loop is re-entered)
-+ nsKDECommandData data;
-+ data.file = replyFile;
-+ data.output = output;
-+ data.success = false;
-+ if( blockUi )
-+ {
-+ data.loop = g_main_loop_new( NULL, FALSE );
-+ GtkWidget* window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
-+ if( parent && gtk_window_get_group(parent) )
-+ gtk_window_group_add_window( gtk_window_get_group(parent), GTK_WINDOW( window ));
-+ gtk_widget_realize( window );
-+ gtk_widget_set_sensitive( window, TRUE );
-+ gtk_grab_add( window );
-+ GIOChannel* channel = g_io_channel_unix_new( fileno( data.file ));
-+ g_io_add_watch( channel, static_cast< GIOCondition >( G_IO_IN | G_IO_ERR | G_IO_HUP ), kdeReadFunc, &data );
-+ g_io_channel_unref( channel );
-+ g_main_loop_run( data.loop );
-+ g_main_loop_unref( data.loop );
-+ gtk_grab_remove( window );
-+ gtk_widget_destroy( window );
-+ }
-+ else
-+ {
-+ data.loop = NULL;
-+ while( kdeReadFunc( NULL, static_cast< GIOCondition >( 0 ), &data ))
-+ ;
-+ }
-+ return data.success;
-+ }
-+
-+bool nsKDEUtils::startHelper()
-+ {
-+ if( helperRunning )
-+ return true;
-+ if( helperFailed )
-+ return false;
-+ helperFailed = true;
-+ int fdcommand[ 2 ];
-+ int fdreply[ 2 ];
-+ if( pipe( fdcommand ) < 0 )
-+ return false;
-+ if( pipe( fdreply ) < 0 )
-+ {
-+ close( fdcommand[ 0 ] );
-+ close( fdcommand[ 1 ] );
-+ return false;
-+ }
-+ char* args[ 2 ] = { const_cast< char* >( 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<nsCString>& command )
-+ {
-+ for( int i = 0;
-+ i < command.Length();
-+ ++i )
-+ {
-+ nsCString line = command[ i ];
-+ line.ReplaceSubstring( "\\", "\\" "\\" ); // \ -> \\ , i.e. escape
-+ line.ReplaceSubstring( "\n", "\\n" );
-+#ifdef DEBUG_KDE
-+ fprintf( stderr, "COMM: %s\n", line.get());
-+#endif
-+ fputs( line.get(), commandFile );
-+ fputs( "\n", commandFile );
-+ }
-+ fputs( "\\E\n", commandFile ); // done as \E, so it cannot happen in normal data
-+ fflush( commandFile );
-+ }
-diff --git a/toolkit/xre/nsKDEUtils.h b/toolkit/xre/nsKDEUtils.h
-new file mode 100644
---- /dev/null
-+++ b/toolkit/xre/nsKDEUtils.h
-@@ -0,0 +1,48 @@
-+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-+/* This Source Code Form is subject to the terms of the Mozilla Public
-+ * License, v. 2.0. If a copy of the MPL was not distributed with this
-+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-+
-+#ifndef nsKDEUtils_h__
-+#define nsKDEUtils_h__
-+
-+#include "nsString.h"
-+#include "nsTArray.h"
-+#include <stdio.h>
-+
-+typedef struct _GtkWindow GtkWindow;
-+
-+class nsIArray;
-+
-+class NS_EXPORT nsKDEUtils
-+ {
-+ public:
-+ /* Returns true if running inside a KDE session (regardless of whether there is KDE
-+ support available for 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<nsCString>& command, nsTArray<nsCString>* output = NULL );
-+ static bool command( nsIArray* command, nsIArray** output = NULL );
-+ /* Like command(), but additionally blocks the parent widget like if there was
-+ a modal dialog shown and enters the event loop (i.e. there are still paint updates,
-+ this is for commands that take long). */
-+ static bool commandBlockUi( const nsTArray<nsCString>& command, GtkWindow* parent, nsTArray<nsCString>* output = NULL );
-+
-+ private:
-+ nsKDEUtils();
-+ ~nsKDEUtils();
-+ static nsKDEUtils* self();
-+ bool startHelper();
-+ void closeHelper();
-+ void feedCommand( const nsTArray<nsCString>& command );
-+ bool internalCommand( const nsTArray<nsCString>& command, GtkWindow* parent, bool isParent,
-+ nsTArray<nsCString>* output );
-+ FILE* commandFile;
-+ FILE* replyFile;
-+ };
-+
-+#endif // nsKDEUtils
-diff --git a/uriloader/exthandler/HandlerServiceParent.cpp b/uriloader/exthandler/HandlerServiceParent.cpp
---- a/uriloader/exthandler/HandlerServiceParent.cpp
-+++ b/uriloader/exthandler/HandlerServiceParent.cpp
-@@ -7,17 +7,17 @@
- #include "mozilla/ipc/ProtocolUtils.h"
- #include "mozilla/Logging.h"
- #include "HandlerServiceParent.h"
- #include "nsIHandlerService.h"
- #include "nsIMIMEInfo.h"
- #include "ContentHandlerService.h"
- #include "nsStringEnumerator.h"
- #ifdef MOZ_WIDGET_GTK
--# include "unix/nsGNOMERegistry.h"
-+# include "unix/nsCommonRegistry.h"
- #endif
-
- using mozilla::dom::ContentHandlerService;
- using mozilla::dom::HandlerApp;
- using mozilla::dom::HandlerInfo;
- using mozilla::dom::RemoteHandlerApp;
-
- namespace {
-@@ -288,17 +288,17 @@ mozilla::ipc::IPCResult HandlerServicePa
- mozilla::ipc::IPCResult HandlerServiceParent::RecvExistsForProtocolOS(
- const nsCString& aProtocolScheme, bool* aHandlerExists) {
- if (aProtocolScheme.Length() > MAX_SCHEME_LENGTH) {
- *aHandlerExists = false;
- return IPC_OK();
- }
- #ifdef MOZ_WIDGET_GTK
- // Check the GNOME registry for a protocol handler
-- *aHandlerExists = nsGNOMERegistry::HandlerExists(aProtocolScheme.get());
-+ *aHandlerExists = nsCommonRegistry::HandlerExists(aProtocolScheme.get());
- #else
- *aHandlerExists = false;
- #endif
- return IPC_OK();
- }
-
- /*
- * Check if a handler exists for the provided protocol. Check the datastore
-@@ -317,17 +317,17 @@ mozilla::ipc::IPCResult HandlerServicePa
- nsCOMPtr<nsIExternalProtocolService> protoSvc =
- do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID, &rv);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- *aHandlerExists = false;
- return IPC_OK();
- }
- rv = protoSvc->ExternalProtocolHandlerExists(aProtocolScheme.get(),
- aHandlerExists);
--
-+##
- if (NS_WARN_IF(NS_FAILED(rv))) {
- *aHandlerExists = false;
- }
- #else
- MOZ_RELEASE_ASSERT(false, "No implementation on this platform.");
- *aHandlerExists = false;
- #endif
- return IPC_OK();
-diff --git a/uriloader/exthandler/moz.build b/uriloader/exthandler/moz.build
---- a/uriloader/exthandler/moz.build
-+++ b/uriloader/exthandler/moz.build
-@@ -85,17 +85,19 @@ else:
- SOURCES += [
- osdir + '/nsOSHelperAppService.cpp',
- ]
- if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
- CXXFLAGS += ['-Wno-error=shadow']
-
- if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
- UNIFIED_SOURCES += [
-+ 'unix/nsCommonRegistry.cpp',
- 'unix/nsGNOMERegistry.cpp',
-+ 'unix/nsKDERegistry.cpp',
- 'unix/nsMIMEInfoUnix.cpp',
- ]
- elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
- UNIFIED_SOURCES += [
- 'android/nsAndroidHandlerApp.cpp',
- 'android/nsExternalURLHandlerService.cpp',
- 'android/nsMIMEInfoAndroid.cpp',
- ]
-@@ -135,16 +137,17 @@ include('/ipc/chromium/chromium-config.m
- FINAL_LIBRARY = 'xul'
-
- LOCAL_INCLUDES += [
- '/docshell/base',
- '/dom/base',
- '/dom/ipc',
- '/netwerk/base',
- '/netwerk/protocol/http',
-+ '/toolkit/xre',
- ]
-
- if CONFIG['MOZ_ENABLE_DBUS']:
- CXXFLAGS += CONFIG['TK_CFLAGS']
- CXXFLAGS += CONFIG['MOZ_DBUS_CFLAGS']
-
- if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
- CXXFLAGS += CONFIG['TK_CFLAGS']
-diff --git a/uriloader/exthandler/unix/nsCommonRegistry.cpp b/uriloader/exthandler/unix/nsCommonRegistry.cpp
-new file mode 100644
---- /dev/null
-+++ b/uriloader/exthandler/unix/nsCommonRegistry.cpp
-@@ -0,0 +1,53 @@
-+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-+/* This Source Code Form is subject to the terms of the Mozilla Public
-+ * License, v. 2.0. If a copy of the MPL was not distributed with this
-+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-+
-+#include "nsCommonRegistry.h"
-+
-+#include "nsGNOMERegistry.h"
-+#include "nsKDERegistry.h"
-+#include "nsString.h"
-+#include "nsKDEUtils.h"
-+
-+/* static */ bool
-+nsCommonRegistry::HandlerExists(const char *aProtocolScheme)
-+{
-+ if( nsKDEUtils::kdeSupport())
-+ return nsKDERegistry::HandlerExists( aProtocolScheme );
-+ return nsGNOMERegistry::HandlerExists( aProtocolScheme );
-+}
-+
-+/* static */ nsresult
-+nsCommonRegistry::LoadURL(nsIURI *aURL)
-+{
-+ if( nsKDEUtils::kdeSupport())
-+ return nsKDERegistry::LoadURL( aURL );
-+ return nsGNOMERegistry::LoadURL( aURL );
-+}
-+
-+/* static */ void
-+nsCommonRegistry::GetAppDescForScheme(const nsACString& aScheme,
-+ nsAString& aDesc)
-+{
-+ if( nsKDEUtils::kdeSupport())
-+ return nsKDERegistry::GetAppDescForScheme( aScheme, aDesc );
-+ return nsGNOMERegistry::GetAppDescForScheme( aScheme, aDesc );
-+}
-+
-+
-+/* static */ already_AddRefed<nsMIMEInfoBase>
-+nsCommonRegistry::GetFromExtension(const nsACString& aFileExt)
-+{
-+ if( nsKDEUtils::kdeSupport())
-+ return nsKDERegistry::GetFromExtension( aFileExt );
-+ return nsGNOMERegistry::GetFromExtension( aFileExt );
-+}
-+
-+/* static */ already_AddRefed<nsMIMEInfoBase>
-+nsCommonRegistry::GetFromType(const nsACString& aMIMEType)
-+{
-+ if( nsKDEUtils::kdeSupport())
-+ return nsKDERegistry::GetFromType( aMIMEType );
-+ return nsGNOMERegistry::GetFromType( aMIMEType );
-+}
-diff --git a/uriloader/exthandler/unix/nsCommonRegistry.h b/uriloader/exthandler/unix/nsCommonRegistry.h
-new file mode 100644
---- /dev/null
-+++ b/uriloader/exthandler/unix/nsCommonRegistry.h
-@@ -0,0 +1,28 @@
-+/* This Source Code Form is subject to the terms of the Mozilla Public
-+ * License, v. 2.0. If a copy of the MPL was not distributed with this
-+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-+
-+#ifndef nsCommonRegistry_h__
-+#define nsCommonRegistry_h__
-+
-+#include "nsIURI.h"
-+#include "nsCOMPtr.h"
-+
-+class nsMIMEInfoBase;
-+
-+class nsCommonRegistry
-+{
-+ public:
-+ static bool HandlerExists(const char *aProtocolScheme);
-+
-+ static nsresult LoadURL(nsIURI *aURL);
-+
-+ static void GetAppDescForScheme(const nsACString& aScheme,
-+ nsAString& aDesc);
-+
-+ static already_AddRefed<nsMIMEInfoBase> GetFromExtension(const nsACString& aFileExt);
-+
-+ static already_AddRefed<nsMIMEInfoBase> GetFromType(const nsACString& aMIMEType);
-+};
-+
-+#endif
-diff --git a/uriloader/exthandler/unix/nsKDERegistry.cpp b/uriloader/exthandler/unix/nsKDERegistry.cpp
-new file mode 100644
---- /dev/null
-+++ b/uriloader/exthandler/unix/nsKDERegistry.cpp
-@@ -0,0 +1,87 @@
-+/* -*- 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 "nsMIMEInfoUnix.h"
-+#include "nsAutoPtr.h"
-+#include "nsKDEUtils.h"
-+
-+/* static */ bool
-+nsKDERegistry::HandlerExists(const char *aProtocolScheme)
-+{
-+ nsTArray<nsCString> command;
-+ command.AppendElement( NS_LITERAL_CSTRING( "HANDLEREXISTS" ));
-+ command.AppendElement( nsAutoCString( aProtocolScheme ));
-+ return nsKDEUtils::command( command );
-+}
-+
-+/* static */ nsresult
-+nsKDERegistry::LoadURL(nsIURI *aURL)
-+{
-+ nsTArray<nsCString> command;
-+ command.AppendElement( NS_LITERAL_CSTRING( "OPEN" ));
-+ nsCString url;
-+ aURL->GetSpec( url );
-+ command.AppendElement( url );
-+ bool rv = nsKDEUtils::command( command );
-+ if (!rv)
-+ return NS_ERROR_FAILURE;
-+
-+ return NS_OK;
-+}
-+
-+/* static */ void
-+nsKDERegistry::GetAppDescForScheme(const nsACString& aScheme,
-+ nsAString& aDesc)
-+{
-+ nsTArray<nsCString> command;
-+ command.AppendElement( NS_LITERAL_CSTRING( "GETAPPDESCFORSCHEME" ));
-+ command.AppendElement( aScheme );
-+ nsTArray<nsCString> output;
-+ if( nsKDEUtils::command( command, &output ) && output.Length() == 1 )
-+ CopyUTF8toUTF16( output[ 0 ], aDesc );
-+}
-+
-+
-+/* static */ already_AddRefed<nsMIMEInfoBase>
-+nsKDERegistry::GetFromExtension(const nsACString& aFileExt)
-+{
-+ NS_ASSERTION(aFileExt[0] != '.', "aFileExt shouldn't start with a dot");
-+ nsTArray<nsCString> command;
-+ command.AppendElement( NS_LITERAL_CSTRING( "G