diff -r ba0c97b018a6 -r 2a24a948b5cf mozilla-kde.patch --- a/mozilla-kde.patch Mon Jun 05 21:17:55 2023 +0200 +++ b/mozilla-kde.patch Sat Jul 29 14:34:45 2023 +0200 @@ -3,22 +3,18 @@ # Date 1559294891 -7200 # Fri May 31 11:28:11 2019 +0200 # Node ID c2aa7198fb925e7fde96abf65b6f68b9b755f112 -# Parent 4f8492f0f4bfa17f5b4523a1cdda15a45e3d74d3 +# Parent 0086fcc0d5c86a31cbac0a261ed7b526dd2df2e8 Description: Add KDE integration to Firefox (toolkit parts) Author: Wolfgang Rosenauer Author: Lubos Lunak Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=140751 https://bugzilla.novell.com/show_bug.cgi?id=170055 -diff --git a/modules/libpref/Preferences.cpp b/modules/libpref/Preferences.cpp ---- a/modules/libpref/Preferences.cpp -+++ b/modules/libpref/Preferences.cpp -@@ -91,16 +91,17 @@ - #include "plstr.h" - #include "prdtoa.h" - #include "prlink.h" - #include "xpcpublic.h" - #include "js/RootingAPI.h" +Index: firefox-115.0/modules/libpref/Preferences.cpp +=================================================================== +--- firefox-115.0.orig/modules/libpref/Preferences.cpp ++++ firefox-115.0/modules/libpref/Preferences.cpp +@@ -95,6 +95,7 @@ #ifdef MOZ_BACKGROUNDTASKS # include "mozilla/BackgroundTasks.h" #endif @@ -26,26 +22,15 @@ #ifdef DEBUG # include - #endif - - #ifdef MOZ_MEMORY - # include "mozmemory.h" - #endif -@@ -4907,16 +4908,27 @@ nsresult Preferences::InitInitialObjects - "unix.js" - # if defined(_AIX) - , - "aix.js" - # endif +@@ -4911,6 +4912,16 @@ nsresult Preferences::InitInitialObjects #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"; ++ 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; + } + } @@ -54,17 +39,7 @@ 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. -@@ -4981,17 +4993,17 @@ nsresult Preferences::InitInitialObjects - } - - nsCOMPtr path = do_QueryInterface(elem); - if (!path) { - continue; +@@ -4985,7 +4996,7 @@ nsresult Preferences::InitInitialObjects } // Do we care if a file provided by this process fails to load? @@ -73,20 +48,11 @@ } } - #if defined(MOZ_WIDGET_GTK) - // To ensure the system-wide preferences are not overwritten by - // firefox/browser/defauts/preferences/*.js we need to load - // the /etc/firefox/defaults/pref/*.js settings as last. - // Under Flatpak, the NS_OS_SYSTEM_CONFIG_DIR points to /app/etc/firefox -diff --git a/modules/libpref/moz.build b/modules/libpref/moz.build ---- a/modules/libpref/moz.build -+++ b/modules/libpref/moz.build -@@ -122,16 +122,20 @@ EXPORTS.mozilla += [ - ] - EXPORTS.mozilla += sorted(["!" + g for g in gen_h]) - - UNIFIED_SOURCES += [ - "Preferences.cpp", +Index: firefox-115.0/modules/libpref/moz.build +=================================================================== +--- firefox-115.0.orig/modules/libpref/moz.build ++++ firefox-115.0/modules/libpref/moz.build +@@ -126,6 +126,10 @@ UNIFIED_SOURCES += [ "SharedPrefMap.cpp", ] @@ -97,20 +63,11 @@ gen_all_tuple = tuple(gen_h + gen_cpp + gen_rs) GeneratedFile( - *gen_all_tuple, - script="init/generate_static_pref_list.py", - entry_point="emit_code", - 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 -@@ -229,16 +229,17 @@ class Flags(OrderedDict): - "os": StringFlag, - "osversion": VersionFlag, - "abi": StringFlag, - "platform": Flag, - "xpcnativewrappers": Flag, +Index: firefox-115.0/python/mozbuild/mozpack/chrome/flags.py +=================================================================== +--- firefox-115.0.orig/python/mozbuild/mozpack/chrome/flags.py ++++ firefox-115.0/python/mozbuild/mozpack/chrome/flags.py +@@ -234,6 +234,7 @@ class Flags(OrderedDict): "tablet": Flag, "process": StringFlag, "backgroundtask": StringFlag, @@ -118,20 +75,11 @@ } 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 -@@ -38,16 +38,17 @@ class ManifestEntry(object): - "os", - "osversion", - "abi", - "xpcnativewrappers", - "tablet", +Index: firefox-115.0/python/mozbuild/mozpack/chrome/manifest.py +=================================================================== +--- firefox-115.0.orig/python/mozbuild/mozpack/chrome/manifest.py ++++ firefox-115.0/python/mozbuild/mozpack/chrome/manifest.py +@@ -43,6 +43,7 @@ class ManifestEntry(object): "process", "contentaccessible", "backgroundtask", @@ -139,20 +87,11 @@ ] 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 -@@ -46,10 +46,14 @@ XPCOM_MANIFESTS += [ - - if CONFIG["MOZ_PLACES"]: - EXTRA_JS_MODULES += [ - "DownloadHistory.sys.mjs", - ] +Index: firefox-115.0/toolkit/components/downloads/moz.build +=================================================================== +--- firefox-115.0.orig/toolkit/components/downloads/moz.build ++++ firefox-115.0/toolkit/components/downloads/moz.build +@@ -51,5 +51,9 @@ if CONFIG["MOZ_PLACES"]: FINAL_LIBRARY = "xul" @@ -162,15 +101,11 @@ + 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 -@@ -1250,36 +1250,66 @@ nsUnknownContentTypeDialog.prototype = { - params.handlerApp && - params.handlerApp.executable && - params.handlerApp.executable.isFile() - ) { - // Remember the file they chose to run. +Index: firefox-115.0/toolkit/mozapps/downloads/HelperAppDlg.sys.mjs +=================================================================== +--- firefox-115.0.orig/toolkit/mozapps/downloads/HelperAppDlg.sys.mjs ++++ firefox-115.0/toolkit/mozapps/downloads/HelperAppDlg.sys.mjs +@@ -1246,26 +1246,56 @@ nsUnknownContentTypeDialog.prototype = { this.chosenApp = params.handlerApp; } } else if ("@mozilla.org/applicationchooser;1" in Cc) { @@ -247,20 +182,11 @@ } 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 -@@ -11,16 +11,18 @@ - #include "prenv.h" - #include "nsInterfaceHashtable.h" - #include "nsHashtablesFwd.h" - #include "nsHashKeys.h" - #include "nsNetUtil.h" +Index: firefox-115.0/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp +=================================================================== +--- firefox-115.0.orig/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp ++++ firefox-115.0/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp +@@ -16,6 +16,8 @@ #include "nsISupportsPrimitives.h" #include "nsIGSettingsService.h" #include "nsReadableUtils.h" @@ -269,17 +195,7 @@ using namespace mozilla; - class nsUnixSystemProxySettings final : public nsISystemProxySettings { - public: - NS_DECL_ISUPPORTS - NS_DECL_NSISYSTEMPROXYSETTINGS - -@@ -34,16 +36,18 @@ class nsUnixSystemProxySettings final : - nsCOMPtr mProxySettings; - nsInterfaceHashtable - mSchemeProxySettings; - nsresult GetProxyFromGSettings(const nsACString& aScheme, - const nsACString& aHost, int32_t aPort, +@@ -39,6 +41,8 @@ class nsUnixSystemProxySettings final : nsACString& aResult); nsresult SetProxyResultFromGSettings(const char* aKeyBase, const char* aType, nsACString& aResult); @@ -288,17 +204,7 @@ }; NS_IMPL_ISUPPORTS(nsUnixSystemProxySettings, nsISystemProxySettings) - - NS_IMETHODIMP - nsUnixSystemProxySettings::GetMainThreadOnly(bool* aMainThreadOnly) { - // dbus prevents us from being threadsafe, but this routine should not block - // anyhow -@@ -392,21 +396,50 @@ nsresult nsUnixSystemProxySettings::GetP - return NS_OK; - } - - nsresult nsUnixSystemProxySettings::GetProxyForURI(const nsACString& aSpec, - const nsACString& aScheme, +@@ -396,6 +400,9 @@ nsresult nsUnixSystemProxySettings::GetP const nsACString& aHost, const int32_t aPort, nsACString& aResult) { @@ -308,51 +214,40 @@ if (mProxySettings) { nsresult rv = GetProxyFromGSettings(aScheme, aHost, aPort, aResult); if (NS_SUCCEEDED(rv)) return rv; - } - +@@ -404,6 +411,28 @@ nsresult nsUnixSystemProxySettings::GetP return GetProxyFromEnvironment(aScheme, aHost, aPort, aResult); } -+nsresult -+nsUnixSystemProxySettings::GetProxyFromKDE(const nsACString& aScheme, -+ const nsACString& aHost, -+ PRInt32 aPort, -+ nsACString& aResult) -+{ ++nsresult nsUnixSystemProxySettings::GetProxyFromKDE(const nsACString& aScheme, ++ const nsACString& aHost, ++ PRInt32 aPort, ++ nsACString& aResult) { + nsAutoCString url; + url = aScheme; + url += "://"; + url += aHost; -+ if( aPort >= 0 ) -+ { ++ if (aPort >= 0) { + url += ":"; + url += nsPrintfCString("%d", aPort); + } + nsTArray command; -+ command.AppendElement( "GETPROXY"_ns ); -+ command.AppendElement( url ); ++ command.AppendElement("GETPROXY"_ns); ++ command.AppendElement(url); + nsTArray result; -+ if( !nsKDEUtils::command( command, &result ) || result.Length() != 1 ) ++ 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(); result->Init(); - return result.forget().downcast(); - } -diff --git a/toolkit/xre/moz.build b/toolkit/xre/moz.build ---- a/toolkit/xre/moz.build -+++ b/toolkit/xre/moz.build -@@ -91,17 +91,19 @@ elif CONFIG["MOZ_WIDGET_TOOLKIT"] == "co - "../components/printingui", - ] - elif CONFIG["MOZ_WIDGET_TOOLKIT"] == "uikit": - UNIFIED_SOURCES += [ - "nsNativeAppSupportDefault.cpp", +Index: firefox-115.0/toolkit/xre/moz.build +=================================================================== +--- firefox-115.0.orig/toolkit/xre/moz.build ++++ firefox-115.0/toolkit/xre/moz.build +@@ -96,7 +96,9 @@ elif CONFIG["MOZ_WIDGET_TOOLKIT"] == "ui "UIKitDirProvider.mm", ] elif CONFIG["MOZ_WIDGET_TOOLKIT"] == "gtk": @@ -362,16 +257,11 @@ "nsNativeAppSupportUnix.cpp", ] CXXFLAGS += CONFIG["MOZ_X11_SM_CFLAGS"] - else: - UNIFIED_SOURCES += [ - "nsNativeAppSupportDefault.cpp", - ] - -diff --git a/toolkit/xre/nsKDEUtils.cpp b/toolkit/xre/nsKDEUtils.cpp -new file mode 100644 +Index: firefox-115.0/toolkit/xre/nsKDEUtils.cpp +=================================================================== --- /dev/null -+++ b/toolkit/xre/nsKDEUtils.cpp -@@ -0,0 +1,321 @@ ++++ firefox-115.0/toolkit/xre/nsKDEUtils.cpp +@@ -0,0 +1,286 @@ +/* -*- 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 @@ -395,309 +285,274 @@ +// 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 */ ++# define None 0L /* universal null resource or null atom */ +#endif + -+//#define DEBUG_KDE ++// #define DEBUG_KDE +#ifdef DEBUG_KDE -+#define KMOZILLAHELPER "kmozillahelper" ++# define KMOZILLAHELPER "kmozillahelper" +#else +// not need for lib64, it's a binary -+#define KMOZILLAHELPER "/usr/lib/mozilla/kmozillahelper" ++# define KMOZILLAHELPER "/usr/lib/mozilla/kmozillahelper" +#endif + +#define KMOZILLAHELPER_VERSION 6 -+#define MAKE_STR2( n ) #n -+#define MAKE_STR( n ) MAKE_STR2( n ) ++#define MAKE_STR2(n) #n ++#define MAKE_STR(n) MAKE_STR2(n) + -+static bool getKdeSession() -+{ -+ if (PR_GetEnv("KDE_FULL_SESSION")) -+ { -+ return true; -+ } -+ return false; ++static bool getKdeSession() { ++ if (PR_GetEnv("KDE_FULL_SESSION")) { ++ return true; ++ } ++ return false; +} + -+static bool getKdeSupport() -+ { -+ nsTArray command; -+ command.AppendElement( "CHECK"_ns ); -+ command.AppendElement( "KMOZILLAHELPER_VERSION"_ns ); -+ bool kde = nsKDEUtils::command( command ); ++static bool getKdeSupport() { ++ nsTArray command; ++ command.AppendElement("CHECK"_ns); ++ command.AppendElement("KMOZILLAHELPER_VERSION"_ns); ++ bool kde = nsKDEUtils::command(command); +#ifdef DEBUG_KDE -+ fprintf( stderr, "KDE RUNNING %d\n", kde ); ++ fprintf(stderr, "KDE RUNNING %d\n", kde); +#endif -+ return kde; -+ } ++ return kde; ++} + -+nsKDEUtils::nsKDEUtils() -+ : commandFile( NULL ) -+ , replyFile( NULL ) -+ { -+ } ++nsKDEUtils::nsKDEUtils() : commandFile(NULL), replyFile(NULL) {} + -+nsKDEUtils::~nsKDEUtils() -+ { -+// closeHelper(); not actually useful, exiting will close the fd too -+ } ++nsKDEUtils::~nsKDEUtils() { ++ // closeHelper(); not actually useful, exiting will close the fd too ++} + -+nsKDEUtils* nsKDEUtils::self() -+ { -+ static nsKDEUtils s; -+ return &s; -+ } ++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::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; ++}; + -+bool nsKDEUtils::kdeSupport() -+ { -+ static bool support = kdeSession() && getKdeSupport(); -+ return support && helperRunning; ++static gboolean kdeReadFunc(GIOChannel*, GIOCondition, gpointer data) { ++ nsKDECommandData* p = static_cast(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); + } ++ } + -+struct nsKDECommandData -+ { -+ FILE* file; -+ nsTArray* output; -+ GMainLoop* loop; -+ bool success; -+ }; ++ 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); ++ } ++ ++ NS_ADDREF(*output = result); ++ return ret; ++} ++ ++bool nsKDEUtils::commandBlockUi(const nsTArray& command, ++ GtkWindow* parent, ++ nsTArray* output) { ++ return self()->internalCommand(command, parent, true, output); ++} + -+static gboolean kdeReadFunc( GIOChannel*, GIOCondition, gpointer data ) ++bool nsKDEUtils::internalCommand(const nsTArray& command, ++ GtkWindow* parent, bool blockUi, ++ nsTArray* output) { ++ if (!startHelper()) return false; ++ feedCommand(command); ++ // do not store the data in 'this' but in extra structure, just in case there ++ // is reentrancy (can there be? the event loop is re-entered) ++ nsKDECommandData data; ++ data.file = replyFile; ++ data.output = output; ++ data.success = false; ++ if (blockUi) { ++ data.loop = g_main_loop_new(NULL, FALSE); ++ GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL); ++ if (parent && gtk_window_get_group(parent)) ++ gtk_window_group_add_window(gtk_window_get_group(parent), ++ GTK_WINDOW(window)); ++ gtk_widget_realize(window); ++ gtk_widget_set_sensitive(window, TRUE); ++ gtk_grab_add(window); ++ GIOChannel* channel = g_io_channel_unix_new(fileno(data.file)); ++ g_io_add_watch(channel, ++ static_cast(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(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(KMOZILLAHELPER), NULL}; ++ switch (fork()) { ++ case -1: { ++ close(fdcommand[0]); ++ close(fdcommand[1]); ++ close(fdreply[0]); ++ close(fdreply[1]); ++ return false; ++ } ++ case 0: // child + { -+ 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; ++ 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 + } -+ -+bool nsKDEUtils::command( const nsTArray& command, nsTArray* output ) -+ { -+ return self()->internalCommand( command, NULL, false, output ); -+ } -+ -+bool nsKDEUtils::command( nsIArray* command, nsIArray** output) ++ default: // parent + { -+ 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 ); -+ } -+ -+ NS_ADDREF( *output = result); -+ return ret; -+ } -+ -+ -+bool nsKDEUtils::commandBlockUi( const nsTArray& command, GtkWindow* parent, nsTArray* output ) -+ { -+ return self()->internalCommand( command, parent, true, output ); -+ } -+ -+bool nsKDEUtils::internalCommand( const nsTArray& command, GtkWindow* parent, bool blockUi, -+ nsTArray* output ) -+ { -+ if( !startHelper()) ++ commandFile = fdopen(fdcommand[1], "w"); ++ replyFile = fdopen(fdreply[0], "r"); ++ close(fdcommand[0]); ++ close(fdreply[1]); ++ if (commandFile == NULL || replyFile == NULL) { ++ closeHelper(); + 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; ++ } ++ // 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; ++} + -+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 ); ++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 -+ execvp( KMOZILLAHELPER, args ); -+#else -+ execv( KMOZILLAHELPER, args ); ++ fprintf(stderr, "COMM: %s\n", line.get()); +#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 ++ fputs(line.get(), commandFile); ++ fputs("\n", commandFile); ++ } ++ fputs("\\E\n", ++ commandFile); // done as \E, so it cannot happen in normal data ++ fflush(commandFile); ++} +Index: firefox-115.0/toolkit/xre/nsKDEUtils.h +=================================================================== --- /dev/null -+++ b/toolkit/xre/nsKDEUtils.h -@@ -0,0 +1,48 @@ ++++ firefox-115.0/toolkit/xre/nsKDEUtils.h +@@ -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 @@ -714,47 +569,48 @@ + +class nsIArray; + -+class NS_EXPORT nsKDEUtils -+ { -+ public: -+ /* Returns true if running inside a KDE session (regardless of whether there is KDE -+ support available for Firefox). This should be used e.g. when determining -+ dialog button order but not for code that requires the KDE support. */ -+ static bool kdeSession(); -+ /* Returns true if running inside a KDE session and KDE support is available -+ for Firefox. This should be used everywhere where the external helper is needed. */ -+ static bool kdeSupport(); -+ /* Executes the given helper command, returns true if helper returned success. */ -+ static bool command( const nsTArray& command, nsTArray* output = NULL ); -+ static bool command( nsIArray* command, nsIArray** output = NULL ); -+ /* Like command(), but additionally blocks the parent widget like if there was -+ a modal dialog shown and enters the event loop (i.e. there are still paint updates, -+ this is for commands that take long). */ -+ static bool commandBlockUi( const nsTArray& command, GtkWindow* parent, nsTArray* output = NULL ); ++class NS_EXPORT nsKDEUtils { ++ public: ++ /* Returns true if running inside a KDE session (regardless of whether there ++ is KDE support available for Firefox). This should be used e.g. when ++ determining dialog button order but not for code that requires the KDE ++ support. */ ++ static bool kdeSession(); ++ /* Returns true if running inside a KDE session and KDE support is available ++ for Firefox. This should be used everywhere where the external helper is ++ needed. */ ++ static bool kdeSupport(); ++ /* Executes the given helper command, returns true if helper returned success. ++ */ ++ static bool command(const nsTArray& command, ++ nsTArray* output = NULL); ++ static bool command(nsIArray* command, nsIArray** output = NULL); ++ /* Like command(), but additionally blocks the parent widget like if there was ++ a modal dialog shown and enters the event loop (i.e. there are still paint ++ updates, this is for commands that take long). */ ++ static bool commandBlockUi(const nsTArray& command, ++ GtkWindow* parent, ++ nsTArray* output = NULL); + -+ private: -+ nsKDEUtils(); -+ ~nsKDEUtils(); -+ static nsKDEUtils* self(); -+ bool startHelper(); -+ void closeHelper(); -+ void feedCommand( const nsTArray& command ); -+ bool internalCommand( const nsTArray& command, GtkWindow* parent, bool isParent, -+ nsTArray* output ); -+ FILE* commandFile; -+ FILE* replyFile; -+ }; ++ private: ++ nsKDEUtils(); ++ ~nsKDEUtils(); ++ static nsKDEUtils* self(); ++ bool startHelper(); ++ void closeHelper(); ++ void feedCommand(const nsTArray& command); ++ bool internalCommand(const nsTArray& command, GtkWindow* parent, ++ bool isParent, nsTArray* output); ++ FILE* commandFile; ++ FILE* replyFile; ++}; + -+#endif // nsKDEUtils -diff --git a/uriloader/exthandler/HandlerServiceParent.cpp b/uriloader/exthandler/HandlerServiceParent.cpp ---- a/uriloader/exthandler/HandlerServiceParent.cpp -+++ b/uriloader/exthandler/HandlerServiceParent.cpp -@@ -13,17 +13,17 @@ - #include "ContentHandlerService.h" - #include "nsIExternalProtocolService.h" - #include "nsStringEnumerator.h" - #include "nsIMutableArray.h" - #include "nsCExternalHandlerService.h" ++#endif // nsKDEUtils +Index: firefox-115.0/uriloader/exthandler/HandlerServiceParent.cpp +=================================================================== +--- firefox-115.0.orig/uriloader/exthandler/HandlerServiceParent.cpp ++++ firefox-115.0/uriloader/exthandler/HandlerServiceParent.cpp +@@ -18,7 +18,7 @@ #include "nsComponentManagerUtils.h" #include "nsServiceManagerUtils.h" #ifdef MOZ_WIDGET_GTK @@ -763,39 +619,22 @@ #endif using mozilla::dom::ContentHandlerService; - using mozilla::dom::HandlerApp; - using mozilla::dom::HandlerInfo; - using mozilla::dom::RemoteHandlerApp; - - namespace { -@@ -306,17 +306,17 @@ mozilla::ipc::IPCResult HandlerServicePa - const nsACString& aProtocolScheme, bool* aHandlerExists) { - if (aProtocolScheme.Length() > MAX_SCHEME_LENGTH) { - *aHandlerExists = false; - return IPC_OK(); +@@ -310,8 +310,8 @@ mozilla::ipc::IPCResult HandlerServicePa } #ifdef MOZ_WIDGET_GTK // Check the GNOME registry for a protocol handler - *aHandlerExists = +- *aHandlerExists = - nsGNOMERegistry::HandlerExists(PromiseFlatCString(aProtocolScheme).get()); -+ nsCommonRegistry::HandlerExists(PromiseFlatCString(aProtocolScheme).get()); ++ *aHandlerExists = nsCommonRegistry::HandlerExists( ++ PromiseFlatCString(aProtocolScheme).get()); #else *aHandlerExists = false; #endif - return IPC_OK(); - } - - /* - * Check if a handler exists for the provided protocol. Check the datastore -diff --git a/uriloader/exthandler/moz.build b/uriloader/exthandler/moz.build ---- a/uriloader/exthandler/moz.build -+++ b/uriloader/exthandler/moz.build -@@ -81,17 +81,19 @@ elif CONFIG["MOZ_WIDGET_TOOLKIT"] == "ui - else: - # These files can't be built in unified mode because they redefine LOG. - SOURCES += [ - osdir + "/nsOSHelperAppService.cpp", - ] +Index: firefox-115.0/uriloader/exthandler/moz.build +=================================================================== +--- firefox-115.0.orig/uriloader/exthandler/moz.build ++++ firefox-115.0/uriloader/exthandler/moz.build +@@ -86,7 +86,9 @@ else: if CONFIG["MOZ_WIDGET_TOOLKIT"] == "gtk": UNIFIED_SOURCES += [ @@ -805,17 +644,7 @@ "unix/nsMIMEInfoUnix.cpp", ] elif CONFIG["MOZ_WIDGET_TOOLKIT"] == "android": - UNIFIED_SOURCES += [ - "android/nsMIMEInfoAndroid.cpp", - ] - elif CONFIG["MOZ_WIDGET_TOOLKIT"] == "windows": - UNIFIED_SOURCES += [ -@@ -129,16 +131,17 @@ include("/ipc/chromium/chromium-config.m - FINAL_LIBRARY = "xul" - - LOCAL_INCLUDES += [ - "/docshell/base", - "/dom/base", +@@ -134,6 +136,7 @@ LOCAL_INCLUDES += [ "/dom/ipc", "/netwerk/base", "/netwerk/protocol/http", @@ -823,16 +652,11 @@ ] if CONFIG["MOZ_ENABLE_DBUS"]: - CXXFLAGS += CONFIG["MOZ_DBUS_CFLAGS"] - - if CONFIG["MOZ_WIDGET_TOOLKIT"] == "gtk": - CXXFLAGS += CONFIG["MOZ_GTK3_CFLAGS"] - CXXFLAGS += CONFIG["MOZ_DBUS_GLIB_CFLAGS"] -diff --git a/uriloader/exthandler/unix/nsCommonRegistry.cpp b/uriloader/exthandler/unix/nsCommonRegistry.cpp -new file mode 100644 +Index: firefox-115.0/uriloader/exthandler/unix/nsCommonRegistry.cpp +=================================================================== --- /dev/null -+++ b/uriloader/exthandler/unix/nsCommonRegistry.cpp -@@ -0,0 +1,53 @@ ++++ firefox-115.0/uriloader/exthandler/unix/nsCommonRegistry.cpp +@@ -0,0 +1,42 @@ +/* -*- 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 @@ -845,51 +669,40 @@ +#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 */ bool nsCommonRegistry::HandlerExists(const char* aProtocolScheme) { ++ if (nsKDEUtils::kdeSupport()) ++ return nsKDERegistry::HandlerExists(aProtocolScheme); ++ return nsGNOMERegistry::HandlerExists(aProtocolScheme); +} + -+/* static */ void -+nsCommonRegistry::GetAppDescForScheme(const nsACString& aScheme, -+ nsAString& aDesc) -+{ -+ if( nsKDEUtils::kdeSupport()) -+ return nsKDERegistry::GetAppDescForScheme( aScheme, aDesc ); -+ return nsGNOMERegistry::GetAppDescForScheme( aScheme, aDesc ); ++/* static */ nsresult nsCommonRegistry::LoadURL(nsIURI* aURL) { ++ if (nsKDEUtils::kdeSupport()) return nsKDERegistry::LoadURL(aURL); ++ return nsGNOMERegistry::LoadURL(aURL); +} + -+ -+/* static */ already_AddRefed -+nsCommonRegistry::GetFromExtension(const nsACString& aFileExt) -+{ -+ if( nsKDEUtils::kdeSupport()) -+ return nsKDERegistry::GetFromExtension( aFileExt ); -+ return nsGNOMERegistry::GetFromExtension( aFileExt ); ++/* 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::GetFromType(const nsACString& aMIMEType) -+{ -+ if( nsKDEUtils::kdeSupport()) -+ return nsKDERegistry::GetFromType( aMIMEType ); -+ return nsGNOMERegistry::GetFromType( aMIMEType ); ++nsCommonRegistry::GetFromExtension(const nsACString& aFileExt) { ++ if (nsKDEUtils::kdeSupport()) ++ return nsKDERegistry::GetFromExtension(aFileExt); ++ return nsGNOMERegistry::GetFromExtension(aFileExt); +} -diff --git a/uriloader/exthandler/unix/nsCommonRegistry.h b/uriloader/exthandler/unix/nsCommonRegistry.h -new file mode 100644 ++ ++/* static */ already_AddRefed nsCommonRegistry::GetFromType( ++ const nsACString& aMIMEType) { ++ if (nsKDEUtils::kdeSupport()) return nsKDERegistry::GetFromType(aMIMEType); ++ return nsGNOMERegistry::GetFromType(aMIMEType); ++} +Index: firefox-115.0/uriloader/exthandler/unix/nsCommonRegistry.h +=================================================================== --- /dev/null -+++ b/uriloader/exthandler/unix/nsCommonRegistry.h ++++ firefox-115.0/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 @@ -903,27 +716,27 @@ + +class nsMIMEInfoBase; + -+class nsCommonRegistry -+{ ++class nsCommonRegistry { + public: -+ static bool HandlerExists(const char *aProtocolScheme); ++ static bool HandlerExists(const char* aProtocolScheme); + -+ static nsresult LoadURL(nsIURI *aURL); ++ static nsresult LoadURL(nsIURI* aURL); + -+ static void GetAppDescForScheme(const nsACString& aScheme, -+ nsAString& aDesc); ++ static void GetAppDescForScheme(const nsACString& aScheme, nsAString& aDesc); + -+ static already_AddRefed GetFromExtension(const nsACString& aFileExt); ++ static already_AddRefed GetFromExtension( ++ const nsACString& aFileExt); + -+ static already_AddRefed GetFromType(const nsACString& aMIMEType); ++ static already_AddRefed GetFromType( ++ const nsACString& aMIMEType); +}; + +#endif -diff --git a/uriloader/exthandler/unix/nsKDERegistry.cpp b/uriloader/exthandler/unix/nsKDERegistry.cpp -new file mode 100644 +Index: firefox-115.0/uriloader/exthandler/unix/nsKDERegistry.cpp +=================================================================== --- /dev/null -+++ b/uriloader/exthandler/unix/nsKDERegistry.cpp -@@ -0,0 +1,89 @@ ++++ firefox-115.0/uriloader/exthandler/unix/nsKDERegistry.cpp +@@ -0,0 +1,75 @@ +/* -*- 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 @@ -937,87 +750,73 @@ +#include "nsMIMEInfoUnix.h" +#include "nsKDEUtils.h" + -+/* static */ bool -+nsKDERegistry::HandlerExists(const char *aProtocolScheme) -+{ -+ nsTArray command; -+ command.AppendElement( "HANDLEREXISTS"_ns ); -+ command.AppendElement( nsAutoCString( aProtocolScheme )); -+ return nsKDEUtils::command( command ); ++/* static */ bool nsKDERegistry::HandlerExists(const char* aProtocolScheme) { ++ nsTArray command; ++ command.AppendElement("HANDLEREXISTS"_ns); ++ command.AppendElement(nsAutoCString(aProtocolScheme)); ++ return nsKDEUtils::command(command); +} + -+/* static */ nsresult -+nsKDERegistry::LoadURL(nsIURI *aURL) -+{ -+ nsTArray command; -+ command.AppendElement( "OPEN"_ns ); -+ nsCString url; -+ aURL->GetSpec( url ); -+ command.AppendElement( url ); -+ bool rv = nsKDEUtils::command( command ); -+ if (!rv) -+ return NS_ERROR_FAILURE; ++/* static */ nsresult nsKDERegistry::LoadURL(nsIURI* aURL) { ++ nsTArray command; ++ command.AppendElement("OPEN"_ns); ++ nsCString url; ++ aURL->GetSpec(url); ++ command.AppendElement(url); ++ bool rv = nsKDEUtils::command(command); ++ if (!rv) return NS_ERROR_FAILURE; + -+ return NS_OK; ++ return NS_OK; +} + -+/* static */ void -+nsKDERegistry::GetAppDescForScheme(const nsACString& aScheme, -+ nsAString& aDesc) -+{ -+ nsTArray command; -+ command.AppendElement( "GETAPPDESCFORSCHEME"_ns ); -+ command.AppendElement( aScheme ); -+ nsTArray output; -+ if( nsKDEUtils::command( command, &output ) && output.Length() == 1 ) -+ CopyUTF8toUTF16( output[ 0 ], aDesc ); ++/* static */ void nsKDERegistry::GetAppDescForScheme(const nsACString& aScheme, ++ nsAString& aDesc) { ++ nsTArray command; ++ command.AppendElement("GETAPPDESCFORSCHEME"_ns); ++ 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( "GETFROMEXTENSION"_ns ); -+ command.AppendElement( aFileExt ); -+ return GetFromHelper( command ); ++/* static */ already_AddRefed nsKDERegistry::GetFromExtension( ++ const nsACString& aFileExt) { ++ NS_ASSERTION(aFileExt[0] != '.', "aFileExt shouldn't start with a dot"); ++ nsTArray command; ++ command.AppendElement("GETFROMEXTENSION"_ns); ++ command.AppendElement(aFileExt); ++ return GetFromHelper(command); +} + -+/* static */ already_AddRefed -+nsKDERegistry::GetFromType(const nsACString& aMIMEType) -+{ -+ nsTArray command; -+ command.AppendElement( "GETFROMTYPE"_ns ); -+ command.AppendElement( aMIMEType ); -+ return GetFromHelper( command ); ++/* static */ already_AddRefed nsKDERegistry::GetFromType( ++ const nsACString& aMIMEType) { ++ nsTArray command; ++ command.AppendElement("GETFROMTYPE"_ns); ++ command.AppendElement(aMIMEType); ++ return GetFromHelper(command); +} + -+/* static */ already_AddRefed -+nsKDERegistry::GetFromHelper(const nsTArray& command) -+{ -+ nsTArray output; -+ if( nsKDEUtils::command( command, &output ) && output.Length() == 3 ) -+ { -+ nsCString mimetype = output[ 0 ]; -+ RefPtr mimeInfo = new nsMIMEInfoUnix( mimetype ); -+ NS_ENSURE_TRUE(mimeInfo, nullptr); -+ nsCString description = output[ 1 ]; -+ mimeInfo->SetDescription(NS_ConvertUTF8toUTF16(description)); -+ nsCString handlerAppName = output[ 2 ]; -+ mozilla::StaticPrefs::browser_download_improvements_to_download_panel() -+ ? mimeInfo->SetPreferredAction(nsIMIMEInfo::saveToDisk) -+ : mimeInfo->SetPreferredAction(nsIMIMEInfo::useSystemDefault); -+ mimeInfo->SetDefaultDescription(NS_ConvertUTF8toUTF16(handlerAppName)); -+ return mimeInfo.forget(); -+ } -+ return nullptr; ++/* static */ already_AddRefed nsKDERegistry::GetFromHelper( ++ const nsTArray& command) { ++ nsTArray output; ++ if (nsKDEUtils::command(command, &output) && output.Length() == 3) { ++ nsCString mimetype = output[0]; ++ RefPtr mimeInfo = new nsMIMEInfoUnix(mimetype); ++ NS_ENSURE_TRUE(mimeInfo, nullptr); ++ nsCString description = output[1]; ++ mimeInfo->SetDescription(NS_ConvertUTF8toUTF16(description)); ++ nsCString handlerAppName = output[2]; ++ mimeInfo->SetPreferredAction(nsIMIMEInfo::saveToDisk); ++ mimeInfo->SetDefaultDescription(NS_ConvertUTF8toUTF16(handlerAppName)); ++ return mimeInfo.forget(); ++ } ++ return nullptr; +} -diff --git a/uriloader/exthandler/unix/nsKDERegistry.h b/uriloader/exthandler/unix/nsKDERegistry.h -new file mode 100644 +Index: firefox-115.0/uriloader/exthandler/unix/nsKDERegistry.h +=================================================================== --- /dev/null -+++ b/uriloader/exthandler/unix/nsKDERegistry.h -@@ -0,0 +1,34 @@ ++++ firefox-115.0/uriloader/exthandler/unix/nsKDERegistry.h +@@ -0,0 +1,35 @@ +/* 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/. */ @@ -1030,36 +829,34 @@ +#include "nsTArray.h" + +class nsMIMEInfoBase; -+//class nsAutoCString; -+//class nsCString; ++// class nsAutoCString; ++// class nsCString; + -+class nsKDERegistry -+{ ++class nsKDERegistry { + public: -+ static bool HandlerExists(const char *aProtocolScheme); ++ static bool HandlerExists(const char* aProtocolScheme); + -+ static nsresult LoadURL(nsIURI *aURL); ++ static nsresult LoadURL(nsIURI* aURL); + -+ static void GetAppDescForScheme(const nsACString& aScheme, -+ nsAString& aDesc); ++ static void GetAppDescForScheme(const nsACString& aScheme, nsAString& aDesc); + -+ static already_AddRefed GetFromExtension(const nsACString& aFileExt); ++ static already_AddRefed GetFromExtension( ++ const nsACString& aFileExt); + -+ static already_AddRefed GetFromType(const nsACString& aMIMEType); ++ static already_AddRefed GetFromType( ++ const nsACString& aMIMEType); ++ + private: -+ static already_AddRefed GetFromHelper(const nsTArray& command); -+ ++ static already_AddRefed GetFromHelper( ++ const nsTArray& command); +}; + -+#endif //nsKDERegistry_h__ -diff --git a/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp b/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp ---- a/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp -+++ b/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp -@@ -1,48 +1,51 @@ - /* -*- Mode: C++; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this ++#endif // nsKDERegistry_h__ +Index: firefox-115.0/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp +=================================================================== +--- firefox-115.0.orig/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp ++++ firefox-115.0/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp +@@ -5,16 +5,19 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsMIMEInfoUnix.h" @@ -1072,7 +869,7 @@ # include "nsDBusHandlerApp.h" #endif +#if defined(XP_UNIX) && !defined(XP_MACOSX) -+#include "nsKDEUtils.h" ++# include "nsKDEUtils.h" +#endif nsresult nsMIMEInfoUnix::LoadUriInternal(nsIURI* aURI) { @@ -1081,14 +878,7 @@ } NS_IMETHODIMP - nsMIMEInfoUnix::GetHasDefaultHandler(bool* _retval) { - // if a default app 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 (GetDefaultApplication()) { - return nsMIMEInfoImpl::GetHasDefaultHandler(_retval); - } - +@@ -29,15 +32,15 @@ nsMIMEInfoUnix::GetHasDefaultHandler(boo *_retval = false; if (mClass == eProtocolInfo) { @@ -1107,33 +897,21 @@ } } if (mimeInfo) *_retval = true; - } - - if (*_retval) return NS_OK; - - return NS_OK; -@@ -54,16 +57,33 @@ nsresult nsMIMEInfoUnix::LaunchDefaultWi - // give the GNOME answer. - if (GetDefaultApplication()) { - return nsMIMEInfoImpl::LaunchDefaultWithFile(aFile); - } - +@@ -59,6 +62,21 @@ nsresult nsMIMEInfoUnix::LaunchDefaultWi nsAutoCString nativePath; aFile->GetNativePath(nativePath); -+ if( nsKDEUtils::kdeSupport()) { ++ if (nsKDEUtils::kdeSupport()) { + bool supports; -+ if( NS_SUCCEEDED( GetHasDefaultHandler( &supports )) && supports ) { ++ if (NS_SUCCEEDED(GetHasDefaultHandler(&supports)) && supports) { + nsTArray command; -+ command.AppendElement( "OPEN"_ns ); -+ command.AppendElement( nativePath ); -+ command.AppendElement( "MIMETYPE"_ns ); -+ command.AppendElement( mSchemeOrType ); -+ if( nsKDEUtils::command( command )) -+ return NS_OK; ++ command.AppendElement("OPEN"_ns); ++ command.AppendElement(nativePath); ++ command.AppendElement("MIMETYPE"_ns); ++ command.AppendElement(mSchemeOrType); ++ if (nsKDEUtils::command(command)) return NS_OK; + } -+ if (!GetDefaultApplication()) -+ return NS_ERROR_FILE_NOT_FOUND; ++ if (!GetDefaultApplication()) return NS_ERROR_FILE_NOT_FOUND; + + return LaunchWithIProcess(GetDefaultApplication(), nativePath); + } @@ -1141,20 +919,11 @@ nsCOMPtr giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID); if (!giovfs) { return NS_ERROR_FAILURE; - } - - // nsGIOMimeApp->Launch wants a URI string instead of local file - nsresult rv; - nsCOMPtr ioservice = -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 -@@ -5,17 +5,17 @@ - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - - #include - #include - +Index: firefox-115.0/uriloader/exthandler/unix/nsOSHelperAppService.cpp +=================================================================== +--- firefox-115.0.orig/uriloader/exthandler/unix/nsOSHelperAppService.cpp ++++ firefox-115.0/uriloader/exthandler/unix/nsOSHelperAppService.cpp +@@ -10,7 +10,7 @@ #include "nsOSHelperAppService.h" #include "nsMIMEInfoUnix.h" #ifdef MOZ_WIDGET_GTK @@ -1163,17 +932,7 @@ # ifdef MOZ_BUILD_APP_IS_BROWSER # include "nsIToolkitShellService.h" # include "nsIGNOMEShellService.h" - # endif - #endif - #include "nsISupports.h" - #include "nsString.h" - #include "nsReadableUtils.h" -@@ -1102,17 +1102,17 @@ nsresult nsOSHelperAppService::GetHandle - - nsresult nsOSHelperAppService::OSProtocolHandlerExists( - const char* aProtocolScheme, bool* aHandlerExists) { - nsresult rv = NS_OK; - +@@ -1106,7 +1106,7 @@ nsresult nsOSHelperAppService::OSProtoco if (!XRE_IsContentProcess()) { #ifdef MOZ_WIDGET_GTK // Check the GNOME registry for a protocol handler @@ -1182,17 +941,7 @@ #else *aHandlerExists = false; #endif - } else { - *aHandlerExists = false; - nsCOMPtr handlerSvc = - do_GetService(NS_HANDLERSERVICE_CONTRACTID, &rv); - if (NS_SUCCEEDED(rv) && handlerSvc) { -@@ -1122,17 +1122,17 @@ nsresult nsOSHelperAppService::OSProtoco - } - - return rv; - } - +@@ -1126,7 +1126,7 @@ nsresult nsOSHelperAppService::OSProtoco NS_IMETHODIMP nsOSHelperAppService::GetApplicationDescription( const nsACString& aScheme, nsAString& _retval) { #ifdef MOZ_WIDGET_GTK @@ -1201,17 +950,7 @@ return _retval.IsEmpty() ? NS_ERROR_NOT_AVAILABLE : NS_OK; #else return NS_ERROR_NOT_AVAILABLE; - #endif - } - - NS_IMETHODIMP nsOSHelperAppService::IsCurrentAppOSDefaultForProtocol( - const nsACString& aScheme, bool* _retval) { -@@ -1227,17 +1227,17 @@ already_AddRefed nsOSHel - nsresult rv = - LookUpTypeAndDescription(NS_ConvertUTF8toUTF16(aFileExt), majorType, - minorType, mime_types_description, true); - - if (NS_FAILED(rv) || majorType.IsEmpty()) { +@@ -1231,7 +1231,7 @@ already_AddRefed nsOSHel #ifdef MOZ_WIDGET_GTK LOG("Looking in GNOME registry\n"); RefPtr gnomeInfo = @@ -1220,17 +959,7 @@ if (gnomeInfo) { LOG("Got MIMEInfo from GNOME registry\n"); return gnomeInfo.forget(); - } - #endif - - rv = LookUpTypeAndDescription(NS_ConvertUTF8toUTF16(aFileExt), majorType, - minorType, mime_types_description, false); -@@ -1342,17 +1342,17 @@ already_AddRefed nsOSHel - - // Now look up our extensions - nsAutoString extensions, mime_types_description; - LookUpExtensionsAndDescription(majorType, minorType, extensions, - mime_types_description); +@@ -1344,7 +1344,7 @@ already_AddRefed nsOSHel #ifdef MOZ_WIDGET_GTK if (handler.IsEmpty()) { @@ -1239,20 +968,11 @@ if (gnomeInfo) { LOG("Got MIMEInfo from GNOME registry without extensions; setting them " "to %s\n", - NS_LossyConvertUTF16toASCII(extensions).get()); - - NS_ASSERTION(!gnomeInfo->HasExtensions(), "How'd that happen?"); - gnomeInfo->SetFileExtensions(NS_ConvertUTF16toUTF8(extensions)); - return gnomeInfo.forget(); -diff --git a/widget/gtk/moz.build b/widget/gtk/moz.build ---- a/widget/gtk/moz.build -+++ b/widget/gtk/moz.build -@@ -142,16 +142,17 @@ FINAL_LIBRARY = "xul" - - LOCAL_INCLUDES += [ - "/layout/base", - "/layout/forms", - "/layout/generic", +Index: firefox-115.0/widget/gtk/moz.build +=================================================================== +--- firefox-115.0.orig/widget/gtk/moz.build ++++ firefox-115.0/widget/gtk/moz.build +@@ -149,6 +149,7 @@ LOCAL_INCLUDES += [ "/layout/xul", "/other-licenses/atk-1.0", "/third_party/cups/include", @@ -1260,19 +980,11 @@ "/widget", "/widget/headless", ] - - if CONFIG["MOZ_X11"] or CONFIG["MOZ_WAYLAND"]: - LOCAL_INCLUDES += [ - "/widget/x11", - ] -diff --git a/widget/gtk/nsFilePicker.cpp b/widget/gtk/nsFilePicker.cpp ---- a/widget/gtk/nsFilePicker.cpp -+++ b/widget/gtk/nsFilePicker.cpp -@@ -1,15 +1,16 @@ - /* -*- 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/. */ +Index: firefox-115.0/widget/gtk/nsFilePicker.cpp +=================================================================== +--- firefox-115.0.orig/widget/gtk/nsFilePicker.cpp ++++ firefox-115.0/widget/gtk/nsFilePicker.cpp +@@ -5,6 +5,7 @@ #include #include @@ -1280,17 +992,7 @@ #include #include #include - - #include "mozilla/Types.h" - #include "nsGtkUtils.h" - #include "nsIFileURL.h" - #include "nsIGIOService.h" -@@ -23,16 +24,18 @@ - #include "nsArrayEnumerator.h" - #include "nsEnumeratorUtils.h" - #include "nsNetUtil.h" - #include "nsReadableUtils.h" - #include "MozContainer.h" +@@ -28,6 +29,8 @@ #include "WidgetUtilsGtk.h" #include "nsFilePicker.h" @@ -1299,60 +1001,41 @@ #undef LOG #ifdef MOZ_LOGGING - # include "mozilla/Logging.h" - # include "nsTArray.h" - # include "Units.h" - extern mozilla::LazyLogModule gWidgetLog; - # define LOG(args) MOZ_LOG(gWidgetLog, mozilla::LogLevel::Debug, args) -@@ -237,17 +240,19 @@ nsFilePicker::AppendFilters(int32_t aFil - mAllowURLs = !!(aFilterMask & filterAllowURLs); - return nsBaseFilePicker::AppendFilters(aFilterMask); - } - - NS_IMETHODIMP +@@ -242,7 +245,8 @@ 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; ++ if (mMode != modeOpen || !nsKDEUtils::kdeSupport()) return NS_OK; } nsAutoCString filter, name; - CopyUTF16toUTF8(aFilter, filter); - CopyUTF16toUTF8(aTitle, name); - - mFilters.AppendElement(filter); - mFilterNames.AppendElement(name); -@@ -347,16 +352,39 @@ nsresult nsFilePicker::Show(nsIFilePicke - return NS_OK; - } - - NS_IMETHODIMP - nsFilePicker::Open(nsIFilePickerShownCallback* aCallback) { +@@ -352,6 +356,31 @@ nsFilePicker::Open(nsIFilePickerShownCal // 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()) { ++ if (nsKDEUtils::kdeSupport()) { + mCallback = aCallback; + mRunning = true; + NS_ADDREF_THIS(); -+ g_idle_add([](gpointer data) -> gboolean { -+ nsFilePicker* queuedPicker = (nsFilePicker*) data; -+ nsIFilePicker::ResultCode result; -+ queuedPicker->kdeFileDialog(&result); -+ if (queuedPicker->mCallback) { -+ queuedPicker->mCallback->Done(result); -+ queuedPicker->mCallback = nullptr; -+ } else { -+ queuedPicker->mResult = result; -+ } -+ queuedPicker->mRunning = false; -+ NS_RELEASE(queuedPicker); -+ return G_SOURCE_REMOVE; -+ }, this); ++ g_idle_add( ++ [](gpointer data) -> gboolean { ++ nsFilePicker* queuedPicker = (nsFilePicker*)data; ++ nsIFilePicker::ResultCode result; ++ queuedPicker->kdeFileDialog(&result); ++ if (queuedPicker->mCallback) { ++ queuedPicker->mCallback->Done(result); ++ queuedPicker->mCallback = nullptr; ++ } else { ++ queuedPicker->mResult = result; ++ } ++ queuedPicker->mRunning = false; ++ NS_RELEASE(queuedPicker); ++ return G_SOURCE_REMOVE; ++ }, ++ this); + + return NS_OK; + } @@ -1360,86 +1043,68 @@ NS_ConvertUTF16toUTF8 title(mTitle); GtkWindow* parent_widget = - GTK_WINDOW(mParentWidget->GetNativeData(NS_NATIVE_SHELLWIDGET)); - - GtkFileChooserAction action = GetGtkFileChooserAction(mMode); - - const gchar* accept_button; -@@ -628,16 +656,244 @@ void nsFilePicker::Done(void* file_choos - mCallback->Done(result); - mCallback = nullptr; - } else { - mResult = result; - } +@@ -633,6 +662,205 @@ void nsFilePicker::Done(void* file_choos 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; -+ } ++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 ); -+ } ++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(nsIFilePicker::ResultCode *aReturn) -+ { -+ NS_ENSURE_ARG_POINTER(aReturn); ++NS_IMETHODIMP nsFilePicker::kdeFileDialog(nsIFilePicker::ResultCode* aReturn) { ++ NS_ENSURE_ARG_POINTER(aReturn); + -+ if( mMode == modeOpen && mFilters.Length() == 1 && mFilters[ 0 ].EqualsLiteral( "..apps" )) -+ return kdeAppsDialog( aReturn ); -+ -+ nsCString title; -+ title.Adopt(ToNewUTF8String(mTitle)); ++ if (mMode == modeOpen && mFilters.Length() == 1 && ++ mFilters[0].EqualsLiteral("..apps")) ++ return kdeAppsDialog(aReturn); + -+ 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; -+ } -+ } ++ nsCString 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) { @@ -1448,203 +1113,164 @@ + mPrevDisplayDirectory->GetNativePath(directory); + } + -+ nsAutoCString startdir; ++ nsAutoCString startdir; + if (!directory.IsEmpty()) { + startdir = directory; + } + if (mMode == nsIFilePicker::modeSave) { -+ if( !startdir.IsEmpty()) -+ { ++ if (!startdir.IsEmpty()) { + startdir += "/"; + startdir += ToNewUTF8String(mDefault); -+ } -+ else ++ } else + startdir = ToNewUTF8String(mDefault); + } + -+ nsAutoCString filters; -+ PRInt32 count = mFilters.Length(); -+ if( count == 0 ) //just in case -+ filters = "*"; -+ else -+ { -+ filters = kdeMakeFilter( 0 ); -+ for (PRInt32 i = 1; i < count; ++i) -+ { -+ filters += "\n"; -+ filters += kdeMakeFilter( i ); -+ } -+ } -+ -+ nsTArray 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( "MULTIPLE"_ns ); -+ if( PRInt32 xid = windowToXid( mParentWidget )) -+ { -+ command.AppendElement( "PARENT"_ns ); -+ 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 :-/ -+ { -+ nsCOMPtr localfile; -+ nsresult rv = NS_NewNativeLocalFile( output[ 0 ], -+ PR_FALSE, -+ getter_AddRefs(localfile)); -+ if (NS_SUCCEEDED(rv)) -+ rv = net_GetURLSpecFromActualFile(localfile, mFileURL); -+ } -+ } -+ // 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); ++ 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); + } + } -+ 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(nsIFilePicker::ResultCode *aReturn) -+ { -+ NS_ENSURE_ARG_POINTER(aReturn); ++ 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("MULTIPLE"_ns); ++ if (PRInt32 xid = windowToXid(mParentWidget)) { ++ command.AppendElement("PARENT"_ns); ++ nsAutoCString parent; ++ parent.AppendInt(xid); ++ command.AppendElement(parent); ++ } + -+ nsCString title; -+ title.Adopt(ToNewUTF8String(mTitle)); ++ 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 :-/ ++ { ++ nsCOMPtr localfile; ++ nsresult rv = NS_NewNativeLocalFile(output[0], PR_FALSE, ++ getter_AddRefs(localfile)); ++ if (NS_SUCCEEDED(rv)) ++ rv = net_GetURLSpecFromActualFile(localfile, mFileURL); ++ } ++ } ++ // Remember last used directory. ++ nsCOMPtr file; ++ GetFile(getter_AddRefs(file)); ++ if (file) { ++ nsCOMPtr dir; ++ file->GetParent(getter_AddRefs(dir)); ++ nsCOMPtr localDir(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; ++} + -+ nsTArray command; -+ command.AppendElement( "APPSDIALOG"_ns ); -+ command.AppendElement( title ); -+ if( PRInt32 xid = windowToXid( mParentWidget )) -+ { -+ command.AppendElement( "PARENT"_ns ); -+ nsAutoCString parent; -+ parent.AppendInt( xid ); -+ command.AppendElement( parent ); -+ } ++NS_IMETHODIMP nsFilePicker::kdeAppsDialog(nsIFilePicker::ResultCode* aReturn) { ++ NS_ENSURE_ARG_POINTER(aReturn); ++ ++ nsCString title; ++ title.Adopt(ToNewUTF8String(mTitle)); + -+ 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; -+ } ++ nsTArray command; ++ command.AppendElement("APPSDIALOG"_ns); ++ command.AppendElement(title); ++ if (PRInt32 xid = windowToXid(mParentWidget)) { ++ command.AppendElement("PARENT"_ns); ++ 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; ++} + // All below functions available as of GTK 3.20+ void* nsFilePicker::GtkFileChooserNew(const gchar* title, GtkWindow* parent, GtkFileChooserAction action, - const gchar* accept_label) { - static auto sGtkFileChooserNativeNewPtr = - (void* (*)(const gchar*, GtkWindow*, GtkFileChooserAction, const gchar*, - const gchar*))dlsym(RTLD_DEFAULT, - "gtk_file_chooser_native_new"); -diff --git a/widget/gtk/nsFilePicker.h b/widget/gtk/nsFilePicker.h ---- a/widget/gtk/nsFilePicker.h -+++ b/widget/gtk/nsFilePicker.h -@@ -69,16 +69,22 @@ class nsFilePicker : public nsBaseFilePi - nsString mDefaultExtension; - - nsTArray mFilters; - nsTArray mFilterNames; - +Index: firefox-115.0/widget/gtk/nsFilePicker.h +=================================================================== +--- firefox-115.0.orig/widget/gtk/nsFilePicker.h ++++ firefox-115.0/widget/gtk/nsFilePicker.h +@@ -74,6 +74,12 @@ class nsFilePicker : public nsBaseFilePi private: static nsIFile* mPrevDisplayDirectory; + bool kdeRunning(); + bool getKdeRunning(); -+ NS_IMETHODIMP kdeFileDialog(nsIFilePicker::ResultCode *aReturn); -+ NS_IMETHODIMP kdeAppsDialog(nsIFilePicker::ResultCode *aReturn); -+ nsCString kdeMakeFilter( int index ); ++ NS_IMETHODIMP kdeFileDialog(nsIFilePicker::ResultCode* aReturn); ++ NS_IMETHODIMP kdeAppsDialog(nsIFilePicker::ResultCode* aReturn); ++ nsCString kdeMakeFilter(int index); + void* GtkFileChooserNew(const gchar* title, GtkWindow* parent, GtkFileChooserAction action, const gchar* accept_label); - void GtkFileChooserShow(void* file_chooser); - void GtkFileChooserDestroy(void* file_chooser); - void GtkFileChooserSetModal(void* file_chooser, GtkWindow* parent_widget, - gboolean modal); - -diff --git a/xpcom/components/ManifestParser.cpp b/xpcom/components/ManifestParser.cpp ---- a/xpcom/components/ManifestParser.cpp -+++ b/xpcom/components/ManifestParser.cpp -@@ -38,16 +38,17 @@ - #include "nsTextFormatter.h" - #include "nsVersionComparator.h" - #include "nsXPCOMCIDInternal.h" - - #include "nsIConsoleService.h" +Index: firefox-115.0/xpcom/components/ManifestParser.cpp +=================================================================== +--- firefox-115.0.orig/xpcom/components/ManifestParser.cpp ++++ firefox-115.0/xpcom/components/ManifestParser.cpp +@@ -43,6 +43,7 @@ #include "nsIScriptError.h" #include "nsIXULAppInfo.h" #include "nsIXULRuntime.h" @@ -1652,17 +1278,7 @@ using namespace mozilla; - struct ManifestDirective { - const char* directive; - int argc; - - bool ischrome; -@@ -389,16 +390,17 @@ void ParseManifest(NSLocationType aType, - constexpr auto kRemoteEnabled = u"remoteenabled"_ns; - constexpr auto kRemoteRequired = u"remoterequired"_ns; - constexpr auto kApplication = u"application"_ns; - constexpr auto kAppVersion = u"appversion"_ns; - constexpr auto kGeckoVersion = u"platformversion"_ns; +@@ -394,6 +395,7 @@ void ParseManifest(NSLocationType aType, constexpr auto kOs = u"os"_ns; constexpr auto kOsVersion = u"osversion"_ns; constexpr auto kABI = u"abi"_ns; @@ -1670,17 +1286,7 @@ constexpr auto kProcess = u"process"_ns; #if defined(MOZ_WIDGET_ANDROID) constexpr auto kTablet = u"tablet"_ns; - #endif - // You might expect this to be guarded by MOZ_BACKGROUNDTASKS, but it's not - // possible to have conditional manifest contents, so we need to recognize and - // discard these tokens even when MOZ_BACKGROUNDTASKS is not set. - constexpr auto kBackgroundTask = u"backgroundtask"_ns; -@@ -448,39 +450,44 @@ void ParseManifest(NSLocationType aType, - CopyUTF8toUTF16(s, abi); - abi.Insert(char16_t('_'), 0); - abi.Insert(osTarget, 0); - } - } +@@ -453,6 +455,7 @@ void ParseManifest(NSLocationType aType, } nsAutoString osVersion; @@ -1688,8 +1294,7 @@ #if defined(XP_WIN) # pragma warning(push) # pragma warning(disable : 4996) // VC12+ deprecates GetVersionEx - OSVERSIONINFO info = {sizeof(OSVERSIONINFO)}; - if (GetVersionEx(&info)) { +@@ -461,14 +464,17 @@ void ParseManifest(NSLocationType aType, nsTextFormatter::ssprintf(osVersion, u"%ld.%ld", info.dwMajorVersion, info.dwMinorVersion); } @@ -1707,7 +1312,7 @@ #elif defined(MOZ_WIDGET_ANDROID) bool isTablet = false; if (jni::IsAvailable()) { - jni::String::LocalRef release = java::sdk::Build::VERSION::RELEASE(); +@@ -476,6 +482,7 @@ void ParseManifest(NSLocationType aType, osVersion.Assign(release->ToString()); isTablet = java::GeckoAppShell::IsTablet(); } @@ -1715,17 +1320,7 @@ #endif if (XRE_IsContentProcess()) { - process = kContent; - } else { - process = kMain; - } - -@@ -571,25 +578,27 @@ void ParseManifest(NSLocationType aType, - // When in background task mode, default to not registering - // category directivies unless backgroundtask=1 is specified. - TriState stBackgroundTask = (BackgroundTasks::IsBackgroundTaskMode() && - strcmp("category", directive->directive) == 0) - ? eBad +@@ -576,6 +583,7 @@ void ParseManifest(NSLocationType aType, : eUnspecified; #endif int flags = 0; @@ -1733,9 +1328,7 @@ while ((token = nsCRT::strtok(whitespace, kWhitespace, &whitespace)) && ok) { - ToLowerCase(token); - NS_ConvertASCIItoUTF16 wtoken(token); - +@@ -585,6 +593,7 @@ void ParseManifest(NSLocationType aType, if (CheckStringFlag(kApplication, wtoken, appID, stApp) || CheckOsFlag(kOs, wtoken, osTarget, stOs) || CheckStringFlag(kABI, wtoken, abi, stABI) || @@ -1743,39 +1336,19 @@ CheckStringFlag(kProcess, wtoken, process, stProcess) || CheckVersionFlag(kOsVersion, wtoken, osVersion, stOsVersion) || CheckVersionFlag(kAppVersion, wtoken, appVersion, stAppVersion) || - CheckVersionFlag(kGeckoVersion, wtoken, geckoVersion, - stGeckoVersion)) { - continue; - } - -@@ -638,17 +647,17 @@ void ParseManifest(NSLocationType aType, - } - - LogMessageWithContext( - aFile, line, "Unrecognized chrome manifest modifier '%s'.", token); - ok = false; - } +@@ -644,6 +653,7 @@ void ParseManifest(NSLocationType aType, if (!ok || stApp == eBad || stAppVersion == eBad || -- stGeckoVersion == eBad || stOs == eBad || stOsVersion == eBad || -+ stGeckoVersion == eBad || stOs == eBad || stOsVersion == eBad || stDesktop == eBad || + stGeckoVersion == eBad || stOs == eBad || stOsVersion == eBad || ++ stDesktop == eBad || #ifdef MOZ_WIDGET_ANDROID stTablet == eBad || #endif - #ifdef MOZ_BACKGROUNDTASKS - stBackgroundTask == eBad || - #endif - stABI == eBad || stProcess == eBad) { - continue; -diff --git a/xpcom/components/moz.build b/xpcom/components/moz.build ---- a/xpcom/components/moz.build -+++ b/xpcom/components/moz.build -@@ -66,16 +66,17 @@ LOCAL_INCLUDES += [ - "!..", - "../base", - "../build", - "../ds", - "/chrome", +Index: firefox-115.0/xpcom/components/moz.build +=================================================================== +--- firefox-115.0.orig/xpcom/components/moz.build ++++ firefox-115.0/xpcom/components/moz.build +@@ -71,6 +71,7 @@ LOCAL_INCLUDES += [ "/js/xpconnect/loader", "/layout/build", "/modules/libjar", @@ -1783,20 +1356,11 @@ ] if CONFIG["MOZ_WIDGET_TOOLKIT"] == "gtk": - CXXFLAGS += CONFIG["MOZ_GTK3_CFLAGS"] - if CONFIG["MOZ_ENABLE_DBUS"]: - CXXFLAGS += CONFIG["MOZ_DBUS_GLIB_CFLAGS"] - - include("/ipc/chromium/chromium-config.mozbuild") -diff --git a/xpcom/io/nsLocalFileUnix.cpp b/xpcom/io/nsLocalFileUnix.cpp ---- a/xpcom/io/nsLocalFileUnix.cpp -+++ b/xpcom/io/nsLocalFileUnix.cpp -@@ -46,16 +46,17 @@ - #include "nsString.h" - #include "nsIDirectoryEnumerator.h" - #include "nsSimpleEnumerator.h" - #include "private/pprio.h" - #include "prlink.h" +Index: firefox-115.0/xpcom/io/nsLocalFileUnix.cpp +=================================================================== +--- firefox-115.0.orig/xpcom/io/nsLocalFileUnix.cpp ++++ firefox-115.0/xpcom/io/nsLocalFileUnix.cpp +@@ -51,6 +51,7 @@ #ifdef MOZ_WIDGET_GTK # include "nsIGIOService.h" @@ -1804,64 +1368,38 @@ #endif #ifdef MOZ_WIDGET_COCOA - # include - # include "CocoaFileUtils.h" - # include "prmem.h" - # include "plbase64.h" - -@@ -2167,20 +2168,29 @@ nsLocalFile::SetPersistentDescriptor(con - - NS_IMETHODIMP - nsLocalFile::Reveal() { - if (!FilePreferences::IsAllowedPath(mPath)) { - return NS_ERROR_FILE_ACCESS_DENIED; +@@ -2172,10 +2173,18 @@ nsLocalFile::Reveal() { } #ifdef MOZ_WIDGET_GTK + nsAutoCString url; nsCOMPtr giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID); - if (!giovfs) { +- return NS_ERROR_FAILURE; + url = mPath; -+ if(nsKDEUtils::kdeSupport()) { ++ if (nsKDEUtils::kdeSupport()) { + nsTArray command; -+ command.AppendElement( "REVEAL"_ns ); -+ command.AppendElement( mPath ); -+ return nsKDEUtils::command( command ) ? NS_OK : NS_ERROR_FAILURE; -+ } ++ command.AppendElement("REVEAL"_ns); ++ command.AppendElement(mPath); ++ return nsKDEUtils::command(command) ? NS_OK : NS_ERROR_FAILURE; + } + -+ if (!giovfs) - return NS_ERROR_FAILURE; -- } ++ if (!giovfs) return NS_ERROR_FAILURE; + return giovfs->RevealFile(this); #elif defined(MOZ_WIDGET_COCOA) CFURLRef url; - if (NS_SUCCEEDED(GetCFURL(&url))) { - nsresult rv = CocoaFileUtils::RevealFileInFinder(url); - ::CFRelease(url); - return rv; - } -@@ -2192,16 +2202,23 @@ nsLocalFile::Reveal() { - - NS_IMETHODIMP - nsLocalFile::Launch() { - if (!FilePreferences::IsAllowedPath(mPath)) { - return NS_ERROR_FILE_ACCESS_DENIED; +@@ -2197,6 +2206,13 @@ nsLocalFile::Launch() { } #ifdef MOZ_WIDGET_GTK -+ if( nsKDEUtils::kdeSupport()) { ++ if (nsKDEUtils::kdeSupport()) { + nsTArray command; -+ command.AppendElement( "OPEN"_ns ); -+ command.AppendElement( mPath ); -+ return nsKDEUtils::command( command ) ? NS_OK : NS_ERROR_FAILURE; ++ command.AppendElement("OPEN"_ns); ++ command.AppendElement(mPath); ++ return nsKDEUtils::command(command) ? NS_OK : NS_ERROR_FAILURE; + } + nsCOMPtr giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID); if (!giovfs) { return NS_ERROR_FAILURE; - } - - return giovfs->LaunchFile(mPath); - #elif defined(MOZ_WIDGET_ANDROID) - // Not supported on GeckoView