diff -r 19a8c8d53349 -r bc5dfe5b853a mozilla-kde.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mozilla-kde.patch Mon Nov 30 13:11:31 2009 +0100 @@ -0,0 +1,4038 @@ +diff --git a/chrome/src/Makefile.in b/chrome/src/Makefile.in +--- a/chrome/src/Makefile.in ++++ b/chrome/src/Makefile.in +@@ -81,16 +81,17 @@ CPPSRCS = \ + + EXTRA_DSO_LDOPTS = \ + $(MOZ_UNICHARUTIL_LIBS) \ + $(MOZ_COMPONENT_LIBS) \ + $(NULL) + + ifneq (,$(filter gtk2,$(MOZ_WIDGET_TOOLKIT))) + EXTRA_DSO_LDOPTS += $(MOZ_GTK2_LIBS) ++LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre + endif + + ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT))) + EXTRA_DSO_LDOPTS += $(TK_LIBS) + endif + + include $(topsrcdir)/config/rules.mk + +diff --git a/chrome/src/nsChromeRegistry.cpp b/chrome/src/nsChromeRegistry.cpp +--- a/chrome/src/nsChromeRegistry.cpp ++++ b/chrome/src/nsChromeRegistry.cpp +@@ -109,16 +109,17 @@ + #include "nsIStyleSheet.h" + #include "nsISupportsArray.h" + #include "nsIVersionComparator.h" + #include "nsIWindowMediator.h" + #include "nsIXPConnect.h" + #include "nsIXULAppInfo.h" + #include "nsIXULRuntime.h" + #include "nsPresShellIterator.h" ++#include "nsKDEUtils.h" + + #define UILOCALE_CMD_LINE_ARG "UILocale" + + #define MATCH_OS_LOCALE_PREF "intl.locale.matchOS" + #define SELECTED_LOCALE_PREF "general.useragent.locale" + #define SELECTED_SKIN_PREF "general.skins.selectedSkin" + + static NS_DEFINE_CID(kCSSLoaderCID, NS_CSS_LOADER_CID); +@@ -1607,16 +1608,17 @@ nsChromeRegistry::ProcessManifestBuffer( + + NS_NAMED_LITERAL_STRING(kPlatform, "platform"); + NS_NAMED_LITERAL_STRING(kXPCNativeWrappers, "xpcnativewrappers"); + NS_NAMED_LITERAL_STRING(kContentAccessible, "contentaccessible"); + NS_NAMED_LITERAL_STRING(kApplication, "application"); + NS_NAMED_LITERAL_STRING(kAppVersion, "appversion"); + NS_NAMED_LITERAL_STRING(kOs, "os"); + NS_NAMED_LITERAL_STRING(kOsVersion, "osversion"); ++ NS_NAMED_LITERAL_STRING(kDesktop, "desktop"); + + nsCOMPtr io (do_GetIOService()); + if (!io) return NS_ERROR_FAILURE; + + nsCOMPtr ph; + rv = io->GetProtocolHandler("resource", getter_AddRefs(ph)); + NS_ENSURE_SUCCESS(rv, rv); + +@@ -1650,35 +1652,39 @@ nsChromeRegistry::ProcessManifestBuffer( + if (NS_SUCCEEDED(rv)) { + CopyUTF8toUTF16(s, osTarget); + ToLowerCase(osTarget); + } + } + } + + nsAutoString osVersion; ++ nsAutoString desktop; + #if defined(XP_WIN) + OSVERSIONINFO info = { sizeof(OSVERSIONINFO) }; + if (GetVersionEx(&info)) { + nsTextFormatter::ssprintf(osVersion, NS_LITERAL_STRING("%ld.%ld").get(), + info.dwMajorVersion, + info.dwMinorVersion); + } ++ desktop = NS_LITERAL_STRING("win"); + #elif defined(XP_MACOSX) + long majorVersion, minorVersion; + if ((Gestalt(gestaltSystemVersionMajor, &majorVersion) == noErr) && + (Gestalt(gestaltSystemVersionMinor, &minorVersion) == noErr)) { + nsTextFormatter::ssprintf(osVersion, NS_LITERAL_STRING("%ld.%ld").get(), + majorVersion, + minorVersion); + } ++ desktop = NS_LITERAL_STRING("macosx"); + #elif defined(MOZ_WIDGET_GTK2) + nsTextFormatter::ssprintf(osVersion, NS_LITERAL_STRING("%ld.%ld").get(), + gtk_major_version, + gtk_minor_version); ++ desktop = nsKDEUtils::kdeSession() ? NS_LITERAL_STRING("kde") : NS_LITERAL_STRING("gnome"); // TODO others? + #endif + + char *token; + char *newline = buf; + PRUint32 line = 0; + + // outer loop tokenizes by newline + while (nsnull != (token = nsCRT::strtok(newline, kNewlines, &newline))) { +@@ -1712,41 +1718,43 @@ nsChromeRegistry::ProcessManifestBuffer( + + PRBool platform = PR_FALSE; + PRBool xpcNativeWrappers = PR_TRUE; + PRBool contentAccessible = PR_FALSE; + TriState stAppVersion = eUnspecified; + TriState stApp = eUnspecified; + TriState stOsVersion = eUnspecified; + TriState stOs = eUnspecified; ++ TriState stDesktop = eUnspecified; + + PRBool badFlag = PR_FALSE; + + while (nsnull != (token = nsCRT::strtok(whitespace, kWhitespace, &whitespace)) && + !badFlag) { + NS_ConvertASCIItoUTF16 wtoken(token); + ToLowerCase(wtoken); + + if (CheckFlag(kPlatform, wtoken, platform) || + CheckFlag(kXPCNativeWrappers, wtoken, xpcNativeWrappers) || + CheckFlag(kContentAccessible, wtoken, contentAccessible) || + CheckStringFlag(kApplication, wtoken, appID, stApp) || + CheckStringFlag(kOs, wtoken, osTarget, stOs) || ++ CheckStringFlag(kDesktop, wtoken, desktop, stDesktop) || + CheckVersionFlag(kOsVersion, wtoken, osVersion, vc, stOsVersion) || + CheckVersionFlag(kAppVersion, wtoken, appVersion, vc, stAppVersion)) + continue; + + LogMessageWithContext(manifestURI, line, nsIScriptError::warningFlag, + "Warning: Unrecognized chrome registration modifier '%s'.", + token); + badFlag = PR_TRUE; + } + + if (badFlag || stApp == eBad || stAppVersion == eBad || +- stOs == eBad || stOsVersion == eBad) ++ stOs == eBad || stOsVersion == eBad || stDesktop == eBad) + continue; + + nsCOMPtr resolved; + rv = io->NewURI(nsDependentCString(uri), nsnull, manifestURI, + getter_AddRefs(resolved)); + if (NS_FAILED(rv)) + continue; + +@@ -1797,38 +1805,40 @@ nsChromeRegistry::ProcessManifestBuffer( + } + + EnsureLowerCase(package); + + TriState stAppVersion = eUnspecified; + TriState stApp = eUnspecified; + TriState stOs = eUnspecified; + TriState stOsVersion = eUnspecified; ++ TriState stDesktop = eUnspecified; + + PRBool badFlag = PR_FALSE; + + while (nsnull != (token = nsCRT::strtok(whitespace, kWhitespace, &whitespace)) && + !badFlag) { + NS_ConvertASCIItoUTF16 wtoken(token); + ToLowerCase(wtoken); + + if (CheckStringFlag(kApplication, wtoken, appID, stApp) || + CheckStringFlag(kOs, wtoken, osTarget, stOs) || ++ CheckStringFlag(kDesktop, wtoken, desktop, stDesktop) || + CheckVersionFlag(kOsVersion, wtoken, osVersion, vc, stOsVersion) || + CheckVersionFlag(kAppVersion, wtoken, appVersion, vc, stAppVersion)) + continue; + + LogMessageWithContext(manifestURI, line, nsIScriptError::warningFlag, + "Warning: Unrecognized chrome registration modifier '%s'.", + token); + badFlag = PR_TRUE; + } + + if (badFlag || stApp == eBad || stAppVersion == eBad || +- stOs == eBad || stOsVersion == eBad) ++ stOs == eBad || stOsVersion == eBad || stDesktop == eBad) + continue; + + nsCOMPtr resolved; + rv = io->NewURI(nsDependentCString(uri), nsnull, manifestURI, + getter_AddRefs(resolved)); + if (NS_FAILED(rv)) + continue; + +@@ -1859,38 +1869,40 @@ nsChromeRegistry::ProcessManifestBuffer( + } + + EnsureLowerCase(package); + + TriState stAppVersion = eUnspecified; + TriState stApp = eUnspecified; + TriState stOs = eUnspecified; + TriState stOsVersion = eUnspecified; ++ TriState stDesktop = eUnspecified; + + PRBool badFlag = PR_FALSE; + + while (nsnull != (token = nsCRT::strtok(whitespace, kWhitespace, &whitespace)) && + !badFlag) { + NS_ConvertASCIItoUTF16 wtoken(token); + ToLowerCase(wtoken); + + if (CheckStringFlag(kApplication, wtoken, appID, stApp) || + CheckStringFlag(kOs, wtoken, osTarget, stOs) || ++ CheckStringFlag(kDesktop, wtoken, desktop, stDesktop) || + CheckVersionFlag(kOsVersion, wtoken, osVersion, vc, stOsVersion) || + CheckVersionFlag(kAppVersion, wtoken, appVersion, vc, stAppVersion)) + continue; + + LogMessageWithContext(manifestURI, line, nsIScriptError::warningFlag, + "Warning: Unrecognized chrome registration modifier '%s'.", + token); + badFlag = PR_TRUE; + } + + if (badFlag || stApp == eBad || stAppVersion == eBad || +- stOs == eBad || stOsVersion == eBad) ++ stOs == eBad || stOsVersion == eBad || stDesktop == eBad) + continue; + + nsCOMPtr resolved; + rv = io->NewURI(nsDependentCString(uri), nsnull, manifestURI, + getter_AddRefs(resolved)); + if (NS_FAILED(rv)) + continue; + +@@ -1923,38 +1935,40 @@ nsChromeRegistry::ProcessManifestBuffer( + "Warning: malformed chrome overlay instruction."); + continue; + } + + TriState stAppVersion = eUnspecified; + TriState stApp = eUnspecified; + TriState stOs = eUnspecified; + TriState stOsVersion = eUnspecified; ++ TriState stDesktop = eUnspecified; + + PRBool badFlag = PR_FALSE; + + while (nsnull != (token = nsCRT::strtok(whitespace, kWhitespace, &whitespace)) && + !badFlag) { + NS_ConvertASCIItoUTF16 wtoken(token); + ToLowerCase(wtoken); + + if (CheckStringFlag(kApplication, wtoken, appID, stApp) || + CheckStringFlag(kOs, wtoken, osTarget, stOs) || ++ CheckStringFlag(kDesktop, wtoken, desktop, stDesktop) || + CheckVersionFlag(kOsVersion, wtoken, osVersion, vc, stOsVersion) || + CheckVersionFlag(kAppVersion, wtoken, appVersion, vc, stAppVersion)) + continue; + + LogMessageWithContext(manifestURI, line, nsIScriptError::warningFlag, + "Warning: Unrecognized chrome registration modifier '%s'.", + token); + badFlag = PR_TRUE; + } + + if (badFlag || stApp == eBad || stAppVersion == eBad || +- stOs == eBad || stOsVersion == eBad) ++ stOs == eBad || stOsVersion == eBad || stDesktop == eBad) + continue; + + nsCOMPtr baseuri, overlayuri; + rv = io->NewURI(nsDependentCString(base), nsnull, nsnull, + getter_AddRefs(baseuri)); + rv |= io->NewURI(nsDependentCString(overlay), nsnull, nsnull, + getter_AddRefs(overlayuri)); + if (NS_FAILED(rv)) { +@@ -1979,38 +1993,40 @@ nsChromeRegistry::ProcessManifestBuffer( + "Warning: malformed chrome style instruction."); + continue; + } + + TriState stAppVersion = eUnspecified; + TriState stApp = eUnspecified; + TriState stOs = eUnspecified; + TriState stOsVersion = eUnspecified; ++ TriState stDesktop = eUnspecified; + + PRBool badFlag = PR_FALSE; + + while (nsnull != (token = nsCRT::strtok(whitespace, kWhitespace, &whitespace)) && + !badFlag) { + NS_ConvertASCIItoUTF16 wtoken(token); + ToLowerCase(wtoken); + + if (CheckStringFlag(kApplication, wtoken, appID, stApp) || + CheckStringFlag(kOs, wtoken, osTarget, stOs) || ++ CheckStringFlag(kDesktop, wtoken, desktop, stDesktop) || + CheckVersionFlag(kOsVersion, wtoken, osVersion, vc, stOsVersion) || + CheckVersionFlag(kAppVersion, wtoken, appVersion, vc, stAppVersion)) + continue; + + LogMessageWithContext(manifestURI, line, nsIScriptError::warningFlag, + "Warning: Unrecognized chrome registration modifier '%s'.", + token); + badFlag = PR_TRUE; + } + + if (badFlag || stApp == eBad || stAppVersion == eBad || +- stOs == eBad || stOsVersion == eBad) ++ stOs == eBad || stOsVersion == eBad || stDesktop == eBad) + continue; + + nsCOMPtr baseuri, overlayuri; + rv = io->NewURI(nsDependentCString(base), nsnull, nsnull, + getter_AddRefs(baseuri)); + rv |= io->NewURI(nsDependentCString(overlay), nsnull, nsnull, + getter_AddRefs(overlayuri)); + if (NS_FAILED(rv)) +@@ -2039,38 +2055,40 @@ nsChromeRegistry::ProcessManifestBuffer( + "Warning: malformed chrome override instruction."); + continue; + } + + TriState stAppVersion = eUnspecified; + TriState stApp = eUnspecified; + TriState stOs = eUnspecified; + TriState stOsVersion = eUnspecified; ++ TriState stDesktop = eUnspecified; + + PRBool badFlag = PR_FALSE; + + while (nsnull != (token = nsCRT::strtok(whitespace, kWhitespace, &whitespace)) && + !badFlag) { + NS_ConvertASCIItoUTF16 wtoken(token); + ToLowerCase(wtoken); + + if (CheckStringFlag(kApplication, wtoken, appID, stApp) || + CheckStringFlag(kOs, wtoken, osTarget, stOs) || ++ CheckStringFlag(kDesktop, wtoken, desktop, stDesktop) || + CheckVersionFlag(kOsVersion, wtoken, osVersion, vc, stOsVersion) || + CheckVersionFlag(kAppVersion, wtoken, appVersion, vc, stAppVersion)) + continue; + + LogMessageWithContext(manifestURI, line, nsIScriptError::warningFlag, + "Warning: Unrecognized chrome registration modifier '%s'.", + token); + badFlag = PR_TRUE; + } + + if (badFlag || stApp == eBad || stAppVersion == eBad || +- stOs == eBad || stOsVersion == eBad) ++ stOs == eBad || stOsVersion == eBad || stDesktop == eBad) + continue; + + nsCOMPtr chromeuri, resolveduri; + rv = io->NewURI(nsDependentCString(chrome), nsnull, nsnull, + getter_AddRefs(chromeuri)); + rv |= io->NewURI(nsDependentCString(resolved), nsnull, manifestURI, + getter_AddRefs(resolveduri)); + if (NS_FAILED(rv)) +@@ -2101,38 +2119,40 @@ nsChromeRegistry::ProcessManifestBuffer( + } + + EnsureLowerCase(package); + + TriState stAppVersion = eUnspecified; + TriState stApp = eUnspecified; + TriState stOsVersion = eUnspecified; + TriState stOs = eUnspecified; ++ TriState stDesktop = eUnspecified; + + PRBool badFlag = PR_FALSE; + + while (nsnull != (token = nsCRT::strtok(whitespace, kWhitespace, &whitespace)) && + !badFlag) { + NS_ConvertASCIItoUTF16 wtoken(token); + ToLowerCase(wtoken); + + if (CheckStringFlag(kApplication, wtoken, appID, stApp) || + CheckStringFlag(kOs, wtoken, osTarget, stOs) || ++ CheckStringFlag(kDesktop, wtoken, desktop, stDesktop) || + CheckVersionFlag(kOsVersion, wtoken, osVersion, vc, stOsVersion) || + CheckVersionFlag(kAppVersion, wtoken, appVersion, vc, stAppVersion)) + continue; + + LogMessageWithContext(manifestURI, line, nsIScriptError::warningFlag, + "Warning: Unrecognized chrome registration modifier '%s'.", + token); + badFlag = PR_TRUE; + } + + if (badFlag || stApp == eBad || stAppVersion == eBad || +- stOs == eBad || stOsVersion == eBad) ++ stOs == eBad || stOsVersion == eBad || stDesktop == eBad) + continue; + + nsDependentCString host(package); + + PRBool exists; + rv = rph->HasSubstitution(host, &exists); + NS_ENSURE_SUCCESS(rv, rv); + if (exists) { +diff --git a/modules/libpref/src/Makefile.in b/modules/libpref/src/Makefile.in +--- a/modules/libpref/src/Makefile.in ++++ b/modules/libpref/src/Makefile.in +@@ -97,8 +97,10 @@ GARBAGE += $(addprefix $(DIST)/bin/defa + + # Optimizer bug with GCC 3.2.2 on OS/2 + ifeq ($(OS_ARCH), OS2) + nsPrefService.$(OBJ_SUFFIX): nsPrefService.cpp + $(REPORT_BUILD) + @$(MAKE_DEPS_AUTO_CXX) + $(ELOG) $(CCC) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS:-O2=-O1) $(_VPATH_SRCS) + endif ++ ++LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre +diff --git a/modules/libpref/src/nsPrefService.cpp b/modules/libpref/src/nsPrefService.cpp +--- a/modules/libpref/src/nsPrefService.cpp ++++ b/modules/libpref/src/nsPrefService.cpp +@@ -47,16 +47,17 @@ + #include "nsILocalFile.h" + #include "nsIObserverService.h" + #include "nsPrefBranch.h" + #include "nsXPIDLString.h" + #include "nsCRT.h" + #include "nsCOMArray.h" + #include "nsXPCOMCID.h" + #include "nsAutoPtr.h" ++#include "nsKDEUtils.h" + + #include "nsQuickSort.h" + #include "prmem.h" + #include "pldhash.h" + + #include "prefapi.h" + #include "prefread.h" + #include "prefapi_private_data.h" +@@ -610,17 +611,18 @@ pref_LoadPrefsInDir(nsIFile* aDir, char + rv = rv2; + } + } + } + + return rv; + } + +-static nsresult pref_LoadPrefsInDirList(const char *listId) ++static nsresult pref_LoadPrefsInDirList(const char *listId, ++ char const *const *aSpecialFiles = NULL, PRUint32 aSpecialFilesCount = 0) + { + nsresult rv; + nsCOMPtr dirSvc(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv)); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr dirList; + dirSvc->Get(listId, + NS_GET_IID(nsISimpleEnumerator), +@@ -629,17 +631,17 @@ static nsresult pref_LoadPrefsInDirList( + PRBool hasMore; + while (NS_SUCCEEDED(dirList->HasMoreElements(&hasMore)) && hasMore) { + nsCOMPtr elem; + dirList->GetNext(getter_AddRefs(elem)); + if (elem) { + nsCOMPtr dir = do_QueryInterface(elem); + if (dir) { + // Do we care if a file provided by this process fails to load? +- pref_LoadPrefsInDir(dir, nsnull, 0); ++ pref_LoadPrefsInDir(dir, aSpecialFiles, aSpecialFilesCount); + } + } + } + } + return NS_OK; + } + + //---------------------------------------------------------------------------------------- +@@ -680,29 +682,41 @@ static nsresult pref_InitInitialObjects( + #if defined(VMS) + , "openvms.js" + #elif defined(_AIX) + , "aix.js" + #endif + #if defined(MOZ_WIDGET_PHOTON) + , "photon.js" + #endif ++ , "" // placeholder for KDE (empty is otherwise harmless) + #elif defined(XP_OS2) + "os2pref.js" + #elif defined(XP_BEOS) + "beos.js" + #endif + }; + ++ if( nsKDEUtils::kdeSession()) { // TODO what if some setup actually requires the helper? ++ for( int i = 0; ++ i < NS_ARRAY_LENGTH(specialFiles); ++ ++i ) { ++ if( *specialFiles[ i ] == '\0' ) { ++ specialFiles[ i ] = "kde.js"; ++ break; ++ } ++ } ++ } ++ + rv = pref_LoadPrefsInDir(defaultPrefDir, specialFiles, NS_ARRAY_LENGTH(specialFiles)); + if (NS_FAILED(rv)) { + NS_WARNING("Error parsing application default preferences."); + } + +- rv = pref_LoadPrefsInDirList(NS_APP_PREFS_DEFAULTS_DIR_LIST); ++ rv = pref_LoadPrefsInDirList(NS_APP_PREFS_DEFAULTS_DIR_LIST, specialFiles, NS_ARRAY_LENGTH(specialFiles)); + NS_ENSURE_SUCCESS(rv, rv); + + NS_CreateServicesFromCategory(NS_PREFSERVICE_APPDEFAULTS_TOPIC_ID, + nsnull, NS_PREFSERVICE_APPDEFAULTS_TOPIC_ID); + + nsCOMPtr observerService = + do_GetService("@mozilla.org/observer-service;1", &rv); + +diff --git a/toolkit/components/downloads/src/Makefile.in b/toolkit/components/downloads/src/Makefile.in +--- a/toolkit/components/downloads/src/Makefile.in ++++ b/toolkit/components/downloads/src/Makefile.in +@@ -92,8 +92,9 @@ EXTRA_COMPONENTS = \ + nsDownloadManagerUI.js \ + $(NULL) + endif + + include $(topsrcdir)/config/rules.mk + + EXTRA_DSO_LDOPTS += $(MOZ_COMPONENT_LIBS) + ++LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre +diff --git a/toolkit/components/downloads/src/nsDownloadManager.cpp b/toolkit/components/downloads/src/nsDownloadManager.cpp +--- a/toolkit/components/downloads/src/nsDownloadManager.cpp ++++ b/toolkit/components/downloads/src/nsDownloadManager.cpp +@@ -71,16 +71,20 @@ + + #if defined(XP_WIN) && !defined(WINCE) + #include + #ifdef DOWNLOAD_SCANNER + #include "nsDownloadScanner.h" + #endif + #endif + ++#if defined(XP_UNIX) && !defined(XP_MACOSX) ++#include "nsKDEUtils.h" ++#endif ++ + #define DOWNLOAD_MANAGER_BUNDLE "chrome://mozapps/locale/downloads/downloads.properties" + #define DOWNLOAD_MANAGER_ALERT_ICON "chrome://mozapps/skin/downloads/downloadIcon.png" + #define PREF_BDM_SHOWALERTONCOMPLETE "browser.download.manager.showAlertOnComplete" + #define PREF_BDM_SHOWALERTINTERVAL "browser.download.manager.showAlertInterval" + #define PREF_BDM_RETENTION "browser.download.manager.retention" + #define PREF_BDM_QUITBEHAVIOR "browser.download.manager.quitBehavior" + #define PREF_BDM_ADDTORECENTDOCS "browser.download.manager.addToRecentDocs" + #define PREF_BDM_SCANWHENDONE "browser.download.manager.scanWhenDone" +@@ -2158,16 +2162,25 @@ nsDownload::SetState(DownloadState aStat + nsCOMPtr pref(do_GetService(NS_PREFSERVICE_CONTRACTID)); + + // Master pref to control this function. + PRBool showTaskbarAlert = PR_TRUE; + if (pref) + pref->GetBoolPref(PREF_BDM_SHOWALERTONCOMPLETE, &showTaskbarAlert); + + if (showTaskbarAlert) { ++ if( nsKDEUtils::kdeSupport()) { ++ nsCStringArray command; ++ command.AppendCString( NS_LITERAL_CSTRING( "DOWNLOADFINISHED" )); ++ nsAutoString displayName; ++ GetDisplayName( displayName ); ++ command.AppendCString( nsCAutoString( ToNewUTF8String( displayName ))); ++ nsKDEUtils::command( command ); ++ } else { ++ // begin non-KDE block + PRInt32 alertInterval = 2000; + if (pref) + pref->GetIntPref(PREF_BDM_SHOWALERTINTERVAL, &alertInterval); + + PRInt64 alertIntervalUSec = alertInterval * PR_USEC_PER_MSEC; + PRInt64 goat = PR_Now() - mStartTime; + showTaskbarAlert = goat > alertIntervalUSec; + +@@ -2193,16 +2206,17 @@ nsDownload::SetState(DownloadState aStat + // because if it is, they'll click open the download manager and + // the items they downloaded will have been removed. + alerts->ShowAlertNotification( + NS_LITERAL_STRING(DOWNLOAD_MANAGER_ALERT_ICON), title, + message, !removeWhenDone, EmptyString(), mDownloadManager, + EmptyString()); + } + } ++ } // end non-KDE block + } + #if defined(XP_WIN) && !defined(WINCE) + nsCOMPtr fileURL = do_QueryInterface(mTarget); + nsCOMPtr file; + nsAutoString path; + + if (fileURL && + NS_SUCCEEDED(fileURL->GetFile(getter_AddRefs(file))) && +diff --git a/toolkit/content/jar.mn b/toolkit/content/jar.mn +--- a/toolkit/content/jar.mn ++++ b/toolkit/content/jar.mn +@@ -44,29 +44,33 @@ toolkit.jar: + *+ content/global/viewZoomOverlay.js (viewZoomOverlay.js) + *+ content/global/bindings/autocomplete.xml (widgets/autocomplete.xml) + *+ content/global/bindings/browser.xml (widgets/browser.xml) + *+ content/global/bindings/button.xml (widgets/button.xml) + *+ content/global/bindings/checkbox.xml (widgets/checkbox.xml) + *+ content/global/bindings/colorpicker.xml (widgets/colorpicker.xml) + *+ content/global/bindings/datetimepicker.xml (widgets/datetimepicker.xml) + *+ 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) + *+ content/global/bindings/findbar.xml (widgets/findbar.xml) + *+ content/global/bindings/general.xml (widgets/general.xml) + *+ content/global/bindings/groupbox.xml (widgets/groupbox.xml) + *+ content/global/bindings/listbox.xml (widgets/listbox.xml) + *+ content/global/bindings/menu.xml (widgets/menu.xml) + *+ content/global/bindings/menulist.xml (widgets/menulist.xml) + *+ content/global/bindings/notification.xml (widgets/notification.xml) + *+ 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/resizer.xml (widgets/resizer.xml) + *+ content/global/bindings/richlistbox.xml (widgets/richlistbox.xml) + *+ content/global/bindings/scale.xml (widgets/scale.xml) + *+ content/global/bindings/scrollbar.xml (widgets/scrollbar.xml) + *+ content/global/bindings/scrollbox.xml (widgets/scrollbox.xml) + *+ content/global/bindings/splitter.xml (widgets/splitter.xml) +diff --git a/toolkit/content/widgets/dialog-kde.xml b/toolkit/content/widgets/dialog-kde.xml +new file mode 100644 +--- /dev/null ++++ b/toolkit/content/widgets/dialog-kde.xml +@@ -0,0 +1,445 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ 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.getPreventDefault()) ++ 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 +--- /dev/null ++++ b/toolkit/content/widgets/preferences-kde.xml +@@ -0,0 +1,1371 @@ ++ ++ ++ ++ %preferencesDTD; ++ ++ %globalKeysDTD; ++]> ++ ++ ++ ++# ++# = Preferences Window Framework ++# ++# The syntax for use looks something like: ++# ++# ++# ++# ++# ++# ++# ++# ++# ++# ++# ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ 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); ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ this.preferences.rootBranchInternal ++ .removeObserver(this.name, this.preferences); ++ ++ ++ ++ ++ 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, false); ++ ++ 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 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ 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")); ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ 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. ++ 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 -*- ++# ***** BEGIN LICENSE BLOCK ***** ++# Version: MPL 1.1/GPL 2.0/LGPL 2.1 ++# ++# The contents of this file are subject to the Mozilla Public License Version ++# 1.1 (the "License"); you may not use this file except in compliance with ++# the License. You may obtain a copy of the License at ++# http://www.mozilla.org/MPL/ ++# ++# Software distributed under the License is distributed on an "AS IS" basis, ++# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License ++# for the specific language governing rights and limitations under the ++# License. ++# ++# The Original Code is the Preferences System. ++# ++# The Initial Developer of the Original Code is ++# Ben Goodger. ++# Portions created by the Initial Developer are Copyright (C) 2005 ++# the Initial Developer. All Rights Reserved. ++# ++# Contributor(s): ++# Ben Goodger ++# Josh Aas ++# ++# Alternatively, the contents of this file may be used under the terms of ++# either the GNU General Public License Version 2 or later (the "GPL"), or ++# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), ++# in which case the provisions of the GPL or the LGPL are applicable instead ++# of those above. If you wish to allow use of your version of this file only ++# under the terms of either the GPL or the LGPL, and not to allow others to ++# use your version of this file under the terms of the MPL, indicate your ++# decision by deleting the provisions above and replace them with the notice ++# and other provisions required by the GPL or the LGPL. If you do not delete ++# the provisions above, a recipient may use your version of this file under ++# the terms of any one of the MPL, the GPL or the LGPL. ++# ++# ***** END LICENSE BLOCK ***** ++ ++# ++# 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/system/unixproxy/Makefile.in b/toolkit/system/unixproxy/Makefile.in +--- a/toolkit/system/unixproxy/Makefile.in ++++ b/toolkit/system/unixproxy/Makefile.in +@@ -54,16 +54,18 @@ LIBXUL_LIBRARY = 1 + + REQUIRES = \ + xpcom \ + string \ + necko \ + mozgnome \ + $(NULL) + ++LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre ++ + EXTRA_DSO_LDOPTS += \ + $(MOZ_LIBPROXY_LIBS) \ + $(MOZ_COMPONENT_LIBS) \ + $(NULL) + + ifdef MOZ_ENABLE_LIBPROXY + + CPPSRCS = \ +diff --git a/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp b/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp +--- a/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp ++++ b/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp +@@ -44,32 +44,35 @@ + #include "nsIURI.h" + #include "nsReadableUtils.h" + #include "nsArrayUtils.h" + #include "prnetdb.h" + #include "prenv.h" + #include "nsPrintfCString.h" + #include "nsNetUtil.h" + #include "nsISupportsPrimitives.h" ++#include "nsVoidArray.h" ++#include "nsKDEUtils.h" + + class nsUnixSystemProxySettings : public nsISystemProxySettings { + public: + NS_DECL_ISUPPORTS + NS_DECL_NSISYSTEMPROXYSETTINGS + + nsUnixSystemProxySettings() {} + nsresult Init(); + + private: + ~nsUnixSystemProxySettings() {} + + nsCOMPtr mGConf; + PRBool IsProxyMode(const char* aMode); + nsresult SetProxyResultFromGConf(const char* aKeyBase, const char* aType, nsACString& aResult); + nsresult GetProxyFromGConf(const nsACString& aScheme, const nsACString& aHost, PRInt32 aPort, nsACString& aResult); ++ nsresult GetProxyFromKDE(const nsACString& aScheme, const nsACString& aHost, PRInt32 aPort, nsACString& aResult); + }; + + NS_IMPL_ISUPPORTS1(nsUnixSystemProxySettings, nsISystemProxySettings) + + nsresult + nsUnixSystemProxySettings::Init() + { + // If this is a GNOME session, load gconf and try to use its preferences. +@@ -407,16 +410,19 @@ nsUnixSystemProxySettings::GetProxyForUR + nsCAutoString host; + rv = aURI->GetHost(host); + NS_ENSURE_SUCCESS(rv, rv); + + PRInt32 port; + rv = aURI->GetPort(&port); + NS_ENSURE_SUCCESS(rv, rv); + ++ if( nsKDEUtils::kdeSupport()) ++ return GetProxyFromKDE( scheme, host, port, aResult ); ++ + if (!mGConf) + return GetProxyFromEnvironment(scheme, host, port, aResult); + + return GetProxyFromGConf(scheme, host, port, aResult); + } + + #define NS_UNIXSYSTEMPROXYSERVICE_CID /* 0fa3158c-d5a7-43de-9181-a285e74cf1d4 */\ + { 0x0fa3158c, 0xd5a7, 0x43de, \ +@@ -427,8 +433,33 @@ NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsUn + static const nsModuleComponentInfo components[] = { + { "Unix System Proxy Settings Service", + NS_UNIXSYSTEMPROXYSERVICE_CID, + NS_SYSTEMPROXYSETTINGS_CONTRACTID, + nsUnixSystemProxySettingsConstructor } + }; + + NS_IMPL_NSGETMODULE(nsUnixProxyModule, components) ++ ++nsresult ++nsUnixSystemProxySettings::GetProxyFromKDE(const nsACString& aScheme, ++ const nsACString& aHost, ++ PRInt32 aPort, ++ nsACString& aResult) ++{ ++ nsCAutoString url; ++ url = aScheme; ++ url += "://"; ++ url += aHost; ++ if( aPort >= 0 ) ++ { ++ url += ":"; ++ url += nsPrintfCString("%d", aPort); ++ } ++ nsCStringArray command; ++ command.AppendCString( NS_LITERAL_CSTRING( "GETPROXY" )); ++ command.AppendCString( url ); ++ nsCStringArray result; ++ if( !nsKDEUtils::command( command, &result ) || result.Count() != 1 ) ++ return NS_ERROR_FAILURE; ++ aResult = *result[ 0 ]; ++ return NS_OK; ++} +diff --git a/toolkit/xre/Makefile.in b/toolkit/xre/Makefile.in +--- a/toolkit/xre/Makefile.in ++++ b/toolkit/xre/Makefile.in +@@ -131,17 +131,17 @@ CMMSRCS = nsNativeAppSupportCocoa.mm + else + ifeq ($(MOZ_WIDGET_TOOLKIT),os2) + CPPSRCS += nsNativeAppSupportOS2.cpp + else + ifeq ($(MOZ_WIDGET_TOOLKIT),beos) + CPPSRCS += nsNativeAppSupportBeOS.cpp + else + ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2) +-CPPSRCS += nsNativeAppSupportUnix.cpp ++CPPSRCS += nsNativeAppSupportUnix.cpp nsKDEUtils.cpp + else + CPPSRCS += nsNativeAppSupportDefault.cpp + endif + endif + endif + endif + endif + +diff --git a/toolkit/xre/nsKDEUtils.cpp b/toolkit/xre/nsKDEUtils.cpp +new file mode 100644 +--- /dev/null ++++ b/toolkit/xre/nsKDEUtils.cpp +@@ -0,0 +1,335 @@ ++/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ ++/* ***** BEGIN LICENSE BLOCK ***** ++ * Version: MPL 1.1/GPL 2.0/LGPL 2.1 ++ * ++ * The contents of this file are subject to the Mozilla Public License Version ++ * 1.1 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * http://www.mozilla.org/MPL/ ++ * ++ * Software distributed under the License is distributed on an "AS IS" basis, ++ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License ++ * for the specific language governing rights and limitations under the ++ * License. ++ * ++ * The Original Code is Unix Native App Support. ++ * ++ * The Initial Developer of the Original Code is ++ * Mozilla Corporation. ++ * Portions created by the Initial Developer are Copyright (C) 2007 ++ * the Initial Developer. All Rights Reserved. ++ * ++ * Contributor(s): ++ * ++ * Alternatively, the contents of this file may be used under the terms of ++ * either the GNU General Public License Version 2 or later (the "GPL"), or ++ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), ++ * in which case the provisions of the GPL or the LGPL are applicable instead ++ * of those above. If you wish to allow use of your version of this file only ++ * under the terms of either the GPL or the LGPL, and not to allow others to ++ * use your version of this file under the terms of the MPL, indicate your ++ * decision by deleting the provisions above and replace them with the notice ++ * and other provisions required by the GPL or the LGPL. If you do not delete ++ * the provisions above, a recipient may use your version of this file under ++ * the terms of any one of the MPL, the GPL or the LGPL. ++ * ++ * ***** END LICENSE BLOCK ***** */ ++ ++#include "nsKDEUtils.h" ++#include "nsIWidget.h" ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++//#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() ++ { ++ nsCStringArray command; ++ command.AppendCString( NS_LITERAL_CSTRING( "CHECK" )); ++ command.AppendCString( 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; ++ nsCStringArray* 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 ); ++ nsCAutoString line( buf ); ++ line.ReplaceSubstring( "\\n", "\n" ); ++ line.ReplaceSubstring( "\\" "\\", "\\" ); // \\ -> \ , i.e. unescape ++ if( p->output && !( command_done || command_failed )) ++ p->output->AppendCString( 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 nsCStringArray& command, nsCStringArray* output ) ++ { ++ return self()->internalCommand( command, NULL, false, output ); ++ } ++ ++bool nsKDEUtils::commandBlockUi( const nsCStringArray& command, const GtkWindow* parent, nsCStringArray* output ) ++ { ++ return self()->internalCommand( command, parent, true, output ); ++ } ++ ++bool nsKDEUtils::internalCommand( const nsCStringArray& command, const GtkWindow* parent, bool blockUi, ++ nsCStringArray* output ) ++ { ++ if( !startHelper()) ++ return false; ++ // if Gtk has meanwhile gotten a grab (bnc#555202, somehow the file dialog ++ // is called with a delay), then do not do anything, as this app would keep ++ // the grabs but block waiting for the helper, which would be unable to do ++ // anything because of the grab ++ if( blockUi && gdk_pointer_is_grabbed()) ++ 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 && parent->group ) ++ gtk_window_group_add_window( parent->group, 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 nsCStringArray& command ) ++ { ++ for( int i = 0; ++ i < command.Count(); ++ ++i ) ++ { ++ nsCString line = *command[ i ]; ++ line.ReplaceSubstring( "\\", "\\" "\\" ); // \ -> \\ , i.e. escape ++ line.ReplaceSubstring( "\n", "\\n" ); ++#ifdef DEBUG_KDE ++ fprintf( stderr, "COMM: %s\n", line.get()); ++#endif ++ fputs( line.get(), commandFile ); ++ fputs( "\n", commandFile ); ++ } ++ fputs( "\\E\n", commandFile ); // done as \E, so it cannot happen in normal data ++ fflush( commandFile ); ++ } +diff --git a/toolkit/xre/nsKDEUtils.h b/toolkit/xre/nsKDEUtils.h +new file mode 100644 +--- /dev/null ++++ b/toolkit/xre/nsKDEUtils.h +@@ -0,0 +1,77 @@ ++/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- ++ * ++ * ***** BEGIN LICENSE BLOCK ***** ++ * Version: MPL 1.1/GPL 2.0/LGPL 2.1 ++ * ++ * The contents of this file are subject to the Mozilla Public License Version ++ * 1.1 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * http://www.mozilla.org/MPL/ ++ * ++ * Software distributed under the License is distributed on an "AS IS" basis, ++ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License ++ * for the specific language governing rights and limitations under the ++ * License. ++ * ++ * The Original Code is Mozilla Communicator client code. ++ * ++ * The Initial Developer of the Original Code is ++ * Netscape Communications Corporation. ++ * Portions created by the Initial Developer are Copyright (C) 1998 ++ * the Initial Developer. All Rights Reserved. ++ * ++ * Contributor(s): ++ * ++ * Alternatively, the contents of this file may be used under the terms of ++ * either of the GNU General Public License Version 2 or later (the "GPL"), ++ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), ++ * in which case the provisions of the GPL or the LGPL are applicable instead ++ * of those above. If you wish to allow use of your version of this file only ++ * under the terms of either the GPL or the LGPL, and not to allow others to ++ * use your version of this file under the terms of the MPL, indicate your ++ * decision by deleting the provisions above and replace them with the notice ++ * and other provisions required by the GPL or the LGPL. If you do not delete ++ * the provisions above, a recipient may use your version of this file under ++ * the terms of any one of the MPL, the GPL or the LGPL. ++ * ++ * ***** END LICENSE BLOCK ***** */ ++ ++#ifndef nsKDEUtils_h__ ++#define nsKDEUtils_h__ ++ ++#include "nsStringGlue.h" ++#include "nsVoidArray.h" ++#include ++ ++typedef struct _GtkWindow GtkWindow; ++ ++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 nsCStringArray& command, nsCStringArray* 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 nsCStringArray& command, const GtkWindow* parent, nsCStringArray* output = NULL ); ++ private: ++ nsKDEUtils(); ++ ~nsKDEUtils(); ++ static nsKDEUtils* self(); ++ bool startHelper(); ++ void closeHelper(); ++ void feedCommand( const nsCStringArray& command ); ++ bool internalCommand( const nsCStringArray& command, const GtkWindow* parent, bool isParent, ++ nsCStringArray* output ); ++ FILE* commandFile; ++ FILE* replyFile; ++ }; ++ ++#endif // nsKDEUtils +diff --git a/uriloader/exthandler/Makefile.in b/uriloader/exthandler/Makefile.in +--- a/uriloader/exthandler/Makefile.in ++++ b/uriloader/exthandler/Makefile.in +@@ -102,18 +102,19 @@ CMMSRCS = nsOSHelperAppService.mm \ + $(NULL) + else + OSHELPER = nsOSHelperAppService.cpp + endif + + LOCAL_INCLUDES = -I$(srcdir) + + ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2) +-OSHELPER += nsGNOMERegistry.cpp ++OSHELPER += nsCommonRegistry.cpp nsGNOMERegistry.cpp nsKDERegistry.cpp + OSHELPER += nsMIMEInfoUnix.cpp ++LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre + endif + + ifeq ($(MOZ_WIDGET_TOOLKIT),qt) + OSHELPER += nsGNOMERegistry.cpp + OSHELPER += nsMIMEInfoUnix.cpp + endif + + ifeq ($(MOZ_WIDGET_TOOLKIT),beos) +diff --git a/uriloader/exthandler/unix/nsCommonRegistry.cpp b/uriloader/exthandler/unix/nsCommonRegistry.cpp +new file mode 100644 +--- /dev/null ++++ b/uriloader/exthandler/unix/nsCommonRegistry.cpp +@@ -0,0 +1,87 @@ ++/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ ++/* ***** BEGIN LICENSE BLOCK ***** ++ * Version: MPL 1.1/GPL 2.0/LGPL 2.1 ++ * ++ * The contents of this file are subject to the Mozilla Public License Version ++ * 1.1 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * http://www.mozilla.org/MPL/ ++ * ++ * Software distributed under the License is distributed on an "AS IS" basis, ++ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License ++ * for the specific language governing rights and limitations under the ++ * License. ++ * ++ * The Original Code is the GNOME helper app implementation. ++ * ++ * The Initial Developer of the Original Code is ++ * IBM Corporation. ++ * Portions created by the Initial Developer are Copyright (C) 2003 ++ * the Initial Developer. All Rights Reserved. ++ * ++ * Contributor(s): ++ * Brian Ryner (Original Author) ++ * ++ * Alternatively, the contents of this file may be used under the terms of ++ * either the GNU General Public License Version 2 or later (the "GPL"), or ++ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), ++ * in which case the provisions of the GPL or the LGPL are applicable instead ++ * of those above. If you wish to allow use of your version of this file only ++ * under the terms of either the GPL or the LGPL, and not to allow others to ++ * use your version of this file under the terms of the MPL, indicate your ++ * decision by deleting the provisions above and replace them with the notice ++ * and other provisions required by the GPL or the LGPL. If you do not delete ++ * the provisions above, a recipient may use your version of this file under ++ * the terms of any one of the MPL, the GPL or the LGPL. ++ * ++ * ***** END LICENSE BLOCK ***** */ ++ ++#include "nsCommonRegistry.h" ++ ++#include "nsGNOMERegistry.h" ++#include "nsKDERegistry.h" ++#include "nsString.h" ++#include "nsVoidArray.h" ++#include "nsKDEUtils.h" ++ ++/* static */ PRBool ++nsCommonRegistry::HandlerExists(const char *aProtocolScheme) ++{ ++ if( nsKDEUtils::kdeSupport()) ++ return nsKDERegistry::HandlerExists( aProtocolScheme ); ++ return nsGNOMERegistry::HandlerExists( aProtocolScheme ); ++} ++ ++/* static */ nsresult ++nsCommonRegistry::LoadURL(nsIURI *aURL) ++{ ++ if( nsKDEUtils::kdeSupport()) ++ return nsKDERegistry::LoadURL( aURL ); ++ return nsGNOMERegistry::LoadURL( aURL ); ++} ++ ++/* static */ void ++nsCommonRegistry::GetAppDescForScheme(const nsACString& aScheme, ++ nsAString& aDesc) ++{ ++ if( nsKDEUtils::kdeSupport()) ++ return nsKDERegistry::GetAppDescForScheme( aScheme, aDesc ); ++ return nsGNOMERegistry::GetAppDescForScheme( aScheme, aDesc ); ++} ++ ++ ++/* static */ already_AddRefed ++nsCommonRegistry::GetFromExtension(const nsACString& aFileExt) ++{ ++ if( nsKDEUtils::kdeSupport()) ++ return nsKDERegistry::GetFromExtension( aFileExt ); ++ return nsGNOMERegistry::GetFromExtension( aFileExt ); ++} ++ ++/* static */ already_AddRefed ++nsCommonRegistry::GetFromType(const nsACString& aMIMEType) ++{ ++ if( nsKDEUtils::kdeSupport()) ++ return nsKDERegistry::GetFromType( aMIMEType ); ++ return nsGNOMERegistry::GetFromType( aMIMEType ); ++} +diff --git a/uriloader/exthandler/unix/nsCommonRegistry.h b/uriloader/exthandler/unix/nsCommonRegistry.h +new file mode 100644 +--- /dev/null ++++ b/uriloader/exthandler/unix/nsCommonRegistry.h +@@ -0,0 +1,56 @@ ++/* ***** BEGIN LICENSE BLOCK ***** ++ * Version: MPL 1.1/GPL 2.0/LGPL 2.1 ++ * ++ * The contents of this file are subject to the Mozilla Public License Version ++ * 1.1 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * http://www.mozilla.org/MPL/ ++ * ++ * Software distributed under the License is distributed on an "AS IS" basis, ++ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License ++ * for the specific language governing rights and limitations under the ++ * License. ++ * ++ * The Original Code is the GNOME helper app implementation. ++ * ++ * The Initial Developer of the Original Code is ++ * IBM Corporation. ++ * Portions created by the Initial Developer are Copyright (C) 2003 ++ * the Initial Developer. All Rights Reserved. ++ * ++ * Contributor(s): ++ * Brian Ryner (Original Author) ++ * ++ * Alternatively, the contents of this file may be used under the terms of ++ * either the GNU General Public License Version 2 or later (the "GPL"), or ++ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), ++ * in which case the provisions of the GPL or the LGPL are applicable instead ++ * of those above. If you wish to allow use of your version of this file only ++ * under the terms of either the GPL or the LGPL, and not to allow others to ++ * use your version of this file under the terms of the MPL, indicate your ++ * decision by deleting the provisions above and replace them with the notice ++ * and other provisions required by the GPL or the LGPL. If you do not delete ++ * the provisions above, a recipient may use your version of this file under ++ * the terms of any one of the MPL, the GPL or the LGPL. ++ * ++ * ***** END LICENSE BLOCK ***** */ ++ ++#include "nsIURI.h" ++#include "nsCOMPtr.h" ++ ++class nsMIMEInfoBase; ++ ++class nsCommonRegistry ++{ ++ public: ++ static PRBool 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); ++}; +diff --git a/uriloader/exthandler/unix/nsKDERegistry.cpp b/uriloader/exthandler/unix/nsKDERegistry.cpp +new file mode 100644 +--- /dev/null ++++ b/uriloader/exthandler/unix/nsKDERegistry.cpp +@@ -0,0 +1,119 @@ ++/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ ++/* ***** BEGIN LICENSE BLOCK ***** ++ * Version: MPL 1.1/GPL 2.0/LGPL 2.1 ++ * ++ * The contents of this file are subject to the Mozilla Public License Version ++ * 1.1 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * http://www.mozilla.org/MPL/ ++ * ++ * Software distributed under the License is distributed on an "AS IS" basis, ++ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License ++ * for the specific language governing rights and limitations under the ++ * License. ++ * ++ * The Original Code is the GNOME helper app implementation. ++ * ++ * The Initial Developer of the Original Code is ++ * IBM Corporation. ++ * Portions created by the Initial Developer are Copyright (C) 2003 ++ * the Initial Developer. All Rights Reserved. ++ * ++ * Contributor(s): ++ * Brian Ryner (Original Author) ++ * ++ * Alternatively, the contents of this file may be used under the terms of ++ * either the GNU General Public License Version 2 or later (the "GPL"), or ++ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), ++ * in which case the provisions of the GPL or the LGPL are applicable instead ++ * of those above. If you wish to allow use of your version of this file only ++ * under the terms of either the GPL or the LGPL, and not to allow others to ++ * use your version of this file under the terms of the MPL, indicate your ++ * decision by deleting the provisions above and replace them with the notice ++ * and other provisions required by the GPL or the LGPL. If you do not delete ++ * the provisions above, a recipient may use your version of this file under ++ * the terms of any one of the MPL, the GPL or the LGPL. ++ * ++ * ***** END LICENSE BLOCK ***** */ ++ ++#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 */ PRBool ++nsKDERegistry::HandlerExists(const char *aProtocolScheme) ++{ ++ nsCStringArray command; ++ command.AppendCString( NS_LITERAL_CSTRING( "HANDLEREXISTS" )); ++ command.AppendCString( nsCAutoString( aProtocolScheme )); ++ return nsKDEUtils::command( command ); ++} ++ ++/* static */ nsresult ++nsKDERegistry::LoadURL(nsIURI *aURL) ++{ ++ nsCStringArray command; ++ command.AppendCString( NS_LITERAL_CSTRING( "OPEN" )); ++ nsCString url; ++ aURL->GetSpec( url ); ++ command.AppendCString( url ); ++ return nsKDEUtils::command( command ); ++} ++ ++/* static */ void ++nsKDERegistry::GetAppDescForScheme(const nsACString& aScheme, ++ nsAString& aDesc) ++{ ++ nsCStringArray command; ++ command.AppendCString( NS_LITERAL_CSTRING( "GETAPPDESCFORSCHEME" )); ++ command.AppendCString( aScheme ); ++ nsCStringArray output; ++ if( nsKDEUtils::command( command, &output ) && output.Count() == 1 ) ++ CopyUTF8toUTF16( *output[ 0 ], aDesc ); ++} ++ ++ ++/* static */ already_AddRefed ++nsKDERegistry::GetFromExtension(const nsACString& aFileExt) ++{ ++ NS_ASSERTION(aFileExt[0] != '.', "aFileExt shouldn't start with a dot"); ++ nsCStringArray command; ++ command.AppendCString( NS_LITERAL_CSTRING( "GETFROMEXTENSION" )); ++ command.AppendCString( aFileExt ); ++ return GetFromHelper( command ); ++} ++ ++/* static */ already_AddRefed ++nsKDERegistry::GetFromType(const nsACString& aMIMEType) ++{ ++ nsCStringArray command; ++ command.AppendCString( NS_LITERAL_CSTRING( "GETFROMTYPE" )); ++ command.AppendCString( aMIMEType ); ++ return GetFromHelper( command ); ++} ++ ++/* static */ already_AddRefed ++nsKDERegistry::GetFromHelper(const nsCStringArray& command) ++{ ++ nsCStringArray output; ++ if( nsKDEUtils::command( command, &output ) && output.Count() == 3 ) ++ { ++ nsCString mimetype = *output[ 0 ]; ++ nsRefPtr mimeInfo = new nsMIMEInfoUnix( mimetype ); ++ NS_ENSURE_TRUE(mimeInfo, nsnull); ++ nsCString description = *output[ 1 ]; ++ mimeInfo->SetDescription(NS_ConvertUTF8toUTF16(description)); ++ nsCString handlerAppName = *output[ 2 ]; ++ mimeInfo->SetDefaultDescription(NS_ConvertUTF8toUTF16(handlerAppName)); ++ mimeInfo->SetPreferredAction(nsIMIMEInfo::useSystemDefault); ++ nsMIMEInfoBase* retval; ++ NS_ADDREF((retval = mimeInfo)); ++ return retval; ++ } ++ return nsnull; ++} +diff --git a/uriloader/exthandler/unix/nsKDERegistry.h b/uriloader/exthandler/unix/nsKDERegistry.h +new file mode 100644 +--- /dev/null ++++ b/uriloader/exthandler/unix/nsKDERegistry.h +@@ -0,0 +1,61 @@ ++/* ***** BEGIN LICENSE BLOCK ***** ++ * Version: MPL 1.1/GPL 2.0/LGPL 2.1 ++ * ++ * The contents of this file are subject to the Mozilla Public License Version ++ * 1.1 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * http://www.mozilla.org/MPL/ ++ * ++ * Software distributed under the License is distributed on an "AS IS" basis, ++ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License ++ * for the specific language governing rights and limitations under the ++ * License. ++ * ++ * The Original Code is the GNOME helper app implementation. ++ * ++ * The Initial Developer of the Original Code is ++ * IBM Corporation. ++ * Portions created by the Initial Developer are Copyright (C) 2003 ++ * the Initial Developer. All Rights Reserved. ++ * ++ * Contributor(s): ++ * Brian Ryner (Original Author) ++ * ++ * Alternatively, the contents of this file may be used under the terms of ++ * either the GNU General Public License Version 2 or later (the "GPL"), or ++ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), ++ * in which case the provisions of the GPL or the LGPL are applicable instead ++ * of those above. If you wish to allow use of your version of this file only ++ * under the terms of either the GPL or the LGPL, and not to allow others to ++ * use your version of this file under the terms of the MPL, indicate your ++ * decision by deleting the provisions above and replace them with the notice ++ * and other provisions required by the GPL or the LGPL. If you do not delete ++ * the provisions above, a recipient may use your version of this file under ++ * the terms of any one of the MPL, the GPL or the LGPL. ++ * ++ * ***** END LICENSE BLOCK ***** */ ++ ++#include "nsIURI.h" ++#include "nsCOMPtr.h" ++ ++class nsMIMEInfoBase; ++class nsCAutoString; ++class nsCStringArray; ++ ++class nsKDERegistry ++{ ++ public: ++ static PRBool 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 nsCStringArray& command); ++ ++}; +diff --git a/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp b/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp +--- a/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp ++++ b/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp +@@ -40,27 +40,30 @@ + #ifdef MOZ_PLATFORM_HILDON + #include + #include + #include + #include + #endif + + #include "nsMIMEInfoUnix.h" +-#include "nsGNOMERegistry.h" ++#include "nsCommonRegistry.h" + #include "nsIGnomeVFSService.h" + #include "nsAutoPtr.h" + #ifdef MOZ_ENABLE_DBUS + #include "nsDBusHandlerApp.h" + #endif ++#if defined(XP_UNIX) && !defined(XP_MACOSX) ++#include "nsKDEUtils.h" ++#endif + + nsresult + nsMIMEInfoUnix::LoadUriInternal(nsIURI * aURI) + { +- nsresult rv = nsGNOMERegistry::LoadURL(aURI); ++ nsresult rv = nsCommonRegistry::LoadURL(aURI); + #ifdef MOZ_PLATFORM_HILDON + if (NS_FAILED(rv)){ + HildonURIAction *action = hildon_uri_get_default_action(mType.get(), nsnull); + if (action) { + nsCAutoString spec; + aURI->GetAsciiSpec(spec); + if (hildon_uri_open(spec.get(), action, nsnull)) + rv = NS_OK; +@@ -70,21 +73,21 @@ nsMIMEInfoUnix::LoadUriInternal(nsIURI * + #endif + return rv; + } + + NS_IMETHODIMP + nsMIMEInfoUnix::GetHasDefaultHandler(PRBool *_retval) + { + *_retval = PR_FALSE; +- nsRefPtr mimeInfo = nsGNOMERegistry::GetFromType(mType); ++ nsRefPtr mimeInfo = nsCommonRegistry::GetFromType(mType); + if (!mimeInfo) { + nsCAutoString ext; + GetPrimaryExtension(ext); +- mimeInfo = nsGNOMERegistry::GetFromExtension(ext); ++ mimeInfo = nsCommonRegistry::GetFromExtension(ext); + } + + if (mimeInfo) + *_retval = PR_TRUE; + + if (*_retval) + return NS_OK; + +@@ -101,31 +104,50 @@ nsMIMEInfoUnix::GetHasDefaultHandler(PRB + return nsMIMEInfoImpl::GetHasDefaultHandler(_retval); + } + + nsresult + nsMIMEInfoUnix::LaunchDefaultWithFile(nsIFile *aFile) + { + nsCAutoString nativePath; + aFile->GetNativePath(nativePath); ++ ++ if( nsKDEUtils::kdeSupport()) ++ { ++ PRBool supports; ++ if( NS_SUCCEEDED( GetHasDefaultHandler( &supports )) && supports ) ++ { ++ nsCStringArray command; ++ command.AppendCString( NS_LITERAL_CSTRING( "OPEN" )); ++ command.AppendCString( nativePath ); ++ command.AppendCString( NS_LITERAL_CSTRING( "MIMETYPE" )); ++ command.AppendCString( mType ); ++ if( nsKDEUtils::command( command )) ++ return NS_OK; ++ } ++ if (!mDefaultApplication) ++ return NS_ERROR_FILE_NOT_FOUND; ++ ++ return LaunchWithIProcess(mDefaultApplication, nativePath); ++ } + + #ifdef MOZ_PLATFORM_HILDON + if(NS_SUCCEEDED(LaunchDefaultWithDBus(PromiseFlatCString(nativePath).get()))) + return NS_OK; + #endif + + nsCOMPtr vfs = do_GetService(NS_GNOMEVFSSERVICE_CONTRACTID); + if (vfs) { + nsCOMPtr app; + if (NS_SUCCEEDED(vfs->GetAppForMimeType(mType, getter_AddRefs(app))) && app) + return app->Launch(nativePath); + + // If we haven't got an app we try to get a valid one by searching for the + // extension mapped type +- nsRefPtr mimeInfo = nsGNOMERegistry::GetFromExtension(nativePath); ++ nsRefPtr mimeInfo = nsCommonRegistry::GetFromExtension(nativePath); + if (mimeInfo) { + nsCAutoString type; + mimeInfo->GetType(type); + if (NS_SUCCEEDED(vfs->GetAppForMimeType(type, getter_AddRefs(app))) && app) + return app->Launch(nativePath); + } + } + +diff --git a/uriloader/exthandler/unix/nsOSHelperAppService.cpp b/uriloader/exthandler/unix/nsOSHelperAppService.cpp +--- a/uriloader/exthandler/unix/nsOSHelperAppService.cpp ++++ b/uriloader/exthandler/unix/nsOSHelperAppService.cpp +@@ -39,17 +39,17 @@ + * ***** END LICENSE BLOCK ***** */ + + #include + #include + + #include "nsOSHelperAppService.h" + #include "nsMIMEInfoUnix.h" + #ifdef MOZ_WIDGET_GTK2 +-#include "nsGNOMERegistry.h" ++#include "nsCommonRegistry.h" + #endif + #include "nsISupports.h" + #include "nsString.h" + #include "nsReadableUtils.h" + #include "nsUnicharUtils.h" + #include "nsXPIDLString.h" + #include "nsIURL.h" + #include "nsIFileStreams.h" +@@ -1205,29 +1205,29 @@ nsOSHelperAppService::GetHandlerAndDescr + nsresult nsOSHelperAppService::OSProtocolHandlerExists(const char * aProtocolScheme, PRBool * aHandlerExists) + { + LOG(("-- nsOSHelperAppService::OSProtocolHandlerExists for '%s'\n", + aProtocolScheme)); + *aHandlerExists = PR_FALSE; + + #ifdef MOZ_WIDGET_GTK2 + // Check the GConf registry for a protocol handler +- *aHandlerExists = nsGNOMERegistry::HandlerExists(aProtocolScheme); ++ *aHandlerExists = nsCommonRegistry::HandlerExists(aProtocolScheme); + #ifdef MOZ_PLATFORM_HILDON + *aHandlerExists = nsMIMEInfoUnix::HandlerExists(aProtocolScheme); + #endif + #endif + + return NS_OK; + } + + NS_IMETHODIMP nsOSHelperAppService::GetApplicationDescription(const nsACString& aScheme, nsAString& _retval) + { + #ifdef MOZ_WIDGET_GTK2 +- nsGNOMERegistry::GetAppDescForScheme(aScheme, _retval); ++ nsCommonRegistry::GetAppDescForScheme(aScheme, _retval); + return _retval.IsEmpty() ? NS_ERROR_NOT_AVAILABLE : NS_OK; + #else + return NS_ERROR_NOT_AVAILABLE; + #endif + } + + nsresult nsOSHelperAppService::GetFileTokenForPath(const PRUnichar * platformAppPath, nsIFile ** aFile) + { +@@ -1313,17 +1313,17 @@ nsOSHelperAppService::GetFromExtension(c + minorType, + mime_types_description, + PR_TRUE); + + if (NS_FAILED(rv) || majorType.IsEmpty()) { + + #ifdef MOZ_WIDGET_GTK2 + LOG(("Looking in GNOME registry\n")); +- nsMIMEInfoBase *gnomeInfo = nsGNOMERegistry::GetFromExtension(aFileExt).get(); ++ nsMIMEInfoBase *gnomeInfo = nsCommonRegistry::GetFromExtension(aFileExt).get(); + if (gnomeInfo) { + LOG(("Got MIMEInfo from GNOME registry\n")); + return gnomeInfo; + } + #endif + + rv = LookUpTypeAndDescription(NS_ConvertUTF8toUTF16(aFileExt), + majorType, +@@ -1439,17 +1439,17 @@ nsOSHelperAppService::GetFromType(const + #ifdef MOZ_WIDGET_GTK2 + nsMIMEInfoBase *gnomeInfo = nsnull; + if (handler.IsEmpty()) { + // No useful data yet. Check the GNOME registry. Unfortunately, newer + // GNOME versions no longer have type-to-extension mappings, so we might + // get back a MIMEInfo without any extensions set. In that case we'll have + // to look in our mime.types files for the extensions. + LOG(("Looking in GNOME registry\n")); +- gnomeInfo = nsGNOMERegistry::GetFromType(aMIMEType).get(); ++ gnomeInfo = nsCommonRegistry::GetFromType(aMIMEType).get(); + if (gnomeInfo && gnomeInfo->HasExtensions()) { + LOG(("Got MIMEInfo from GNOME registry, and it has extensions set\n")); + return gnomeInfo; + } + } + #endif + + // Now look up our extensions +diff --git a/widget/src/gtk2/Makefile.in b/widget/src/gtk2/Makefile.in +--- a/widget/src/gtk2/Makefile.in ++++ b/widget/src/gtk2/Makefile.in +@@ -184,8 +184,11 @@ EXTRA_DSO_LDOPTS += -lgfxpsshar + endif + + + DEFINES += + INCLUDES += \ + -I$(srcdir)/../xpwidgets \ + -I$(topsrcdir)/other-licenses/atk-1.0 \ + $(NULL) ++ ++LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre ++ +diff --git a/widget/src/gtk2/nsFilePicker.cpp b/widget/src/gtk2/nsFilePicker.cpp +--- a/widget/src/gtk2/nsFilePicker.cpp ++++ b/widget/src/gtk2/nsFilePicker.cpp +@@ -50,16 +50,17 @@ + #include "nsReadableUtils.h" + #include "mozcontainer.h" + + #include "prmem.h" + #include "prlink.h" + + #include "nsFilePicker.h" + #include "nsAccessibilityHelper.h" ++#include "nsKDEUtils.h" + + #ifdef MOZ_PLATFORM_HILDON + #include + #endif + + #define MAX_PREVIEW_SIZE 180 + + nsILocalFile *nsFilePicker::mPrevDisplayDirectory = nsnull; +@@ -270,17 +271,19 @@ nsFilePicker::AppendFilters(PRInt32 aFil + return nsBaseFilePicker::AppendFilters(aFilterMask); + } + + NS_IMETHODIMP + nsFilePicker::AppendFilter(const nsAString& aTitle, const nsAString& aFilter) + { + if (aFilter.EqualsLiteral("..apps")) { + // No platform specific thing we can do here, really.... +- return NS_OK; ++ // Unless it's KDE. ++ if( mMode != modeOpen || !nsKDEUtils::kdeSupport()) ++ return NS_OK; + } + + nsCAutoString filter, name; + CopyUTF16toUTF8(aFilter, filter); + CopyUTF16toUTF8(aTitle, name); + + mFilters.AppendElement(filter); + mFilterNames.AppendElement(name); +@@ -418,16 +421,19 @@ confirm_overwrite_file(GtkWidget *parent + gtk_widget_destroy(dialog); + + return result; + } + + NS_IMETHODIMP + nsFilePicker::Show(PRInt16 *aReturn) + { ++ if( nsKDEUtils::kdeSupport()) ++ return kdeFileDialog( aReturn ); ++ + NS_ENSURE_ARG_POINTER(aReturn); + + nsXPIDLCString title; + title.Adopt(ToNewUTF8String(mTitle)); + + GtkWindow *parent_widget = get_gtk_window_for_nsiwidget(mParentWidget); + + GtkFileChooserAction action = GetGtkFileChooserAction(mMode); +@@ -568,8 +574,234 @@ nsFilePicker::Show(PRInt16 *aReturn) + *aReturn = nsIFilePicker::returnCancel; + break; + } + + gtk_widget_destroy(file_chooser); + + return NS_OK; + } ++ ++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 = get_gtk_window_for_nsiwidget( widget ); ++ 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.Count() == 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; ++ } ++ } ++ ++ nsCAutoString directory; ++ if (mDisplayDirectory) { ++ mDisplayDirectory->GetNativePath(directory); ++ } else if (mPrevDisplayDirectory) { ++ mPrevDisplayDirectory->GetNativePath(directory); ++ } ++ ++ nsCAutoString startdir; ++ if (!directory.IsEmpty()) { ++ startdir = directory; ++ } ++ if (mMode == nsIFilePicker::modeSave) { ++ if( !startdir.IsEmpty()) ++ { ++ startdir += "/"; ++ startdir += ToNewUTF8String(mDefault); ++ } ++ else ++ startdir = ToNewUTF8String(mDefault); ++ } ++ if( startdir.IsEmpty()) ++ startdir = "."; ++ ++ nsCAutoString filters; ++ PRInt32 count = mFilters.Count(); ++ if( count == 0 ) //just in case ++ filters = "*"; ++ else ++ { ++ filters = kdeMakeFilter( 0 ); ++ for (PRInt32 i = 1; i < count; ++i) ++ { ++ filters += "\n"; ++ filters += kdeMakeFilter( i ); ++ } ++ } ++ ++ nsCStringArray command; ++ command.AppendCString( nsCAutoString( arg )); ++ command.AppendCString( startdir ); ++ if( mMode != nsIFilePicker::modeGetFolder ) ++ { ++ command.AppendCString( filters ); ++ nsCAutoString selected; ++ selected.AppendInt( mSelectedType ); ++ command.AppendCString( selected ); ++ } ++ command.AppendCString( title ); ++ if( mMode == nsIFilePicker::modeOpenMultiple ) ++ command.AppendCString( NS_LITERAL_CSTRING( "MULTIPLE" )); ++ if( PRInt32 xid = windowToXid( mParentWidget )) ++ { ++ command.AppendCString( NS_LITERAL_CSTRING( "PARENT" )); ++ nsCAutoString parent; ++ parent.AppendInt( xid ); ++ command.AppendCString( parent ); ++ } ++ ++ nsCStringArray output; ++ if( nsKDEUtils::commandBlockUi( command, get_gtk_window_for_nsiwidget( mParentWidget ), &output )) ++ { ++ *aReturn = nsIFilePicker::returnOK; ++ mFiles.Clear(); ++ if( mMode != nsIFilePicker::modeGetFolder ) ++ { ++ mSelectedType = atoi( output[ 0 ]->get()); ++ output.RemoveCStringAt( 0 ); ++ } ++ if (mMode == nsIFilePicker::modeOpenMultiple) ++ { ++ mFileURL.Truncate(); ++ PRUint32 count = output.Count(); ++ 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.Count() == 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) ++ { ++ PRBool exists = PR_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)); ++ ++ nsCStringArray command; ++ command.AppendCString( NS_LITERAL_CSTRING( "APPSDIALOG" )); ++ command.AppendCString( title ); ++ if( PRInt32 xid = windowToXid( mParentWidget )) ++ { ++ command.AppendCString( NS_LITERAL_CSTRING( "PARENT" )); ++ nsCAutoString parent; ++ parent.AppendInt( xid ); ++ command.AppendCString( parent ); ++ } ++ ++ nsCStringArray output; ++ if( nsKDEUtils::commandBlockUi( command, get_gtk_window_for_nsiwidget( mParentWidget ), &output )) ++ { ++ *aReturn = nsIFilePicker::returnOK; ++ mFileURL = output.Count() > 0 ? *output[ 0 ] : nsCString(); ++ } ++ else ++ { ++ *aReturn = nsIFilePicker::returnCancel; ++ } ++ return NS_OK; ++ } +diff --git a/widget/src/gtk2/nsFilePicker.h b/widget/src/gtk2/nsFilePicker.h +--- a/widget/src/gtk2/nsFilePicker.h ++++ b/widget/src/gtk2/nsFilePicker.h +@@ -89,11 +89,17 @@ protected: + nsString mDefault; + nsString mDefaultExtension; + + nsTArray mFilters; + nsTArray mFilterNames; + + private: + static nsILocalFile *mPrevDisplayDirectory; ++ ++ bool kdeRunning(); ++ bool getKdeRunning(); ++ NS_IMETHODIMP kdeFileDialog(PRInt16 *aReturn); ++ NS_IMETHODIMP kdeAppsDialog(PRInt16 *aReturn); ++ nsCString kdeMakeFilter( int index ); + }; + + #endif +diff --git a/xpcom/io/Makefile.in b/xpcom/io/Makefile.in +--- a/xpcom/io/Makefile.in ++++ b/xpcom/io/Makefile.in +@@ -195,14 +195,15 @@ DEFINES += -D_IMPL_NS_COM + + ifeq ($(OS_ARCH),Linux) + ifneq (,$(findstring lib64,$(libdir))) + DEFINES += -DHAVE_USR_LIB64_DIR + endif + endif + + LOCAL_INCLUDES = -I.. ++LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre + + ifdef MOZ_PLATFORM_HILDON + CFLAGS += $(MOZ_DBUS_GLIB_CFLAGS) $(LIBHILDONMIME_CFLAGS) + CXXFLAGS += $(MOZ_DBUS_GLIB_CFLAGS) $(LIBHILDONMIME_CFLAGS) + endif + +diff --git a/xpcom/io/nsLocalFileUnix.cpp b/xpcom/io/nsLocalFileUnix.cpp +--- a/xpcom/io/nsLocalFileUnix.cpp ++++ b/xpcom/io/nsLocalFileUnix.cpp +@@ -79,16 +79,17 @@ + #include "nsXPIDLString.h" + #include "prproces.h" + #include "nsIDirectoryEnumerator.h" + #include "nsISimpleEnumerator.h" + #include "nsITimelineService.h" + + #ifdef MOZ_WIDGET_GTK2 + #include "nsIGnomeVFSService.h" ++#include "nsKDEUtils.h" + #endif + + #ifdef MOZ_PLATFORM_HILDON + #include + #include + #include + #include + #endif +@@ -1627,36 +1628,46 @@ nsLocalFile::Launch() + + return NS_OK; + } + #else + NS_IMETHODIMP + nsLocalFile::Reveal() + { + #ifdef MOZ_WIDGET_GTK2 +- nsCOMPtr vfs = do_GetService(NS_GNOMEVFSSERVICE_CONTRACTID); +- if (!vfs) +- return NS_ERROR_FAILURE; +- ++ nsCAutoString url; + PRBool isDirectory; + if (NS_FAILED(IsDirectory(&isDirectory))) + return NS_ERROR_FAILURE; + + if (isDirectory) { +- return vfs->ShowURIForInput(mPath); ++ url = mPath; + } else { + nsCOMPtr parentDir; + nsCAutoString dirPath; + if (NS_FAILED(GetParent(getter_AddRefs(parentDir)))) + return NS_ERROR_FAILURE; + if (NS_FAILED(parentDir->GetNativePath(dirPath))) + return NS_ERROR_FAILURE; + +- return vfs->ShowURIForInput(dirPath); ++ url = dirPath; + } ++ ++ if( nsKDEUtils::kdeSupport()) { ++ nsCStringArray command; ++ command.AppendCString( NS_LITERAL_CSTRING( "OPEN" )); ++ command.AppendCString( url ); ++ return nsKDEUtils::command( command ) ? NS_OK : NS_ERROR_FAILURE; ++ } ++ ++ nsCOMPtr vfs = do_GetService(NS_GNOMEVFSSERVICE_CONTRACTID); ++ if (!vfs) ++ return NS_ERROR_FAILURE; ++ return vfs->ShowURIForInput(url); ++ + #else + return NS_ERROR_FAILURE; + #endif + } + + NS_IMETHODIMP + nsLocalFile::Launch() + { +@@ -1674,16 +1685,23 @@ nsLocalFile::Launch() + + if (nsnull == connection) + return NS_ERROR_FAILURE; + + if (hildon_mime_open_file(connection, mPath.get()) != kHILDON_SUCCESS) + return NS_ERROR_FAILURE; + return NS_OK; + #else ++ if( nsKDEUtils::kdeSupport()) { ++ nsCStringArray command; ++ command.AppendCString( NS_LITERAL_CSTRING( "OPEN" )); ++ command.AppendCString( mPath ); ++ return nsKDEUtils::command( command ) ? NS_OK : NS_ERROR_FAILURE; ++ } ++ + nsCOMPtr vfs = do_GetService(NS_GNOMEVFSSERVICE_CONTRACTID); + if (!vfs) + return NS_ERROR_FAILURE; + + return vfs->ShowURIForInput(mPath); + #endif + #else + return NS_ERROR_FAILURE;