Mageia Bugzilla – Attachment 10718 Details for
Bug 24258
Firefox 60.5
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
New Account
|
Forgot Password
[patch]
rediffed mozilla-kde.patch
mozilla-kde.patch (text/plain), 72.24 KB, created by
Giuseppe Ghibò
on 2019-02-02 18:15:53 CET
(
hide
)
Description:
rediffed mozilla-kde.patch
Filename:
MIME Type:
Creator:
Giuseppe Ghibò
Created:
2019-02-02 18:15:53 CET
Size:
72.24 KB
patch
obsolete
>diff -up firefox-60.5.0/modules/libpref/moz.build.mozilla-kde firefox-60.5.0/modules/libpref/moz.build >--- firefox-60.5.0/modules/libpref/moz.build.mozilla-kde 2019-01-24 18:31:16.000000000 +0100 >+++ firefox-60.5.0/modules/libpref/moz.build 2019-01-31 20:24:11.277698990 +0100 >@@ -32,6 +32,10 @@ UNIFIED_SOURCES += [ > 'Preferences.cpp', > ] > >+LOCAL_INCLUDES += [ >+ '/toolkit/xre' >+] >+ > include('/ipc/chromium/chromium-config.mozbuild') > > FINAL_LIBRARY = 'xul' >diff -up firefox-60.5.0/modules/libpref/Preferences.cpp.mozilla-kde firefox-60.5.0/modules/libpref/Preferences.cpp >--- firefox-60.5.0/modules/libpref/Preferences.cpp.mozilla-kde 2019-01-24 18:31:10.000000000 +0100 >+++ firefox-60.5.0/modules/libpref/Preferences.cpp 2019-01-31 20:29:22.778041821 +0100 >@@ -81,6 +81,7 @@ > #include "PLDHashTable.h" > #include "plstr.h" > #include "prlink.h" >+#include "nsKDEUtils.h" > > #ifdef XP_WIN > #include "windows.h" >@@ -3524,6 +3525,7 @@ static nsresult pref_ReadPrefFromJar(nsZ > "winpref.js" > #elif defined(XP_UNIX) > "unix.js" >+ , "" // placeholder for KDE (empty is otherwise harmless) > #if defined(_AIX) > , > "aix.js" >@@ -3533,6 +3535,17 @@ static nsresult pref_ReadPrefFromJar(nsZ > #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)) { >@@ -3590,7 +3603,7 @@ static nsresult pref_ReadPrefFromJar(nsZ > } > > // Do we care if a file provided by this process fails to load? >- pref_LoadPrefsInDir(path, nullptr, 0); >+ pref_LoadPrefsInDir(path, specialFiles, ArrayLength(specialFiles)); > } > } > >diff -up firefox-60.5.0/python/mozbuild/mozpack/chrome/flags.py.mozilla-kde firefox-60.5.0/python/mozbuild/mozpack/chrome/flags.py >--- firefox-60.5.0/python/mozbuild/mozpack/chrome/flags.py.mozilla-kde 2019-01-24 18:31:20.000000000 +0100 >+++ firefox-60.5.0/python/mozbuild/mozpack/chrome/flags.py 2019-01-31 20:24:11.287699003 +0100 >@@ -225,6 +225,7 @@ class Flags(OrderedDict): > 'xpcnativewrappers': Flag, > 'tablet': Flag, > 'process': StringFlag, >+ 'desktop': StringFlag, > } > RE = re.compile(r'([!<>=]+)') > >diff -up firefox-60.5.0/python/mozbuild/mozpack/chrome/manifest.py.mozilla-kde firefox-60.5.0/python/mozbuild/mozpack/chrome/manifest.py >--- firefox-60.5.0/python/mozbuild/mozpack/chrome/manifest.py.mozilla-kde 2019-01-24 18:31:10.000000000 +0100 >+++ firefox-60.5.0/python/mozbuild/mozpack/chrome/manifest.py 2019-01-31 20:24:11.287699003 +0100 >@@ -39,6 +39,7 @@ class ManifestEntry(object): > 'tablet', > 'process', > 'contentaccessible', >+ 'desktop', > ] > > def __init__(self, base, *flags): >diff -up firefox-60.5.0/toolkit/components/downloads/moz.build.mozilla-kde firefox-60.5.0/toolkit/components/downloads/moz.build >--- firefox-60.5.0/toolkit/components/downloads/moz.build.mozilla-kde 2019-01-24 18:31:29.000000000 +0100 >+++ firefox-60.5.0/toolkit/components/downloads/moz.build 2019-01-31 20:24:11.297699013 +0100 >@@ -46,5 +46,9 @@ if CONFIG['MOZ_PLACES']: > > FINAL_LIBRARY = 'xul' > >+LOCAL_INCLUDES += [ >+ '/toolkit/xre' >+] >+ > with Files('**'): > BUG_COMPONENT = ('Toolkit', 'Download Manager') >diff -up firefox-60.5.0/toolkit/content/jar.mn.mozilla-kde firefox-60.5.0/toolkit/content/jar.mn >--- firefox-60.5.0/toolkit/content/jar.mn.mozilla-kde 2019-01-24 18:31:47.000000000 +0100 >+++ firefox-60.5.0/toolkit/content/jar.mn 2019-01-31 20:24:11.297699013 +0100 >@@ -74,6 +74,8 @@ toolkit.jar: > content/global/bindings/datetimebox.xml (widgets/datetimebox.xml) > content/global/bindings/datetimebox.css (widgets/datetimebox.css) > * content/global/bindings/dialog.xml (widgets/dialog.xml) >+* content/global/bindings/dialog-kde.xml (widgets/dialog-kde.xml) >+% override chrome://global/content/bindings/dialog.xml chrome://global/content/bindings/dialog-kde.xml desktop=kde > content/global/bindings/editor.xml (widgets/editor.xml) > content/global/bindings/filefield.xml (widgets/filefield.xml) > * content/global/bindings/findbar.xml (widgets/findbar.xml) >diff -up firefox-60.5.0/toolkit/content/widgets/dialog-kde.xml.mozilla-kde firefox-60.5.0/toolkit/content/widgets/dialog-kde.xml >--- firefox-60.5.0/toolkit/content/widgets/dialog-kde.xml.mozilla-kde 2019-01-31 20:24:11.297699013 +0100 >+++ firefox-60.5.0/toolkit/content/widgets/dialog-kde.xml 2019-01-31 20:24:11.297699013 +0100 >@@ -0,0 +1,478 @@ >+<?xml version="1.0"?> >+<!-- 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/. --> >+ >+<!DOCTYPE bindings [ >+ <!ENTITY % globalKeysDTD SYSTEM "chrome://global/locale/globalKeys.dtd"> >+ %globalKeysDTD; >+]> >+ >+<bindings id="dialogBindings" >+ xmlns="http://www.mozilla.org/xbl" >+ xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" >+ xmlns:xbl="http://www.mozilla.org/xbl"> >+ >+ <binding id="dialog"> >+ <resources> >+ <stylesheet src="chrome://global/skin/dialog.css"/> >+ </resources> >+ <content> >+ <xul:vbox class="box-inherit dialog-content-box" flex="1"> >+ <children/> >+ </xul:vbox> >+ >+ <xul:hbox class="dialog-button-box" anonid="buttons" >+ xbl:inherits="pack=buttonpack,align=buttonalign,dir=buttondir,orient=buttonorient" >+#ifdef XP_UNIX_GNOME >+ > >+ <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/> >+ <xul:button dlgtype="help" class="dialog-button" hidden="true"/> >+ <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/> >+ <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/> >+ <xul:spacer anonid="spacer" flex="1"/> >+ <xul:button dlgtype="cancel" class="dialog-button"/> >+ <xul:button dlgtype="accept" class="dialog-button" xbl:inherits="disabled=buttondisabledaccept"/> >+#elif XP_UNIX >+ > >+ <xul:button dlgtype="help" class="dialog-button" hidden="true"/> >+ <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/> >+ <xul:spacer anonid="spacer" flex="1"/> >+ <xul:button dlgtype="accept" class="dialog-button" xbl:inherits="disabled=buttondisabledaccept"/> >+ <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/> >+ <xul:button dlgtype="cancel" class="dialog-button"/> >+ <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/> >+#else >+ pack="end"> >+ <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/> >+ <xul:spacer anonid="spacer" flex="1" hidden="true"/> >+ <xul:button dlgtype="accept" class="dialog-button" xbl:inherits="disabled=buttondisabledaccept"/> >+ <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/> >+ <xul:button dlgtype="cancel" class="dialog-button"/> >+ <xul:button dlgtype="help" class="dialog-button" hidden="true"/> >+ <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/> >+#endif >+ </xul:hbox> >+ >+ <xul:keyset> >+ <xul:key phase="capturing" oncommand="document.documentElement.openHelp(event)" >+#ifdef XP_MACOSX >+ key="&openHelpMac.commandkey;" modifiers="accel"/> >+#else >+ keycode="&openHelp.commandkey;"/> >+#endif >+ </xul:keyset> >+ >+ </content> >+ >+ <implementation> >+ <field name="_mStrBundle">null</field> >+ <field name="_closeHandler">(function(event) { >+ if (!document.documentElement.cancelDialog()) >+ event.preventDefault(); >+ })</field> >+ >+ <property name="buttons" >+ onget="return this.getAttribute('buttons');" >+ onset="this._configureButtons(val); return val;"/> >+ >+ <property name="defaultButton"> >+ <getter> >+ <![CDATA[ >+ if (this.hasAttribute("defaultButton")) >+ return this.getAttribute("defaultButton"); >+ return "accept"; // default to the accept button >+ ]]> >+ </getter> >+ <setter> >+ <![CDATA[ >+ this._setDefaultButton(val); >+ return val; >+ ]]> >+ </setter> >+ </property> >+ >+ <method name="acceptDialog"> >+ <body> >+ <![CDATA[ >+ return this._doButtonCommand("accept"); >+ ]]> >+ </body> >+ </method> >+ >+ <method name="cancelDialog"> >+ <body> >+ <![CDATA[ >+ return this._doButtonCommand("cancel"); >+ ]]> >+ </body> >+ </method> >+ >+ <method name="getButton"> >+ <parameter name="aDlgType"/> >+ <body> >+ <![CDATA[ >+ return this._buttons[aDlgType]; >+ ]]> >+ </body> >+ </method> >+ >+ <method name="moveToAlertPosition"> >+ <body> >+ <![CDATA[ >+ // hack. we need this so the window has something like its final size >+ if (window.outerWidth == 1) { >+ dump("Trying to position a sizeless window; caller should have called sizeToContent() or sizeTo(). See bug 75649.\n"); >+ sizeToContent(); >+ } >+ >+ if (opener) { >+ var xOffset = (opener.outerWidth - window.outerWidth) / 2; >+ var yOffset = opener.outerHeight / 5; >+ >+ var newX = opener.screenX + xOffset; >+ var newY = opener.screenY + yOffset; >+ } else { >+ newX = (screen.availWidth - window.outerWidth) / 2; >+ newY = (screen.availHeight - window.outerHeight) / 2; >+ } >+ >+ // ensure the window is fully onscreen (if smaller than the screen) >+ if (newX < screen.availLeft) >+ newX = screen.availLeft + 20; >+ if ((newX + window.outerWidth) > (screen.availLeft + screen.availWidth)) >+ newX = (screen.availLeft + screen.availWidth) - window.outerWidth - 20; >+ >+ if (newY < screen.availTop) >+ newY = screen.availTop + 20; >+ if ((newY + window.outerHeight) > (screen.availTop + screen.availHeight)) >+ newY = (screen.availTop + screen.availHeight) - window.outerHeight - 60; >+ >+ window.moveTo( newX, newY ); >+ ]]> >+ </body> >+ </method> >+ >+ <method name="centerWindowOnScreen"> >+ <body> >+ <![CDATA[ >+ var xOffset = screen.availWidth / 2 - window.outerWidth / 2; >+ var yOffset = screen.availHeight / 2 - window.outerHeight / 2; >+ >+ xOffset = xOffset > 0 ? xOffset : 0; >+ yOffset = yOffset > 0 ? yOffset : 0; >+ window.moveTo(xOffset, yOffset); >+ ]]> >+ </body> >+ </method> >+ >+ <constructor> >+ <![CDATA[ >+ this._configureButtons(this.buttons); >+ >+ // listen for when window is closed via native close buttons >+ window.addEventListener("close", this._closeHandler); >+ >+ // for things that we need to initialize after onload fires >+ window.addEventListener("load", this.postLoadInit); >+ >+ window.moveToAlertPosition = this.moveToAlertPosition; >+ window.centerWindowOnScreen = this.centerWindowOnScreen; >+ ]]> >+ </constructor> >+ >+ <method name="postLoadInit"> >+ <parameter name="aEvent"/> >+ <body> >+ <![CDATA[ >+ function focusInit() { >+ const dialog = document.documentElement; >+ const defaultButton = dialog.getButton(dialog.defaultButton); >+ // give focus to the first focusable element in the dialog >+ if (!document.commandDispatcher.focusedElement) { >+ document.commandDispatcher.advanceFocusIntoSubtree(dialog); >+ >+ var focusedElt = document.commandDispatcher.focusedElement; >+ if (focusedElt) { >+ var initialFocusedElt = focusedElt; >+ while (focusedElt.localName == "tab" || >+ focusedElt.getAttribute("noinitialfocus") == "true") { >+ document.commandDispatcher.advanceFocusIntoSubtree(focusedElt); >+ focusedElt = document.commandDispatcher.focusedElement; >+ if (focusedElt == initialFocusedElt) { >+ if (focusedElt.getAttribute("noinitialfocus") == "true") { >+ focusedElt.blur(); >+ } >+ break; >+ } >+ } >+ >+ if (initialFocusedElt.localName == "tab") { >+ if (focusedElt.hasAttribute("dlgtype")) { >+ // We don't want to focus on anonymous OK, Cancel, etc. buttons, >+ // so return focus to the tab itself >+ initialFocusedElt.focus(); >+ } >+ } else if (!/Mac/.test(navigator.platform) && >+ focusedElt.hasAttribute("dlgtype") && focusedElt != defaultButton) { >+ defaultButton.focus(); >+ } >+ } >+ } >+ >+ try { >+ if (defaultButton) >+ window.notifyDefaultButtonLoaded(defaultButton); >+ } catch (e) { } >+ } >+ >+ // Give focus after onload completes, see bug 103197. >+ setTimeout(focusInit, 0); >+ ]]> >+ </body> >+ </method> >+ >+ <method name="openHelp"> >+ <parameter name="event"/> >+ <body> >+ <![CDATA[ >+ var helpButton = document.documentElement.getButton("help"); >+ if (helpButton.disabled || helpButton.hidden) >+ return; >+ this._fireButtonEvent("help"); >+ event.stopPropagation(); >+ event.preventDefault(); >+ ]]> >+ </body> >+ </method> >+ >+ <property name="mStrBundle"> >+ <getter> >+ <![CDATA[ >+ if (!this._mStrBundle) { >+ // need to create string bundle manually instead of using <xul:stringbundle/> >+ // see bug 63370 for details >+ this._mStrBundle = Cc["@mozilla.org/intl/stringbundle;1"] >+ .getService(Ci.nsIStringBundleService) >+ .createBundle("chrome://global/locale/dialog.properties"); >+ } >+ return this._mStrBundle; >+ ]]></getter> >+ </property> >+ >+ <method name="_configureButtons"> >+ <parameter name="aButtons"/> >+ <body> >+ <![CDATA[ >+ // by default, get all the anonymous button elements >+ var buttons = {}; >+ this._buttons = buttons; >+ buttons.accept = document.getAnonymousElementByAttribute(this, "dlgtype", "accept"); >+ buttons.cancel = document.getAnonymousElementByAttribute(this, "dlgtype", "cancel"); >+ buttons.extra1 = document.getAnonymousElementByAttribute(this, "dlgtype", "extra1"); >+ buttons.extra2 = document.getAnonymousElementByAttribute(this, "dlgtype", "extra2"); >+ buttons.help = document.getAnonymousElementByAttribute(this, "dlgtype", "help"); >+ buttons.disclosure = document.getAnonymousElementByAttribute(this, "dlgtype", "disclosure"); >+ >+ // look for any overriding explicit button elements >+ var exBtns = this.getElementsByAttribute("dlgtype", "*"); >+ var dlgtype; >+ var i; >+ for (i = 0; i < exBtns.length; ++i) { >+ dlgtype = exBtns[i].getAttribute("dlgtype"); >+ buttons[dlgtype].hidden = true; // hide the anonymous button >+ buttons[dlgtype] = exBtns[i]; >+ } >+ >+ // add the label and oncommand handler to each button >+ for (dlgtype in buttons) { >+ var button = buttons[dlgtype]; >+ button.addEventListener("command", this._handleButtonCommand, true); >+ >+ // don't override custom labels with pre-defined labels on explicit buttons >+ if (!button.hasAttribute("label")) { >+ // dialog attributes override the default labels in dialog.properties >+ if (this.hasAttribute("buttonlabel" + dlgtype)) { >+ button.setAttribute("label", this.getAttribute("buttonlabel" + dlgtype)); >+ if (this.hasAttribute("buttonaccesskey" + dlgtype)) >+ button.setAttribute("accesskey", this.getAttribute("buttonaccesskey" + dlgtype)); >+ } else if (dlgtype != "extra1" && dlgtype != "extra2") { >+ button.setAttribute("label", this.mStrBundle.GetStringFromName("button-" + dlgtype)); >+ var accessKey = this.mStrBundle.GetStringFromName("accesskey-" + dlgtype); >+ if (accessKey) >+ button.setAttribute("accesskey", accessKey); >+ } >+ } >+ // allow specifying alternate icons in the dialog header >+ if (!button.hasAttribute("icon")) { >+ // if there's an icon specified, use that >+ if (this.hasAttribute("buttonicon" + dlgtype)) >+ button.setAttribute("icon", this.getAttribute("buttonicon" + dlgtype)); >+ // otherwise set defaults >+ else >+ switch (dlgtype) { >+ case "accept": >+ button.setAttribute("icon", "accept"); >+ break; >+ case "cancel": >+ button.setAttribute("icon", "cancel"); >+ break; >+ case "disclosure": >+ button.setAttribute("icon", "properties"); >+ break; >+ case "help": >+ button.setAttribute("icon", "help"); >+ break; >+ default: >+ break; >+ } >+ } >+ } >+ >+ // ensure that hitting enter triggers the default button command >+ this.defaultButton = this.defaultButton; >+ >+ // if there is a special button configuration, use it >+ if (aButtons) { >+ // expect a comma delimited list of dlgtype values >+ var list = aButtons.split(","); >+ >+ // mark shown dlgtypes as true >+ var shown = { accept: false, cancel: false, help: false, >+ disclosure: false, extra1: false, extra2: false }; >+ for (i = 0; i < list.length; ++i) >+ shown[list[i].replace(/ /g, "")] = true; >+ >+ // hide/show the buttons we want >+ for (dlgtype in buttons) >+ buttons[dlgtype].hidden = !shown[dlgtype]; >+ >+ // show the spacer on Windows only when the extra2 button is present >+ if (/Win/.test(navigator.platform)) { >+ var spacer = document.getAnonymousElementByAttribute(this, "anonid", "spacer"); >+ spacer.removeAttribute("hidden"); >+ spacer.setAttribute("flex", shown.extra2 ? "1" : "0"); >+ } >+ } >+ ]]> >+ </body> >+ </method> >+ >+ <method name="_setDefaultButton"> >+ <parameter name="aNewDefault"/> >+ <body> >+ <![CDATA[ >+ // remove the default attribute from the previous default button, if any >+ var oldDefaultButton = this.getButton(this.defaultButton); >+ if (oldDefaultButton) >+ oldDefaultButton.removeAttribute("default"); >+ >+ var newDefaultButton = this.getButton(aNewDefault); >+ if (newDefaultButton) { >+ this.setAttribute("defaultButton", aNewDefault); >+ newDefaultButton.setAttribute("default", "true"); >+ } else { >+ this.setAttribute("defaultButton", "none"); >+ if (aNewDefault != "none") >+ dump("invalid new default button: " + aNewDefault + ", assuming: none\n"); >+ } >+ ]]> >+ </body> >+ </method> >+ >+ <method name="_handleButtonCommand"> >+ <parameter name="aEvent"/> >+ <body> >+ <![CDATA[ >+ return document.documentElement._doButtonCommand( >+ aEvent.target.getAttribute("dlgtype")); >+ ]]> >+ </body> >+ </method> >+ >+ <method name="_doButtonCommand"> >+ <parameter name="aDlgType"/> >+ <body> >+ <![CDATA[ >+ var button = this.getButton(aDlgType); >+ if (!button.disabled) { >+ var noCancel = this._fireButtonEvent(aDlgType); >+ if (noCancel) { >+ if (aDlgType == "accept" || aDlgType == "cancel") { >+ var closingEvent = new CustomEvent("dialogclosing", { >+ bubbles: true, >+ detail: { button: aDlgType }, >+ }); >+ this.dispatchEvent(closingEvent); >+ window.close(); >+ } >+ } >+ return noCancel; >+ } >+ return true; >+ ]]> >+ </body> >+ </method> >+ >+ <method name="_fireButtonEvent"> >+ <parameter name="aDlgType"/> >+ <body> >+ <![CDATA[ >+ var event = document.createEvent("Events"); >+ event.initEvent("dialog" + aDlgType, true, true); >+ >+ // handle dom event handlers >+ var noCancel = this.dispatchEvent(event); >+ >+ // handle any xml attribute event handlers >+ var handler = this.getAttribute("ondialog" + aDlgType); >+ if (handler != "") { >+ var fn = new Function("event", handler); >+ var returned = fn(event); >+ // eslint-disable-next-line mozilla/no-compare-against-boolean-literals >+ if (returned == false) >+ noCancel = false; >+ } >+ >+ return noCancel; >+ ]]> >+ </body> >+ </method> >+ >+ <method name="_hitEnter"> >+ <parameter name="evt"/> >+ <body> >+ <![CDATA[ >+ if (evt.defaultPrevented) >+ return; >+ >+ var btn = this.getButton(this.defaultButton); >+ if (btn) >+ this._doButtonCommand(this.defaultButton); >+ ]]> >+ </body> >+ </method> >+ >+ </implementation> >+ >+ <handlers> >+ <handler event="keypress" keycode="VK_RETURN" >+ group="system" action="this._hitEnter(event);"/> >+ <handler event="keypress" keycode="VK_ESCAPE" group="system"> >+ if (!event.defaultPrevented) >+ this.cancelDialog(); >+ </handler> >+#ifdef XP_MACOSX >+ <handler event="keypress" key="." modifiers="meta" phase="capturing" action="this.cancelDialog();"/> >+#else >+ <handler event="focus" phase="capturing"> >+ var btn = this.getButton(this.defaultButton); >+ if (btn) >+ btn.setAttribute("default", event.originalTarget == btn || !(event.originalTarget instanceof Ci.nsIDOMXULButtonElement)); >+ </handler> >+#endif >+ </handlers> >+ >+ </binding> >+ >+</bindings> >diff -up firefox-60.5.0/toolkit/mozapps/downloads/nsHelperAppDlg.js.mozilla-kde firefox-60.5.0/toolkit/mozapps/downloads/nsHelperAppDlg.js >--- firefox-60.5.0/toolkit/mozapps/downloads/nsHelperAppDlg.js.mozilla-kde 2019-01-24 18:31:47.000000000 +0100 >+++ firefox-60.5.0/toolkit/mozapps/downloads/nsHelperAppDlg.js 2019-01-31 20:24:11.297699013 +0100 >@@ -632,7 +632,7 @@ nsUnknownContentTypeDialog.prototype = { > let [size, unit] = DownloadUtils. > convertByteUnits(this.mLauncher.contentLength); > type.value = this.dialogElement("strings") >- .getFormattedString("orderedFileSizeWithType", >+ .getFormattedString("orderedFileSizeWithType", > [typeString, size, unit]); > } > else { >@@ -806,7 +806,7 @@ nsUnknownContentTypeDialog.prototype = { > case 1: > // only enable the OK button if we have a default app to use or if > // the user chose an app.... >- ok = this.chosenApp || /\S/.test(this.dialogElement("otherHandler").getAttribute("path")); >+ ok = this.chosenApp || /\S/.test(this.dialogElement("otherHandler").getAttribute("path")); > break; > } > } >@@ -1071,20 +1071,50 @@ nsUnknownContentTypeDialog.prototype = { > 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"] >diff -up firefox-60.5.0/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp.mozilla-kde firefox-60.5.0/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp >--- firefox-60.5.0/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp.mozilla-kde 2019-01-24 18:31:42.000000000 +0100 >+++ firefox-60.5.0/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp 2019-01-31 20:31:17.808168514 +0100 >@@ -20,6 +20,7 @@ > #include "nsInterfaceHashtable.h" > #include "mozilla/Attributes.h" > #include "nsIURI.h" >+#include "nsKDEUtils.h" > > class nsUnixSystemProxySettings final : public nsISystemProxySettings { > public: >@@ -47,6 +48,8 @@ class nsUnixSystemProxySettings final : > 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) >@@ -490,6 +493,9 @@ nsresult nsUnixSystemProxySettings::GetP > 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; >@@ -523,3 +529,29 @@ static const mozilla::Module kUnixProxyM > mozilla::Module::kVersion, kUnixProxyCIDs, kUnixProxyContracts}; > > NSMODULE_DEFN(nsUnixProxyModule) = &kUnixProxyModule; >+ >+nsresult >+nsUnixSystemProxySettings::GetProxyFromKDE(const nsACString& aScheme, >+ const nsACString& aHost, >+ PRInt32 aPort, >+ nsACString& aResult) >+{ >+ nsAutoCString url; >+ url = aScheme; >+ url += "://"; >+ url += aHost; >+ if( aPort >= 0 ) >+ { >+ url += ":"; >+ url += nsPrintfCString("%d", aPort); >+ } >+ nsTArray<nsCString> command; >+ command.AppendElement( NS_LITERAL_CSTRING( "GETPROXY" )); >+ command.AppendElement( url ); >+ nsTArray<nsCString> result; >+ if( !nsKDEUtils::command( command, &result ) || result.Length() != 1 ) >+ return NS_ERROR_FAILURE; >+ aResult = result[0]; >+ return NS_OK; >+} >+ >diff -up firefox-60.5.0/toolkit/xre/moz.build.mozilla-kde firefox-60.5.0/toolkit/xre/moz.build >--- firefox-60.5.0/toolkit/xre/moz.build.mozilla-kde 2019-01-24 18:31:47.000000000 +0100 >+++ firefox-60.5.0/toolkit/xre/moz.build 2019-01-31 20:24:11.307699024 +0100 >@@ -70,7 +70,9 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'ui > 'UIKitDirProvider.mm', > ] > elif 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']: >+ EXPORTS += ['nsKDEUtils.h'] > UNIFIED_SOURCES += [ >+ 'nsKDEUtils.cpp', > 'nsNativeAppSupportUnix.cpp', > ] > else: >diff -up firefox-60.5.0/toolkit/xre/nsKDEUtils.cpp.mozilla-kde firefox-60.5.0/toolkit/xre/nsKDEUtils.cpp >--- firefox-60.5.0/toolkit/xre/nsKDEUtils.cpp.mozilla-kde 2019-01-31 20:24:11.307699024 +0100 >+++ firefox-60.5.0/toolkit/xre/nsKDEUtils.cpp 2019-01-31 20:24:11.307699024 +0100 >@@ -0,0 +1,344 @@ >+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ >+/* This Source Code Form is subject to the terms of the Mozilla Public >+ * License, v. 2.0. If a copy of the MPL was not distributed with this >+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ >+ >+#include "nsKDEUtils.h" >+#include "nsIWidget.h" >+#include "nsISupportsPrimitives.h" >+#include "nsIMutableArray.h" >+#include "nsComponentManagerUtils.h" >+#include "nsArrayUtils.h" >+ >+#include <gtk/gtk.h> >+ >+#include <limits.h> >+#include <stdio.h> >+#include <sys/wait.h> >+#include <sys/resource.h> >+#include <unistd.h> >+#include <X11/Xlib.h> >+// copied from X11/X.h as a hack since for an unknown >+// reason it's not picked up from X11/X.h >+#ifndef None >+#define None 0L /* universal null resource or null atom */ >+#endif >+ >+//#define DEBUG_KDE >+#ifdef DEBUG_KDE >+#define KMOZILLAHELPER "kmozillahelper" >+#else >+// not need for lib64, it's a binary >+#define KMOZILLAHELPER "/usr/lib/mozilla/kmozillahelper" >+#endif >+ >+#define KMOZILLAHELPER_VERSION 6 >+#define MAKE_STR2( n ) #n >+#define MAKE_STR( n ) MAKE_STR2( n ) >+ >+static bool getKdeSession() >+ { >+ Display* dpy = XOpenDisplay( NULL ); >+ if( dpy == NULL ) >+ return false; >+ Atom kde_full_session = XInternAtom( dpy, "KDE_FULL_SESSION", True ); >+ bool kde = false; >+ if( kde_full_session != None ) >+ { >+ int cnt; >+ if( Atom* props = XListProperties( dpy, DefaultRootWindow( dpy ), &cnt )) >+ { >+ for( int i = 0; >+ i < cnt; >+ ++i ) >+ { >+ if( props[ i ] == kde_full_session ) >+ { >+ kde = true; >+#ifdef DEBUG_KDE >+ fprintf( stderr, "KDE SESSION %d\n", kde ); >+#endif >+ break; >+ } >+ } >+ XFree( props ); >+ } >+ } >+ XCloseDisplay( dpy ); >+ return kde; >+ } >+ >+static bool getKdeSupport() >+ { >+ nsTArray<nsCString> command; >+ command.AppendElement( NS_LITERAL_CSTRING( "CHECK" )); >+ command.AppendElement( NS_LITERAL_CSTRING( MAKE_STR( KMOZILLAHELPER_VERSION ))); >+ bool kde = nsKDEUtils::command( command ); >+#ifdef DEBUG_KDE >+ fprintf( stderr, "KDE RUNNING %d\n", kde ); >+#endif >+ return kde; >+ } >+ >+nsKDEUtils::nsKDEUtils() >+ : commandFile( NULL ) >+ , replyFile( NULL ) >+ { >+ } >+ >+nsKDEUtils::~nsKDEUtils() >+ { >+// closeHelper(); not actually useful, exiting will close the fd too >+ } >+ >+nsKDEUtils* nsKDEUtils::self() >+ { >+ static nsKDEUtils s; >+ return &s; >+ } >+ >+static bool helperRunning = false; >+static bool helperFailed = false; >+ >+bool nsKDEUtils::kdeSession() >+ { >+ static bool session = getKdeSession(); >+ return session; >+ } >+ >+bool nsKDEUtils::kdeSupport() >+ { >+ static bool support = kdeSession() && getKdeSupport(); >+ return support && helperRunning; >+ } >+ >+struct nsKDECommandData >+ { >+ FILE* file; >+ nsTArray<nsCString>* output; >+ GMainLoop* loop; >+ bool success; >+ }; >+ >+static gboolean kdeReadFunc( GIOChannel*, GIOCondition, gpointer data ) >+ { >+ nsKDECommandData* p = static_cast< nsKDECommandData* >( data ); >+ char buf[ 8192 ]; // TODO big enough >+ bool command_done = false; >+ bool command_failed = false; >+ while( !command_done && !command_failed && fgets( buf, 8192, p->file ) != NULL ) >+ { // TODO what if the kernel splits a line into two chunks? >+//#ifdef DEBUG_KDE >+// fprintf( stderr, "READ: %s %d\n", buf, feof( p->file )); >+//#endif >+ if( char* eol = strchr( buf, '\n' )) >+ *eol = '\0'; >+ command_done = ( strcmp( buf, "\\1" ) == 0 ); >+ command_failed = ( strcmp( buf, "\\0" ) == 0 ); >+ nsAutoCString line( buf ); >+ line.ReplaceSubstring( "\\n", "\n" ); >+ line.ReplaceSubstring( "\\" "\\", "\\" ); // \\ -> \ , i.e. unescape >+ if( p->output && !( command_done || command_failed )) >+ p->output->AppendElement( nsCString( buf )); // TODO utf8? >+ } >+ bool quit = false; >+ if( feof( p->file ) || command_failed ) >+ { >+ quit = true; >+ p->success = false; >+ } >+ if( command_done ) >+ { // reading one reply finished >+ quit = true; >+ p->success = true; >+ } >+ if( quit ) >+ { >+ if( p->loop ) >+ g_main_loop_quit( p->loop ); >+ return FALSE; >+ } >+ return TRUE; >+ } >+ >+bool nsKDEUtils::command( const nsTArray<nsCString>& command, nsTArray<nsCString>* output ) >+ { >+ return self()->internalCommand( command, NULL, false, output ); >+ } >+ >+bool nsKDEUtils::command( nsIArray* command, nsIArray** output) >+ { >+ nsTArray<nsCString> in; >+ PRUint32 length; >+ command->GetLength( &length ); >+ for ( PRUint32 i = 0; i < length; i++ ) >+ { >+ nsCOMPtr<nsISupportsCString> str = do_QueryElementAt( command, i ); >+ if( str ) >+ { >+ nsAutoCString s; >+ str->GetData( s ); >+ in.AppendElement( s ); >+ } >+ } >+ >+ nsTArray<nsCString> out; >+ bool ret = self()->internalCommand( in, NULL, false, &out ); >+ >+ if ( !output ) return ret; >+ >+ nsCOMPtr<nsIMutableArray> result = do_CreateInstance( NS_ARRAY_CONTRACTID ); >+ if ( !result ) return false; >+ >+ for ( PRUint32 i = 0; i < out.Length(); i++ ) >+ { >+ nsCOMPtr<nsISupportsCString> rstr = do_CreateInstance( NS_SUPPORTS_CSTRING_CONTRACTID ); >+ if ( !rstr ) return false; >+ >+ rstr->SetData( out[i] ); >+ result->AppendElement( rstr ); >+ } >+ >+ NS_ADDREF( *output = result); >+ return ret; >+ } >+ >+ >+bool nsKDEUtils::commandBlockUi( const nsTArray<nsCString>& command, GtkWindow* parent, nsTArray<nsCString>* output ) >+ { >+ return self()->internalCommand( command, parent, true, output ); >+ } >+ >+bool nsKDEUtils::internalCommand( const nsTArray<nsCString>& command, GtkWindow* parent, bool blockUi, >+ nsTArray<nsCString>* output ) >+ { >+ if( !startHelper()) >+ return false; >+ feedCommand( command ); >+ // do not store the data in 'this' but in extra structure, just in case there >+ // is reentrancy (can there be? the event loop is re-entered) >+ nsKDECommandData data; >+ data.file = replyFile; >+ data.output = output; >+ data.success = false; >+ if( blockUi ) >+ { >+ data.loop = g_main_loop_new( NULL, FALSE ); >+ GtkWidget* window = gtk_window_new( GTK_WINDOW_TOPLEVEL ); >+ if( parent && gtk_window_get_group(parent) ) >+ gtk_window_group_add_window( gtk_window_get_group(parent), GTK_WINDOW( window )); >+ gtk_widget_realize( window ); >+ gtk_widget_set_sensitive( window, TRUE ); >+ gtk_grab_add( window ); >+ GIOChannel* channel = g_io_channel_unix_new( fileno( data.file )); >+ g_io_add_watch( channel, static_cast< GIOCondition >( G_IO_IN | G_IO_ERR | G_IO_HUP ), kdeReadFunc, &data ); >+ g_io_channel_unref( channel ); >+ g_main_loop_run( data.loop ); >+ g_main_loop_unref( data.loop ); >+ gtk_grab_remove( window ); >+ gtk_widget_destroy( window ); >+ } >+ else >+ { >+ data.loop = NULL; >+ while( kdeReadFunc( NULL, static_cast< GIOCondition >( 0 ), &data )) >+ ; >+ } >+ return data.success; >+ } >+ >+bool nsKDEUtils::startHelper() >+ { >+ if( helperRunning ) >+ return true; >+ if( helperFailed ) >+ return false; >+ helperFailed = true; >+ int fdcommand[ 2 ]; >+ int fdreply[ 2 ]; >+ if( pipe( fdcommand ) < 0 ) >+ return false; >+ if( pipe( fdreply ) < 0 ) >+ { >+ close( fdcommand[ 0 ] ); >+ close( fdcommand[ 1 ] ); >+ return false; >+ } >+ char* args[ 2 ] = { const_cast< char* >( KMOZILLAHELPER ), NULL }; >+ switch( fork()) >+ { >+ case -1: >+ { >+ close( fdcommand[ 0 ] ); >+ close( fdcommand[ 1 ] ); >+ close( fdreply[ 0 ] ); >+ close( fdreply[ 1 ] ); >+ return false; >+ } >+ case 0: // child >+ { >+ if( dup2( fdcommand[ 0 ], STDIN_FILENO ) < 0 ) >+ _exit( 1 ); >+ if( dup2( fdreply[ 1 ], STDOUT_FILENO ) < 0 ) >+ _exit( 1 ); >+ int maxfd = 1024; // close all other fds >+ struct rlimit rl; >+ if( getrlimit( RLIMIT_NOFILE, &rl ) == 0 ) >+ maxfd = rl.rlim_max; >+ for( int i = 3; >+ i < maxfd; >+ ++i ) >+ close( i ); >+#ifdef DEBUG_KDE >+ execvp( KMOZILLAHELPER, args ); >+#else >+ execv( KMOZILLAHELPER, args ); >+#endif >+ _exit( 1 ); // failed >+ } >+ default: // parent >+ { >+ commandFile = fdopen( fdcommand[ 1 ], "w" ); >+ replyFile = fdopen( fdreply[ 0 ], "r" ); >+ close( fdcommand[ 0 ] ); >+ close( fdreply[ 1 ] ); >+ if( commandFile == NULL || replyFile == NULL ) >+ { >+ closeHelper(); >+ return false; >+ } >+ // ok, helper ready, getKdeRunning() will check if it works >+ } >+ } >+ helperFailed = false; >+ helperRunning = true; >+ return true; >+ } >+ >+void nsKDEUtils::closeHelper() >+ { >+ if( commandFile != NULL ) >+ fclose( commandFile ); // this will also make the helper quit >+ if( replyFile != NULL ) >+ fclose( replyFile ); >+ helperRunning = false; >+ } >+ >+void nsKDEUtils::feedCommand( const nsTArray<nsCString>& command ) >+ { >+ for( int i = 0; >+ i < command.Length(); >+ ++i ) >+ { >+ nsCString line = command[ i ]; >+ line.ReplaceSubstring( "\\", "\\" "\\" ); // \ -> \\ , i.e. escape >+ line.ReplaceSubstring( "\n", "\\n" ); >+#ifdef DEBUG_KDE >+ fprintf( stderr, "COMM: %s\n", line.get()); >+#endif >+ fputs( line.get(), commandFile ); >+ fputs( "\n", commandFile ); >+ } >+ fputs( "\\E\n", commandFile ); // done as \E, so it cannot happen in normal data >+ fflush( commandFile ); >+ } >diff -up firefox-60.5.0/toolkit/xre/nsKDEUtils.h.mozilla-kde firefox-60.5.0/toolkit/xre/nsKDEUtils.h >--- firefox-60.5.0/toolkit/xre/nsKDEUtils.h.mozilla-kde 2019-01-31 20:24:11.307699024 +0100 >+++ firefox-60.5.0/toolkit/xre/nsKDEUtils.h 2019-01-31 20:24:11.307699024 +0100 >@@ -0,0 +1,48 @@ >+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ >+/* This Source Code Form is subject to the terms of the Mozilla Public >+ * License, v. 2.0. If a copy of the MPL was not distributed with this >+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ >+ >+#ifndef nsKDEUtils_h__ >+#define nsKDEUtils_h__ >+ >+#include "nsString.h" >+#include "nsTArray.h" >+#include <stdio.h> >+ >+typedef struct _GtkWindow GtkWindow; >+ >+class nsIArray; >+ >+class NS_EXPORT nsKDEUtils >+ { >+ public: >+ /* Returns true if running inside a KDE session (regardless of whether there is KDE >+ support available for Firefox). This should be used e.g. when determining >+ dialog button order but not for code that requires the KDE support. */ >+ static bool kdeSession(); >+ /* Returns true if running inside a KDE session and KDE support is available >+ for Firefox. This should be used everywhere where the external helper is needed. */ >+ static bool kdeSupport(); >+ /* Executes the given helper command, returns true if helper returned success. */ >+ static bool command( const nsTArray<nsCString>& command, nsTArray<nsCString>* output = NULL ); >+ static bool command( nsIArray* command, nsIArray** output = NULL ); >+ /* Like command(), but additionally blocks the parent widget like if there was >+ a modal dialog shown and enters the event loop (i.e. there are still paint updates, >+ this is for commands that take long). */ >+ static bool commandBlockUi( const nsTArray<nsCString>& command, GtkWindow* parent, nsTArray<nsCString>* output = NULL ); >+ >+ private: >+ nsKDEUtils(); >+ ~nsKDEUtils(); >+ static nsKDEUtils* self(); >+ bool startHelper(); >+ void closeHelper(); >+ void feedCommand( const nsTArray<nsCString>& command ); >+ bool internalCommand( const nsTArray<nsCString>& command, GtkWindow* parent, bool isParent, >+ nsTArray<nsCString>* output ); >+ FILE* commandFile; >+ FILE* replyFile; >+ }; >+ >+#endif // nsKDEUtils >diff -up firefox-60.5.0/uriloader/exthandler/HandlerServiceParent.cpp.mozilla-kde firefox-60.5.0/uriloader/exthandler/HandlerServiceParent.cpp >--- firefox-60.5.0/uriloader/exthandler/HandlerServiceParent.cpp.mozilla-kde 2019-01-24 18:31:46.000000000 +0100 >+++ firefox-60.5.0/uriloader/exthandler/HandlerServiceParent.cpp 2019-01-31 20:24:11.307699024 +0100 >@@ -5,7 +5,7 @@ > #include "ContentHandlerService.h" > #include "nsStringEnumerator.h" > #ifdef MOZ_WIDGET_GTK >-#include "unix/nsGNOMERegistry.h" >+#include "unix/nsCommonRegistry.h" > #endif > > using mozilla::dom::ContentHandlerService; >@@ -250,7 +250,7 @@ mozilla::ipc::IPCResult HandlerServicePa > const nsCString& aProtocolScheme, bool* aHandlerExists) { > #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 >diff -up firefox-60.5.0/uriloader/exthandler/moz.build.mozilla-kde firefox-60.5.0/uriloader/exthandler/moz.build >--- firefox-60.5.0/uriloader/exthandler/moz.build.mozilla-kde 2019-01-24 18:31:43.000000000 +0100 >+++ firefox-60.5.0/uriloader/exthandler/moz.build 2019-01-31 20:24:11.317699035 +0100 >@@ -82,7 +82,9 @@ else: > > if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']: > UNIFIED_SOURCES += [ >+ 'unix/nsCommonRegistry.cpp', > 'unix/nsGNOMERegistry.cpp', >+ 'unix/nsKDERegistry.cpp', > 'unix/nsMIMEInfoUnix.cpp', > ] > elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android': >@@ -129,6 +131,7 @@ LOCAL_INCLUDES += [ > '/dom/ipc', > '/netwerk/base', > '/netwerk/protocol/http', >+ '/toolkit/xre', > ] > > if CONFIG['MOZ_ENABLE_DBUS']: >diff -up firefox-60.5.0/uriloader/exthandler/unix/nsCommonRegistry.cpp.mozilla-kde firefox-60.5.0/uriloader/exthandler/unix/nsCommonRegistry.cpp >--- firefox-60.5.0/uriloader/exthandler/unix/nsCommonRegistry.cpp.mozilla-kde 2019-01-31 20:24:11.317699035 +0100 >+++ firefox-60.5.0/uriloader/exthandler/unix/nsCommonRegistry.cpp 2019-01-31 20:24:11.317699035 +0100 >@@ -0,0 +1,53 @@ >+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ >+/* This Source Code Form is subject to the terms of the Mozilla Public >+ * License, v. 2.0. If a copy of the MPL was not distributed with this >+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ >+ >+#include "nsCommonRegistry.h" >+ >+#include "nsGNOMERegistry.h" >+#include "nsKDERegistry.h" >+#include "nsString.h" >+#include "nsKDEUtils.h" >+ >+/* static */ bool >+nsCommonRegistry::HandlerExists(const char *aProtocolScheme) >+{ >+ if( nsKDEUtils::kdeSupport()) >+ return nsKDERegistry::HandlerExists( aProtocolScheme ); >+ return nsGNOMERegistry::HandlerExists( aProtocolScheme ); >+} >+ >+/* static */ nsresult >+nsCommonRegistry::LoadURL(nsIURI *aURL) >+{ >+ if( nsKDEUtils::kdeSupport()) >+ return nsKDERegistry::LoadURL( aURL ); >+ return nsGNOMERegistry::LoadURL( aURL ); >+} >+ >+/* static */ void >+nsCommonRegistry::GetAppDescForScheme(const nsACString& aScheme, >+ nsAString& aDesc) >+{ >+ if( nsKDEUtils::kdeSupport()) >+ return nsKDERegistry::GetAppDescForScheme( aScheme, aDesc ); >+ return nsGNOMERegistry::GetAppDescForScheme( aScheme, aDesc ); >+} >+ >+ >+/* static */ already_AddRefed<nsMIMEInfoBase> >+nsCommonRegistry::GetFromExtension(const nsACString& aFileExt) >+{ >+ if( nsKDEUtils::kdeSupport()) >+ return nsKDERegistry::GetFromExtension( aFileExt ); >+ return nsGNOMERegistry::GetFromExtension( aFileExt ); >+} >+ >+/* static */ already_AddRefed<nsMIMEInfoBase> >+nsCommonRegistry::GetFromType(const nsACString& aMIMEType) >+{ >+ if( nsKDEUtils::kdeSupport()) >+ return nsKDERegistry::GetFromType( aMIMEType ); >+ return nsGNOMERegistry::GetFromType( aMIMEType ); >+} >diff -up firefox-60.5.0/uriloader/exthandler/unix/nsCommonRegistry.h.mozilla-kde firefox-60.5.0/uriloader/exthandler/unix/nsCommonRegistry.h >--- firefox-60.5.0/uriloader/exthandler/unix/nsCommonRegistry.h.mozilla-kde 2019-01-31 20:24:11.317699035 +0100 >+++ firefox-60.5.0/uriloader/exthandler/unix/nsCommonRegistry.h 2019-01-31 20:24:11.317699035 +0100 >@@ -0,0 +1,28 @@ >+/* This Source Code Form is subject to the terms of the Mozilla Public >+ * License, v. 2.0. If a copy of the MPL was not distributed with this >+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ >+ >+#ifndef nsCommonRegistry_h__ >+#define nsCommonRegistry_h__ >+ >+#include "nsIURI.h" >+#include "nsCOMPtr.h" >+ >+class nsMIMEInfoBase; >+ >+class nsCommonRegistry >+{ >+ public: >+ static bool HandlerExists(const char *aProtocolScheme); >+ >+ static nsresult LoadURL(nsIURI *aURL); >+ >+ static void GetAppDescForScheme(const nsACString& aScheme, >+ nsAString& aDesc); >+ >+ static already_AddRefed<nsMIMEInfoBase> GetFromExtension(const nsACString& aFileExt); >+ >+ static already_AddRefed<nsMIMEInfoBase> GetFromType(const nsACString& aMIMEType); >+}; >+ >+#endif >diff -up firefox-60.5.0/uriloader/exthandler/unix/nsKDERegistry.cpp.mozilla-kde firefox-60.5.0/uriloader/exthandler/unix/nsKDERegistry.cpp >--- firefox-60.5.0/uriloader/exthandler/unix/nsKDERegistry.cpp.mozilla-kde 2019-01-31 20:24:11.317699035 +0100 >+++ firefox-60.5.0/uriloader/exthandler/unix/nsKDERegistry.cpp 2019-01-31 20:24:11.317699035 +0100 >@@ -0,0 +1,87 @@ >+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ >+/* This Source Code Form is subject to the terms of the Mozilla Public >+ * License, v. 2.0. If a copy of the MPL was not distributed with this >+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ >+ >+#include "nsKDERegistry.h" >+#include "prlink.h" >+#include "prmem.h" >+#include "nsString.h" >+#include "nsMIMEInfoUnix.h" >+#include "nsAutoPtr.h" >+#include "nsKDEUtils.h" >+ >+/* static */ bool >+nsKDERegistry::HandlerExists(const char *aProtocolScheme) >+{ >+ nsTArray<nsCString> command; >+ command.AppendElement( NS_LITERAL_CSTRING( "HANDLEREXISTS" )); >+ command.AppendElement( nsAutoCString( aProtocolScheme )); >+ return nsKDEUtils::command( command ); >+} >+ >+/* static */ nsresult >+nsKDERegistry::LoadURL(nsIURI *aURL) >+{ >+ nsTArray<nsCString> command; >+ command.AppendElement( NS_LITERAL_CSTRING( "OPEN" )); >+ nsCString url; >+ aURL->GetSpec( url ); >+ command.AppendElement( url ); >+ bool rv = nsKDEUtils::command( command ); >+ if (!rv) >+ return NS_ERROR_FAILURE; >+ >+ return NS_OK; >+} >+ >+/* static */ void >+nsKDERegistry::GetAppDescForScheme(const nsACString& aScheme, >+ nsAString& aDesc) >+{ >+ nsTArray<nsCString> command; >+ command.AppendElement( NS_LITERAL_CSTRING( "GETAPPDESCFORSCHEME" )); >+ command.AppendElement( aScheme ); >+ nsTArray<nsCString> output; >+ if( nsKDEUtils::command( command, &output ) && output.Length() == 1 ) >+ CopyUTF8toUTF16( output[ 0 ], aDesc ); >+} >+ >+ >+/* static */ already_AddRefed<nsMIMEInfoBase> >+nsKDERegistry::GetFromExtension(const nsACString& aFileExt) >+{ >+ NS_ASSERTION(aFileExt[0] != '.', "aFileExt shouldn't start with a dot"); >+ nsTArray<nsCString> command; >+ command.AppendElement( NS_LITERAL_CSTRING( "GETFROMEXTENSION" )); >+ command.AppendElement( aFileExt ); >+ return GetFromHelper( command ); >+} >+ >+/* static */ already_AddRefed<nsMIMEInfoBase> >+nsKDERegistry::GetFromType(const nsACString& aMIMEType) >+{ >+ nsTArray<nsCString> command; >+ command.AppendElement( NS_LITERAL_CSTRING( "GETFROMTYPE" )); >+ command.AppendElement( aMIMEType ); >+ return GetFromHelper( command ); >+} >+ >+/* static */ already_AddRefed<nsMIMEInfoBase> >+nsKDERegistry::GetFromHelper(const nsTArray<nsCString>& command) >+{ >+ nsTArray<nsCString> output; >+ if( nsKDEUtils::command( command, &output ) && output.Length() == 3 ) >+ { >+ nsCString mimetype = output[ 0 ]; >+ RefPtr<nsMIMEInfoUnix> 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 -up firefox-60.5.0/uriloader/exthandler/unix/nsKDERegistry.h.mozilla-kde firefox-60.5.0/uriloader/exthandler/unix/nsKDERegistry.h >--- firefox-60.5.0/uriloader/exthandler/unix/nsKDERegistry.h.mozilla-kde 2019-01-31 20:24:11.317699035 +0100 >+++ firefox-60.5.0/uriloader/exthandler/unix/nsKDERegistry.h 2019-01-31 20:24:11.317699035 +0100 >@@ -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<nsMIMEInfoBase> GetFromExtension(const nsACString& aFileExt); >+ >+ static already_AddRefed<nsMIMEInfoBase> GetFromType(const nsACString& aMIMEType); >+ private: >+ static already_AddRefed<nsMIMEInfoBase> GetFromHelper(const nsTArray<nsCString>& command); >+ >+}; >+ >+#endif //nsKDERegistry_h__ >diff -up firefox-60.5.0/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp.mozilla-kde firefox-60.5.0/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp >--- firefox-60.5.0/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp.mozilla-kde 2019-01-24 18:31:47.000000000 +0100 >+++ firefox-60.5.0/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp 2019-01-31 20:56:12.450143516 +0100 >@@ -5,7 +5,7 @@ > * 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" >@@ -13,9 +13,12 @@ > #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 >@@ -28,15 +31,15 @@ nsMIMEInfoUnix::GetHasDefaultHandler(boo > *_retval = false; > > if (mClass == eProtocolInfo) { >- *_retval = nsGNOMERegistry::HandlerExists(mSchemeOrType.get()); >+ *_retval = nsCommonRegistry::HandlerExists(mSchemeOrType.get()); > } else { > RefPtr<nsMIMEInfoBase> 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; >@@ -56,6 +59,23 @@ nsresult nsMIMEInfoUnix::LaunchDefaultWi > nsAutoCString nativePath; > aFile->GetNativePath(nativePath); > >+ if( nsKDEUtils::kdeSupport()) { >+ bool supports; >+ if( NS_SUCCEEDED( GetHasDefaultHandler( &supports )) && supports ) { >+ nsTArray<nsCString> command; >+ command.AppendElement( NS_LITERAL_CSTRING( "OPEN" )); >+ command.AppendElement( nativePath ); >+ command.AppendElement( NS_LITERAL_CSTRING( "MIMETYPE" )); >+ command.AppendElement( mSchemeOrType ); >+ if( nsKDEUtils::command( command )) >+ return NS_OK; >+ } >+ if (!mDefaultApplication) >+ return NS_ERROR_FILE_NOT_FOUND; >+ >+ return LaunchWithIProcess(mDefaultApplication, nativePath); >+ } >+ > nsCOMPtr<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID); > if (!giovfs) { > return NS_ERROR_FAILURE; >diff -up firefox-60.5.0/uriloader/exthandler/unix/nsOSHelperAppService.cpp.mozilla-kde firefox-60.5.0/uriloader/exthandler/unix/nsOSHelperAppService.cpp >--- firefox-60.5.0/uriloader/exthandler/unix/nsOSHelperAppService.cpp.mozilla-kde 2019-01-24 18:31:47.000000000 +0100 >+++ firefox-60.5.0/uriloader/exthandler/unix/nsOSHelperAppService.cpp 2019-01-31 20:32:05.148220602 +0100 >@@ -10,7 +10,7 @@ > #include "nsOSHelperAppService.h" > #include "nsMIMEInfoUnix.h" > #ifdef MOZ_WIDGET_GTK >-#include "nsGNOMERegistry.h" >+#include "nsCommonRegistry.h" > #endif > #include "nsISupports.h" > #include "nsString.h" >@@ -1045,7 +1045,7 @@ nsresult nsOSHelperAppService::OSProtoco > 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 >@@ -1065,7 +1065,7 @@ nsresult nsOSHelperAppService::OSProtoco > 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; >@@ -1156,7 +1156,7 @@ already_AddRefed<nsMIMEInfoBase> nsOSHel > #ifdef MOZ_WIDGET_GTK > LOG(("Looking in GNOME registry\n")); > RefPtr<nsMIMEInfoBase> gnomeInfo = >- nsGNOMERegistry::GetFromExtension(aFileExt); >+ nsCommonRegistry::GetFromExtension(aFileExt); > if (gnomeInfo) { > LOG(("Got MIMEInfo from GNOME registry\n")); > return gnomeInfo.forget(); >@@ -1268,7 +1268,7 @@ already_AddRefed<nsMIMEInfoBase> nsOSHel > > #ifdef MOZ_WIDGET_GTK > if (handler.IsEmpty()) { >- RefPtr<nsMIMEInfoBase> gnomeInfo = nsGNOMERegistry::GetFromType(aMIMEType); >+ RefPtr<nsMIMEInfoBase> gnomeInfo = nsCommonRegistry::GetFromType(aMIMEType); > if (gnomeInfo) { > LOG( > ("Got MIMEInfo from GNOME registry without extensions; setting them " >diff -up firefox-60.5.0/widget/gtk/moz.build.mozilla-kde firefox-60.5.0/widget/gtk/moz.build >--- firefox-60.5.0/widget/gtk/moz.build.mozilla-kde 2019-01-24 18:31:47.000000000 +0100 >+++ firefox-60.5.0/widget/gtk/moz.build 2019-01-31 20:24:11.327699047 +0100 >@@ -126,6 +126,7 @@ LOCAL_INCLUDES += [ > '/layout/generic', > '/layout/xul', > '/other-licenses/atk-1.0', >+ '/toolkit/xre', > '/widget', > '/widget/headless', > ] >diff -up firefox-60.5.0/widget/gtk/nsFilePicker.cpp.mozilla-kde firefox-60.5.0/widget/gtk/nsFilePicker.cpp >--- firefox-60.5.0/widget/gtk/nsFilePicker.cpp.mozilla-kde 2019-01-24 18:31:43.000000000 +0100 >+++ firefox-60.5.0/widget/gtk/nsFilePicker.cpp 2019-01-31 20:24:11.337699057 +0100 >@@ -9,6 +9,7 @@ > #include <unistd.h> > > #include <gtk/gtk.h> >+#include <gdk/gdkx.h> > > #include "nsGtkUtils.h" > #include "nsIFileURL.h" >@@ -25,6 +26,7 @@ > #include "mozcontainer.h" > > #include "nsFilePicker.h" >+#include "nsKDEUtils.h" > > using namespace mozilla; > >@@ -230,7 +232,9 @@ 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; >@@ -340,6 +344,29 @@ 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()) { >+ 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; >+ } >+ > nsCString title; > title.Adopt(ToNewUTF8String(mTitle)); > >@@ -577,3 +604,228 @@ void nsFilePicker::Done(GtkWidget *file_ > } > 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<nsCString> command; >+ command.AppendElement( nsAutoCString( arg )); >+ command.AppendElement( startdir ); >+ if( mMode != nsIFilePicker::modeGetFolder ) >+ { >+ command.AppendElement( filters ); >+ nsAutoCString selected; >+ selected.AppendInt( mSelectedType ); >+ command.AppendElement( selected ); >+ } >+ command.AppendElement( title ); >+ if( mMode == nsIFilePicker::modeOpenMultiple ) >+ command.AppendElement( NS_LITERAL_CSTRING( "MULTIPLE" )); >+ if( PRInt32 xid = windowToXid( mParentWidget )) >+ { >+ command.AppendElement( NS_LITERAL_CSTRING( "PARENT" )); >+ nsAutoCString parent; >+ parent.AppendInt( xid ); >+ command.AppendElement( parent ); >+ } >+ >+ nsTArray<nsCString> 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<nsIFile> localfile; >+ nsresult rv = NS_NewNativeLocalFile( output[ i ], >+ PR_FALSE, >+ getter_AddRefs(localfile)); >+ if (NS_SUCCEEDED(rv)) >+ mFiles.AppendObject(localfile); >+ } >+ } >+ else >+ { >+ if( output.Length() == 0 ) >+ mFileURL = nsCString(); >+ else if( mAllowURLs ) >+ mFileURL = output[ 0 ]; >+ else // GetFile() actually requires it to be url even for local files :-/ >+ { >+ mFileURL = nsCString( "file://" ); >+ mFileURL.Append( output[ 0 ] ); >+ } >+ } >+ // Remember last used directory. >+ nsCOMPtr<nsIFile> file; >+ GetFile(getter_AddRefs(file)); >+ if (file) { >+ nsCOMPtr<nsIFile> dir; >+ file->GetParent(getter_AddRefs(dir)); >+ nsCOMPtr<nsIFile> localDir(do_QueryInterface(dir)); >+ if (localDir) { >+ localDir.swap(mPrevDisplayDirectory); >+ } >+ } >+ if (mMode == nsIFilePicker::modeSave) >+ { >+ nsCOMPtr<nsIFile> 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<nsCString> command; >+ command.AppendElement( NS_LITERAL_CSTRING( "APPSDIALOG" )); >+ command.AppendElement( title ); >+ if( PRInt32 xid = windowToXid( mParentWidget )) >+ { >+ command.AppendElement( NS_LITERAL_CSTRING( "PARENT" )); >+ nsAutoCString parent; >+ parent.AppendInt( xid ); >+ command.AppendElement( parent ); >+ } >+ >+ nsTArray<nsCString> output; >+ if( nsKDEUtils::commandBlockUi( command, GTK_WINDOW(mParentWidget->GetNativeData(NS_NATIVE_SHELLWIDGET)), &output )) >+ { >+ *aReturn = nsIFilePicker::returnOK; >+ mFileURL = output.Length() > 0 ? output[ 0 ] : nsCString(); >+ } >+ else >+ { >+ *aReturn = nsIFilePicker::returnCancel; >+ } >+ return NS_OK; >+ } >+ >diff -up firefox-60.5.0/widget/gtk/nsFilePicker.h.mozilla-kde firefox-60.5.0/widget/gtk/nsFilePicker.h >--- firefox-60.5.0/widget/gtk/nsFilePicker.h.mozilla-kde 2019-01-24 18:31:42.000000000 +0100 >+++ firefox-60.5.0/widget/gtk/nsFilePicker.h 2019-01-31 20:24:11.337699057 +0100 >@@ -72,6 +72,12 @@ class nsFilePicker : public nsBaseFilePi > private: > static nsIFile* mPrevDisplayDirectory; > >+ bool kdeRunning(); >+ bool getKdeRunning(); >+ NS_IMETHODIMP kdeFileDialog(PRInt16 *aReturn); >+ NS_IMETHODIMP kdeAppsDialog(PRInt16 *aReturn); >+ nsCString kdeMakeFilter( int index ); >+ > #ifdef MOZ_WIDGET_GTK > GtkFileChooserWidget* mFileChooserDelegate; > #endif >diff -up firefox-60.5.0/xpcom/components/ManifestParser.cpp.mozilla-kde firefox-60.5.0/xpcom/components/ManifestParser.cpp >--- firefox-60.5.0/xpcom/components/ManifestParser.cpp.mozilla-kde 2019-01-24 18:31:42.000000000 +0100 >+++ firefox-60.5.0/xpcom/components/ManifestParser.cpp 2019-01-31 20:26:38.247860704 +0100 >@@ -38,6 +38,7 @@ > #include "nsIScriptError.h" > #include "nsIXULAppInfo.h" > #include "nsIXULRuntime.h" >+#include "nsKDEUtils.h" > > using namespace mozilla; > >@@ -423,6 +424,7 @@ void ParseManifest(NSLocationType aType, > NS_NAMED_LITERAL_STRING(kOs, "os"); > NS_NAMED_LITERAL_STRING(kOsVersion, "osversion"); > NS_NAMED_LITERAL_STRING(kABI, "abi"); >+ NS_NAMED_LITERAL_STRING(kDesktop, "desktop"); > NS_NAMED_LITERAL_STRING(kProcess, "process"); > #if defined(MOZ_WIDGET_ANDROID) > NS_NAMED_LITERAL_STRING(kTablet, "tablet"); >@@ -478,6 +480,7 @@ void ParseManifest(NSLocationType aType, > } > > nsAutoString osVersion; >+ nsAutoString desktop; > #if defined(XP_WIN) > #pragma warning(push) > #pragma warning(disable : 4996) // VC12+ deprecates GetVersionEx >@@ -486,14 +489,17 @@ void ParseManifest(NSLocationType aType, > nsTextFormatter::ssprintf(osVersion, u"%ld.%ld", info.dwMajorVersion, > info.dwMinorVersion); > } >+ desktop = NS_LITERAL_STRING("win"); > #pragma warning(pop) > #elif defined(MOZ_WIDGET_COCOA) > SInt32 majorVersion = nsCocoaFeatures::OSXVersionMajor(); > SInt32 minorVersion = nsCocoaFeatures::OSXVersionMinor(); > nsTextFormatter::ssprintf(osVersion, u"%ld.%ld", majorVersion, minorVersion); >+ desktop = NS_LITERAL_STRING("macosx"); > #elif defined(MOZ_WIDGET_GTK) > nsTextFormatter::ssprintf(osVersion, u"%ld.%ld", gtk_major_version, > gtk_minor_version); >+ desktop = nsKDEUtils::kdeSession() ? NS_LITERAL_STRING("kde") : NS_LITERAL_STRING("gnome"); > #elif defined(MOZ_WIDGET_ANDROID) > bool isTablet = false; > if (mozilla::AndroidBridge::Bridge()) { >@@ -501,6 +507,7 @@ void ParseManifest(NSLocationType aType, > "android/os/Build$VERSION", "RELEASE", osVersion); > isTablet = java::GeckoAppShell::IsTablet(); > } >+ desktop = NS_LITERAL_STRING("android"); > #endif > > if (XRE_IsContentProcess()) { >@@ -613,6 +620,7 @@ void ParseManifest(NSLocationType aType, > TriState stTablet = eUnspecified; > #endif > int flags = 0; >+ TriState stDesktop = eUnspecified; > > while ((token = nsCRT::strtok(whitespace, kWhitespace, &whitespace)) && > ok) { >@@ -622,6 +630,7 @@ void ParseManifest(NSLocationType aType, > 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) || >@@ -668,7 +677,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 || > #ifdef MOZ_WIDGET_ANDROID > stTablet == eBad || > #endif >diff -up firefox-60.5.0/xpcom/components/moz.build.mozilla-kde firefox-60.5.0/xpcom/components/moz.build >--- firefox-60.5.0/xpcom/components/moz.build.mozilla-kde 2019-01-24 18:31:47.000000000 +0100 >+++ firefox-60.5.0/xpcom/components/moz.build 2019-01-31 20:24:11.347699068 +0100 >@@ -49,6 +49,7 @@ LOCAL_INCLUDES += [ > '../reflect/xptinfo', > '/chrome', > '/modules/libjar', >+ '/toolkit/xre' > ] > > if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']: >diff -up firefox-60.5.0/xpcom/io/nsLocalFileUnix.cpp.mozilla-kde firefox-60.5.0/xpcom/io/nsLocalFileUnix.cpp >--- firefox-60.5.0/xpcom/io/nsLocalFileUnix.cpp.mozilla-kde 2019-01-24 18:31:33.000000000 +0100 >+++ firefox-60.5.0/xpcom/io/nsLocalFileUnix.cpp 2019-01-31 20:24:11.347699068 +0100 >@@ -52,6 +52,7 @@ > > #ifdef MOZ_WIDGET_GTK > #include "nsIGIOService.h" >+#include "nsKDEUtils.h" > #endif > > #ifdef MOZ_WIDGET_COCOA >@@ -1906,18 +1907,16 @@ nsLocalFile::Reveal() { > } > > #ifdef MOZ_WIDGET_GTK >- nsCOMPtr<nsIGIOService> 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<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID); > if (isDirectory) { >- return giovfs->ShowURIForInput(mPath); >+ url = mPath; > } > if (NS_SUCCEEDED(giovfs->OrgFreedesktopFileManager1ShowItems(mPath))) { > return NS_OK; >@@ -1931,7 +1930,7 @@ nsLocalFile::Reveal() { > return NS_ERROR_FAILURE; > } > >- return giovfs->ShowURIForInput(dirPath); >+ url = dirPath; > #elif defined(MOZ_WIDGET_COCOA) > CFURLRef url; > if (NS_SUCCEEDED(GetCFURL(&url))) { >@@ -1943,6 +1942,17 @@ nsLocalFile::Reveal() { > #else > return NS_ERROR_FAILURE; > #endif >+ if(nsKDEUtils::kdeSupport()) { >+ nsTArray<nsCString> command; >+ command.AppendElement( NS_LITERAL_CSTRING("REVEAL") ); >+ command.AppendElement( mPath ); >+ return nsKDEUtils::command( command ) ? NS_OK : NS_ERROR_FAILURE; >+ } >+ >+ if (!giovfs) >+ return NS_ERROR_FAILURE; >+ >+ return giovfs->ShowURIForInput(url); > } > > NS_IMETHODIMP >@@ -1952,6 +1962,12 @@ nsLocalFile::Launch() { > } > > #ifdef MOZ_WIDGET_GTK >+ if( nsKDEUtils::kdeSupport()) { >+ nsTArray<nsCString> command; >+ command.AppendElement( NS_LITERAL_CSTRING("OPEN") ); >+ command.AppendElement( mPath ); >+ return nsKDEUtils::command( command ) ? NS_OK : NS_ERROR_FAILURE; >+ } > nsCOMPtr<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID); > if (!giovfs) { > return NS_ERROR_FAILURE;
diff -up firefox-60.5.0/modules/libpref/moz.build.mozilla-kde firefox-60.5.0/modules/libpref/moz.build --- firefox-60.5.0/modules/libpref/moz.build.mozilla-kde 2019-01-24 18:31:16.000000000 +0100 +++ firefox-60.5.0/modules/libpref/moz.build 2019-01-31 20:24:11.277698990 +0100 @@ -32,6 +32,10 @@ UNIFIED_SOURCES += [ 'Preferences.cpp', ] +LOCAL_INCLUDES += [ + '/toolkit/xre' +] + include('/ipc/chromium/chromium-config.mozbuild') FINAL_LIBRARY = 'xul' diff -up firefox-60.5.0/modules/libpref/Preferences.cpp.mozilla-kde firefox-60.5.0/modules/libpref/Preferences.cpp --- firefox-60.5.0/modules/libpref/Preferences.cpp.mozilla-kde 2019-01-24 18:31:10.000000000 +0100 +++ firefox-60.5.0/modules/libpref/Preferences.cpp 2019-01-31 20:29:22.778041821 +0100 @@ -81,6 +81,7 @@ #include "PLDHashTable.h" #include "plstr.h" #include "prlink.h" +#include "nsKDEUtils.h" #ifdef XP_WIN #include "windows.h" @@ -3524,6 +3525,7 @@ static nsresult pref_ReadPrefFromJar(nsZ "winpref.js" #elif defined(XP_UNIX) "unix.js" + , "" // placeholder for KDE (empty is otherwise harmless) #if defined(_AIX) , "aix.js" @@ -3533,6 +3535,17 @@ static nsresult pref_ReadPrefFromJar(nsZ #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)) { @@ -3590,7 +3603,7 @@ static nsresult pref_ReadPrefFromJar(nsZ } // Do we care if a file provided by this process fails to load? - pref_LoadPrefsInDir(path, nullptr, 0); + pref_LoadPrefsInDir(path, specialFiles, ArrayLength(specialFiles)); } } diff -up firefox-60.5.0/python/mozbuild/mozpack/chrome/flags.py.mozilla-kde firefox-60.5.0/python/mozbuild/mozpack/chrome/flags.py --- firefox-60.5.0/python/mozbuild/mozpack/chrome/flags.py.mozilla-kde 2019-01-24 18:31:20.000000000 +0100 +++ firefox-60.5.0/python/mozbuild/mozpack/chrome/flags.py 2019-01-31 20:24:11.287699003 +0100 @@ -225,6 +225,7 @@ class Flags(OrderedDict): 'xpcnativewrappers': Flag, 'tablet': Flag, 'process': StringFlag, + 'desktop': StringFlag, } RE = re.compile(r'([!<>=]+)') diff -up firefox-60.5.0/python/mozbuild/mozpack/chrome/manifest.py.mozilla-kde firefox-60.5.0/python/mozbuild/mozpack/chrome/manifest.py --- firefox-60.5.0/python/mozbuild/mozpack/chrome/manifest.py.mozilla-kde 2019-01-24 18:31:10.000000000 +0100 +++ firefox-60.5.0/python/mozbuild/mozpack/chrome/manifest.py 2019-01-31 20:24:11.287699003 +0100 @@ -39,6 +39,7 @@ class ManifestEntry(object): 'tablet', 'process', 'contentaccessible', + 'desktop', ] def __init__(self, base, *flags): diff -up firefox-60.5.0/toolkit/components/downloads/moz.build.mozilla-kde firefox-60.5.0/toolkit/components/downloads/moz.build --- firefox-60.5.0/toolkit/components/downloads/moz.build.mozilla-kde 2019-01-24 18:31:29.000000000 +0100 +++ firefox-60.5.0/toolkit/components/downloads/moz.build 2019-01-31 20:24:11.297699013 +0100 @@ -46,5 +46,9 @@ if CONFIG['MOZ_PLACES']: FINAL_LIBRARY = 'xul' +LOCAL_INCLUDES += [ + '/toolkit/xre' +] + with Files('**'): BUG_COMPONENT = ('Toolkit', 'Download Manager') diff -up firefox-60.5.0/toolkit/content/jar.mn.mozilla-kde firefox-60.5.0/toolkit/content/jar.mn --- firefox-60.5.0/toolkit/content/jar.mn.mozilla-kde 2019-01-24 18:31:47.000000000 +0100 +++ firefox-60.5.0/toolkit/content/jar.mn 2019-01-31 20:24:11.297699013 +0100 @@ -74,6 +74,8 @@ toolkit.jar: content/global/bindings/datetimebox.xml (widgets/datetimebox.xml) content/global/bindings/datetimebox.css (widgets/datetimebox.css) * content/global/bindings/dialog.xml (widgets/dialog.xml) +* content/global/bindings/dialog-kde.xml (widgets/dialog-kde.xml) +% override chrome://global/content/bindings/dialog.xml chrome://global/content/bindings/dialog-kde.xml desktop=kde content/global/bindings/editor.xml (widgets/editor.xml) content/global/bindings/filefield.xml (widgets/filefield.xml) * content/global/bindings/findbar.xml (widgets/findbar.xml) diff -up firefox-60.5.0/toolkit/content/widgets/dialog-kde.xml.mozilla-kde firefox-60.5.0/toolkit/content/widgets/dialog-kde.xml --- firefox-60.5.0/toolkit/content/widgets/dialog-kde.xml.mozilla-kde 2019-01-31 20:24:11.297699013 +0100 +++ firefox-60.5.0/toolkit/content/widgets/dialog-kde.xml 2019-01-31 20:24:11.297699013 +0100 @@ -0,0 +1,478 @@ +<?xml version="1.0"?> +<!-- 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/. --> + +<!DOCTYPE bindings [ + <!ENTITY % globalKeysDTD SYSTEM "chrome://global/locale/globalKeys.dtd"> + %globalKeysDTD; +]> + +<bindings id="dialogBindings" + xmlns="http://www.mozilla.org/xbl" + xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + xmlns:xbl="http://www.mozilla.org/xbl"> + + <binding id="dialog"> + <resources> + <stylesheet src="chrome://global/skin/dialog.css"/> + </resources> + <content> + <xul:vbox class="box-inherit dialog-content-box" flex="1"> + <children/> + </xul:vbox> + + <xul:hbox class="dialog-button-box" anonid="buttons" + xbl:inherits="pack=buttonpack,align=buttonalign,dir=buttondir,orient=buttonorient" +#ifdef XP_UNIX_GNOME + > + <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/> + <xul:button dlgtype="help" class="dialog-button" hidden="true"/> + <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/> + <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/> + <xul:spacer anonid="spacer" flex="1"/> + <xul:button dlgtype="cancel" class="dialog-button"/> + <xul:button dlgtype="accept" class="dialog-button" xbl:inherits="disabled=buttondisabledaccept"/> +#elif XP_UNIX + > + <xul:button dlgtype="help" class="dialog-button" hidden="true"/> + <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/> + <xul:spacer anonid="spacer" flex="1"/> + <xul:button dlgtype="accept" class="dialog-button" xbl:inherits="disabled=buttondisabledaccept"/> + <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/> + <xul:button dlgtype="cancel" class="dialog-button"/> + <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/> +#else + pack="end"> + <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/> + <xul:spacer anonid="spacer" flex="1" hidden="true"/> + <xul:button dlgtype="accept" class="dialog-button" xbl:inherits="disabled=buttondisabledaccept"/> + <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/> + <xul:button dlgtype="cancel" class="dialog-button"/> + <xul:button dlgtype="help" class="dialog-button" hidden="true"/> + <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/> +#endif + </xul:hbox> + + <xul:keyset> + <xul:key phase="capturing" oncommand="document.documentElement.openHelp(event)" +#ifdef XP_MACOSX + key="&openHelpMac.commandkey;" modifiers="accel"/> +#else + keycode="&openHelp.commandkey;"/> +#endif + </xul:keyset> + + </content> + + <implementation> + <field name="_mStrBundle">null</field> + <field name="_closeHandler">(function(event) { + if (!document.documentElement.cancelDialog()) + event.preventDefault(); + })</field> + + <property name="buttons" + onget="return this.getAttribute('buttons');" + onset="this._configureButtons(val); return val;"/> + + <property name="defaultButton"> + <getter> + <![CDATA[ + if (this.hasAttribute("defaultButton")) + return this.getAttribute("defaultButton"); + return "accept"; // default to the accept button + ]]> + </getter> + <setter> + <![CDATA[ + this._setDefaultButton(val); + return val; + ]]> + </setter> + </property> + + <method name="acceptDialog"> + <body> + <![CDATA[ + return this._doButtonCommand("accept"); + ]]> + </body> + </method> + + <method name="cancelDialog"> + <body> + <![CDATA[ + return this._doButtonCommand("cancel"); + ]]> + </body> + </method> + + <method name="getButton"> + <parameter name="aDlgType"/> + <body> + <![CDATA[ + return this._buttons[aDlgType]; + ]]> + </body> + </method> + + <method name="moveToAlertPosition"> + <body> + <![CDATA[ + // hack. we need this so the window has something like its final size + if (window.outerWidth == 1) { + dump("Trying to position a sizeless window; caller should have called sizeToContent() or sizeTo(). See bug 75649.\n"); + sizeToContent(); + } + + if (opener) { + var xOffset = (opener.outerWidth - window.outerWidth) / 2; + var yOffset = opener.outerHeight / 5; + + var newX = opener.screenX + xOffset; + var newY = opener.screenY + yOffset; + } else { + newX = (screen.availWidth - window.outerWidth) / 2; + newY = (screen.availHeight - window.outerHeight) / 2; + } + + // ensure the window is fully onscreen (if smaller than the screen) + if (newX < screen.availLeft) + newX = screen.availLeft + 20; + if ((newX + window.outerWidth) > (screen.availLeft + screen.availWidth)) + newX = (screen.availLeft + screen.availWidth) - window.outerWidth - 20; + + if (newY < screen.availTop) + newY = screen.availTop + 20; + if ((newY + window.outerHeight) > (screen.availTop + screen.availHeight)) + newY = (screen.availTop + screen.availHeight) - window.outerHeight - 60; + + window.moveTo( newX, newY ); + ]]> + </body> + </method> + + <method name="centerWindowOnScreen"> + <body> + <![CDATA[ + var xOffset = screen.availWidth / 2 - window.outerWidth / 2; + var yOffset = screen.availHeight / 2 - window.outerHeight / 2; + + xOffset = xOffset > 0 ? xOffset : 0; + yOffset = yOffset > 0 ? yOffset : 0; + window.moveTo(xOffset, yOffset); + ]]> + </body> + </method> + + <constructor> + <![CDATA[ + this._configureButtons(this.buttons); + + // listen for when window is closed via native close buttons + window.addEventListener("close", this._closeHandler); + + // for things that we need to initialize after onload fires + window.addEventListener("load", this.postLoadInit); + + window.moveToAlertPosition = this.moveToAlertPosition; + window.centerWindowOnScreen = this.centerWindowOnScreen; + ]]> + </constructor> + + <method name="postLoadInit"> + <parameter name="aEvent"/> + <body> + <![CDATA[ + function focusInit() { + const dialog = document.documentElement; + const defaultButton = dialog.getButton(dialog.defaultButton); + // give focus to the first focusable element in the dialog + if (!document.commandDispatcher.focusedElement) { + document.commandDispatcher.advanceFocusIntoSubtree(dialog); + + var focusedElt = document.commandDispatcher.focusedElement; + if (focusedElt) { + var initialFocusedElt = focusedElt; + while (focusedElt.localName == "tab" || + focusedElt.getAttribute("noinitialfocus") == "true") { + document.commandDispatcher.advanceFocusIntoSubtree(focusedElt); + focusedElt = document.commandDispatcher.focusedElement; + if (focusedElt == initialFocusedElt) { + if (focusedElt.getAttribute("noinitialfocus") == "true") { + focusedElt.blur(); + } + break; + } + } + + if (initialFocusedElt.localName == "tab") { + if (focusedElt.hasAttribute("dlgtype")) { + // We don't want to focus on anonymous OK, Cancel, etc. buttons, + // so return focus to the tab itself + initialFocusedElt.focus(); + } + } else if (!/Mac/.test(navigator.platform) && + focusedElt.hasAttribute("dlgtype") && focusedElt != defaultButton) { + defaultButton.focus(); + } + } + } + + try { + if (defaultButton) + window.notifyDefaultButtonLoaded(defaultButton); + } catch (e) { } + } + + // Give focus after onload completes, see bug 103197. + setTimeout(focusInit, 0); + ]]> + </body> + </method> + + <method name="openHelp"> + <parameter name="event"/> + <body> + <![CDATA[ + var helpButton = document.documentElement.getButton("help"); + if (helpButton.disabled || helpButton.hidden) + return; + this._fireButtonEvent("help"); + event.stopPropagation(); + event.preventDefault(); + ]]> + </body> + </method> + + <property name="mStrBundle"> + <getter> + <![CDATA[ + if (!this._mStrBundle) { + // need to create string bundle manually instead of using <xul:stringbundle/> + // see bug 63370 for details + this._mStrBundle = Cc["@mozilla.org/intl/stringbundle;1"] + .getService(Ci.nsIStringBundleService) + .createBundle("chrome://global/locale/dialog.properties"); + } + return this._mStrBundle; + ]]></getter> + </property> + + <method name="_configureButtons"> + <parameter name="aButtons"/> + <body> + <![CDATA[ + // by default, get all the anonymous button elements + var buttons = {}; + this._buttons = buttons; + buttons.accept = document.getAnonymousElementByAttribute(this, "dlgtype", "accept"); + buttons.cancel = document.getAnonymousElementByAttribute(this, "dlgtype", "cancel"); + buttons.extra1 = document.getAnonymousElementByAttribute(this, "dlgtype", "extra1"); + buttons.extra2 = document.getAnonymousElementByAttribute(this, "dlgtype", "extra2"); + buttons.help = document.getAnonymousElementByAttribute(this, "dlgtype", "help"); + buttons.disclosure = document.getAnonymousElementByAttribute(this, "dlgtype", "disclosure"); + + // look for any overriding explicit button elements + var exBtns = this.getElementsByAttribute("dlgtype", "*"); + var dlgtype; + var i; + for (i = 0; i < exBtns.length; ++i) { + dlgtype = exBtns[i].getAttribute("dlgtype"); + buttons[dlgtype].hidden = true; // hide the anonymous button + buttons[dlgtype] = exBtns[i]; + } + + // add the label and oncommand handler to each button + for (dlgtype in buttons) { + var button = buttons[dlgtype]; + button.addEventListener("command", this._handleButtonCommand, true); + + // don't override custom labels with pre-defined labels on explicit buttons + if (!button.hasAttribute("label")) { + // dialog attributes override the default labels in dialog.properties + if (this.hasAttribute("buttonlabel" + dlgtype)) { + button.setAttribute("label", this.getAttribute("buttonlabel" + dlgtype)); + if (this.hasAttribute("buttonaccesskey" + dlgtype)) + button.setAttribute("accesskey", this.getAttribute("buttonaccesskey" + dlgtype)); + } else if (dlgtype != "extra1" && dlgtype != "extra2") { + button.setAttribute("label", this.mStrBundle.GetStringFromName("button-" + dlgtype)); + var accessKey = this.mStrBundle.GetStringFromName("accesskey-" + dlgtype); + if (accessKey) + button.setAttribute("accesskey", accessKey); + } + } + // allow specifying alternate icons in the dialog header + if (!button.hasAttribute("icon")) { + // if there's an icon specified, use that + if (this.hasAttribute("buttonicon" + dlgtype)) + button.setAttribute("icon", this.getAttribute("buttonicon" + dlgtype)); + // otherwise set defaults + else + switch (dlgtype) { + case "accept": + button.setAttribute("icon", "accept"); + break; + case "cancel": + button.setAttribute("icon", "cancel"); + break; + case "disclosure": + button.setAttribute("icon", "properties"); + break; + case "help": + button.setAttribute("icon", "help"); + break; + default: + break; + } + } + } + + // ensure that hitting enter triggers the default button command + this.defaultButton = this.defaultButton; + + // if there is a special button configuration, use it + if (aButtons) { + // expect a comma delimited list of dlgtype values + var list = aButtons.split(","); + + // mark shown dlgtypes as true + var shown = { accept: false, cancel: false, help: false, + disclosure: false, extra1: false, extra2: false }; + for (i = 0; i < list.length; ++i) + shown[list[i].replace(/ /g, "")] = true; + + // hide/show the buttons we want + for (dlgtype in buttons) + buttons[dlgtype].hidden = !shown[dlgtype]; + + // show the spacer on Windows only when the extra2 button is present + if (/Win/.test(navigator.platform)) { + var spacer = document.getAnonymousElementByAttribute(this, "anonid", "spacer"); + spacer.removeAttribute("hidden"); + spacer.setAttribute("flex", shown.extra2 ? "1" : "0"); + } + } + ]]> + </body> + </method> + + <method name="_setDefaultButton"> + <parameter name="aNewDefault"/> + <body> + <![CDATA[ + // remove the default attribute from the previous default button, if any + var oldDefaultButton = this.getButton(this.defaultButton); + if (oldDefaultButton) + oldDefaultButton.removeAttribute("default"); + + var newDefaultButton = this.getButton(aNewDefault); + if (newDefaultButton) { + this.setAttribute("defaultButton", aNewDefault); + newDefaultButton.setAttribute("default", "true"); + } else { + this.setAttribute("defaultButton", "none"); + if (aNewDefault != "none") + dump("invalid new default button: " + aNewDefault + ", assuming: none\n"); + } + ]]> + </body> + </method> + + <method name="_handleButtonCommand"> + <parameter name="aEvent"/> + <body> + <![CDATA[ + return document.documentElement._doButtonCommand( + aEvent.target.getAttribute("dlgtype")); + ]]> + </body> + </method> + + <method name="_doButtonCommand"> + <parameter name="aDlgType"/> + <body> + <![CDATA[ + var button = this.getButton(aDlgType); + if (!button.disabled) { + var noCancel = this._fireButtonEvent(aDlgType); + if (noCancel) { + if (aDlgType == "accept" || aDlgType == "cancel") { + var closingEvent = new CustomEvent("dialogclosing", { + bubbles: true, + detail: { button: aDlgType }, + }); + this.dispatchEvent(closingEvent); + window.close(); + } + } + return noCancel; + } + return true; + ]]> + </body> + </method> + + <method name="_fireButtonEvent"> + <parameter name="aDlgType"/> + <body> + <![CDATA[ + var event = document.createEvent("Events"); + event.initEvent("dialog" + aDlgType, true, true); + + // handle dom event handlers + var noCancel = this.dispatchEvent(event); + + // handle any xml attribute event handlers + var handler = this.getAttribute("ondialog" + aDlgType); + if (handler != "") { + var fn = new Function("event", handler); + var returned = fn(event); + // eslint-disable-next-line mozilla/no-compare-against-boolean-literals + if (returned == false) + noCancel = false; + } + + return noCancel; + ]]> + </body> + </method> + + <method name="_hitEnter"> + <parameter name="evt"/> + <body> + <![CDATA[ + if (evt.defaultPrevented) + return; + + var btn = this.getButton(this.defaultButton); + if (btn) + this._doButtonCommand(this.defaultButton); + ]]> + </body> + </method> + + </implementation> + + <handlers> + <handler event="keypress" keycode="VK_RETURN" + group="system" action="this._hitEnter(event);"/> + <handler event="keypress" keycode="VK_ESCAPE" group="system"> + if (!event.defaultPrevented) + this.cancelDialog(); + </handler> +#ifdef XP_MACOSX + <handler event="keypress" key="." modifiers="meta" phase="capturing" action="this.cancelDialog();"/> +#else + <handler event="focus" phase="capturing"> + var btn = this.getButton(this.defaultButton); + if (btn) + btn.setAttribute("default", event.originalTarget == btn || !(event.originalTarget instanceof Ci.nsIDOMXULButtonElement)); + </handler> +#endif + </handlers> + + </binding> + +</bindings> diff -up firefox-60.5.0/toolkit/mozapps/downloads/nsHelperAppDlg.js.mozilla-kde firefox-60.5.0/toolkit/mozapps/downloads/nsHelperAppDlg.js --- firefox-60.5.0/toolkit/mozapps/downloads/nsHelperAppDlg.js.mozilla-kde 2019-01-24 18:31:47.000000000 +0100 +++ firefox-60.5.0/toolkit/mozapps/downloads/nsHelperAppDlg.js 2019-01-31 20:24:11.297699013 +0100 @@ -632,7 +632,7 @@ nsUnknownContentTypeDialog.prototype = { let [size, unit] = DownloadUtils. convertByteUnits(this.mLauncher.contentLength); type.value = this.dialogElement("strings") - .getFormattedString("orderedFileSizeWithType", + .getFormattedString("orderedFileSizeWithType", [typeString, size, unit]); } else { @@ -806,7 +806,7 @@ nsUnknownContentTypeDialog.prototype = { case 1: // only enable the OK button if we have a default app to use or if // the user chose an app.... - ok = this.chosenApp || /\S/.test(this.dialogElement("otherHandler").getAttribute("path")); + ok = this.chosenApp || /\S/.test(this.dialogElement("otherHandler").getAttribute("path")); break; } } @@ -1071,20 +1071,50 @@ nsUnknownContentTypeDialog.prototype = { 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"] diff -up firefox-60.5.0/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp.mozilla-kde firefox-60.5.0/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp --- firefox-60.5.0/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp.mozilla-kde 2019-01-24 18:31:42.000000000 +0100 +++ firefox-60.5.0/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp 2019-01-31 20:31:17.808168514 +0100 @@ -20,6 +20,7 @@ #include "nsInterfaceHashtable.h" #include "mozilla/Attributes.h" #include "nsIURI.h" +#include "nsKDEUtils.h" class nsUnixSystemProxySettings final : public nsISystemProxySettings { public: @@ -47,6 +48,8 @@ class nsUnixSystemProxySettings final : 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) @@ -490,6 +493,9 @@ nsresult nsUnixSystemProxySettings::GetP 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; @@ -523,3 +529,29 @@ static const mozilla::Module kUnixProxyM mozilla::Module::kVersion, kUnixProxyCIDs, kUnixProxyContracts}; NSMODULE_DEFN(nsUnixProxyModule) = &kUnixProxyModule; + +nsresult +nsUnixSystemProxySettings::GetProxyFromKDE(const nsACString& aScheme, + const nsACString& aHost, + PRInt32 aPort, + nsACString& aResult) +{ + nsAutoCString url; + url = aScheme; + url += "://"; + url += aHost; + if( aPort >= 0 ) + { + url += ":"; + url += nsPrintfCString("%d", aPort); + } + nsTArray<nsCString> command; + command.AppendElement( NS_LITERAL_CSTRING( "GETPROXY" )); + command.AppendElement( url ); + nsTArray<nsCString> result; + if( !nsKDEUtils::command( command, &result ) || result.Length() != 1 ) + return NS_ERROR_FAILURE; + aResult = result[0]; + return NS_OK; +} + diff -up firefox-60.5.0/toolkit/xre/moz.build.mozilla-kde firefox-60.5.0/toolkit/xre/moz.build --- firefox-60.5.0/toolkit/xre/moz.build.mozilla-kde 2019-01-24 18:31:47.000000000 +0100 +++ firefox-60.5.0/toolkit/xre/moz.build 2019-01-31 20:24:11.307699024 +0100 @@ -70,7 +70,9 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'ui 'UIKitDirProvider.mm', ] elif 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']: + EXPORTS += ['nsKDEUtils.h'] UNIFIED_SOURCES += [ + 'nsKDEUtils.cpp', 'nsNativeAppSupportUnix.cpp', ] else: diff -up firefox-60.5.0/toolkit/xre/nsKDEUtils.cpp.mozilla-kde firefox-60.5.0/toolkit/xre/nsKDEUtils.cpp --- firefox-60.5.0/toolkit/xre/nsKDEUtils.cpp.mozilla-kde 2019-01-31 20:24:11.307699024 +0100 +++ firefox-60.5.0/toolkit/xre/nsKDEUtils.cpp 2019-01-31 20:24:11.307699024 +0100 @@ -0,0 +1,344 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsKDEUtils.h" +#include "nsIWidget.h" +#include "nsISupportsPrimitives.h" +#include "nsIMutableArray.h" +#include "nsComponentManagerUtils.h" +#include "nsArrayUtils.h" + +#include <gtk/gtk.h> + +#include <limits.h> +#include <stdio.h> +#include <sys/wait.h> +#include <sys/resource.h> +#include <unistd.h> +#include <X11/Xlib.h> +// copied from X11/X.h as a hack since for an unknown +// reason it's not picked up from X11/X.h +#ifndef None +#define None 0L /* universal null resource or null atom */ +#endif + +//#define DEBUG_KDE +#ifdef DEBUG_KDE +#define KMOZILLAHELPER "kmozillahelper" +#else +// not need for lib64, it's a binary +#define KMOZILLAHELPER "/usr/lib/mozilla/kmozillahelper" +#endif + +#define KMOZILLAHELPER_VERSION 6 +#define MAKE_STR2( n ) #n +#define MAKE_STR( n ) MAKE_STR2( n ) + +static bool getKdeSession() + { + Display* dpy = XOpenDisplay( NULL ); + if( dpy == NULL ) + return false; + Atom kde_full_session = XInternAtom( dpy, "KDE_FULL_SESSION", True ); + bool kde = false; + if( kde_full_session != None ) + { + int cnt; + if( Atom* props = XListProperties( dpy, DefaultRootWindow( dpy ), &cnt )) + { + for( int i = 0; + i < cnt; + ++i ) + { + if( props[ i ] == kde_full_session ) + { + kde = true; +#ifdef DEBUG_KDE + fprintf( stderr, "KDE SESSION %d\n", kde ); +#endif + break; + } + } + XFree( props ); + } + } + XCloseDisplay( dpy ); + return kde; + } + +static bool getKdeSupport() + { + nsTArray<nsCString> command; + command.AppendElement( NS_LITERAL_CSTRING( "CHECK" )); + command.AppendElement( NS_LITERAL_CSTRING( MAKE_STR( KMOZILLAHELPER_VERSION ))); + bool kde = nsKDEUtils::command( command ); +#ifdef DEBUG_KDE + fprintf( stderr, "KDE RUNNING %d\n", kde ); +#endif + return kde; + } + +nsKDEUtils::nsKDEUtils() + : commandFile( NULL ) + , replyFile( NULL ) + { + } + +nsKDEUtils::~nsKDEUtils() + { +// closeHelper(); not actually useful, exiting will close the fd too + } + +nsKDEUtils* nsKDEUtils::self() + { + static nsKDEUtils s; + return &s; + } + +static bool helperRunning = false; +static bool helperFailed = false; + +bool nsKDEUtils::kdeSession() + { + static bool session = getKdeSession(); + return session; + } + +bool nsKDEUtils::kdeSupport() + { + static bool support = kdeSession() && getKdeSupport(); + return support && helperRunning; + } + +struct nsKDECommandData + { + FILE* file; + nsTArray<nsCString>* output; + GMainLoop* loop; + bool success; + }; + +static gboolean kdeReadFunc( GIOChannel*, GIOCondition, gpointer data ) + { + nsKDECommandData* p = static_cast< nsKDECommandData* >( data ); + char buf[ 8192 ]; // TODO big enough + bool command_done = false; + bool command_failed = false; + while( !command_done && !command_failed && fgets( buf, 8192, p->file ) != NULL ) + { // TODO what if the kernel splits a line into two chunks? +//#ifdef DEBUG_KDE +// fprintf( stderr, "READ: %s %d\n", buf, feof( p->file )); +//#endif + if( char* eol = strchr( buf, '\n' )) + *eol = '\0'; + command_done = ( strcmp( buf, "\\1" ) == 0 ); + command_failed = ( strcmp( buf, "\\0" ) == 0 ); + nsAutoCString line( buf ); + line.ReplaceSubstring( "\\n", "\n" ); + line.ReplaceSubstring( "\\" "\\", "\\" ); // \\ -> \ , i.e. unescape + if( p->output && !( command_done || command_failed )) + p->output->AppendElement( nsCString( buf )); // TODO utf8? + } + bool quit = false; + if( feof( p->file ) || command_failed ) + { + quit = true; + p->success = false; + } + if( command_done ) + { // reading one reply finished + quit = true; + p->success = true; + } + if( quit ) + { + if( p->loop ) + g_main_loop_quit( p->loop ); + return FALSE; + } + return TRUE; + } + +bool nsKDEUtils::command( const nsTArray<nsCString>& command, nsTArray<nsCString>* output ) + { + return self()->internalCommand( command, NULL, false, output ); + } + +bool nsKDEUtils::command( nsIArray* command, nsIArray** output) + { + nsTArray<nsCString> in; + PRUint32 length; + command->GetLength( &length ); + for ( PRUint32 i = 0; i < length; i++ ) + { + nsCOMPtr<nsISupportsCString> str = do_QueryElementAt( command, i ); + if( str ) + { + nsAutoCString s; + str->GetData( s ); + in.AppendElement( s ); + } + } + + nsTArray<nsCString> out; + bool ret = self()->internalCommand( in, NULL, false, &out ); + + if ( !output ) return ret; + + nsCOMPtr<nsIMutableArray> result = do_CreateInstance( NS_ARRAY_CONTRACTID ); + if ( !result ) return false; + + for ( PRUint32 i = 0; i < out.Length(); i++ ) + { + nsCOMPtr<nsISupportsCString> rstr = do_CreateInstance( NS_SUPPORTS_CSTRING_CONTRACTID ); + if ( !rstr ) return false; + + rstr->SetData( out[i] ); + result->AppendElement( rstr ); + } + + NS_ADDREF( *output = result); + return ret; + } + + +bool nsKDEUtils::commandBlockUi( const nsTArray<nsCString>& command, GtkWindow* parent, nsTArray<nsCString>* output ) + { + return self()->internalCommand( command, parent, true, output ); + } + +bool nsKDEUtils::internalCommand( const nsTArray<nsCString>& command, GtkWindow* parent, bool blockUi, + nsTArray<nsCString>* output ) + { + if( !startHelper()) + return false; + feedCommand( command ); + // do not store the data in 'this' but in extra structure, just in case there + // is reentrancy (can there be? the event loop is re-entered) + nsKDECommandData data; + data.file = replyFile; + data.output = output; + data.success = false; + if( blockUi ) + { + data.loop = g_main_loop_new( NULL, FALSE ); + GtkWidget* window = gtk_window_new( GTK_WINDOW_TOPLEVEL ); + if( parent && gtk_window_get_group(parent) ) + gtk_window_group_add_window( gtk_window_get_group(parent), GTK_WINDOW( window )); + gtk_widget_realize( window ); + gtk_widget_set_sensitive( window, TRUE ); + gtk_grab_add( window ); + GIOChannel* channel = g_io_channel_unix_new( fileno( data.file )); + g_io_add_watch( channel, static_cast< GIOCondition >( G_IO_IN | G_IO_ERR | G_IO_HUP ), kdeReadFunc, &data ); + g_io_channel_unref( channel ); + g_main_loop_run( data.loop ); + g_main_loop_unref( data.loop ); + gtk_grab_remove( window ); + gtk_widget_destroy( window ); + } + else + { + data.loop = NULL; + while( kdeReadFunc( NULL, static_cast< GIOCondition >( 0 ), &data )) + ; + } + return data.success; + } + +bool nsKDEUtils::startHelper() + { + if( helperRunning ) + return true; + if( helperFailed ) + return false; + helperFailed = true; + int fdcommand[ 2 ]; + int fdreply[ 2 ]; + if( pipe( fdcommand ) < 0 ) + return false; + if( pipe( fdreply ) < 0 ) + { + close( fdcommand[ 0 ] ); + close( fdcommand[ 1 ] ); + return false; + } + char* args[ 2 ] = { const_cast< char* >( KMOZILLAHELPER ), NULL }; + switch( fork()) + { + case -1: + { + close( fdcommand[ 0 ] ); + close( fdcommand[ 1 ] ); + close( fdreply[ 0 ] ); + close( fdreply[ 1 ] ); + return false; + } + case 0: // child + { + if( dup2( fdcommand[ 0 ], STDIN_FILENO ) < 0 ) + _exit( 1 ); + if( dup2( fdreply[ 1 ], STDOUT_FILENO ) < 0 ) + _exit( 1 ); + int maxfd = 1024; // close all other fds + struct rlimit rl; + if( getrlimit( RLIMIT_NOFILE, &rl ) == 0 ) + maxfd = rl.rlim_max; + for( int i = 3; + i < maxfd; + ++i ) + close( i ); +#ifdef DEBUG_KDE + execvp( KMOZILLAHELPER, args ); +#else + execv( KMOZILLAHELPER, args ); +#endif + _exit( 1 ); // failed + } + default: // parent + { + commandFile = fdopen( fdcommand[ 1 ], "w" ); + replyFile = fdopen( fdreply[ 0 ], "r" ); + close( fdcommand[ 0 ] ); + close( fdreply[ 1 ] ); + if( commandFile == NULL || replyFile == NULL ) + { + closeHelper(); + return false; + } + // ok, helper ready, getKdeRunning() will check if it works + } + } + helperFailed = false; + helperRunning = true; + return true; + } + +void nsKDEUtils::closeHelper() + { + if( commandFile != NULL ) + fclose( commandFile ); // this will also make the helper quit + if( replyFile != NULL ) + fclose( replyFile ); + helperRunning = false; + } + +void nsKDEUtils::feedCommand( const nsTArray<nsCString>& command ) + { + for( int i = 0; + i < command.Length(); + ++i ) + { + nsCString line = command[ i ]; + line.ReplaceSubstring( "\\", "\\" "\\" ); // \ -> \\ , i.e. escape + line.ReplaceSubstring( "\n", "\\n" ); +#ifdef DEBUG_KDE + fprintf( stderr, "COMM: %s\n", line.get()); +#endif + fputs( line.get(), commandFile ); + fputs( "\n", commandFile ); + } + fputs( "\\E\n", commandFile ); // done as \E, so it cannot happen in normal data + fflush( commandFile ); + } diff -up firefox-60.5.0/toolkit/xre/nsKDEUtils.h.mozilla-kde firefox-60.5.0/toolkit/xre/nsKDEUtils.h --- firefox-60.5.0/toolkit/xre/nsKDEUtils.h.mozilla-kde 2019-01-31 20:24:11.307699024 +0100 +++ firefox-60.5.0/toolkit/xre/nsKDEUtils.h 2019-01-31 20:24:11.307699024 +0100 @@ -0,0 +1,48 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef nsKDEUtils_h__ +#define nsKDEUtils_h__ + +#include "nsString.h" +#include "nsTArray.h" +#include <stdio.h> + +typedef struct _GtkWindow GtkWindow; + +class nsIArray; + +class NS_EXPORT nsKDEUtils + { + public: + /* Returns true if running inside a KDE session (regardless of whether there is KDE + support available for Firefox). This should be used e.g. when determining + dialog button order but not for code that requires the KDE support. */ + static bool kdeSession(); + /* Returns true if running inside a KDE session and KDE support is available + for Firefox. This should be used everywhere where the external helper is needed. */ + static bool kdeSupport(); + /* Executes the given helper command, returns true if helper returned success. */ + static bool command( const nsTArray<nsCString>& command, nsTArray<nsCString>* output = NULL ); + static bool command( nsIArray* command, nsIArray** output = NULL ); + /* Like command(), but additionally blocks the parent widget like if there was + a modal dialog shown and enters the event loop (i.e. there are still paint updates, + this is for commands that take long). */ + static bool commandBlockUi( const nsTArray<nsCString>& command, GtkWindow* parent, nsTArray<nsCString>* output = NULL ); + + private: + nsKDEUtils(); + ~nsKDEUtils(); + static nsKDEUtils* self(); + bool startHelper(); + void closeHelper(); + void feedCommand( const nsTArray<nsCString>& command ); + bool internalCommand( const nsTArray<nsCString>& command, GtkWindow* parent, bool isParent, + nsTArray<nsCString>* output ); + FILE* commandFile; + FILE* replyFile; + }; + +#endif // nsKDEUtils diff -up firefox-60.5.0/uriloader/exthandler/HandlerServiceParent.cpp.mozilla-kde firefox-60.5.0/uriloader/exthandler/HandlerServiceParent.cpp --- firefox-60.5.0/uriloader/exthandler/HandlerServiceParent.cpp.mozilla-kde 2019-01-24 18:31:46.000000000 +0100 +++ firefox-60.5.0/uriloader/exthandler/HandlerServiceParent.cpp 2019-01-31 20:24:11.307699024 +0100 @@ -5,7 +5,7 @@ #include "ContentHandlerService.h" #include "nsStringEnumerator.h" #ifdef MOZ_WIDGET_GTK -#include "unix/nsGNOMERegistry.h" +#include "unix/nsCommonRegistry.h" #endif using mozilla::dom::ContentHandlerService; @@ -250,7 +250,7 @@ mozilla::ipc::IPCResult HandlerServicePa const nsCString& aProtocolScheme, bool* aHandlerExists) { #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 diff -up firefox-60.5.0/uriloader/exthandler/moz.build.mozilla-kde firefox-60.5.0/uriloader/exthandler/moz.build --- firefox-60.5.0/uriloader/exthandler/moz.build.mozilla-kde 2019-01-24 18:31:43.000000000 +0100 +++ firefox-60.5.0/uriloader/exthandler/moz.build 2019-01-31 20:24:11.317699035 +0100 @@ -82,7 +82,9 @@ else: if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']: UNIFIED_SOURCES += [ + 'unix/nsCommonRegistry.cpp', 'unix/nsGNOMERegistry.cpp', + 'unix/nsKDERegistry.cpp', 'unix/nsMIMEInfoUnix.cpp', ] elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android': @@ -129,6 +131,7 @@ LOCAL_INCLUDES += [ '/dom/ipc', '/netwerk/base', '/netwerk/protocol/http', + '/toolkit/xre', ] if CONFIG['MOZ_ENABLE_DBUS']: diff -up firefox-60.5.0/uriloader/exthandler/unix/nsCommonRegistry.cpp.mozilla-kde firefox-60.5.0/uriloader/exthandler/unix/nsCommonRegistry.cpp --- firefox-60.5.0/uriloader/exthandler/unix/nsCommonRegistry.cpp.mozilla-kde 2019-01-31 20:24:11.317699035 +0100 +++ firefox-60.5.0/uriloader/exthandler/unix/nsCommonRegistry.cpp 2019-01-31 20:24:11.317699035 +0100 @@ -0,0 +1,53 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsCommonRegistry.h" + +#include "nsGNOMERegistry.h" +#include "nsKDERegistry.h" +#include "nsString.h" +#include "nsKDEUtils.h" + +/* static */ bool +nsCommonRegistry::HandlerExists(const char *aProtocolScheme) +{ + if( nsKDEUtils::kdeSupport()) + return nsKDERegistry::HandlerExists( aProtocolScheme ); + return nsGNOMERegistry::HandlerExists( aProtocolScheme ); +} + +/* static */ nsresult +nsCommonRegistry::LoadURL(nsIURI *aURL) +{ + if( nsKDEUtils::kdeSupport()) + return nsKDERegistry::LoadURL( aURL ); + return nsGNOMERegistry::LoadURL( aURL ); +} + +/* static */ void +nsCommonRegistry::GetAppDescForScheme(const nsACString& aScheme, + nsAString& aDesc) +{ + if( nsKDEUtils::kdeSupport()) + return nsKDERegistry::GetAppDescForScheme( aScheme, aDesc ); + return nsGNOMERegistry::GetAppDescForScheme( aScheme, aDesc ); +} + + +/* static */ already_AddRefed<nsMIMEInfoBase> +nsCommonRegistry::GetFromExtension(const nsACString& aFileExt) +{ + if( nsKDEUtils::kdeSupport()) + return nsKDERegistry::GetFromExtension( aFileExt ); + return nsGNOMERegistry::GetFromExtension( aFileExt ); +} + +/* static */ already_AddRefed<nsMIMEInfoBase> +nsCommonRegistry::GetFromType(const nsACString& aMIMEType) +{ + if( nsKDEUtils::kdeSupport()) + return nsKDERegistry::GetFromType( aMIMEType ); + return nsGNOMERegistry::GetFromType( aMIMEType ); +} diff -up firefox-60.5.0/uriloader/exthandler/unix/nsCommonRegistry.h.mozilla-kde firefox-60.5.0/uriloader/exthandler/unix/nsCommonRegistry.h --- firefox-60.5.0/uriloader/exthandler/unix/nsCommonRegistry.h.mozilla-kde 2019-01-31 20:24:11.317699035 +0100 +++ firefox-60.5.0/uriloader/exthandler/unix/nsCommonRegistry.h 2019-01-31 20:24:11.317699035 +0100 @@ -0,0 +1,28 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef nsCommonRegistry_h__ +#define nsCommonRegistry_h__ + +#include "nsIURI.h" +#include "nsCOMPtr.h" + +class nsMIMEInfoBase; + +class nsCommonRegistry +{ + public: + static bool HandlerExists(const char *aProtocolScheme); + + static nsresult LoadURL(nsIURI *aURL); + + static void GetAppDescForScheme(const nsACString& aScheme, + nsAString& aDesc); + + static already_AddRefed<nsMIMEInfoBase> GetFromExtension(const nsACString& aFileExt); + + static already_AddRefed<nsMIMEInfoBase> GetFromType(const nsACString& aMIMEType); +}; + +#endif diff -up firefox-60.5.0/uriloader/exthandler/unix/nsKDERegistry.cpp.mozilla-kde firefox-60.5.0/uriloader/exthandler/unix/nsKDERegistry.cpp --- firefox-60.5.0/uriloader/exthandler/unix/nsKDERegistry.cpp.mozilla-kde 2019-01-31 20:24:11.317699035 +0100 +++ firefox-60.5.0/uriloader/exthandler/unix/nsKDERegistry.cpp 2019-01-31 20:24:11.317699035 +0100 @@ -0,0 +1,87 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsKDERegistry.h" +#include "prlink.h" +#include "prmem.h" +#include "nsString.h" +#include "nsMIMEInfoUnix.h" +#include "nsAutoPtr.h" +#include "nsKDEUtils.h" + +/* static */ bool +nsKDERegistry::HandlerExists(const char *aProtocolScheme) +{ + nsTArray<nsCString> command; + command.AppendElement( NS_LITERAL_CSTRING( "HANDLEREXISTS" )); + command.AppendElement( nsAutoCString( aProtocolScheme )); + return nsKDEUtils::command( command ); +} + +/* static */ nsresult +nsKDERegistry::LoadURL(nsIURI *aURL) +{ + nsTArray<nsCString> command; + command.AppendElement( NS_LITERAL_CSTRING( "OPEN" )); + nsCString url; + aURL->GetSpec( url ); + command.AppendElement( url ); + bool rv = nsKDEUtils::command( command ); + if (!rv) + return NS_ERROR_FAILURE; + + return NS_OK; +} + +/* static */ void +nsKDERegistry::GetAppDescForScheme(const nsACString& aScheme, + nsAString& aDesc) +{ + nsTArray<nsCString> command; + command.AppendElement( NS_LITERAL_CSTRING( "GETAPPDESCFORSCHEME" )); + command.AppendElement( aScheme ); + nsTArray<nsCString> output; + if( nsKDEUtils::command( command, &output ) && output.Length() == 1 ) + CopyUTF8toUTF16( output[ 0 ], aDesc ); +} + + +/* static */ already_AddRefed<nsMIMEInfoBase> +nsKDERegistry::GetFromExtension(const nsACString& aFileExt) +{ + NS_ASSERTION(aFileExt[0] != '.', "aFileExt shouldn't start with a dot"); + nsTArray<nsCString> command; + command.AppendElement( NS_LITERAL_CSTRING( "GETFROMEXTENSION" )); + command.AppendElement( aFileExt ); + return GetFromHelper( command ); +} + +/* static */ already_AddRefed<nsMIMEInfoBase> +nsKDERegistry::GetFromType(const nsACString& aMIMEType) +{ + nsTArray<nsCString> command; + command.AppendElement( NS_LITERAL_CSTRING( "GETFROMTYPE" )); + command.AppendElement( aMIMEType ); + return GetFromHelper( command ); +} + +/* static */ already_AddRefed<nsMIMEInfoBase> +nsKDERegistry::GetFromHelper(const nsTArray<nsCString>& command) +{ + nsTArray<nsCString> output; + if( nsKDEUtils::command( command, &output ) && output.Length() == 3 ) + { + nsCString mimetype = output[ 0 ]; + RefPtr<nsMIMEInfoUnix> 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 -up firefox-60.5.0/uriloader/exthandler/unix/nsKDERegistry.h.mozilla-kde firefox-60.5.0/uriloader/exthandler/unix/nsKDERegistry.h --- firefox-60.5.0/uriloader/exthandler/unix/nsKDERegistry.h.mozilla-kde 2019-01-31 20:24:11.317699035 +0100 +++ firefox-60.5.0/uriloader/exthandler/unix/nsKDERegistry.h 2019-01-31 20:24:11.317699035 +0100 @@ -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<nsMIMEInfoBase> GetFromExtension(const nsACString& aFileExt); + + static already_AddRefed<nsMIMEInfoBase> GetFromType(const nsACString& aMIMEType); + private: + static already_AddRefed<nsMIMEInfoBase> GetFromHelper(const nsTArray<nsCString>& command); + +}; + +#endif //nsKDERegistry_h__ diff -up firefox-60.5.0/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp.mozilla-kde firefox-60.5.0/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp --- firefox-60.5.0/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp.mozilla-kde 2019-01-24 18:31:47.000000000 +0100 +++ firefox-60.5.0/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp 2019-01-31 20:56:12.450143516 +0100 @@ -5,7 +5,7 @@ * 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" @@ -13,9 +13,12 @@ #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 @@ -28,15 +31,15 @@ nsMIMEInfoUnix::GetHasDefaultHandler(boo *_retval = false; if (mClass == eProtocolInfo) { - *_retval = nsGNOMERegistry::HandlerExists(mSchemeOrType.get()); + *_retval = nsCommonRegistry::HandlerExists(mSchemeOrType.get()); } else { RefPtr<nsMIMEInfoBase> 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; @@ -56,6 +59,23 @@ nsresult nsMIMEInfoUnix::LaunchDefaultWi nsAutoCString nativePath; aFile->GetNativePath(nativePath); + if( nsKDEUtils::kdeSupport()) { + bool supports; + if( NS_SUCCEEDED( GetHasDefaultHandler( &supports )) && supports ) { + nsTArray<nsCString> command; + command.AppendElement( NS_LITERAL_CSTRING( "OPEN" )); + command.AppendElement( nativePath ); + command.AppendElement( NS_LITERAL_CSTRING( "MIMETYPE" )); + command.AppendElement( mSchemeOrType ); + if( nsKDEUtils::command( command )) + return NS_OK; + } + if (!mDefaultApplication) + return NS_ERROR_FILE_NOT_FOUND; + + return LaunchWithIProcess(mDefaultApplication, nativePath); + } + nsCOMPtr<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID); if (!giovfs) { return NS_ERROR_FAILURE; diff -up firefox-60.5.0/uriloader/exthandler/unix/nsOSHelperAppService.cpp.mozilla-kde firefox-60.5.0/uriloader/exthandler/unix/nsOSHelperAppService.cpp --- firefox-60.5.0/uriloader/exthandler/unix/nsOSHelperAppService.cpp.mozilla-kde 2019-01-24 18:31:47.000000000 +0100 +++ firefox-60.5.0/uriloader/exthandler/unix/nsOSHelperAppService.cpp 2019-01-31 20:32:05.148220602 +0100 @@ -10,7 +10,7 @@ #include "nsOSHelperAppService.h" #include "nsMIMEInfoUnix.h" #ifdef MOZ_WIDGET_GTK -#include "nsGNOMERegistry.h" +#include "nsCommonRegistry.h" #endif #include "nsISupports.h" #include "nsString.h" @@ -1045,7 +1045,7 @@ nsresult nsOSHelperAppService::OSProtoco 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 @@ -1065,7 +1065,7 @@ nsresult nsOSHelperAppService::OSProtoco 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; @@ -1156,7 +1156,7 @@ already_AddRefed<nsMIMEInfoBase> nsOSHel #ifdef MOZ_WIDGET_GTK LOG(("Looking in GNOME registry\n")); RefPtr<nsMIMEInfoBase> gnomeInfo = - nsGNOMERegistry::GetFromExtension(aFileExt); + nsCommonRegistry::GetFromExtension(aFileExt); if (gnomeInfo) { LOG(("Got MIMEInfo from GNOME registry\n")); return gnomeInfo.forget(); @@ -1268,7 +1268,7 @@ already_AddRefed<nsMIMEInfoBase> nsOSHel #ifdef MOZ_WIDGET_GTK if (handler.IsEmpty()) { - RefPtr<nsMIMEInfoBase> gnomeInfo = nsGNOMERegistry::GetFromType(aMIMEType); + RefPtr<nsMIMEInfoBase> gnomeInfo = nsCommonRegistry::GetFromType(aMIMEType); if (gnomeInfo) { LOG( ("Got MIMEInfo from GNOME registry without extensions; setting them " diff -up firefox-60.5.0/widget/gtk/moz.build.mozilla-kde firefox-60.5.0/widget/gtk/moz.build --- firefox-60.5.0/widget/gtk/moz.build.mozilla-kde 2019-01-24 18:31:47.000000000 +0100 +++ firefox-60.5.0/widget/gtk/moz.build 2019-01-31 20:24:11.327699047 +0100 @@ -126,6 +126,7 @@ LOCAL_INCLUDES += [ '/layout/generic', '/layout/xul', '/other-licenses/atk-1.0', + '/toolkit/xre', '/widget', '/widget/headless', ] diff -up firefox-60.5.0/widget/gtk/nsFilePicker.cpp.mozilla-kde firefox-60.5.0/widget/gtk/nsFilePicker.cpp --- firefox-60.5.0/widget/gtk/nsFilePicker.cpp.mozilla-kde 2019-01-24 18:31:43.000000000 +0100 +++ firefox-60.5.0/widget/gtk/nsFilePicker.cpp 2019-01-31 20:24:11.337699057 +0100 @@ -9,6 +9,7 @@ #include <unistd.h> #include <gtk/gtk.h> +#include <gdk/gdkx.h> #include "nsGtkUtils.h" #include "nsIFileURL.h" @@ -25,6 +26,7 @@ #include "mozcontainer.h" #include "nsFilePicker.h" +#include "nsKDEUtils.h" using namespace mozilla; @@ -230,7 +232,9 @@ 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; @@ -340,6 +344,29 @@ 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()) { + 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; + } + nsCString title; title.Adopt(ToNewUTF8String(mTitle)); @@ -577,3 +604,228 @@ void nsFilePicker::Done(GtkWidget *file_ } 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<nsCString> command; + command.AppendElement( nsAutoCString( arg )); + command.AppendElement( startdir ); + if( mMode != nsIFilePicker::modeGetFolder ) + { + command.AppendElement( filters ); + nsAutoCString selected; + selected.AppendInt( mSelectedType ); + command.AppendElement( selected ); + } + command.AppendElement( title ); + if( mMode == nsIFilePicker::modeOpenMultiple ) + command.AppendElement( NS_LITERAL_CSTRING( "MULTIPLE" )); + if( PRInt32 xid = windowToXid( mParentWidget )) + { + command.AppendElement( NS_LITERAL_CSTRING( "PARENT" )); + nsAutoCString parent; + parent.AppendInt( xid ); + command.AppendElement( parent ); + } + + nsTArray<nsCString> 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<nsIFile> localfile; + nsresult rv = NS_NewNativeLocalFile( output[ i ], + PR_FALSE, + getter_AddRefs(localfile)); + if (NS_SUCCEEDED(rv)) + mFiles.AppendObject(localfile); + } + } + else + { + if( output.Length() == 0 ) + mFileURL = nsCString(); + else if( mAllowURLs ) + mFileURL = output[ 0 ]; + else // GetFile() actually requires it to be url even for local files :-/ + { + mFileURL = nsCString( "file://" ); + mFileURL.Append( output[ 0 ] ); + } + } + // Remember last used directory. + nsCOMPtr<nsIFile> file; + GetFile(getter_AddRefs(file)); + if (file) { + nsCOMPtr<nsIFile> dir; + file->GetParent(getter_AddRefs(dir)); + nsCOMPtr<nsIFile> localDir(do_QueryInterface(dir)); + if (localDir) { + localDir.swap(mPrevDisplayDirectory); + } + } + if (mMode == nsIFilePicker::modeSave) + { + nsCOMPtr<nsIFile> 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<nsCString> command; + command.AppendElement( NS_LITERAL_CSTRING( "APPSDIALOG" )); + command.AppendElement( title ); + if( PRInt32 xid = windowToXid( mParentWidget )) + { + command.AppendElement( NS_LITERAL_CSTRING( "PARENT" )); + nsAutoCString parent; + parent.AppendInt( xid ); + command.AppendElement( parent ); + } + + nsTArray<nsCString> output; + if( nsKDEUtils::commandBlockUi( command, GTK_WINDOW(mParentWidget->GetNativeData(NS_NATIVE_SHELLWIDGET)), &output )) + { + *aReturn = nsIFilePicker::returnOK; + mFileURL = output.Length() > 0 ? output[ 0 ] : nsCString(); + } + else + { + *aReturn = nsIFilePicker::returnCancel; + } + return NS_OK; + } + diff -up firefox-60.5.0/widget/gtk/nsFilePicker.h.mozilla-kde firefox-60.5.0/widget/gtk/nsFilePicker.h --- firefox-60.5.0/widget/gtk/nsFilePicker.h.mozilla-kde 2019-01-24 18:31:42.000000000 +0100 +++ firefox-60.5.0/widget/gtk/nsFilePicker.h 2019-01-31 20:24:11.337699057 +0100 @@ -72,6 +72,12 @@ class nsFilePicker : public nsBaseFilePi private: static nsIFile* mPrevDisplayDirectory; + bool kdeRunning(); + bool getKdeRunning(); + NS_IMETHODIMP kdeFileDialog(PRInt16 *aReturn); + NS_IMETHODIMP kdeAppsDialog(PRInt16 *aReturn); + nsCString kdeMakeFilter( int index ); + #ifdef MOZ_WIDGET_GTK GtkFileChooserWidget* mFileChooserDelegate; #endif diff -up firefox-60.5.0/xpcom/components/ManifestParser.cpp.mozilla-kde firefox-60.5.0/xpcom/components/ManifestParser.cpp --- firefox-60.5.0/xpcom/components/ManifestParser.cpp.mozilla-kde 2019-01-24 18:31:42.000000000 +0100 +++ firefox-60.5.0/xpcom/components/ManifestParser.cpp 2019-01-31 20:26:38.247860704 +0100 @@ -38,6 +38,7 @@ #include "nsIScriptError.h" #include "nsIXULAppInfo.h" #include "nsIXULRuntime.h" +#include "nsKDEUtils.h" using namespace mozilla; @@ -423,6 +424,7 @@ void ParseManifest(NSLocationType aType, NS_NAMED_LITERAL_STRING(kOs, "os"); NS_NAMED_LITERAL_STRING(kOsVersion, "osversion"); NS_NAMED_LITERAL_STRING(kABI, "abi"); + NS_NAMED_LITERAL_STRING(kDesktop, "desktop"); NS_NAMED_LITERAL_STRING(kProcess, "process"); #if defined(MOZ_WIDGET_ANDROID) NS_NAMED_LITERAL_STRING(kTablet, "tablet"); @@ -478,6 +480,7 @@ void ParseManifest(NSLocationType aType, } nsAutoString osVersion; + nsAutoString desktop; #if defined(XP_WIN) #pragma warning(push) #pragma warning(disable : 4996) // VC12+ deprecates GetVersionEx @@ -486,14 +489,17 @@ void ParseManifest(NSLocationType aType, nsTextFormatter::ssprintf(osVersion, u"%ld.%ld", info.dwMajorVersion, info.dwMinorVersion); } + desktop = NS_LITERAL_STRING("win"); #pragma warning(pop) #elif defined(MOZ_WIDGET_COCOA) SInt32 majorVersion = nsCocoaFeatures::OSXVersionMajor(); SInt32 minorVersion = nsCocoaFeatures::OSXVersionMinor(); nsTextFormatter::ssprintf(osVersion, u"%ld.%ld", majorVersion, minorVersion); + desktop = NS_LITERAL_STRING("macosx"); #elif defined(MOZ_WIDGET_GTK) nsTextFormatter::ssprintf(osVersion, u"%ld.%ld", gtk_major_version, gtk_minor_version); + desktop = nsKDEUtils::kdeSession() ? NS_LITERAL_STRING("kde") : NS_LITERAL_STRING("gnome"); #elif defined(MOZ_WIDGET_ANDROID) bool isTablet = false; if (mozilla::AndroidBridge::Bridge()) { @@ -501,6 +507,7 @@ void ParseManifest(NSLocationType aType, "android/os/Build$VERSION", "RELEASE", osVersion); isTablet = java::GeckoAppShell::IsTablet(); } + desktop = NS_LITERAL_STRING("android"); #endif if (XRE_IsContentProcess()) { @@ -613,6 +620,7 @@ void ParseManifest(NSLocationType aType, TriState stTablet = eUnspecified; #endif int flags = 0; + TriState stDesktop = eUnspecified; while ((token = nsCRT::strtok(whitespace, kWhitespace, &whitespace)) && ok) { @@ -622,6 +630,7 @@ void ParseManifest(NSLocationType aType, 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) || @@ -668,7 +677,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 || #ifdef MOZ_WIDGET_ANDROID stTablet == eBad || #endif diff -up firefox-60.5.0/xpcom/components/moz.build.mozilla-kde firefox-60.5.0/xpcom/components/moz.build --- firefox-60.5.0/xpcom/components/moz.build.mozilla-kde 2019-01-24 18:31:47.000000000 +0100 +++ firefox-60.5.0/xpcom/components/moz.build 2019-01-31 20:24:11.347699068 +0100 @@ -49,6 +49,7 @@ LOCAL_INCLUDES += [ '../reflect/xptinfo', '/chrome', '/modules/libjar', + '/toolkit/xre' ] if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']: diff -up firefox-60.5.0/xpcom/io/nsLocalFileUnix.cpp.mozilla-kde firefox-60.5.0/xpcom/io/nsLocalFileUnix.cpp --- firefox-60.5.0/xpcom/io/nsLocalFileUnix.cpp.mozilla-kde 2019-01-24 18:31:33.000000000 +0100 +++ firefox-60.5.0/xpcom/io/nsLocalFileUnix.cpp 2019-01-31 20:24:11.347699068 +0100 @@ -52,6 +52,7 @@ #ifdef MOZ_WIDGET_GTK #include "nsIGIOService.h" +#include "nsKDEUtils.h" #endif #ifdef MOZ_WIDGET_COCOA @@ -1906,18 +1907,16 @@ nsLocalFile::Reveal() { } #ifdef MOZ_WIDGET_GTK - nsCOMPtr<nsIGIOService> 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<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID); if (isDirectory) { - return giovfs->ShowURIForInput(mPath); + url = mPath; } if (NS_SUCCEEDED(giovfs->OrgFreedesktopFileManager1ShowItems(mPath))) { return NS_OK; @@ -1931,7 +1930,7 @@ nsLocalFile::Reveal() { return NS_ERROR_FAILURE; } - return giovfs->ShowURIForInput(dirPath); + url = dirPath; #elif defined(MOZ_WIDGET_COCOA) CFURLRef url; if (NS_SUCCEEDED(GetCFURL(&url))) { @@ -1943,6 +1942,17 @@ nsLocalFile::Reveal() { #else return NS_ERROR_FAILURE; #endif + if(nsKDEUtils::kdeSupport()) { + nsTArray<nsCString> command; + command.AppendElement( NS_LITERAL_CSTRING("REVEAL") ); + command.AppendElement( mPath ); + return nsKDEUtils::command( command ) ? NS_OK : NS_ERROR_FAILURE; + } + + if (!giovfs) + return NS_ERROR_FAILURE; + + return giovfs->ShowURIForInput(url); } NS_IMETHODIMP @@ -1952,6 +1962,12 @@ nsLocalFile::Launch() { } #ifdef MOZ_WIDGET_GTK + if( nsKDEUtils::kdeSupport()) { + nsTArray<nsCString> command; + command.AppendElement( NS_LITERAL_CSTRING("OPEN") ); + command.AppendElement( mPath ); + return nsKDEUtils::command( command ) ? NS_OK : NS_ERROR_FAILURE; + } nsCOMPtr<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID); if (!giovfs) { return NS_ERROR_FAILURE;
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 24258
:
10716
|
10717
| 10718