diff --git a/.SRCINFO b/.SRCINFO index a348bf3..67052f4 100644 --- a/.SRCINFO +++ b/.SRCINFO @@ -33,6 +33,7 @@ pkgbase = firedragon makedepends = git makedepends = binutils makedepends = lld + makedepends = dump_syms depends = gtk3 depends = libxt depends = mime-types @@ -67,7 +68,6 @@ pkgbase = firedragon optdepends = appmenu-gtk-module-git: Appmenu for GTK only optdepends = plasma5-applets-window-appmenu: Appmenu for Plasma only conflicts = firedragon-hg - replaces = firedragon-stable options = !emptydirs options = !makeflags options = !strip @@ -77,10 +77,6 @@ pkgbase = firedragon source = firedragon.desktop source = git+https://gitlab.com/dr460nf1r3/common.git source = git+https://gitlab.com/dr460nf1r3/settings.git - source = remove_addons.patch::https://gitlab.com/librewolf-community/browser/linux/-/raw/9e90fb3a9bc38aad9921530ee69ecabf6ac8c7bf/remove_addons.patch - source = context-menu.patch::https://gitlab.com/librewolf-community/browser/linux/-/raw/9e90fb3a9bc38aad9921530ee69ecabf6ac8c7bf/context-menu.patch - source = unity-menubar.patch::https://gitlab.com/librewolf-community/browser/linux/-/raw/9e90fb3a9bc38aad9921530ee69ecabf6ac8c7bf/unity-menubar.patch - source = mozilla-vpn-ad.patch::https://gitlab.com/librewolf-community/browser/linux/-/raw/9e90fb3a9bc38aad9921530ee69ecabf6ac8c7bf/mozilla-vpn-ad.patch source = 0001-Use-remoting-name-for-GDK-application-names.patch source = firefox-kde-aedbca44a8a2958947bed31f28e3083ac0496f4a.patch::https://raw.githubusercontent.com/openSUSE/firefox-maintenance/aedbca44a8a2958947bed31f28e3083ac0496f4a/firefox/firefox-kde.patch source = mozilla-kde-aedbca44a8a2958947bed31f28e3083ac0496f4a.patch::https://raw.githubusercontent.com/openSUSE/firefox-maintenance/aedbca44a8a2958947bed31f28e3083ac0496f4a/mozilla-kde.patch @@ -96,10 +92,6 @@ pkgbase = firedragon sha256sums = 158152bdb9ef6a83bad62ae03a3d9bc8ae693b34926e53cc8c4de07df20ab22d sha256sums = SKIP sha256sums = SKIP - sha256sums = af9d9341917cf3c5844fc46597ad2d842642c937c9be574bfacfe5c242b1114c - sha256sums = 3bc57d97ef58c5e80f6099b0e82dab23a4404de04710529d8a8dd0eaa079afcd - sha256sums = 860e49ab14ce2c9416a479d313a2da799e023db58e93b81ca4cb869c5afb39a7 - sha256sums = f3fd29e24207d5cc83f9df6c9ffa960aabdab598ea59a61fec57e9947b1d8bc9 sha256sums = 6ca7ff71cb4a7c72eca39769afe8e18ec81cba36d9b570df15fc243867049243 sha256sums = 0ae5bce3da13b7f58e37be6d7115bef323256d776195279592f4371179497f8a sha256sums = 9843662fd9b766801a70bdef22bb996a1abd9d7c3781f1fb58b7034e575350a1 @@ -111,9 +103,7 @@ pkgbase = firedragon sha256sums = 82129e30512477232556e939ee8ed64b999b0e095001d043b121c5e5d334692c sha256sums = 1034a3edda8ffa889fcb4dcf57cb93f8f296f7c37e5cfcf1e5c6071a6f8f4261 sha256sums = 923a9373afc019202c0c07a7cba47042e9ebc78cc2605baecd99602beeaf82ed - source_aarch64 = arm.patch::https://gitlab.com/librewolf-community/browser/linux/-/raw/9e90fb3a9bc38aad9921530ee69ecabf6ac8c7bf/arm.patch source_aarch64 = https://raw.githubusercontent.com/archlinuxarm/PKGBUILDs/master/extra/firefox/build-arm-libopus.patch - sha256sums_aarch64 = 6ca87d2ac7dc48e6f595ca49ac8151936afced30d268a831c6a064b52037f6b7 sha256sums_aarch64 = 2d4d91f7e35d0860225084e37ec320ca6cae669f6c9c8fe7735cdbd542e3a7c9 pkgname = firedragon diff --git a/PKGBUILD b/PKGBUILD index 03b6b6a..e238d97 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -1,4 +1,4 @@ -# Maintainer: dr460nf1r3 +# Maintainer: dr460nf1r3 # Contributor: torvic9 AT mailbox DOT org # Contributor: lsf @@ -17,7 +17,7 @@ depends=(gtk3 libxt mime-types dbus-glib ffmpeg nss nspr ttf-font libpulse graphite dav1d kfiredragonhelper) makedepends=(unzip zip diffutils yasm mesa imake inetutils xorg-server-xvfb rust ccache autoconf2.13 clang llvm jack gtk2 nodejs cbindgen nasm - python-setuptools python-psutil python-zstandard git binutils lld) + python-setuptools python-psutil python-zstandard git binutils lld dump_syms) optdepends=('firejail-git: Sandboxing the browser using the included profiles' 'profile-sync-daemon: Load the browser profile into RAM' 'whoogle: Searching the web using a locally running Whoogle instance' @@ -31,12 +31,11 @@ optdepends=('firejail-git: Sandboxing the browser using the included profiles' 'appmenu-gtk-module-git: Appmenu for GTK only' 'plasma5-applets-window-appmenu: Appmenu for Plasma only') options=(!emptydirs !makeflags !strip) -replaces=('firedragon-stable') conflicts=('firedragon-hg') install=$pkgname.install _arch_svn=https://git.archlinux.org/svntogit/packages.git/plain/trunk -_linux_commit=9e90fb3a9bc38aad9921530ee69ecabf6ac8c7bf -_settings_commit=1b9cc88ccf64993951fe28cf426cf883e37e1b4d +_common_commit=5bce5285fa7046e6987ec3e5a8931ac17ca6c7c0 +_settings_commit=c78c50fbefe2fcf830611e21dcc0fe79180d1e01 _mbrev=2389 _patchrevsuse=aedbca44a8a2958947bed31f28e3083ac0496f4a _pfdate=20210420 @@ -45,45 +44,35 @@ source=(https://archive.mozilla.org/pub/firefox/releases/$pkgver/source/firefox- $pkgname.desktop "git+https://gitlab.com/dr460nf1r3/common.git" "git+https://gitlab.com/dr460nf1r3/settings.git" - "remove_addons.patch::https://gitlab.com/librewolf-community/browser/linux/-/raw/${_linux_commit}/remove_addons.patch" - "context-menu.patch::https://gitlab.com/librewolf-community/browser/linux/-/raw/${_linux_commit}/context-menu.patch" - "unity-menubar.patch::https://gitlab.com/librewolf-community/browser/linux/-/raw/${_linux_commit}/unity-menubar.patch" - "mozilla-vpn-ad.patch::https://gitlab.com/librewolf-community/browser/linux/-/raw/${_linux_commit}/mozilla-vpn-ad.patch" - 0001-Use-remoting-name-for-GDK-application-names.patch firefox-kde-$_patchrevsuse.patch::$_patchurl/firefox/firefox-kde.patch mozilla-kde-$_patchrevsuse.patch::$_patchurl/mozilla-kde.patch mozilla-nongnome-proxies-$_patchrevsuse.patch::$_patchurl/mozilla-nongnome-proxies.patch fix-hidden-buttons-with-csd-menubar.patch + 0001-Use-remoting-name-for-GDK-application-names.patch 0004-bmo-847568-Support-system-harfbuzz.patch 0005-bmo-847568-Support-system-graphite2.patch 0006-bmo-1559213-Support-system-av1.patch 0021-bmo-1516081-Disable-watchdog-during-PGO-builds.patch 0029-LTO-Only-enable-LTO-for-Rust-when-complete-build-use.patch reduce-rust-debuginfo.patch) -source_aarch64=("arm.patch::https://gitlab.com/librewolf-community/browser/linux/-/raw/${_linux_commit}/arm.patch" - https://raw.githubusercontent.com/archlinuxarm/PKGBUILDs/master/extra/firefox/build-arm-libopus.patch) +source_aarch64=(https://raw.githubusercontent.com/archlinuxarm/PKGBUILDs/master/extra/firefox/build-arm-libopus.patch) sha256sums=('83df1eae0e28fe99661fd5d39d705cdab2e108b4a24ce12c2db6183c632804cc' '158152bdb9ef6a83bad62ae03a3d9bc8ae693b34926e53cc8c4de07df20ab22d' 'SKIP' 'SKIP' - 'af9d9341917cf3c5844fc46597ad2d842642c937c9be574bfacfe5c242b1114c' - '3bc57d97ef58c5e80f6099b0e82dab23a4404de04710529d8a8dd0eaa079afcd' - '860e49ab14ce2c9416a479d313a2da799e023db58e93b81ca4cb869c5afb39a7' - 'f3fd29e24207d5cc83f9df6c9ffa960aabdab598ea59a61fec57e9947b1d8bc9' - '6ca7ff71cb4a7c72eca39769afe8e18ec81cba36d9b570df15fc243867049243' '0ae5bce3da13b7f58e37be6d7115bef323256d776195279592f4371179497f8a' '9843662fd9b766801a70bdef22bb996a1abd9d7c3781f1fb58b7034e575350a1' 'fbd95cbcbc32673ef549b43b0d2de3ef0ef4fa303b6336e64993f2c8a73264e4' '482935782429b30f5e1581347a9a798705068c40f20bf4eee9304a254fd81bc8' + '6ca7ff71cb4a7c72eca39769afe8e18ec81cba36d9b570df15fc243867049243' 'e17f631bc9b1873419ff10fef5fad6061e8695b961b6bb90616ec04444834608' '00d3524f5361614fee7eb448a528a0b53833f0a328055e17e07ea38038e5aa70' 'be41698666dbd321884c35b661c3ac457ecc5bf699fe2374ad6ad9273c6489e4' '82129e30512477232556e939ee8ed64b999b0e095001d043b121c5e5d334692c' '1034a3edda8ffa889fcb4dcf57cb93f8f296f7c37e5cfcf1e5c6071a6f8f4261' '923a9373afc019202c0c07a7cba47042e9ebc78cc2605baecd99602beeaf82ed') -sha256sums_aarch64=('6ca87d2ac7dc48e6f595ca49ac8151936afced30d268a831c6a064b52037f6b7' - '2d4d91f7e35d0860225084e37ec320ca6cae669f6c9c8fe7735cdbd542e3a7c9') +sha256sums_aarch64=('2d4d91f7e35d0860225084e37ec320ca6cae669f6c9c8fe7735cdbd542e3a7c9') prepare() { if [[ ! -d mozbuild ]];then @@ -91,6 +80,8 @@ prepare() { fi cd firefox-$pkgver + local _patches_dir="${srcdir}/common/patches" + sed -i 's/\"BrowserApplication\"\, \"firefox\"/\"BrowserApplication\"\, \"firedragon\"/g' $srcdir/firefox-kde-$_patchrevsuse.patch sed -i 's/kmozillahelper/kfiredragonhelper/g' $srcdir/mozilla-kde-$_patchrevsuse.patch @@ -168,26 +159,26 @@ ac_add_options --with-system-webp ac_add_options --with-system-zlib # Features -ac_add_options --enable-pulseaudio -ac_add_options --enable-alsa -ac_add_options --enable-jack -ac_add_options --disable-warnings-as-errors -ac_add_options --disable-crashreporter -ac_add_options --disable-tests -ac_add_options --disable-debug -ac_add_options --disable-updater -ac_add_options --enable-strip -ac_add_options --disable-gpsd -ac_add_options --disable-synth-speechd -ac_add_options --disable-debug-symbols -ac_add_options --disable-debug-js-modules ac_add_options --disable-cdp -ac_add_options --disable-trace-logging -ac_add_options --disable-rust-tests +ac_add_options --disable-crashreporter +ac_add_options --disable-debug +ac_add_options --disable-debug-js-modules +ac_add_options --disable-debug-symbols +ac_add_options --disable-gpsd ac_add_options --disable-ipdl-tests ac_add_options --disable-necko-wifi +ac_add_options --disable-rust-tests +ac_add_options --disable-synth-speechd +ac_add_options --disable-tests +ac_add_options --disable-trace-logging +ac_add_options --disable-updater +ac_add_options --disable-warnings-as-errors ac_add_options --disable-webspeech ac_add_options --disable-webspeechtestbackend +ac_add_options --enable-alsa +ac_add_options --enable-jack +ac_add_options --enable-pulseaudio +ac_add_options --enable-strip # Disables crash reporting, telemetry and other data gathering tools mk_add_options MOZ_CRASHREPORTER=0 @@ -217,8 +208,8 @@ END # we should have more than enough RAM on the CI spot instances. # ...or maybe not? export LDFLAGS+=" -Wl,--no-keep-memory" - patch -p1 -i ../arm.patch - patch -p1 -i ../build-arm-libopus.patch + patch -Np1 -i ${_patches_dir}/arm.patch + patch -Np1 -i ../${pkgver}-${pkgrel}_build-arm-libopus.patch else @@ -229,39 +220,34 @@ END fi # Remove some pre-installed addons that might be questionable - patch -p1 -i ../remove_addons.patch + patch -Np1 -i ${_patches_dir}/remove_addons.patch + + # Disable (some) megabar functionality + # Adapted from https://github.com/WesleyBranton/userChrome.css-Customizations + patch -Np1 -i ${_patches_dir}/megabar.patch # Debian patch to enable global menubar - patch -p1 -i ../unity-menubar.patch + patch -Np1 -i ${_patches_dir}/unity-menubar.patch # Disabling Pocket - sed -i 's/"pocket"/# "pocket"/g' browser/components/moz.build - - patch -p1 -i ../context-menu.patch + patch -Np1 -i ${_patches_dir}/sed-patches/disable-pocket.patch # Remove Mozilla VPN ads - patch -p1 -i ../mozilla-vpn-ad.patch - - # This one only to remove an annoying error message: - sed -i 's#SaveToPocket.init();#// SaveToPocket.init();#g' browser/components/BrowserGlue.jsm + patch -Np1 -i ${_patches_dir}/mozilla-vpn-ad.patch # Remove Internal Plugin Certificates - _cert_sed='s#if (aCert.organizationalUnit == "Mozilla [[:alpha:]]\+") {\n' - _cert_sed+='[[:blank:]]\+return AddonManager\.SIGNEDSTATE_[[:upper:]]\+;\n' - _cert_sed+='[[:blank:]]\+}#' - _cert_sed+='// NOTE: removed#g' - sed -z "$_cert_sed" -i toolkit/mozapps/extensions/internal/XPIInstall.jsm + patch -Np1 -i ${_patches_dir}/sed-patches/remove-internal-plugin-certs.patch # Allow SearchEngines option in non-ESR builds - sed -i 's#"enterprise_only": true,#"enterprise_only": false,#g' browser/components/enterprisepolicies/schemas/policies-schema.json - - _settings_services_sed='s#firefox.settings.services.mozilla.com#f.s.s.m.c.qjz9zk#g' + patch -Np1 -i ${_patches_dir}/sed-patches/allow-searchengines-non-esr.patch # Stop some undesired requests (https://gitlab.com/librewolf-community/browser/common/-/issues/10) - sed "$_settings_services_sed" -i browser/components/newtab/data/content/activity-stream.bundle.js - sed "$_settings_services_sed" -i modules/libpref/init/all.js - sed "$_settings_services_sed" -i services/settings/Utils.jsm - sed "$_settings_services_sed" -i toolkit/components/search/SearchUtils.jsm + patch -Np1 -i ${_patches_dir}/sed-patches/stop-undesired-requests.patch + + # Assorted patches + patch -Np1 -i ${_patches_dir}/context-menu.patch + patch -Np1 -i ${_patches_dir}/browser-confvars.patch + patch -Np1 -i ${_patches_dir}/urlbarprovider-interventions.patch rm -f ${srcdir}/common/source_files/mozconfig cp -r ${srcdir}/common/source_files/* ./ @@ -310,21 +296,19 @@ fi xvfb-run -s "-screen 0 1920x1080x24 -nolisten local" \ ./mach python build/pgo/profileserver.py - if [[ ! -s merged.profdata ]]; then - echo "No profile data produced." - return 1 - fi + stat -c "Profile data found (%s bytes)" merged.profdata + test -s merged.profdata - if [[ ! -s jarlog ]]; then - echo "No jar log produced." - return 1 - fi + stat -c "Jar log found (%s bytes)" jarlog + test -s jarlog echo "Removing instrumented browser..." ./mach clobber echo "Building optimized browser..." + echo "Building optimized browser..." + if [[ $CARCH == 'aarch64' ]]; then cat >.mozconfig ../mozconfig - < -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 -@@ -84,16 +84,17 @@ - #include "plbase64.h" - #include "PLDHashTable.h" - #include "plstr.h" - #include "prlink.h" - #include "xpcpublic.h" - #ifdef MOZ_BACKGROUNDTASKS - # include "mozilla/BackgroundTasks.h" - #endif -+#include "nsKDEUtils.h" - - #ifdef DEBUG - # include - #endif - - #ifdef MOZ_MEMORY - # include "mozmemory.h" - #endif -@@ -4573,25 +4574,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. -@@ -4656,17 +4669,17 @@ nsresult Preferences::InitInitialObjects - } - - nsCOMPtr 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(); - } - - if (aIsStartup) { -diff --git a/modules/libpref/moz.build b/modules/libpref/moz.build ---- a/modules/libpref/moz.build -+++ b/modules/libpref/moz.build -@@ -117,16 +117,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) - - 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, - "tablet": Flag, - "process": StringFlag, - "backgroundtask": 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 -@@ -39,16 +39,17 @@ class ManifestEntry(object): - "os", - "osversion", - "abi", - "xpcnativewrappers", - "tablet", - "process", - "contentaccessible", - "backgroundtask", -+ "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 -@@ -45,10 +45,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 -@@ -1231,36 +1231,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 -@@ -13,16 +13,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 - -@@ -36,16 +37,18 @@ class nsUnixSystemProxySettings final : - nsCOMPtr mProxySettings; - nsInterfaceHashtable - 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 command; -+ command.AppendElement( "GETPROXY"_ns ); -+ command.AppendElement( url ); -+ nsTArray 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(); - 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 -@@ -92,17 +92,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 -+ -+#include -+#include -+#include -+#include -+#include -+#include -+// 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 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 ); -+#endif -+ return kde; -+ } -+ -+nsKDEUtils::nsKDEUtils() -+ : commandFile( NULL ) -+ , replyFile( NULL ) -+ { -+ } -+ -+nsKDEUtils::~nsKDEUtils() -+ { -+// closeHelper(); not actually useful, exiting will close the fd too -+ } -+ -+nsKDEUtils* nsKDEUtils::self() -+ { -+ static nsKDEUtils s; -+ return &s; -+ } -+ -+static bool helperRunning = false; -+static bool helperFailed = false; -+ -+bool nsKDEUtils::kdeSession() -+ { -+ static bool session = getKdeSession(); -+ return session; -+ } -+ -+bool nsKDEUtils::kdeSupport() -+ { -+ static bool support = kdeSession() && getKdeSupport(); -+ return support && helperRunning; -+ } -+ -+struct nsKDECommandData -+ { -+ FILE* file; -+ nsTArray* output; -+ GMainLoop* loop; -+ bool success; -+ }; -+ -+static gboolean kdeReadFunc( GIOChannel*, GIOCondition, gpointer data ) -+ { -+ nsKDECommandData* p = static_cast< nsKDECommandData* >( data ); -+ char buf[ 8192 ]; // TODO big enough -+ bool command_done = false; -+ bool command_failed = false; -+ while( !command_done && !command_failed && fgets( buf, 8192, p->file ) != NULL ) -+ { // TODO what if the kernel splits a line into two chunks? -+//#ifdef DEBUG_KDE -+// fprintf( stderr, "READ: %s %d\n", buf, feof( p->file )); -+//#endif -+ if( char* eol = strchr( buf, '\n' )) -+ *eol = '\0'; -+ command_done = ( strcmp( buf, "\\1" ) == 0 ); -+ command_failed = ( strcmp( buf, "\\0" ) == 0 ); -+ nsAutoCString line( buf ); -+ line.ReplaceSubstring( "\\n", "\n" ); -+ line.ReplaceSubstring( "\\" "\\", "\\" ); // \\ -> \ , i.e. unescape -+ if( p->output && !( command_done || command_failed )) -+ p->output->AppendElement( nsCString( buf )); // TODO utf8? -+ } -+ bool quit = false; -+ if( feof( p->file ) || command_failed ) -+ { -+ quit = true; -+ p->success = false; -+ } -+ if( command_done ) -+ { // reading one reply finished -+ quit = true; -+ p->success = true; -+ } -+ if( quit ) -+ { -+ if( p->loop ) -+ g_main_loop_quit( p->loop ); -+ return FALSE; -+ } -+ return TRUE; -+ } -+ -+bool nsKDEUtils::command( const nsTArray& command, nsTArray* output ) -+ { -+ return self()->internalCommand( command, NULL, false, output ); -+ } -+ -+bool nsKDEUtils::command( nsIArray* command, nsIArray** output) -+ { -+ nsTArray in; -+ PRUint32 length; -+ command->GetLength( &length ); -+ for ( PRUint32 i = 0; i < length; i++ ) -+ { -+ nsCOMPtr str = do_QueryElementAt( command, i ); -+ if( str ) -+ { -+ nsAutoCString s; -+ str->GetData( s ); -+ in.AppendElement( s ); -+ } -+ } -+ -+ nsTArray out; -+ bool ret = self()->internalCommand( in, NULL, false, &out ); -+ -+ if ( !output ) return ret; -+ -+ nsCOMPtr result = do_CreateInstance( NS_ARRAY_CONTRACTID ); -+ if ( !result ) return false; -+ -+ for ( PRUint32 i = 0; i < out.Length(); i++ ) -+ { -+ nsCOMPtr rstr = do_CreateInstance( NS_SUPPORTS_CSTRING_CONTRACTID ); -+ if ( !rstr ) return false; -+ -+ rstr->SetData( out[i] ); -+ result->AppendElement( rstr ); -+ } -+ -+ NS_ADDREF( *output = result); -+ return ret; -+ } -+ -+ -+bool nsKDEUtils::commandBlockUi( const nsTArray& command, GtkWindow* parent, nsTArray* output ) -+ { -+ return self()->internalCommand( command, parent, true, output ); -+ } -+ -+bool nsKDEUtils::internalCommand( const nsTArray& command, GtkWindow* parent, bool blockUi, -+ nsTArray* output ) -+ { -+ if( !startHelper()) -+ return false; -+ feedCommand( command ); -+ // do not store the data in 'this' but in extra structure, just in case there -+ // is reentrancy (can there be? the event loop is re-entered) -+ nsKDECommandData data; -+ data.file = replyFile; -+ data.output = output; -+ data.success = false; -+ if( blockUi ) -+ { -+ data.loop = g_main_loop_new( NULL, FALSE ); -+ GtkWidget* window = gtk_window_new( GTK_WINDOW_TOPLEVEL ); -+ if( parent && gtk_window_get_group(parent) ) -+ gtk_window_group_add_window( gtk_window_get_group(parent), GTK_WINDOW( window )); -+ gtk_widget_realize( window ); -+ gtk_widget_set_sensitive( window, TRUE ); -+ gtk_grab_add( window ); -+ GIOChannel* channel = g_io_channel_unix_new( fileno( data.file )); -+ g_io_add_watch( channel, static_cast< GIOCondition >( G_IO_IN | G_IO_ERR | G_IO_HUP ), kdeReadFunc, &data ); -+ g_io_channel_unref( channel ); -+ g_main_loop_run( data.loop ); -+ g_main_loop_unref( data.loop ); -+ gtk_grab_remove( window ); -+ gtk_widget_destroy( window ); -+ } -+ else -+ { -+ data.loop = NULL; -+ while( kdeReadFunc( NULL, static_cast< GIOCondition >( 0 ), &data )) -+ ; -+ } -+ return data.success; -+ } -+ -+bool nsKDEUtils::startHelper() -+ { -+ if( helperRunning ) -+ return true; -+ if( helperFailed ) -+ return false; -+ helperFailed = true; -+ int fdcommand[ 2 ]; -+ int fdreply[ 2 ]; -+ if( pipe( fdcommand ) < 0 ) -+ return false; -+ if( pipe( fdreply ) < 0 ) -+ { -+ close( fdcommand[ 0 ] ); -+ close( fdcommand[ 1 ] ); -+ return false; -+ } -+ char* args[ 2 ] = { const_cast< char* >( KMOZILLAHELPER ), NULL }; -+ switch( fork()) -+ { -+ case -1: -+ { -+ close( fdcommand[ 0 ] ); -+ close( fdcommand[ 1 ] ); -+ close( fdreply[ 0 ] ); -+ close( fdreply[ 1 ] ); -+ return false; -+ } -+ case 0: // child -+ { -+ if( dup2( fdcommand[ 0 ], STDIN_FILENO ) < 0 ) -+ _exit( 1 ); -+ if( dup2( fdreply[ 1 ], STDOUT_FILENO ) < 0 ) -+ _exit( 1 ); -+ int maxfd = 1024; // close all other fds -+ struct rlimit rl; -+ if( getrlimit( RLIMIT_NOFILE, &rl ) == 0 ) -+ maxfd = rl.rlim_max; -+ for( int i = 3; -+ i < maxfd; -+ ++i ) -+ close( i ); -+#ifdef DEBUG_KDE -+ execvp( KMOZILLAHELPER, args ); -+#else -+ execv( KMOZILLAHELPER, args ); -+#endif -+ _exit( 1 ); // failed -+ } -+ default: // parent -+ { -+ commandFile = fdopen( fdcommand[ 1 ], "w" ); -+ replyFile = fdopen( fdreply[ 0 ], "r" ); -+ close( fdcommand[ 0 ] ); -+ close( fdreply[ 1 ] ); -+ if( commandFile == NULL || replyFile == NULL ) -+ { -+ closeHelper(); -+ return false; -+ } -+ // ok, helper ready, getKdeRunning() will check if it works -+ } -+ } -+ helperFailed = false; -+ helperRunning = true; -+ return true; -+ } -+ -+void nsKDEUtils::closeHelper() -+ { -+ if( commandFile != NULL ) -+ fclose( commandFile ); // this will also make the helper quit -+ if( replyFile != NULL ) -+ fclose( replyFile ); -+ helperRunning = false; -+ } -+ -+void nsKDEUtils::feedCommand( const nsTArray& command ) -+ { -+ for( int i = 0; -+ i < command.Length(); -+ ++i ) -+ { -+ nsCString line = command[ i ]; -+ line.ReplaceSubstring( "\\", "\\" "\\" ); // \ -> \\ , i.e. escape -+ line.ReplaceSubstring( "\n", "\\n" ); -+#ifdef DEBUG_KDE -+ fprintf( stderr, "COMM: %s\n", line.get()); -+#endif -+ fputs( line.get(), commandFile ); -+ fputs( "\n", commandFile ); -+ } -+ fputs( "\\E\n", commandFile ); // done as \E, so it cannot happen in normal data -+ fflush( commandFile ); -+ } -diff --git a/toolkit/xre/nsKDEUtils.h b/toolkit/xre/nsKDEUtils.h -new file mode 100644 ---- /dev/null -+++ b/toolkit/xre/nsKDEUtils.h -@@ -0,0 +1,48 @@ -+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -+/* This Source Code Form is subject to the terms of the Mozilla Public -+ * License, v. 2.0. If a copy of the MPL was not distributed with this -+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -+ -+#ifndef nsKDEUtils_h__ -+#define nsKDEUtils_h__ -+ -+#include "nsString.h" -+#include "nsTArray.h" -+#include -+ -+typedef struct _GtkWindow GtkWindow; -+ -+class nsIArray; -+ -+class NS_EXPORT nsKDEUtils -+ { -+ public: -+ /* Returns true if running inside a KDE session (regardless of whether there is KDE -+ support available for Firefox). This should be used e.g. when determining -+ dialog button order but not for code that requires the KDE support. */ -+ static bool kdeSession(); -+ /* Returns true if running inside a KDE session and KDE support is available -+ for Firefox. This should be used everywhere where the external helper is needed. */ -+ static bool kdeSupport(); -+ /* Executes the given helper command, returns true if helper returned success. */ -+ static bool command( const nsTArray& command, nsTArray* output = NULL ); -+ static bool command( nsIArray* command, nsIArray** output = NULL ); -+ /* Like command(), but additionally blocks the parent widget like if there was -+ a modal dialog shown and enters the event loop (i.e. there are still paint updates, -+ this is for commands that take long). */ -+ static bool commandBlockUi( const nsTArray& command, GtkWindow* parent, nsTArray* output = NULL ); -+ -+ private: -+ nsKDEUtils(); -+ ~nsKDEUtils(); -+ static nsKDEUtils* self(); -+ bool startHelper(); -+ void closeHelper(); -+ void feedCommand( const nsTArray& command ); -+ bool internalCommand( const nsTArray& command, GtkWindow* parent, bool isParent, -+ nsTArray* output ); -+ FILE* commandFile; -+ FILE* replyFile; -+ }; -+ -+#endif // nsKDEUtils -diff --git a/uriloader/exthandler/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 { -@@ -299,17 +299,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 -@@ -328,17 +328,17 @@ mozilla::ipc::IPCResult HandlerServicePa - nsCOMPtr 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 -@@ -86,17 +86,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/nsMIMEInfoAndroid.cpp", - ] - elif CONFIG["MOZ_WIDGET_TOOLKIT"] == "windows": - UNIFIED_SOURCES += [ -@@ -136,16 +138,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 -+nsCommonRegistry::GetFromExtension(const nsACString& aFileExt) -+{ -+ if( nsKDEUtils::kdeSupport()) -+ return nsKDERegistry::GetFromExtension( aFileExt ); -+ return nsGNOMERegistry::GetFromExtension( aFileExt ); -+} -+ -+/* static */ already_AddRefed -+nsCommonRegistry::GetFromType(const nsACString& aMIMEType) -+{ -+ if( nsKDEUtils::kdeSupport()) -+ return nsKDERegistry::GetFromType( aMIMEType ); -+ return nsGNOMERegistry::GetFromType( aMIMEType ); -+} -diff --git a/uriloader/exthandler/unix/nsCommonRegistry.h b/uriloader/exthandler/unix/nsCommonRegistry.h -new file mode 100644 ---- /dev/null -+++ b/uriloader/exthandler/unix/nsCommonRegistry.h -@@ -0,0 +1,28 @@ -+/* This Source Code Form is subject to the terms of the Mozilla Public -+ * License, v. 2.0. If a copy of the MPL was not distributed with this -+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -+ -+#ifndef nsCommonRegistry_h__ -+#define nsCommonRegistry_h__ -+ -+#include "nsIURI.h" -+#include "nsCOMPtr.h" -+ -+class nsMIMEInfoBase; -+ -+class nsCommonRegistry -+{ -+ public: -+ static bool HandlerExists(const char *aProtocolScheme); -+ -+ static nsresult LoadURL(nsIURI *aURL); -+ -+ static void GetAppDescForScheme(const nsACString& aScheme, -+ nsAString& aDesc); -+ -+ static already_AddRefed GetFromExtension(const nsACString& aFileExt); -+ -+ static already_AddRefed GetFromType(const nsACString& aMIMEType); -+}; -+ -+#endif -diff --git a/uriloader/exthandler/unix/nsKDERegistry.cpp b/uriloader/exthandler/unix/nsKDERegistry.cpp -new file mode 100644 ---- /dev/null -+++ b/uriloader/exthandler/unix/nsKDERegistry.cpp -@@ -0,0 +1,86 @@ -+/* -*- 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 "nsKDEUtils.h" -+ -+/* 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; -+ -+ 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 */ 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::GetFromHelper(const nsTArray& command) -+{ -+ nsTArray output; -+ if( nsKDEUtils::command( command, &output ) && output.Length() == 3 ) -+ { -+ nsCString mimetype = output[ 0 ]; -+ RefPtr mimeInfo = new nsMIMEInfoUnix( mimetype ); -+ NS_ENSURE_TRUE(mimeInfo, nullptr); -+ nsCString description = output[ 1 ]; -+ mimeInfo->SetDescription(NS_ConvertUTF8toUTF16(description)); -+ nsCString handlerAppName = output[ 2 ]; -+ mimeInfo->SetDefaultDescription(NS_ConvertUTF8toUTF16(handlerAppName)); -+ mimeInfo->SetPreferredAction(nsIMIMEInfo::useSystemDefault); -+ return mimeInfo.forget(); -+ } -+ return nullptr; -+} -diff --git a/uriloader/exthandler/unix/nsKDERegistry.h b/uriloader/exthandler/unix/nsKDERegistry.h -new file mode 100644 ---- /dev/null -+++ b/uriloader/exthandler/unix/nsKDERegistry.h -@@ -0,0 +1,34 @@ -+/* This Source Code Form is subject to the terms of the Mozilla Public -+ * License, v. 2.0. If a copy of the MPL was not distributed with this -+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -+ -+#ifndef nsKDERegistry_h__ -+#define nsKDERegistry_h__ -+ -+#include "nsIURI.h" -+#include "nsCOMPtr.h" -+#include "nsTArray.h" -+ -+class nsMIMEInfoBase; -+//class nsAutoCString; -+//class nsCString; -+ -+class nsKDERegistry -+{ -+ public: -+ static bool HandlerExists(const char *aProtocolScheme); -+ -+ static nsresult LoadURL(nsIURI *aURL); -+ -+ static void GetAppDescForScheme(const nsACString& aScheme, -+ nsAString& aDesc); -+ -+ static already_AddRefed GetFromExtension(const nsACString& aFileExt); -+ -+ static already_AddRefed GetFromType(const nsACString& aMIMEType); -+ private: -+ static already_AddRefed GetFromHelper(const nsTArray& command); -+ -+}; -+ -+#endif //nsKDERegistry_h__ -diff --git a/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp b/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp ---- a/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp -+++ b/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp -@@ -1,46 +1,49 @@ - /* -*- Mode: C++; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - - #include "nsMIMEInfoUnix.h" --#include "nsGNOMERegistry.h" -+#include "nsCommonRegistry.h" - #include "nsIGIOService.h" - #include "nsNetCID.h" - #include "nsIIOService.h" - #ifdef MOZ_ENABLE_DBUS - # include "nsDBusHandlerApp.h" - #endif -+#if defined(XP_UNIX) && !defined(XP_MACOSX) -+#include "nsKDEUtils.h" -+#endif - - nsresult nsMIMEInfoUnix::LoadUriInternal(nsIURI* aURI) { -- return nsGNOMERegistry::LoadURL(aURI); -+ return nsCommonRegistry::LoadURL(aURI); - } - - NS_IMETHODIMP - nsMIMEInfoUnix::GetHasDefaultHandler(bool* _retval) { - // if mDefaultApplication is set, it means the application has been set from - // either /etc/mailcap or ${HOME}/.mailcap, in which case we don't want to - // give the GNOME answer. - if (mDefaultApplication) return nsMIMEInfoImpl::GetHasDefaultHandler(_retval); - - *_retval = false; - - if (mClass == eProtocolInfo) { -- *_retval = nsGNOMERegistry::HandlerExists(mSchemeOrType.get()); -+ *_retval = nsCommonRegistry::HandlerExists(mSchemeOrType.get()); - } else { - RefPtr mimeInfo = -- nsGNOMERegistry::GetFromType(mSchemeOrType); -+ nsCommonRegistry::GetFromType(mSchemeOrType); - if (!mimeInfo) { - nsAutoCString ext; - nsresult rv = GetPrimaryExtension(ext); - if (NS_SUCCEEDED(rv)) { -- mimeInfo = nsGNOMERegistry::GetFromExtension(ext); -+ mimeInfo = nsCommonRegistry::GetFromExtension(ext); - } - } - if (mimeInfo) *_retval = true; - } - - if (*_retval) return NS_OK; - - return NS_OK; -@@ -50,16 +53,33 @@ nsresult nsMIMEInfoUnix::LaunchDefaultWi - // if mDefaultApplication is set, it means the application has been set from - // either /etc/mailcap or ${HOME}/.mailcap, in which case we don't want to - // give the GNOME answer. - if (mDefaultApplication) return nsMIMEInfoImpl::LaunchDefaultWithFile(aFile); - - nsAutoCString nativePath; - aFile->GetNativePath(nativePath); - -+ if( nsKDEUtils::kdeSupport()) { -+ bool 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; -+ } -+ if (!mDefaultApplication) -+ return NS_ERROR_FILE_NOT_FOUND; -+ -+ return LaunchWithIProcess(mDefaultApplication, nativePath); -+ } -+ - nsCOMPtr giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID); - if (!giovfs) { - return NS_ERROR_FAILURE; - } - - // nsGIOMimeApp->Launch wants a URI string instead of local file - nsresult rv; - nsCOMPtr ioservice = -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 - - #include "nsOSHelperAppService.h" - #include "nsMIMEInfoUnix.h" - #ifdef MOZ_WIDGET_GTK --# include "nsGNOMERegistry.h" -+# include "nsCommonRegistry.h" - #endif - #include "nsISupports.h" - #include "nsString.h" - #include "nsReadableUtils.h" - #include "nsUnicharUtils.h" - #include "nsIFileStreams.h" - #include "nsILineInputStream.h" - #include "nsIFile.h" -@@ -1020,17 +1020,17 @@ nsresult nsOSHelperAppService::GetHandle - - nsresult nsOSHelperAppService::OSProtocolHandlerExists( - const char* aProtocolScheme, bool* aHandlerExists) { - nsresult rv = NS_OK; - - if (!XRE_IsContentProcess()) { - #ifdef MOZ_WIDGET_GTK - // Check the GNOME registry for a protocol handler -- *aHandlerExists = nsGNOMERegistry::HandlerExists(aProtocolScheme); -+ *aHandlerExists = nsCommonRegistry::HandlerExists(aProtocolScheme); - #else - *aHandlerExists = false; - #endif - } else { - *aHandlerExists = false; - nsCOMPtr handlerSvc = - do_GetService(NS_HANDLERSERVICE_CONTRACTID, &rv); - if (NS_SUCCEEDED(rv) && handlerSvc) { -@@ -1040,17 +1040,17 @@ nsresult nsOSHelperAppService::OSProtoco - } - - return rv; - } - - NS_IMETHODIMP nsOSHelperAppService::GetApplicationDescription( - const nsACString& aScheme, nsAString& _retval) { - #ifdef MOZ_WIDGET_GTK -- nsGNOMERegistry::GetAppDescForScheme(aScheme, _retval); -+ nsCommonRegistry::GetAppDescForScheme(aScheme, _retval); - return _retval.IsEmpty() ? NS_ERROR_NOT_AVAILABLE : NS_OK; - #else - return NS_ERROR_NOT_AVAILABLE; - #endif - } - - NS_IMETHODIMP nsOSHelperAppService::IsCurrentAppOSDefaultForProtocol( - const nsACString& aScheme, bool* _retval) { -@@ -1137,17 +1137,17 @@ already_AddRefed nsOSHel - nsresult rv = - LookUpTypeAndDescription(NS_ConvertUTF8toUTF16(aFileExt), majorType, - minorType, mime_types_description, true); - - if (NS_FAILED(rv) || majorType.IsEmpty()) { - #ifdef MOZ_WIDGET_GTK - LOG(("Looking in GNOME registry\n")); - RefPtr gnomeInfo = -- nsGNOMERegistry::GetFromExtension(aFileExt); -+ nsCommonRegistry::GetFromExtension(aFileExt); - if (gnomeInfo) { - LOG(("Got MIMEInfo from GNOME registry\n")); - return gnomeInfo.forget(); - } - #endif - - rv = LookUpTypeAndDescription(NS_ConvertUTF8toUTF16(aFileExt), majorType, - minorType, mime_types_description, false); -@@ -1248,17 +1248,17 @@ already_AddRefed nsOSHel - - // Now look up our extensions - nsAutoString extensions, mime_types_description; - LookUpExtensionsAndDescription(majorType, minorType, extensions, - mime_types_description); - - #ifdef MOZ_WIDGET_GTK - if (handler.IsEmpty()) { -- RefPtr gnomeInfo = nsGNOMERegistry::GetFromType(aMIMEType); -+ RefPtr gnomeInfo = nsCommonRegistry::GetFromType(aMIMEType); - if (gnomeInfo) { - LOG( - ("Got MIMEInfo from GNOME registry without extensions; setting them " - "to %s\n", - NS_LossyConvertUTF16toASCII(extensions).get())); - - NS_ASSERTION(!gnomeInfo->HasExtensions(), "How'd that happen?"); - gnomeInfo->SetFileExtensions(NS_ConvertUTF16toUTF8(extensions)); -diff --git a/widget/gtk/moz.build b/widget/gtk/moz.build ---- a/widget/gtk/moz.build -+++ b/widget/gtk/moz.build -@@ -137,16 +137,17 @@ FINAL_LIBRARY = "xul" - - LOCAL_INCLUDES += [ - "/layout/base", - "/layout/forms", - "/layout/generic", - "/layout/xul", - "/other-licenses/atk-1.0", - "/third_party/cups/include", -+ "/toolkit/xre", - "/widget", - "/widget/headless", - ] - - if CONFIG["MOZ_X11"]: - LOCAL_INCLUDES += [ - "/widget/x11", - ] -diff --git a/widget/gtk/nsFilePicker.cpp b/widget/gtk/nsFilePicker.cpp ---- a/widget/gtk/nsFilePicker.cpp -+++ b/widget/gtk/nsFilePicker.cpp -@@ -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/. */ - - #include - #include -+#include - #include - #include - #include - - #include "mozilla/Types.h" - #include "nsGtkUtils.h" - #include "nsIFileURL.h" - #include "nsIGIOService.h" -@@ -22,16 +23,18 @@ - #include "nsMemory.h" - #include "nsEnumeratorUtils.h" - #include "nsNetUtil.h" - #include "nsReadableUtils.h" - #include "MozContainer.h" - #include "gfxPlatformGtk.h" - - #include "nsFilePicker.h" -+#include "nsKDEUtils.h" -+#include "nsURLHelper.h" - - using namespace mozilla; - - #define MAX_PREVIEW_SIZE 180 - // bug 1184009 - #define MAX_PREVIEW_SOURCE_SIZE 4096 - - nsIFile* nsFilePicker::mPrevDisplayDirectory = nullptr; -@@ -231,17 +234,19 @@ nsFilePicker::AppendFilters(int32_t aFil - mAllowURLs = !!(aFilterMask & filterAllowURLs); - return nsBaseFilePicker::AppendFilters(aFilterMask); - } - - NS_IMETHODIMP - nsFilePicker::AppendFilter(const nsAString& aTitle, const nsAString& aFilter) { - if (aFilter.EqualsLiteral("..apps")) { - // No platform specific thing we can do here, really.... -- return NS_OK; -+ // Unless it's KDE. -+ if( mMode != modeOpen || !nsKDEUtils::kdeSupport()) -+ return NS_OK; - } - - nsAutoCString filter, name; - CopyUTF16toUTF8(aFilter, filter); - CopyUTF16toUTF8(aTitle, name); - - mFilters.AppendElement(filter); - mFilterNames.AppendElement(name); -@@ -341,16 +346,39 @@ nsresult nsFilePicker::Show(int16_t* aRe - return NS_OK; - } - - NS_IMETHODIMP - nsFilePicker::Open(nsIFilePickerShownCallback* aCallback) { - // Can't show two dialogs concurrently with the same filepicker - if (mRunning) return NS_ERROR_NOT_AVAILABLE; - -+ // KDE file picker is not handled via callback -+ if( nsKDEUtils::kdeSupport()) { -+ mCallback = aCallback; -+ mRunning = true; -+ NS_ADDREF_THIS(); -+ g_idle_add([](gpointer data) -> gboolean { -+ nsFilePicker* queuedPicker = (nsFilePicker*) data; -+ int16_t result; -+ queuedPicker->kdeFileDialog(&result); -+ if (queuedPicker->mCallback) { -+ queuedPicker->mCallback->Done(result); -+ queuedPicker->mCallback = nullptr; -+ } else { -+ queuedPicker->mResult = result; -+ } -+ queuedPicker->mRunning = false; -+ NS_RELEASE(queuedPicker); -+ return G_SOURCE_REMOVE; -+ }, this); -+ -+ return NS_OK; -+ } -+ - NS_ConvertUTF16toUTF8 title(mTitle); - - GtkWindow* parent_widget = - GTK_WINDOW(mParentWidget->GetNativeData(NS_NATIVE_SHELLWIDGET)); - - GtkFileChooserAction action = GetGtkFileChooserAction(mMode); - - const gchar* accept_button; -@@ -570,16 +598,244 @@ void nsFilePicker::Done(void* file_choos - mCallback->Done(result); - mCallback = nullptr; - } else { - mResult = result; - } - NS_RELEASE_THIS(); - } - -+nsCString nsFilePicker::kdeMakeFilter( int index ) -+ { -+ nsCString buf = mFilters[ index ]; -+ for( PRUint32 i = 0; -+ i < buf.Length(); -+ ++i ) -+ if( buf[ i ] == ';' ) // KDE separates just using spaces -+ buf.SetCharAt( ' ', i ); -+ if (!mFilterNames[index].IsEmpty()) -+ { -+ buf += "|"; -+ buf += mFilterNames[index].get(); -+ } -+ return buf; -+ } -+ -+static PRInt32 windowToXid( nsIWidget* widget ) -+ { -+ GtkWindow *parent_widget = GTK_WINDOW(widget->GetNativeData(NS_NATIVE_SHELLWIDGET)); -+ GdkWindow* gdk_window = gtk_widget_get_window( gtk_widget_get_toplevel( GTK_WIDGET( parent_widget ))); -+ return GDK_WINDOW_XID( gdk_window ); -+ } -+ -+NS_IMETHODIMP nsFilePicker::kdeFileDialog(PRInt16 *aReturn) -+ { -+ NS_ENSURE_ARG_POINTER(aReturn); -+ -+ if( mMode == modeOpen && mFilters.Length() == 1 && mFilters[ 0 ].EqualsLiteral( "..apps" )) -+ return kdeAppsDialog( aReturn ); -+ -+ 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) { -+ mDisplayDirectory->GetNativePath(directory); -+ } else if (mPrevDisplayDirectory) { -+ mPrevDisplayDirectory->GetNativePath(directory); -+ } -+ -+ nsAutoCString startdir; -+ if (!directory.IsEmpty()) { -+ startdir = directory; -+ } -+ if (mMode == nsIFilePicker::modeSave) { -+ if( !startdir.IsEmpty()) -+ { -+ startdir += "/"; -+ startdir += ToNewUTF8String(mDefault); -+ } -+ else -+ startdir = ToNewUTF8String(mDefault); -+ } -+ -+ nsAutoCString filters; -+ PRInt32 count = mFilters.Length(); -+ if( count == 0 ) //just in case -+ filters = "*"; -+ else -+ { -+ filters = kdeMakeFilter( 0 ); -+ for (PRInt32 i = 1; i < count; ++i) -+ { -+ filters += "\n"; -+ filters += kdeMakeFilter( i ); -+ } -+ } -+ -+ nsTArray 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); -+ } -+ } -+ if (mMode == nsIFilePicker::modeSave) -+ { -+ nsCOMPtr file; -+ GetFile(getter_AddRefs(file)); -+ if (file) -+ { -+ bool exists = false; -+ file->Exists(&exists); -+ if (exists) // TODO do overwrite check in the helper app -+ *aReturn = nsIFilePicker::returnReplace; -+ } -+ } -+ } -+ else -+ { -+ *aReturn = nsIFilePicker::returnCancel; -+ } -+ return NS_OK; -+ } -+ -+ -+NS_IMETHODIMP nsFilePicker::kdeAppsDialog(PRInt16 *aReturn) -+ { -+ NS_ENSURE_ARG_POINTER(aReturn); -+ -+ nsCString title; -+ title.Adopt(ToNewUTF8String(mTitle)); -+ -+ 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 -@@ -67,16 +67,22 @@ class nsFilePicker : public nsBaseFilePi - nsString mDefaultExtension; - - nsTArray mFilters; - nsTArray mFilterNames; - - private: - static nsIFile* mPrevDisplayDirectory; - -+ bool kdeRunning(); -+ bool getKdeRunning(); -+ NS_IMETHODIMP kdeFileDialog(PRInt16 *aReturn); -+ NS_IMETHODIMP kdeAppsDialog(PRInt16 *aReturn); -+ nsCString kdeMakeFilter( int index ); -+ - 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" - #include "nsIScriptError.h" - #include "nsIXULAppInfo.h" - #include "nsIXULRuntime.h" -+#include "nsKDEUtils.h" - - using namespace mozilla; - - struct ManifestDirective { - const char* directive; - int argc; - - bool ischrome; -@@ -397,16 +398,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; - constexpr auto kOs = u"os"_ns; - constexpr auto kOsVersion = u"osversion"_ns; - constexpr auto kABI = u"abi"_ns; -+ constexpr auto kDesktop = u"desktop"_ns; - 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; -@@ -456,39 +458,44 @@ void ParseManifest(NSLocationType aType, - CopyUTF8toUTF16(s, abi); - abi.Insert(char16_t('_'), 0); - abi.Insert(osTarget, 0); - } - } - } - - nsAutoString osVersion; -+ nsAutoString desktop; - #if defined(XP_WIN) - # pragma warning(push) - # pragma warning(disable : 4996) // VC12+ deprecates GetVersionEx - OSVERSIONINFO info = {sizeof(OSVERSIONINFO)}; - if (GetVersionEx(&info)) { - nsTextFormatter::ssprintf(osVersion, u"%ld.%ld", info.dwMajorVersion, - info.dwMinorVersion); - } -+ desktop = u"win"_ns; - # pragma warning(pop) - #elif defined(MOZ_WIDGET_COCOA) - SInt32 majorVersion = nsCocoaFeatures::macOSVersionMajor(); - SInt32 minorVersion = nsCocoaFeatures::macOSVersionMinor(); - nsTextFormatter::ssprintf(osVersion, u"%ld.%ld", majorVersion, minorVersion); -+ desktop = u"macosx"_ns); - #elif defined(MOZ_WIDGET_GTK) - nsTextFormatter::ssprintf(osVersion, u"%ld.%ld", gtk_major_version, - gtk_minor_version); -+ desktop = nsKDEUtils::kdeSession() ? u"kde"_ns : u"gnome"_ns; - #elif defined(MOZ_WIDGET_ANDROID) - bool isTablet = false; - if (mozilla::AndroidBridge::Bridge()) { - mozilla::AndroidBridge::Bridge()->GetStaticStringField( - "android/os/Build$VERSION", "RELEASE", osVersion); - isTablet = java::GeckoAppShell::IsTablet(); - } -+ desktop = u"android"_ns; - #endif - - if (XRE_IsContentProcess()) { - process = kContent; - } else { - process = kMain; - } - -@@ -583,25 +590,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 - : eUnspecified; - #endif - int flags = 0; -+ TriState stDesktop = eUnspecified; - - while ((token = nsCRT::strtok(whitespace, kWhitespace, &whitespace)) && - ok) { - ToLowerCase(token); - NS_ConvertASCIItoUTF16 wtoken(token); - - if (CheckStringFlag(kApplication, wtoken, appID, stApp) || - CheckOsFlag(kOs, wtoken, osTarget, stOs) || - CheckStringFlag(kABI, wtoken, abi, stABI) || -+ CheckStringFlag(kDesktop, wtoken, desktop, stDesktop) || - CheckStringFlag(kProcess, wtoken, process, stProcess) || - CheckVersionFlag(kOsVersion, wtoken, osVersion, stOsVersion) || - CheckVersionFlag(kAppVersion, wtoken, appVersion, stAppVersion) || - CheckVersionFlag(kGeckoVersion, wtoken, geckoVersion, - stGeckoVersion)) { - continue; - } - -@@ -650,17 +659,17 @@ void ParseManifest(NSLocationType aType, - } - - LogMessageWithContext( - aFile, line, "Unrecognized chrome manifest modifier '%s'.", token); - ok = false; - } - - if (!ok || stApp == eBad || stAppVersion == eBad || -- stGeckoVersion == eBad || stOs == eBad || stOsVersion == 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", - "/js/xpconnect/loader", - "/layout/build", - "/modules/libjar", -+ "/toolkit/xre", - ] - - if CONFIG["MOZ_WIDGET_TOOLKIT"] == "gtk": - CXXFLAGS += CONFIG["TK_CFLAGS"] - if CONFIG["MOZ_ENABLE_DBUS"]: - CXXFLAGS += CONFIG["MOZ_DBUS_GLIB_CFLAGS"] - - if CONFIG["MOZ_BACKGROUNDTASKS"]: -diff --git a/xpcom/io/nsLocalFileUnix.cpp b/xpcom/io/nsLocalFileUnix.cpp ---- a/xpcom/io/nsLocalFileUnix.cpp -+++ b/xpcom/io/nsLocalFileUnix.cpp -@@ -49,16 +49,17 @@ - #include "prproces.h" - #include "nsIDirectoryEnumerator.h" - #include "nsSimpleEnumerator.h" - #include "private/pprio.h" - #include "prlink.h" - - #ifdef MOZ_WIDGET_GTK - # include "nsIGIOService.h" -+# include "nsKDEUtils.h" - #endif - - #ifdef MOZ_WIDGET_COCOA - # include - # include "CocoaFileUtils.h" - # include "prmem.h" - # include "plbase64.h" - -@@ -2001,62 +2002,77 @@ nsLocalFile::SetPersistentDescriptor(con - - NS_IMETHODIMP - nsLocalFile::Reveal() { - if (!FilePreferences::IsAllowedPath(mPath)) { - return NS_ERROR_FILE_ACCESS_DENIED; - } - - #ifdef MOZ_WIDGET_GTK -- nsCOMPtr giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID); -- if (!giovfs) { -- return NS_ERROR_FAILURE; -- } -+ nsAutoCString url; - - bool isDirectory; - if (NS_FAILED(IsDirectory(&isDirectory))) { - return NS_ERROR_FAILURE; - } - -+ nsCOMPtr giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID); - if (isDirectory) { -- return giovfs->ShowURIForInput(mPath); -+ url = mPath; - } - if (NS_SUCCEEDED(giovfs->OrgFreedesktopFileManager1ShowItems(mPath))) { - return NS_OK; - } - nsCOMPtr parentDir; - nsAutoCString dirPath; - if (NS_FAILED(GetParent(getter_AddRefs(parentDir)))) { - return NS_ERROR_FAILURE; - } - if (NS_FAILED(parentDir->GetNativePath(dirPath))) { - return NS_ERROR_FAILURE; - } - -- return giovfs->ShowURIForInput(dirPath); -+ url = dirPath; - #elif defined(MOZ_WIDGET_COCOA) - CFURLRef url; - if (NS_SUCCEEDED(GetCFURL(&url))) { - nsresult rv = CocoaFileUtils::RevealFileInFinder(url); - ::CFRelease(url); - return rv; - } - return NS_ERROR_FAILURE; - #else - return NS_ERROR_FAILURE; - #endif -+ if(nsKDEUtils::kdeSupport()) { -+ nsTArray command; -+ command.AppendElement( "REVEAL"_ns ); -+ command.AppendElement( mPath ); -+ return nsKDEUtils::command( command ) ? NS_OK : NS_ERROR_FAILURE; -+ } -+ -+ if (!giovfs) -+ return NS_ERROR_FAILURE; -+ -+ return giovfs->ShowURIForInput(url); - } - - NS_IMETHODIMP - nsLocalFile::Launch() { - if (!FilePreferences::IsAllowedPath(mPath)) { - return NS_ERROR_FILE_ACCESS_DENIED; - } - - #ifdef MOZ_WIDGET_GTK -+ if( nsKDEUtils::kdeSupport()) { -+ nsTArray command; -+ 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->ShowURIForInput(mPath); - #elif defined(MOZ_WIDGET_ANDROID) - // Try to get a mimetype, if this fails just use the file uri alone