Merged few patches into one patch and fixed for Waterfox Original authors of patch for Firefox: Wolfgang Rosenauer Lubos Lunak Original patches => http://www.rosenauer.org/hg/mozilla/file/firefox56 diff --git a/browser/base/jar.mn b/browser/base/jar.mn index ce46eaf6d392..b9ee0712859a 100644 --- a/browser/base/jar.mn +++ b/browser/base/jar.mn @@ -57,6 +57,8 @@ browser.jar: * content/browser/browser.css (content/browser.css) content/browser/browser.js (content/browser.js) * content/browser/browser.xul (content/browser.xul) +* content/browser/browser-kde.xul (content/browser-kde.xul) +% override chrome://browser/content/browser.xul chrome://browser/content/browser-kde.xul desktop=kde content/browser/browser-addons.js (content/browser-addons.js) content/browser/browser-captivePortal.js (content/browser-captivePortal.js) content/browser/browser-ctrlTab.js (content/browser-ctrlTab.js) diff --git a/browser/components/build/nsModule.cpp b/browser/components/build/nsModule.cpp index ef0da3dddcf5..5e72b39eb650 100644 --- a/browser/components/build/nsModule.cpp +++ b/browser/components/build/nsModule.cpp @@ -13,7 +13,7 @@ #elif defined(XP_MACOSX) #include "nsMacShellService.h" #elif defined(MOZ_WIDGET_GTK) -#include "nsGNOMEShellService.h" +#include "nsUnixShellService.h" #endif #if defined(XP_WIN) @@ -36,8 +36,6 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(DirectoryProvider) NS_GENERIC_FACTORY_CONSTRUCTOR(nsWindowsShellService) #elif defined(XP_MACOSX) NS_GENERIC_FACTORY_CONSTRUCTOR(nsMacShellService) -#elif defined(MOZ_WIDGET_GTK) -NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsGNOMEShellService, Init) #endif #if defined(XP_WIN) @@ -65,7 +63,7 @@ static const mozilla::Module::CIDEntry kBrowserCIDs[] = { #if defined(XP_WIN) { &kNS_SHELLSERVICE_CID, false, nullptr, nsWindowsShellServiceConstructor }, #elif defined(MOZ_WIDGET_GTK) - { &kNS_SHELLSERVICE_CID, false, nullptr, nsGNOMEShellServiceConstructor }, + { &kNS_SHELLSERVICE_CID, false, nullptr, nsUnixShellServiceConstructor }, #endif { &kNS_FEEDSNIFFER_CID, false, nullptr, nsFeedSnifferConstructor }, { &kNS_BROWSER_ABOUT_REDIRECTOR_CID, false, nullptr, AboutRedirector::Create }, diff --git a/browser/components/preferences/in-content/main.js b/browser/components/preferences/in-content/main.js index c89fe4928660..54c466d1bd93 100644 --- a/browser/components/preferences/in-content/main.js +++ b/browser/components/preferences/in-content/main.js @@ -46,6 +46,13 @@ var gMainPane = { } } + var env = Components.classes["@mozilla.org/process/environment;1"] + .getService(Components.interfaces.nsIEnvironment); + var kde_session = 0; + if (env.get('KDE_FULL_SESSION') == "true") { + kde_session = 1; + } + this.buildContentProcessCountMenuList(); this.updateDefaultPerformanceSettingsPref(); @@ -932,6 +939,17 @@ var gMainPane = { return; try { shellSvc.setDefaultBrowser(true, false); + if (kde_session == 1) { + var shellObj = Components.classes["@mozilla.org/file/local;1"] + .createInstance(Components.interfaces.nsILocalFile); + shellObj.initWithPath("/usr/bin/kwriteconfig"); + var process = Components.classes["@mozilla.org/process/util;1"] + .createInstance(Components.interfaces.nsIProcess); + process.init(shellObj); + var args = ["--file", "kdeglobals", "--group", "General", "--key", + "BrowserApplication", "waterfox-classic"]; + process.run(false, args, args.length); + } } catch (ex) { Cu.reportError(ex); return; diff --git a/browser/components/shell/moz.build b/browser/components/shell/moz.build index d4a234b4a069..97689cb0d882 100644 --- a/browser/components/shell/moz.build +++ b/browser/components/shell/moz.build @@ -43,6 +43,8 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa': elif 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']: SOURCES += [ 'nsGNOMEShellService.cpp', + 'nsKDEShellService.cpp', + 'nsUnixShellService.cpp', ] if SOURCES: diff --git a/browser/components/shell/nsKDEShellService.cpp b/browser/components/shell/nsKDEShellService.cpp new file mode 100644 index 000000000000..11ae6c709841 --- /dev/null +++ b/browser/components/shell/nsKDEShellService.cpp @@ -0,0 +1,203 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/ArrayUtils.h" + +#include "nsCOMPtr.h" +#include "nsKDEShellService.h" +#include "nsShellService.h" +#include "nsKDEUtils.h" +#include "nsIPrefService.h" +#include "nsIProcess.h" +#include "nsIFile.h" +#include "nsServiceManagerUtils.h" +#include "nsComponentManagerUtils.h" +#include "nsIMutableArray.h" +#include "nsISupportsPrimitives.h" +#include "nsArrayUtils.h" + +using namespace mozilla; + +nsresult +nsKDEShellService::Init() +{ + if( !nsKDEUtils::kdeSupport()) + return NS_ERROR_NOT_AVAILABLE; + return NS_OK; +} + +NS_IMPL_ISUPPORTS(nsKDEShellService, nsIGNOMEShellService, nsIShellService) + +NS_IMETHODIMP +nsKDEShellService::IsDefaultBrowser(bool aStartupCheck, + bool aForAllTypes, + bool* aIsDefaultBrowser) +{ + *aIsDefaultBrowser = false; + if (aStartupCheck) + mCheckedThisSession = true; + + nsCOMPtr command = do_CreateInstance( NS_ARRAY_CONTRACTID ); + if (!command) + return NS_ERROR_FAILURE; + + nsCOMPtr str = do_CreateInstance( NS_SUPPORTS_CSTRING_CONTRACTID ); + if (!str) + return NS_ERROR_FAILURE; + + str->SetData( NS_LITERAL_CSTRING( "ISDEFAULTBROWSER" )); + command->AppendElement( str, false ); + + if( nsKDEUtils::command( command )) + *aIsDefaultBrowser = true; + return NS_OK; +} + +NS_IMETHODIMP +nsKDEShellService::SetDefaultBrowser(bool aClaimAllTypes, + bool aForAllUsers) +{ + nsCOMPtr command = do_CreateInstance( NS_ARRAY_CONTRACTID ); + if (!command) + return NS_ERROR_FAILURE; + + nsCOMPtr cmdstr = do_CreateInstance( NS_SUPPORTS_CSTRING_CONTRACTID ); + nsCOMPtr paramstr = do_CreateInstance( NS_SUPPORTS_CSTRING_CONTRACTID ); + if (!cmdstr || !paramstr) + return NS_ERROR_FAILURE; + + cmdstr->SetData( NS_LITERAL_CSTRING( "SETDEFAULTBROWSER" )); + command->AppendElement( cmdstr, false ); + + paramstr->SetData( aClaimAllTypes ? NS_LITERAL_CSTRING( "ALLTYPES" ) : NS_LITERAL_CSTRING( "NORMAL" )); + command->AppendElement( paramstr, false ); + + return nsKDEUtils::command( command ) ? NS_OK : NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsKDEShellService::GetCanSetDesktopBackground(bool* aResult) +{ + *aResult = true; + return NS_OK; +} + +NS_IMETHODIMP +nsKDEShellService::SetDesktopBackground(nsIDOMElement* aElement, + PRInt32 aPosition) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsKDEShellService::GetDesktopBackgroundColor(PRUint32 *aColor) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsKDEShellService::SetDesktopBackgroundColor(PRUint32 aColor) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsKDEShellService::OpenApplication(PRInt32 aApplication) +{ + nsCOMPtr command = do_CreateInstance( NS_ARRAY_CONTRACTID ); + if (!command) + return NS_ERROR_FAILURE; + + nsCOMPtr str = do_CreateInstance( NS_SUPPORTS_CSTRING_CONTRACTID ); + if (!str) + return NS_ERROR_FAILURE; + + if( aApplication == APPLICATION_MAIL ) + str->SetData( NS_LITERAL_CSTRING( "OPENMAIL" )); + else if( aApplication == APPLICATION_NEWS ) + str->SetData( NS_LITERAL_CSTRING( "OPENNEWS" )); + else + return NS_ERROR_NOT_IMPLEMENTED; + + command->AppendElement( str, false ); + return nsKDEUtils::command( command ) ? NS_OK : NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsKDEShellService::OpenApplicationWithURI(nsIFile* aApplication, const nsACString& aURI) +{ + nsCOMPtr command = do_CreateInstance( NS_ARRAY_CONTRACTID ); + if (!command) + return NS_ERROR_FAILURE; + + nsCOMPtr cmdstr = do_CreateInstance( NS_SUPPORTS_CSTRING_CONTRACTID ); + nsCOMPtr appstr = do_CreateInstance( NS_SUPPORTS_CSTRING_CONTRACTID ); + nsCOMPtr uristr = do_CreateInstance( NS_SUPPORTS_CSTRING_CONTRACTID ); + if (!cmdstr || !appstr || !uristr) + return NS_ERROR_FAILURE; + + cmdstr->SetData( NS_LITERAL_CSTRING( "RUN" )); + command->AppendElement( cmdstr, false ); + nsAutoCString app; + nsresult rv = aApplication->GetNativePath( app ); + NS_ENSURE_SUCCESS( rv, rv ); + appstr->SetData( app ); + command->AppendElement( appstr, false ); + uristr->SetData( aURI ); + command->AppendElement( uristr, false ); + return nsKDEUtils::command( command ) ? NS_OK : NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsKDEShellService::GetDefaultFeedReader(nsIFile** _retval) +{ + *_retval = nullptr; + + nsCOMPtr command = do_CreateInstance( NS_ARRAY_CONTRACTID ); + if( !command ) + return NS_ERROR_FAILURE; + + nsCOMPtr str = do_CreateInstance( NS_SUPPORTS_CSTRING_CONTRACTID ); + if( !str ) + return NS_ERROR_FAILURE; + + str->SetData( NS_LITERAL_CSTRING( "GETDEFAULTFEEDREADER" )); + command->AppendElement( str, false ); + + nsCOMPtr output; + if( !nsKDEUtils::command( command, getter_AddRefs( output ) ) ) + return NS_ERROR_FAILURE; + + PRUint32 length; + output->GetLength( &length ); + if( length != 1 ) + return NS_ERROR_FAILURE; + + nsCOMPtr resstr = do_QueryElementAt( output, 0 ); + if( !resstr ) + return NS_ERROR_FAILURE; + + nsAutoCString path; + resstr->GetData( path ); + if (path.IsEmpty()) + return NS_ERROR_FAILURE; + + nsresult rv; + nsCOMPtr defaultReader = + do_CreateInstance("@mozilla.org/file/local;1", &rv); + NS_ENSURE_SUCCESS(rv, rv); + + rv = defaultReader->InitWithNativePath(path); + NS_ENSURE_SUCCESS(rv, rv); + + bool exists; + rv = defaultReader->Exists(&exists); + NS_ENSURE_SUCCESS(rv, rv); + if (!exists) + return NS_ERROR_FAILURE; + + NS_ADDREF(*_retval = defaultReader); + return NS_OK; +} diff --git a/browser/components/shell/nsKDEShellService.h b/browser/components/shell/nsKDEShellService.h new file mode 100644 index 000000000000..8baad7d98ea8 --- /dev/null +++ b/browser/components/shell/nsKDEShellService.h @@ -0,0 +1,30 @@ +/* -*- 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 nskdeshellservice_h____ +#define nskdeshellservice_h____ + +#include "nsIGNOMEShellService.h" +#include "nsString.h" +#include "mozilla/Attributes.h" + +class nsKDEShellService final : public nsIGNOMEShellService +{ +public: + nsKDEShellService() : mCheckedThisSession(false) { } + + NS_DECL_ISUPPORTS + NS_DECL_NSIGNOMESHELLSERVICE + NS_DECL_NSISHELLSERVICE + + nsresult Init(); + +private: + ~nsKDEShellService() {} + + bool mCheckedThisSession; +}; + +#endif // nskdeshellservice_h____ diff --git a/browser/components/shell/nsUnixShellService.cpp b/browser/components/shell/nsUnixShellService.cpp new file mode 100644 index 000000000000..a6827209d9e7 --- /dev/null +++ b/browser/components/shell/nsUnixShellService.cpp @@ -0,0 +1,22 @@ +/* -*- 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 "nsUnixShellService.h" +#include "nsGNOMEShellService.h" +#include "nsKDEShellService.h" +#include "nsKDEUtils.h" +#include "mozilla/ModuleUtils.h" + +NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsGNOMEShellService, Init) +NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsKDEShellService, Init) + +NS_IMETHODIMP +nsUnixShellServiceConstructor(nsISupports *aOuter, REFNSIID aIID, void **aResult) +{ + if( nsKDEUtils::kdeSupport()) + return nsKDEShellServiceConstructor( aOuter, aIID, aResult ); + return nsGNOMEShellServiceConstructor( aOuter, aIID, aResult ); +} diff --git a/browser/components/shell/nsUnixShellService.h b/browser/components/shell/nsUnixShellService.h new file mode 100644 index 000000000000..26b5dbac47dd --- /dev/null +++ b/browser/components/shell/nsUnixShellService.h @@ -0,0 +1,15 @@ +/* -*- 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 nsunixshellservice_h____ +#define nsunixshellservice_h____ + +#include "nsIGNOMEShellService.h" + +NS_IMETHODIMP +nsUnixShellServiceConstructor(nsISupports *aOuter, REFNSIID aIID, void **aResult); + +#endif // nsunixshellservice_h____ diff --git a/browser/installer/package-manifest.in b/browser/installer/package-manifest.in index beb799c7b822..26eec70489bd 100644 --- a/browser/installer/package-manifest.in +++ b/browser/installer/package-manifest.in @@ -677,6 +677,8 @@ ; gre location for now. @RESPATH@/defaults/pref/channel-prefs.js +@BINPATH@/defaults/pref/kde.js + ; Remote control protocol prefs ; defined in ../../testing/marionette/prefs/marionette.js @RESPATH@/defaults/pref/marionette.js diff --git a/modules/libpref/Preferences.cpp b/modules/libpref/Preferences.cpp index 4b9ef83c1559..96e0d09dac85 100644 --- a/modules/libpref/Preferences.cpp +++ b/modules/libpref/Preferences.cpp @@ -38,6 +38,7 @@ #include "nsXPCOMCID.h" #include "nsAutoPtr.h" #include "nsPrintfCString.h" +#include "nsKDEUtils.h" #include "nsQuickSort.h" #include "PLDHashTable.h" @@ -1440,6 +1441,24 @@ static nsresult pref_LoadPrefsInDirList(const char *listId) if (NS_FAILED(rv)) return rv; + // make sure we load these special files after all the others + static const char* specialFiles[] = { +#if defined(XP_UNIX) + "" +#endif + }; + + if (nsKDEUtils::kdeSession()) { + for(int i = 0; + i < MOZ_ARRAY_LENGTH(specialFiles); + ++i ) { + if (*specialFiles[ i ] == '\0') { + specialFiles[ i ] = "kde.js"; + break; + } + } + } + nsCOMPtr list; dirSvc->Get(listId, NS_GET_IID(nsISimpleEnumerator), @@ -1465,7 +1484,7 @@ static nsresult pref_LoadPrefsInDirList(const char *listId) if (Substring(leaf, leaf.Length() - 4).EqualsLiteral(".xpi")) ReadExtensionPrefs(path); else - pref_LoadPrefsInDir(path, nullptr, 0); + pref_LoadPrefsInDir(path, specialFiles, MOZ_ARRAY_LENGTH(specialFiles)); } return NS_OK; } @@ -1571,6 +1590,7 @@ pref_InitInitialObjects() "winpref.js" #elif defined(XP_UNIX) "unix.js" + , "" // placeholder for KDE (empty is otherwise harmless) #if defined(_AIX) , "aix.js" #endif @@ -1579,6 +1599,17 @@ pref_InitInitialObjects() #endif }; + if(nsKDEUtils::kdeSession()) { // TODO what if some setup actually requires the helper? + for(int i = 0; + i < MOZ_ARRAY_LENGTH(specialFiles); + ++i ) { + if( *specialFiles[ i ] == '\0' ) { + specialFiles[ i ] = "kde.js"; + break; + } + } + } + rv = pref_LoadPrefsInDir(defaultPrefDir, specialFiles, ArrayLength(specialFiles)); if (NS_FAILED(rv)) NS_WARNING("Error parsing application default preferences."); diff --git a/modules/libpref/moz.build b/modules/libpref/moz.build index 5696929c6035..59333b99828f 100644 --- a/modules/libpref/moz.build +++ b/modules/libpref/moz.build @@ -38,6 +38,10 @@ UNIFIED_SOURCES += [ 'prefread.cpp', ] +LOCAL_INCLUDES += [ + '/toolkit/xre' +] + include('/ipc/chromium/chromium-config.mozbuild') FINAL_LIBRARY = 'xul' diff --git a/python/mozbuild/mozpack/chrome/flags.py b/python/mozbuild/mozpack/chrome/flags.py index 62aabcd3e71d..d937be879081 100644 --- a/python/mozbuild/mozpack/chrome/flags.py +++ b/python/mozbuild/mozpack/chrome/flags.py @@ -225,6 +225,7 @@ class Flags(OrderedDict): 'xpcnativewrappers': Flag, 'tablet': Flag, 'process': StringFlag, + 'desktop': StringFlag, } RE = re.compile(r'([!<>=]+)') diff --git a/python/mozbuild/mozpack/chrome/manifest.py b/python/mozbuild/mozpack/chrome/manifest.py index 5c5b51f9949c..31a9f54b9260 100644 --- a/python/mozbuild/mozpack/chrome/manifest.py +++ b/python/mozbuild/mozpack/chrome/manifest.py @@ -39,6 +39,7 @@ class ManifestEntry(object): 'tablet', 'process', 'contentaccessible', + 'desktop', ] def __init__(self, base, *flags): diff --git a/toolkit/components/downloads/moz.build b/toolkit/components/downloads/moz.build index 1621564c24cf..69d490fd19a2 100644 --- a/toolkit/components/downloads/moz.build +++ b/toolkit/components/downloads/moz.build @@ -42,6 +42,7 @@ FINAL_LIBRARY = 'xul' LOCAL_INCLUDES += [ '../protobuf', '/ipc/chromium/src', + '/toolkit/xre', 'chromium' ] diff --git a/toolkit/content/jar.mn b/toolkit/content/jar.mn index d724bd084d9a..ca5595c87ae1 100644 --- a/toolkit/content/jar.mn +++ b/toolkit/content/jar.mn @@ -80,6 +80,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/expander.xml (widgets/expander.xml) content/global/bindings/filefield.xml (widgets/filefield.xml) @@ -93,6 +95,8 @@ toolkit.jar: content/global/bindings/numberbox.xml (widgets/numberbox.xml) content/global/bindings/popup.xml (widgets/popup.xml) * content/global/bindings/preferences.xml (widgets/preferences.xml) +* content/global/bindings/preferences-kde.xml (widgets/preferences-kde.xml) +% override chrome://global/content/bindings/preferences.xml chrome://global/content/bindings/preferences-kde.xml desktop=kde content/global/bindings/progressmeter.xml (widgets/progressmeter.xml) content/global/bindings/radio.xml (widgets/radio.xml) content/global/bindings/remote-browser.xml (widgets/remote-browser.xml) diff --git a/toolkit/content/widgets/dialog-kde.xml b/toolkit/content/widgets/dialog-kde.xml new file mode 100644 index 000000000000..d7e1a80c4f5c --- /dev/null +++ b/toolkit/content/widgets/dialog-kde.xml @@ -0,0 +1,455 @@ + + + + + + + + + + + + + + + + + + + + + null + (function(event) { + if (!document.documentElement.cancelDialog()) + event.preventDefault(); + }) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + (screen.availLeft + screen.availWidth)) + newX = (screen.availLeft + screen.availWidth) - window.outerWidth - 20; + + if (newY < screen.availTop) + newY = screen.availTop + 20; + if ((newY + window.outerHeight) > (screen.availTop + screen.availHeight)) + newY = (screen.availTop + screen.availHeight) - window.outerHeight - 60; + + window.moveTo( newX, newY ); + ]]> + + + + + + 0 ? xOffset : 0; + yOffset = yOffset > 0 ? yOffset : 0; + window.moveTo(xOffset, yOffset); + ]]> + + + + + + + + + + + + + + + + + + // see bug 63370 for details + this._mStrBundle = Components.classes["@mozilla.org/intl/stringbundle;1"] + .getService(Components.interfaces.nsIStringBundleService) + .createBundle("chrome://global/locale/dialog.properties"); + } + return this._mStrBundle; + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + if (!event.defaultPrevented) + this.cancelDialog(); + +#ifdef XP_MACOSX + +#else + + var btn = this.getButton(this.defaultButton); + if (btn) + btn.setAttribute("default", event.originalTarget == btn || !(event.originalTarget instanceof Components.interfaces.nsIDOMXULButtonElement)); + +#endif + + + + + + + + + + + + + + + diff --git a/toolkit/content/widgets/preferences-kde.xml b/toolkit/content/widgets/preferences-kde.xml new file mode 100644 index 000000000000..85684fbeae8e --- /dev/null +++ b/toolkit/content/widgets/preferences-kde.xml @@ -0,0 +1,1409 @@ + + + + %preferencesDTD; + + %globalKeysDTD; +]> + + + +# +# = Preferences Window Framework +# +# The syntax for use looks something like: +# +# +# +# +# +# +# +# +# +# +# + + + + + + elements is constructed. Its purpose is to propagate + // the values to the associated form elements. Sometimes the code for + // some initializers depend on other elements + // being initialized so we wait and call updateElements on all of them + // once the last one has been constructed. See bugs 997570 and 992185. + + var elements = this.getElementsByTagName("preference"); + for (let element of elements) { + element.updateElements(); + } + + this._constructAfterChildrenCalled = true; + ]]> + + + + + + + + + + + + + + + + + + + + Components.classes["@mozilla.org/preferences-service;1"] + .getService(Components.interfaces.nsIPrefService); + + + Components.classes["@mozilla.org/preferences-service;1"] + .getService(Components.interfaces.nsIPrefBranch); + + + this.service.getDefaultBranch(""); + + + Components.classes["@mozilla.org/preferences-service;1"] + .getService(Components.interfaces.nsIPrefBranchInternal); + + + + + + + + + + + + + + 0 + null + + false + + + + + + + + + + was added after _constructAfterChildren() was already called. + // We can directly call updateElements(). + this.updateElements(); + return; + } + this.preferences._constructedChildrenCount++; + if (this.preferences._constructedChildrenCount == + this.preferences._preferenceChildren.length) { + // This is the last , time to updateElements() on all of them. + this.preferences._constructAfterChildren(); + } + ]]> + + + this.preferences.rootBranchInternal + .removeObserver(this.name, this.preferences); + + false + + + if (this.getAttribute("instantApply") == "false") + return false; + return this.getAttribute("instantApply") == "true" || this.preferences.instantApply; + + + + + + + if (val == this.name) + return val; + + this.preferences.rootBranchInternal + .removeObserver(this.name, this.preferences); + this.setAttribute("name", val); + this.preferences.rootBranchInternal + .addObserver(val, this.preferences); + + return val; + + + + + + + null + + + + + + + + + + + return this.preferences.rootBranch.prefIsLocked(this.name); + + + + + + return this.getAttribute("disabled") == "true"; + + + + + + + + + return parseInt(this.getAttribute("tabindex")); + + + + + + + + + + + + + + + // defer reset until preference update + this.value = undefined; + + + + false + + + + + + + + + return this._useDefault ? this.preferences.defaultBranch : this.preferences.rootBranch; + + + + false + + + + with id='" + this.id + "' and name='" + + this.name + "' has unknown type '" + this.type + "'."; + consoleService.logStringMessage(msg); + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + this.updateElements(); + + + + + + + + + +#else + title="&preferencesDefaultTitleMac.title;"> +#endif + + + + + + + + + +#ifndef XP_UNIX + + + + + + + + + + + + + + + + false + + false + + + + + + + + + + this.setAttribute("lastSelected", val); + document.persist(this.id, "lastSelected"); + return val; + + + + + if (!this._currentPane) + this._currentPane = this.preferencePanes[0]; + + return this._currentPane; + + + null + + + + + + + + + + + + + + + + + + + + + + + + + false + + + + 1) + aPaneElement.removeAttribute("flex"); + // Calling sizeToContent after the first prefpane is loaded + // will size the windows contents so style information is + // available to calculate correct sizing. + if (!this._initialized && prefpanes.length > 1) { + if (this._shouldAnimate) + this.style.minHeight = 0; + window.sizeToContent(); + } + + var oldPane = this.lastSelected ? document.getElementById(this.lastSelected) : this.preferencePanes[0]; + oldPane.selected = !(aPaneElement.selected = true); + this.lastSelected = aPaneElement.id; + this.currentPane = aPaneElement; + this._initialized = true; + + // Only animate if we've switched between prefpanes + if (this._shouldAnimate && oldPane.id != aPaneElement.id) { + aPaneElement.style.opacity = 0.0; + this.animate(oldPane, aPaneElement); + } else if (!this._shouldAnimate && prefpanes.length > 1) { + var targetHeight = parseInt(window.getComputedStyle(this._paneDeckContainer).height); + var verticalPadding = parseInt(window.getComputedStyle(aPaneElement).paddingTop); + verticalPadding += parseInt(window.getComputedStyle(aPaneElement).paddingBottom); + if (aPaneElement.contentHeight > targetHeight - verticalPadding) { + // To workaround the bottom border of a groupbox from being + // cutoff an hbox with a class of bottomBox may enclose it. + // This needs to include its padding to resize properly. + // See bug 394433 + var bottomPadding = 0; + var bottomBox = aPaneElement.getElementsByAttribute("class", "bottomBox")[0]; + if (bottomBox) + bottomPadding = parseInt(window.getComputedStyle(bottomBox).paddingBottom); + window.innerHeight += bottomPadding + verticalPadding + aPaneElement.contentHeight - targetHeight; + } + + // XXX rstrong - extend the contents of the prefpane to + // prevent elements from being cutoff (see bug 349098). + if (aPaneElement.contentHeight + verticalPadding < targetHeight) + aPaneElement._content.style.height = targetHeight - verticalPadding + "px"; + } + } + break; + } + } + ]]> + + + + + + + + + + + + + + oldHeight ? 1 : -1; + var sizeDelta = Math.abs(oldHeight - aNewPane.contentHeight); + this._animateRemainder = sizeDelta % this._animateIncrement; + + this._setUpAnimationTimer(oldHeight); + ]]> + + + + + + 0 && this._currentHeight >= lastSelectedPane.contentHeight) || + (this._multiplier < 0 && this._currentHeight <= lastSelectedPane.contentHeight)) + return 0; + + if ((this._multiplier > 0 && newHeight > lastSelectedPane.contentHeight) || + (this._multiplier < 0 && newHeight < lastSelectedPane.contentHeight)) + increment = this._animateRemainder * this._multiplier; + return increment; + ]]> + + + + + + + + + + + + + + + + + + + + + + + + null + null + 15 + 40 + 5 + 0.40 + 0 + 0 + 0 + + + + + + + + + + + + + + return openDialog(aURL, "", "modal,centerscreen,resizable=no" + (aFeatures != "" ? ("," + aFeatures) : ""), aParams); + + + + + + + + + + + + + + + + + + + if (event.originalTarget.hasAttribute("pane")) { + var pane = document.getElementById(event.originalTarget.getAttribute("pane")); + this.showPane(pane); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + + + + return document.getElementById(aElement.getAttribute("preference")); + + + + + + + + + + + + + + + + + + + + + new Set(); + + + + + + + + + + + + + + + + var targetHeight = parseInt(window.getComputedStyle(this._content).height); + targetHeight += parseInt(window.getComputedStyle(this._content).marginTop); + targetHeight += parseInt(window.getComputedStyle(this._content).marginBottom); + return targetHeight; + + + + document.getAnonymousElementByAttribute(this, "class", "content-box"); + + + + + // This "command" event handler tracks changes made to preferences by + // the user in this window. + if (event.sourceEvent) + event = event.sourceEvent; + this.userChangedValue(event.target); + + + // This "select" event handler tracks changes made to colorpicker + // preferences by the user in this window. + if (event.target.localName == "colorpicker") + this.userChangedValue(event.target); + + + // This "change" event handler tracks changes made to preferences by + // the user in this window. + this.userChangedValue(event.target); + + + // This "input" event handler tracks changes made to preferences by + // the user in this window. + this.userChangedValue(event.target); + + + + + + + + + + + + + + + + + + + +# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +# +# This is PrefWindow 6. The Code Could Well Be Ready, Are You? +# +# Historical References: +# PrefWindow V (February 1, 2003) +# PrefWindow IV (April 24, 2000) +# PrefWindow III (January 6, 2000) +# PrefWindow II (???) +# PrefWindow I (June 4, 1999) +# diff --git a/toolkit/content/xul.css b/toolkit/content/xul.css index 1d2c13a063f5..270c65bb9251 100644 --- a/toolkit/content/xul.css +++ b/toolkit/content/xul.css @@ -331,6 +331,18 @@ toolbar[type="menubar"]:not([customizing="true"]) { } %endif +%ifdef MOZ_WIDGET_GTK +window[shellshowingmenubar="true"] menubar { + display: none !important; +} + +window[shellshowingmenubar="true"] +toolbar[type="menubar"]:not([customizing="true"]) { + min-height: 0 !important; + border: 0 !important; +} +%endif + toolbarseparator { -moz-binding: url("chrome://global/content/bindings/toolbar.xml#toolbardecoration"); } diff --git a/toolkit/mozapps/downloads/nsHelperAppDlg.js b/toolkit/mozapps/downloads/nsHelperAppDlg.js index 986acae2fe5a..828b30a77581 100644 --- a/toolkit/mozapps/downloads/nsHelperAppDlg.js +++ b/toolkit/mozapps/downloads/nsHelperAppDlg.js @@ -633,7 +633,7 @@ nsUnknownContentTypeDialog.prototype = { let [size, unit] = DownloadUtils. convertByteUnits(this.mLauncher.contentLength); type.value = this.dialogElement("strings") - .getFormattedString("orderedFileSizeWithType", + .getFormattedString("orderedFileSizeWithType", [typeString, size, unit]); } else { @@ -807,7 +807,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; } } @@ -1072,20 +1072,47 @@ nsUnknownContentTypeDialog.prototype = { this.chosenApp = params.handlerApp; } } else if ("@mozilla.org/applicationchooser;1" in Components.classes) { - var nsIApplicationChooser = Components.interfaces.nsIApplicationChooser; - var appChooser = Components.classes["@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(Components.interfaces.nsILocalHandlerApp); + // 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 = Components.interfaces.nsIFilePicker; + var fp = Components.classes["@mozilla.org/filepicker;1"] + .createInstance(nsIFilePicker); + fp.init(this.mDialog, + this.dialogElement("strings").getString("chooseAppFilePickerTitle"), + nsIFilePicker.modeOpen); + + fp.appendFilters(nsIFilePicker.filterApps); + + if (fp.show() == nsIFilePicker.returnOK && fp.file) { + // Remember the file they chose to run. + var localHandlerApp = + Components.classes["@mozilla.org/uriloader/local-handler-app;1"]. + createInstance(Components.interfaces.nsILocalHandlerApp); + localHandlerApp.executable = fp.file; + this.chosenApp = localHandlerApp; + } + } else { + var nsIApplicationChooser = Components.interfaces.nsIApplicationChooser; + var appChooser = Components.classes["@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(Components.interfaces.nsILocalHandlerApp); + } + contentTypeDialogObj.finishChooseApp(); + }; + appChooser.open(this.mLauncher.MIMEInfo.MIMEType, appChooserCallback); + // The finishChooseApp is called from appChooserCallback + return; } - contentTypeDialogObj.finishChooseApp(); - }; - appChooser.open(this.mLauncher.MIMEInfo.MIMEType, appChooserCallback); - // The finishChooseApp is called from appChooserCallback - return; } else { var nsIFilePicker = Components.interfaces.nsIFilePicker; var fp = Components.classes["@mozilla.org/filepicker;1"] diff --git a/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp b/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp index 8b4c9a89597f..9cc4152358da 100644 --- a/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp +++ b/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp @@ -20,6 +20,7 @@ #include "nsInterfaceHashtable.h" #include "mozilla/Attributes.h" #include "nsIURI.h" +#include "nsKDEUtils.h" class nsUnixSystemProxySettings final : public nsISystemProxySettings { public: @@ -44,6 +45,7 @@ private: nsresult GetProxyFromGConf(const nsACString& aScheme, const nsACString& aHost, int32_t aPort, nsACString& aResult); nsresult GetProxyFromGSettings(const nsACString& aScheme, const nsACString& aHost, int32_t aPort, nsACString& aResult); nsresult SetProxyResultFromGSettings(const char* aKeyBase, const char* aType, nsACString& aResult); + nsresult GetProxyFromKDE(const nsACString& aScheme, const nsACString& aHost, PRInt32 aPort, nsACString& aResult); }; NS_IMPL_ISUPPORTS(nsUnixSystemProxySettings, nsISystemProxySettings) @@ -510,6 +512,9 @@ nsUnixSystemProxySettings::GetProxyForURI(const nsACString & aSpec, 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)) @@ -545,3 +550,28 @@ static const mozilla::Module kUnixProxyModule = { }; NSMODULE_DEFN(nsUnixProxyModule) = &kUnixProxyModule; + +nsresult +nsUnixSystemProxySettings::GetProxyFromKDE(const nsACString& aScheme, + const nsACString& aHost, + PRInt32 aPort, + nsACString& aResult) +{ + nsAutoCString url; + url = aScheme; + url += "://"; + url += aHost; + if( aPort >= 0 ) + { + url += ":"; + url += nsPrintfCString("%d", aPort); + } + nsTArray command; + command.AppendElement( NS_LITERAL_CSTRING( "GETPROXY" )); + command.AppendElement( url ); + nsTArray result; + if( !nsKDEUtils::command( command, &result ) || result.Length() != 1 ) + return NS_ERROR_FAILURE; + aResult = result[0]; + return NS_OK; +} diff --git a/toolkit/xre/moz.build b/toolkit/xre/moz.build index 1f28d7142fe8..b680934b149c 100644 --- a/toolkit/xre/moz.build +++ b/toolkit/xre/moz.build @@ -66,7 +66,9 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'uikit': 'UIKitDirProvider.mm', ] elif 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']: + EXPORTS += ['nsKDEUtils.h'] UNIFIED_SOURCES += [ + 'nsKDEUtils.cpp', 'nsNativeAppSupportUnix.cpp', ] else: diff --git a/toolkit/xre/nsKDEUtils.cpp b/toolkit/xre/nsKDEUtils.cpp new file mode 100644 index 000000000000..7d3b9da15645 --- /dev/null +++ b/toolkit/xre/nsKDEUtils.cpp @@ -0,0 +1,344 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsKDEUtils.h" +#include "nsIWidget.h" +#include "nsISupportsPrimitives.h" +#include "nsIMutableArray.h" +#include "nsComponentManagerUtils.h" +#include "nsArrayUtils.h" + +#include + +#include +#include +#include +#include +#include +#include +// copied from X11/X.h as a hack since for an unknown +// reason it's not picked up from X11/X.h +#ifndef None +#define None 0L /* universal null resource or null atom */ +#endif + +//#define DEBUG_KDE +#ifdef DEBUG_KDE +#define KWATERFOXHELPER "kwaterfoxhelper" +#else +// not need for lib64, it's a binary +#define KWATERFOXHELPER "/usr/lib/waterfox/kwaterfoxhelper" +#endif + +#define KWATERFOXHELPER_VERSION 6 +#define MAKE_STR2( n ) #n +#define MAKE_STR( n ) MAKE_STR2( n ) + +static bool getKdeSession() + { + Display* dpy = XOpenDisplay( NULL ); + if( dpy == NULL ) + return false; + Atom kde_full_session = XInternAtom( dpy, "KDE_FULL_SESSION", True ); + bool kde = false; + if( kde_full_session != None ) + { + int cnt; + if( Atom* props = XListProperties( dpy, DefaultRootWindow( dpy ), &cnt )) + { + for( int i = 0; + i < cnt; + ++i ) + { + if( props[ i ] == kde_full_session ) + { + kde = true; +#ifdef DEBUG_KDE + fprintf( stderr, "KDE SESSION %d\n", kde ); +#endif + break; + } + } + XFree( props ); + } + } + XCloseDisplay( dpy ); + return kde; + } + +static bool getKdeSupport() + { + nsTArray command; + command.AppendElement( NS_LITERAL_CSTRING( "CHECK" )); + command.AppendElement( NS_LITERAL_CSTRING( MAKE_STR( KWATERFOXHELPER_VERSION ))); + bool kde = nsKDEUtils::command( command ); +#ifdef DEBUG_KDE + fprintf( stderr, "KDE RUNNING %d\n", kde ); +#endif + return kde; + } + +nsKDEUtils::nsKDEUtils() + : commandFile( NULL ) + , replyFile( NULL ) + { + } + +nsKDEUtils::~nsKDEUtils() + { +// closeHelper(); not actually useful, exiting will close the fd too + } + +nsKDEUtils* nsKDEUtils::self() + { + static nsKDEUtils s; + return &s; + } + +static bool helperRunning = false; +static bool helperFailed = false; + +bool nsKDEUtils::kdeSession() + { + static bool session = getKdeSession(); + return session; + } + +bool nsKDEUtils::kdeSupport() + { + static bool support = kdeSession() && getKdeSupport(); + return support && helperRunning; + } + +struct nsKDECommandData + { + FILE* file; + nsTArray* output; + GMainLoop* loop; + bool success; + }; + +static gboolean kdeReadFunc( GIOChannel*, GIOCondition, gpointer data ) + { + nsKDECommandData* p = static_cast< nsKDECommandData* >( data ); + char buf[ 8192 ]; // TODO big enough + bool command_done = false; + bool command_failed = false; + while( !command_done && !command_failed && fgets( buf, 8192, p->file ) != NULL ) + { // TODO what if the kernel splits a line into two chunks? +//#ifdef DEBUG_KDE +// fprintf( stderr, "READ: %s %d\n", buf, feof( p->file )); +//#endif + if( char* eol = strchr( buf, '\n' )) + *eol = '\0'; + command_done = ( strcmp( buf, "\\1" ) == 0 ); + command_failed = ( strcmp( buf, "\\0" ) == 0 ); + nsAutoCString line( buf ); + line.ReplaceSubstring( "\\n", "\n" ); + line.ReplaceSubstring( "\\" "\\", "\\" ); // \\ -> \ , i.e. unescape + if( p->output && !( command_done || command_failed )) + p->output->AppendElement( nsCString( buf )); // TODO utf8? + } + bool quit = false; + if( feof( p->file ) || command_failed ) + { + quit = true; + p->success = false; + } + if( command_done ) + { // reading one reply finished + quit = true; + p->success = true; + } + if( quit ) + { + if( p->loop ) + g_main_loop_quit( p->loop ); + return FALSE; + } + return TRUE; + } + +bool nsKDEUtils::command( const nsTArray& command, nsTArray* output ) + { + return self()->internalCommand( command, NULL, false, output ); + } + +bool nsKDEUtils::command( nsIArray* command, nsIArray** output) + { + nsTArray in; + PRUint32 length; + command->GetLength( &length ); + for ( PRUint32 i = 0; i < length; i++ ) + { + nsCOMPtr str = do_QueryElementAt( command, i ); + if( str ) + { + nsAutoCString s; + str->GetData( s ); + in.AppendElement( s ); + } + } + + nsTArray out; + bool ret = self()->internalCommand( in, NULL, false, &out ); + + if ( !output ) return ret; + + nsCOMPtr result = do_CreateInstance( NS_ARRAY_CONTRACTID ); + if ( !result ) return false; + + for ( PRUint32 i = 0; i < out.Length(); i++ ) + { + nsCOMPtr rstr = do_CreateInstance( NS_SUPPORTS_CSTRING_CONTRACTID ); + if ( !rstr ) return false; + + rstr->SetData( out[i] ); + result->AppendElement( rstr, false ); + } + + NS_ADDREF( *output = result); + return ret; + } + + +bool nsKDEUtils::commandBlockUi( const nsTArray& command, GtkWindow* parent, nsTArray* output ) + { + return self()->internalCommand( command, parent, true, output ); + } + +bool nsKDEUtils::internalCommand( const nsTArray& command, GtkWindow* parent, bool blockUi, + nsTArray* output ) + { + if( !startHelper()) + return false; + feedCommand( command ); + // do not store the data in 'this' but in extra structure, just in case there + // is reentrancy (can there be? the event loop is re-entered) + nsKDECommandData data; + data.file = replyFile; + data.output = output; + data.success = false; + if( blockUi ) + { + data.loop = g_main_loop_new( NULL, FALSE ); + GtkWidget* window = gtk_window_new( GTK_WINDOW_TOPLEVEL ); + if( parent && gtk_window_get_group(parent) ) + gtk_window_group_add_window( gtk_window_get_group(parent), GTK_WINDOW( window )); + gtk_widget_realize( window ); + gtk_widget_set_sensitive( window, TRUE ); + gtk_grab_add( window ); + GIOChannel* channel = g_io_channel_unix_new( fileno( data.file )); + g_io_add_watch( channel, static_cast< GIOCondition >( G_IO_IN | G_IO_ERR | G_IO_HUP ), kdeReadFunc, &data ); + g_io_channel_unref( channel ); + g_main_loop_run( data.loop ); + g_main_loop_unref( data.loop ); + gtk_grab_remove( window ); + gtk_widget_destroy( window ); + } + else + { + data.loop = NULL; + while( kdeReadFunc( NULL, static_cast< GIOCondition >( 0 ), &data )) + ; + } + return data.success; + } + +bool nsKDEUtils::startHelper() + { + if( helperRunning ) + return true; + if( helperFailed ) + return false; + helperFailed = true; + int fdcommand[ 2 ]; + int fdreply[ 2 ]; + if( pipe( fdcommand ) < 0 ) + return false; + if( pipe( fdreply ) < 0 ) + { + close( fdcommand[ 0 ] ); + close( fdcommand[ 1 ] ); + return false; + } + char* args[ 2 ] = { const_cast< char* >( KWATERFOXHELPER ), 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( KWATERFOXHELPER, args ); +#else + execv( KWATERFOXHELPER, args ); +#endif + _exit( 1 ); // failed + } + default: // parent + { + commandFile = fdopen( fdcommand[ 1 ], "w" ); + replyFile = fdopen( fdreply[ 0 ], "r" ); + close( fdcommand[ 0 ] ); + close( fdreply[ 1 ] ); + if( commandFile == NULL || replyFile == NULL ) + { + closeHelper(); + return false; + } + // ok, helper ready, getKdeRunning() will check if it works + } + } + helperFailed = false; + helperRunning = true; + return true; + } + +void nsKDEUtils::closeHelper() + { + if( commandFile != NULL ) + fclose( commandFile ); // this will also make the helper quit + if( replyFile != NULL ) + fclose( replyFile ); + helperRunning = false; + } + +void nsKDEUtils::feedCommand( const nsTArray& command ) + { + for( int i = 0; + i < command.Length(); + ++i ) + { + nsCString line = command[ i ]; + line.ReplaceSubstring( "\\", "\\" "\\" ); // \ -> \\ , i.e. escape + line.ReplaceSubstring( "\n", "\\n" ); +#ifdef DEBUG_KDE + fprintf( stderr, "COMM: %s\n", line.get()); +#endif + fputs( line.get(), commandFile ); + fputs( "\n", commandFile ); + } + fputs( "\\E\n", commandFile ); // done as \E, so it cannot happen in normal data + fflush( commandFile ); + } diff --git a/toolkit/xre/nsKDEUtils.h b/toolkit/xre/nsKDEUtils.h new file mode 100644 index 000000000000..a19271b98f78 --- /dev/null +++ b/toolkit/xre/nsKDEUtils.h @@ -0,0 +1,48 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef nsKDEUtils_h__ +#define nsKDEUtils_h__ + +#include "nsStringGlue.h" +#include "nsTArray.h" +#include + +typedef struct _GtkWindow GtkWindow; + +class nsIArray; + +class NS_EXPORT nsKDEUtils + { + public: + /* Returns true if running inside a KDE session (regardless of whether there is KDE + support available for Waterfox). 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 Waterfox. This should be used everywhere where the external helper is needed. */ + static bool kdeSupport(); + /* Executes the given helper command, returns true if helper returned success. */ + static bool command( const nsTArray& command, nsTArray* output = NULL ); + static bool command( nsIArray* command, nsIArray** output = NULL ); + /* Like command(), but additionally blocks the parent widget like if there was + a modal dialog shown and enters the event loop (i.e. there are still paint updates, + this is for commands that take long). */ + static bool commandBlockUi( const nsTArray& command, GtkWindow* parent, nsTArray* output = NULL ); + + private: + nsKDEUtils(); + ~nsKDEUtils(); + static nsKDEUtils* self(); + bool startHelper(); + void closeHelper(); + void feedCommand( const nsTArray& command ); + bool internalCommand( const nsTArray& command, GtkWindow* parent, bool isParent, + nsTArray* output ); + FILE* commandFile; + FILE* replyFile; + }; + +#endif // nsKDEUtils diff --git a/uriloader/exthandler/moz.build b/uriloader/exthandler/moz.build index 3349d5006901..fc8d57a09355 100644 --- a/uriloader/exthandler/moz.build +++ b/uriloader/exthandler/moz.build @@ -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': @@ -130,6 +132,7 @@ LOCAL_INCLUDES += [ '/dom/ipc', '/netwerk/base', '/netwerk/protocol/http', + '/toolkit/xre', ] if CONFIG['MOZ_ENABLE_DBUS']: diff --git a/uriloader/exthandler/unix/nsCommonRegistry.cpp b/uriloader/exthandler/unix/nsCommonRegistry.cpp new file mode 100644 index 000000000000..630ab6147db3 --- /dev/null +++ b/uriloader/exthandler/unix/nsCommonRegistry.cpp @@ -0,0 +1,53 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsCommonRegistry.h" + +#include "nsGNOMERegistry.h" +#include "nsKDERegistry.h" +#include "nsString.h" +#include "nsKDEUtils.h" + +/* static */ bool +nsCommonRegistry::HandlerExists(const char *aProtocolScheme) +{ + if( nsKDEUtils::kdeSupport()) + return nsKDERegistry::HandlerExists( aProtocolScheme ); + return nsGNOMERegistry::HandlerExists( aProtocolScheme ); +} + +/* static */ nsresult +nsCommonRegistry::LoadURL(nsIURI *aURL) +{ + if( nsKDEUtils::kdeSupport()) + return nsKDERegistry::LoadURL( aURL ); + return nsGNOMERegistry::LoadURL( aURL ); +} + +/* static */ void +nsCommonRegistry::GetAppDescForScheme(const nsACString& aScheme, + nsAString& aDesc) +{ + if( nsKDEUtils::kdeSupport()) + return nsKDERegistry::GetAppDescForScheme( aScheme, aDesc ); + return nsGNOMERegistry::GetAppDescForScheme( aScheme, aDesc ); +} + + +/* static */ already_AddRefed +nsCommonRegistry::GetFromExtension(const nsACString& aFileExt) +{ + if( nsKDEUtils::kdeSupport()) + return nsKDERegistry::GetFromExtension( aFileExt ); + return nsGNOMERegistry::GetFromExtension( aFileExt ); +} + +/* static */ already_AddRefed +nsCommonRegistry::GetFromType(const nsACString& aMIMEType) +{ + if( nsKDEUtils::kdeSupport()) + return nsKDERegistry::GetFromType( aMIMEType ); + return nsGNOMERegistry::GetFromType( aMIMEType ); +} diff --git a/uriloader/exthandler/unix/nsCommonRegistry.h b/uriloader/exthandler/unix/nsCommonRegistry.h new file mode 100644 index 000000000000..85b3d9cee25e --- /dev/null +++ b/uriloader/exthandler/unix/nsCommonRegistry.h @@ -0,0 +1,28 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef nsCommonRegistry_h__ +#define nsCommonRegistry_h__ + +#include "nsIURI.h" +#include "nsCOMPtr.h" + +class nsMIMEInfoBase; + +class nsCommonRegistry +{ + public: + static bool HandlerExists(const char *aProtocolScheme); + + static nsresult LoadURL(nsIURI *aURL); + + static void GetAppDescForScheme(const nsACString& aScheme, + nsAString& aDesc); + + static already_AddRefed GetFromExtension(const nsACString& aFileExt); + + static already_AddRefed GetFromType(const nsACString& aMIMEType); +}; + +#endif diff --git a/uriloader/exthandler/unix/nsKDERegistry.cpp b/uriloader/exthandler/unix/nsKDERegistry.cpp new file mode 100644 index 000000000000..6a2ca0abc7e1 --- /dev/null +++ b/uriloader/exthandler/unix/nsKDERegistry.cpp @@ -0,0 +1,88 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsKDERegistry.h" +#include "prlink.h" +#include "prmem.h" +#include "nsString.h" +#include "nsILocalFile.h" +#include "nsMIMEInfoUnix.h" +#include "nsAutoPtr.h" +#include "nsKDEUtils.h" + +/* static */ bool +nsKDERegistry::HandlerExists(const char *aProtocolScheme) +{ + nsTArray command; + command.AppendElement( NS_LITERAL_CSTRING( "HANDLEREXISTS" )); + command.AppendElement( nsAutoCString( aProtocolScheme )); + return nsKDEUtils::command( command ); +} + +/* static */ nsresult +nsKDERegistry::LoadURL(nsIURI *aURL) +{ + nsTArray command; + command.AppendElement( NS_LITERAL_CSTRING( "OPEN" )); + nsCString url; + aURL->GetSpec( url ); + command.AppendElement( url ); + bool rv = nsKDEUtils::command( command ); + if (!rv) + return NS_ERROR_FAILURE; + + return NS_OK; +} + +/* static */ void +nsKDERegistry::GetAppDescForScheme(const nsACString& aScheme, + nsAString& aDesc) +{ + nsTArray command; + command.AppendElement( NS_LITERAL_CSTRING( "GETAPPDESCFORSCHEME" )); + command.AppendElement( aScheme ); + nsTArray output; + if( nsKDEUtils::command( command, &output ) && output.Length() == 1 ) + CopyUTF8toUTF16( output[ 0 ], aDesc ); +} + + +/* static */ already_AddRefed +nsKDERegistry::GetFromExtension(const nsACString& aFileExt) +{ + NS_ASSERTION(aFileExt[0] != '.', "aFileExt shouldn't start with a dot"); + nsTArray command; + command.AppendElement( NS_LITERAL_CSTRING( "GETFROMEXTENSION" )); + command.AppendElement( aFileExt ); + return GetFromHelper( command ); +} + +/* static */ already_AddRefed +nsKDERegistry::GetFromType(const nsACString& aMIMEType) +{ + nsTArray command; + command.AppendElement( NS_LITERAL_CSTRING( "GETFROMTYPE" )); + command.AppendElement( aMIMEType ); + return GetFromHelper( command ); +} + +/* static */ already_AddRefed +nsKDERegistry::GetFromHelper(const nsTArray& command) +{ + nsTArray output; + if( nsKDEUtils::command( command, &output ) && output.Length() == 3 ) + { + nsCString mimetype = output[ 0 ]; + RefPtr mimeInfo = new nsMIMEInfoUnix( mimetype ); + NS_ENSURE_TRUE(mimeInfo, nullptr); + nsCString description = output[ 1 ]; + mimeInfo->SetDescription(NS_ConvertUTF8toUTF16(description)); + nsCString handlerAppName = output[ 2 ]; + mimeInfo->SetDefaultDescription(NS_ConvertUTF8toUTF16(handlerAppName)); + mimeInfo->SetPreferredAction(nsIMIMEInfo::useSystemDefault); + return mimeInfo.forget(); + } + return nullptr; +} diff --git a/uriloader/exthandler/unix/nsKDERegistry.h b/uriloader/exthandler/unix/nsKDERegistry.h new file mode 100644 index 000000000000..4eaaa4493efd --- /dev/null +++ b/uriloader/exthandler/unix/nsKDERegistry.h @@ -0,0 +1,34 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef nsKDERegistry_h__ +#define nsKDERegistry_h__ + +#include "nsIURI.h" +#include "nsCOMPtr.h" +#include "nsTArray.h" + +class nsMIMEInfoBase; +class nsAutoCString; +class nsCString; + +class nsKDERegistry +{ + public: + static bool HandlerExists(const char *aProtocolScheme); + + static nsresult LoadURL(nsIURI *aURL); + + static void GetAppDescForScheme(const nsACString& aScheme, + nsAString& aDesc); + + static already_AddRefed GetFromExtension(const nsACString& aFileExt); + + static already_AddRefed GetFromType(const nsACString& aMIMEType); + private: + static already_AddRefed GetFromHelper(const nsTArray& command); + +}; + +#endif //nsKDERegistry_h__ diff --git a/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp b/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp index e51660887354..95989b990bba 100644 --- a/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp +++ b/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp @@ -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,11 +13,14 @@ #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 @@ -32,14 +35,14 @@ nsMIMEInfoUnix::GetHasDefaultHandler(bool *_retval) *_retval = false; if (mClass == eProtocolInfo) { - *_retval = nsGNOMERegistry::HandlerExists(mSchemeOrType.get()); + *_retval = nsCommonRegistry::HandlerExists(mSchemeOrType.get()); } else { - RefPtr mimeInfo = nsGNOMERegistry::GetFromType(mSchemeOrType); + RefPtr mimeInfo = nsCommonRegistry::GetFromType(mSchemeOrType); if (!mimeInfo) { nsAutoCString ext; nsresult rv = GetPrimaryExtension(ext); if (NS_SUCCEEDED(rv)) { - mimeInfo = nsGNOMERegistry::GetFromExtension(ext); + mimeInfo = nsCommonRegistry::GetFromExtension(ext); } } if (mimeInfo) @@ -84,6 +87,23 @@ nsMIMEInfoUnix::LaunchDefaultWithFile(nsIFile *aFile) return NS_ERROR_FAILURE; #endif + if( nsKDEUtils::kdeSupport()) { + bool supports; + if( NS_SUCCEEDED( GetHasDefaultHandler( &supports )) && supports ) { + nsTArray command; + command.AppendElement( NS_LITERAL_CSTRING( "OPEN" )); + command.AppendElement( nativePath ); + command.AppendElement( NS_LITERAL_CSTRING( "MIMETYPE" )); + command.AppendElement( mSchemeOrType ); + if( nsKDEUtils::command( command )) + return NS_OK; + } + if (!mDefaultApplication) + return NS_ERROR_FILE_NOT_FOUND; + + return LaunchWithIProcess(mDefaultApplication, nativePath); + } + nsCOMPtr giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID); if (!giovfs) { return NS_ERROR_FAILURE; diff --git a/uriloader/exthandler/unix/nsOSHelperAppService.cpp b/uriloader/exthandler/unix/nsOSHelperAppService.cpp index e1ac2582e65b..ea762d0c1383 100644 --- a/uriloader/exthandler/unix/nsOSHelperAppService.cpp +++ b/uriloader/exthandler/unix/nsOSHelperAppService.cpp @@ -15,7 +15,7 @@ #include "nsOSHelperAppService.h" #include "nsMIMEInfoUnix.h" #ifdef MOZ_WIDGET_GTK -#include "nsGNOMERegistry.h" +#include "nsCommonRegistry.h" #endif #include "nsISupports.h" #include "nsString.h" @@ -1148,7 +1148,7 @@ nsresult nsOSHelperAppService::OSProtocolHandlerExists(const char * aProtocolSch #ifdef MOZ_WIDGET_GTK // Check the GNOME registry for a protocol handler - *aHandlerExists = nsGNOMERegistry::HandlerExists(aProtocolScheme); + *aHandlerExists = nsCommonRegistry::HandlerExists(aProtocolScheme); #endif return NS_OK; @@ -1157,7 +1157,7 @@ nsresult nsOSHelperAppService::OSProtocolHandlerExists(const char * aProtocolSch 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; @@ -1254,7 +1254,7 @@ nsOSHelperAppService::GetFromExtension(const nsCString& aFileExt) { #ifdef MOZ_WIDGET_GTK LOG(("Looking in GNOME registry\n")); RefPtr gnomeInfo = - nsGNOMERegistry::GetFromExtension(aFileExt); + nsCommonRegistry::GetFromExtension(aFileExt); if (gnomeInfo) { LOG(("Got MIMEInfo from GNOME registry\n")); return gnomeInfo.forget(); @@ -1375,7 +1375,7 @@ nsOSHelperAppService::GetFromType(const nsCString& aMIMEType) { #ifdef MOZ_WIDGET_GTK if (handler.IsEmpty()) { - RefPtr gnomeInfo = nsGNOMERegistry::GetFromType(aMIMEType); + RefPtr gnomeInfo = nsCommonRegistry::GetFromType(aMIMEType); if (gnomeInfo) { LOG(("Got MIMEInfo from GNOME registry without extensions; setting them " "to %s\n", NS_LossyConvertUTF16toASCII(extensions).get())); diff --git a/widget/gtk/moz.build b/widget/gtk/moz.build index 208fb1200931..1c4a66fcf8f3 100644 --- a/widget/gtk/moz.build +++ b/widget/gtk/moz.build @@ -126,6 +126,7 @@ LOCAL_INCLUDES += [ '/layout/style', '/layout/xul', '/other-licenses/atk-1.0', + '/toolkit/xre', '/widget', '/widget/headless', ] diff --git a/widget/gtk/nsFilePicker.cpp b/widget/gtk/nsFilePicker.cpp index a2d2e1cff437..4aa29ab29054 100644 --- a/widget/gtk/nsFilePicker.cpp +++ b/widget/gtk/nsFilePicker.cpp @@ -9,6 +9,7 @@ #include #include +#include #include "nsGtkUtils.h" #include "nsIFileURL.h" @@ -25,6 +26,7 @@ #include "mozcontainer.h" #include "nsFilePicker.h" +#include "nsKDEUtils.h" using namespace mozilla; @@ -251,7 +253,9 @@ 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; @@ -376,6 +380,29 @@ nsFilePicker::Open(nsIFilePickerShownCallback *aCallback) 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; + } + nsXPIDLCString title; title.Adopt(ToNewUTF8String(mTitle)); @@ -669,3 +696,227 @@ nsFilePicker::GtkFileChooserSetModal(void *file_chooser, } } } + +nsCString nsFilePicker::kdeMakeFilter( int index ) + { + nsCString buf = mFilters[ index ]; + for( PRUint32 i = 0; + i < buf.Length(); + ++i ) + if( buf[ i ] == ';' ) // KDE separates just using spaces + buf.SetCharAt( ' ', i ); + if (!mFilterNames[index].IsEmpty()) + { + buf += "|"; + buf += mFilterNames[index].get(); + } + return buf; + } + +static PRInt32 windowToXid( nsIWidget* widget ) + { + GtkWindow *parent_widget = GTK_WINDOW(widget->GetNativeData(NS_NATIVE_SHELLWIDGET)); + GdkWindow* gdk_window = gtk_widget_get_window( gtk_widget_get_toplevel( GTK_WIDGET( parent_widget ))); + return GDK_WINDOW_XID( gdk_window ); + } + +NS_IMETHODIMP nsFilePicker::kdeFileDialog(PRInt16 *aReturn) + { + NS_ENSURE_ARG_POINTER(aReturn); + + if( mMode == modeOpen && mFilters.Length() == 1 && mFilters[ 0 ].EqualsLiteral( "..apps" )) + return kdeAppsDialog( aReturn ); + + nsXPIDLCString title; + title.Adopt(ToNewUTF8String(mTitle)); + + const char* arg = NULL; + if( mAllowURLs ) + { + switch( mMode ) + { + case nsIFilePicker::modeOpen: + case nsIFilePicker::modeOpenMultiple: + arg = "GETOPENURL"; + break; + case nsIFilePicker::modeSave: + arg = "GETSAVEURL"; + break; + case nsIFilePicker::modeGetFolder: + arg = "GETDIRECTORYURL"; + break; + } + } + else + { + switch( mMode ) + { + case nsIFilePicker::modeOpen: + case nsIFilePicker::modeOpenMultiple: + arg = "GETOPENFILENAME"; + break; + case nsIFilePicker::modeSave: + arg = "GETSAVEFILENAME"; + break; + case nsIFilePicker::modeGetFolder: + arg = "GETDIRECTORYFILENAME"; + break; + } + } + + nsAutoCString directory; + if (mDisplayDirectory) { + mDisplayDirectory->GetNativePath(directory); + } else if (mPrevDisplayDirectory) { + mPrevDisplayDirectory->GetNativePath(directory); + } + + nsAutoCString startdir; + if (!directory.IsEmpty()) { + startdir = directory; + } + if (mMode == nsIFilePicker::modeSave) { + if( !startdir.IsEmpty()) + { + startdir += "/"; + startdir += ToNewUTF8String(mDefault); + } + else + startdir = ToNewUTF8String(mDefault); + } + + nsAutoCString filters; + PRInt32 count = mFilters.Length(); + if( count == 0 ) //just in case + filters = "*"; + else + { + filters = kdeMakeFilter( 0 ); + for (PRInt32 i = 1; i < count; ++i) + { + filters += "\n"; + filters += kdeMakeFilter( i ); + } + } + + nsTArray command; + command.AppendElement( nsAutoCString( arg )); + command.AppendElement( startdir ); + if( mMode != nsIFilePicker::modeGetFolder ) + { + command.AppendElement( filters ); + nsAutoCString selected; + selected.AppendInt( mSelectedType ); + command.AppendElement( selected ); + } + command.AppendElement( title ); + if( mMode == nsIFilePicker::modeOpenMultiple ) + command.AppendElement( NS_LITERAL_CSTRING( "MULTIPLE" )); + if( PRInt32 xid = windowToXid( mParentWidget )) + { + command.AppendElement( NS_LITERAL_CSTRING( "PARENT" )); + nsAutoCString parent; + parent.AppendInt( xid ); + command.AppendElement( parent ); + } + + nsTArray output; + if( nsKDEUtils::commandBlockUi( command, GTK_WINDOW(mParentWidget->GetNativeData(NS_NATIVE_SHELLWIDGET)), &output )) + { + *aReturn = nsIFilePicker::returnOK; + mFiles.Clear(); + if( mMode != nsIFilePicker::modeGetFolder ) + { + mSelectedType = atoi( output[ 0 ].get()); + output.RemoveElementAt( 0 ); + } + if (mMode == nsIFilePicker::modeOpenMultiple) + { + mFileURL.Truncate(); + PRUint32 count = output.Length(); + for( PRUint32 i = 0; + i < count; + ++i ) + { + nsCOMPtr localfile; + nsresult rv = NS_NewNativeLocalFile( output[ i ], + PR_FALSE, + getter_AddRefs(localfile)); + if (NS_SUCCEEDED(rv)) + mFiles.AppendObject(localfile); + } + } + else + { + if( output.Length() == 0 ) + mFileURL = nsCString(); + else if( mAllowURLs ) + mFileURL = output[ 0 ]; + else // GetFile() actually requires it to be url even for local files :-/ + { + mFileURL = nsCString( "file://" ); + mFileURL.Append( output[ 0 ] ); + } + } + // Remember last used directory. + nsCOMPtr file; + GetFile(getter_AddRefs(file)); + if (file) { + nsCOMPtr dir; + file->GetParent(getter_AddRefs(dir)); + nsCOMPtr localDir(do_QueryInterface(dir)); + if (localDir) { + localDir.swap(mPrevDisplayDirectory); + } + } + if (mMode == nsIFilePicker::modeSave) + { + nsCOMPtr file; + GetFile(getter_AddRefs(file)); + if (file) + { + bool exists = false; + file->Exists(&exists); + if (exists) // TODO do overwrite check in the helper app + *aReturn = nsIFilePicker::returnReplace; + } + } + } + else + { + *aReturn = nsIFilePicker::returnCancel; + } + return NS_OK; + } + + +NS_IMETHODIMP nsFilePicker::kdeAppsDialog(PRInt16 *aReturn) + { + NS_ENSURE_ARG_POINTER(aReturn); + + nsXPIDLCString title; + title.Adopt(ToNewUTF8String(mTitle)); + + nsTArray command; + command.AppendElement( NS_LITERAL_CSTRING( "APPSDIALOG" )); + command.AppendElement( title ); + if( PRInt32 xid = windowToXid( mParentWidget )) + { + command.AppendElement( NS_LITERAL_CSTRING( "PARENT" )); + nsAutoCString parent; + parent.AppendInt( xid ); + command.AppendElement( parent ); + } + + nsTArray output; + if( nsKDEUtils::commandBlockUi( command, GTK_WINDOW(mParentWidget->GetNativeData(NS_NATIVE_SHELLWIDGET)), &output )) + { + *aReturn = nsIFilePicker::returnOK; + mFileURL = output.Length() > 0 ? output[ 0 ] : nsCString(); + } + else + { + *aReturn = nsIFilePicker::returnCancel; + } + return NS_OK; + } diff --git a/widget/gtk/nsFilePicker.h b/widget/gtk/nsFilePicker.h index f462ca32452c..cecb00d463b3 100644 --- a/widget/gtk/nsFilePicker.h +++ b/widget/gtk/nsFilePicker.h @@ -83,6 +83,12 @@ private: void GtkFileChooserSetModal(void *file_chooser, GtkWindow* parent_widget, gboolean modal); + bool kdeRunning(); + bool getKdeRunning(); + NS_IMETHODIMP kdeFileDialog(PRInt16 *aReturn); + NS_IMETHODIMP kdeAppsDialog(PRInt16 *aReturn); + nsCString kdeMakeFilter( int index ); + #if (MOZ_WIDGET_GTK == 3) GtkFileChooserWidget *mFileChooserDelegate; #endif diff --git a/xpcom/components/ManifestParser.cpp b/xpcom/components/ManifestParser.cpp index 63d7d56523d4..e6d294b84929 100644 --- a/xpcom/components/ManifestParser.cpp +++ b/xpcom/components/ManifestParser.cpp @@ -38,6 +38,7 @@ #include "nsIScriptError.h" #include "nsIXULAppInfo.h" #include "nsIXULRuntime.h" +#include "nsKDEUtils.h" using namespace mozilla; @@ -471,6 +472,7 @@ ParseManifest(NSLocationType aType, FileLocation& aFile, char* aBuf, 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"); @@ -531,6 +533,7 @@ ParseManifest(NSLocationType aType, FileLocation& aFile, char* aBuf, } nsAutoString osVersion; + nsAutoString desktop; #if defined(XP_WIN) #pragma warning(push) #pragma warning(disable:4996) // VC12+ deprecates GetVersionEx @@ -540,6 +543,7 @@ ParseManifest(NSLocationType aType, FileLocation& aFile, char* aBuf, info.dwMajorVersion, info.dwMinorVersion); } + desktop = NS_LITERAL_STRING("win"); #pragma warning(pop) #elif defined(MOZ_WIDGET_COCOA) SInt32 majorVersion = nsCocoaFeatures::OSXVersionMajor(); @@ -547,10 +551,12 @@ ParseManifest(NSLocationType aType, FileLocation& aFile, char* aBuf, 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()) { @@ -559,6 +565,7 @@ ParseManifest(NSLocationType aType, FileLocation& aFile, char* aBuf, osVersion); isTablet = java::GeckoAppShell::IsTablet(); } + desktop = NS_LITERAL_STRING("android"); #endif if (XRE_IsContentProcess()) { @@ -671,6 +678,7 @@ ParseManifest(NSLocationType aType, FileLocation& aFile, char* aBuf, TriState stTablet = eUnspecified; #endif int flags = 0; + TriState stDesktop = eUnspecified; while ((token = nsCRT::strtok(whitespace, kWhitespace, &whitespace)) && ok) { @@ -680,6 +688,7 @@ ParseManifest(NSLocationType aType, FileLocation& aFile, char* aBuf, 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) || @@ -734,6 +743,7 @@ ParseManifest(NSLocationType aType, FileLocation& aFile, char* aBuf, stGeckoVersion == eBad || stOs == eBad || stOsVersion == eBad || + stDesktop == eBad || #ifdef MOZ_WIDGET_ANDROID stTablet == eBad || #endif diff --git a/xpcom/components/moz.build b/xpcom/components/moz.build index 3efbc8739972..ea761d31bd3f 100644 --- a/xpcom/components/moz.build +++ b/xpcom/components/moz.build @@ -49,6 +49,7 @@ LOCAL_INCLUDES += [ '../reflect/xptinfo', '/chrome', '/modules/libjar', + '/toolkit/xre' ] if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']: diff --git a/xpcom/io/nsLocalFileUnix.cpp b/xpcom/io/nsLocalFileUnix.cpp index aec8f79303ff..65431c240eec 100644 --- a/xpcom/io/nsLocalFileUnix.cpp +++ b/xpcom/io/nsLocalFileUnix.cpp @@ -51,6 +51,7 @@ #ifdef MOZ_WIDGET_GTK #include "nsIGIOService.h" +#include "nsKDEUtils.h" #endif #ifdef MOZ_WIDGET_COCOA @@ -1949,18 +1950,16 @@ NS_IMETHODIMP nsLocalFile::Reveal() { #ifdef MOZ_WIDGET_GTK - nsCOMPtr giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID); - if (!giovfs) { - return NS_ERROR_FAILURE; - } + nsAutoCString url; bool isDirectory; if (NS_FAILED(IsDirectory(&isDirectory))) { return NS_ERROR_FAILURE; } + nsCOMPtr giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID); if (isDirectory) { - return giovfs->ShowURIForInput(mPath); + url = mPath; } if (NS_SUCCEEDED(giovfs->OrgFreedesktopFileManager1ShowItems(mPath))) { return NS_OK; @@ -1974,7 +1973,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))) { @@ -1986,12 +1985,29 @@ nsLocalFile::Reveal() #else return NS_ERROR_FAILURE; #endif + if(nsKDEUtils::kdeSupport()) { + nsTArray 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 nsLocalFile::Launch() { #ifdef MOZ_WIDGET_GTK + if( nsKDEUtils::kdeSupport()) { + nsTArray command; + command.AppendElement( NS_LITERAL_CSTRING("OPEN") ); + command.AppendElement( mPath ); + return nsKDEUtils::command( command ) ? NS_OK : NS_ERROR_FAILURE; + } nsCOMPtr giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID); if (!giovfs) { return NS_ERROR_FAILURE; -- 2.25.1