>From 6512cf91d1aa9efd232b3a7f61d4dde81365a110 Mon Sep 17 00:00:00 2001 From: asac Date: Wed, 21 Feb 2007 03:34:14 +0100 Subject: [PATCH] bz273524-gnome-mime-registry-ubuntu + gnome-mime-registry impl: https://bugzilla.mozilla.org/show_bug.cgi?id=273524 + ... this patch differs from current upstream patch which is included in gnome-mime-registry-upstream --- uriloader/exthandler/Makefile.in | 2 uriloader/exthandler/unix/nsGNOMERegistry.cpp | 26 +- uriloader/exthandler/unix/nsGNOMERegistry.h | 11 - uriloader/exthandler/unix/nsMIMEInfoUnix.cpp | 197 +++++++++++++++++++++ uriloader/exthandler/unix/nsMIMEInfoUnix.h | 48 +++++ uriloader/exthandler/unix/nsOSHelperAppService.cpp | 26 +- 6 files changed, 284 insertions(+), 26 deletions(-) Index: mozilla/uriloader/exthandler/Makefile.in =================================================================== --- mozilla.orig/uriloader/exthandler/Makefile.in 2007-04-04 18:47:48.000000000 +0200 +++ mozilla/uriloader/exthandler/Makefile.in 2007-04-04 18:48:22.000000000 +0200 @@ -98,17 +98,17 @@ nsInternetConfigService.cpp \ nsMIMEInfoMac.cpp \ $(NULL) endif LOCAL_INCLUDES = -I$(srcdir) ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2) -OSHELPER += nsGNOMERegistry.cpp +OSHELPER += nsMIMEInfoUnix.cpp nsGNOMERegistry.cpp endif ifeq ($(MOZ_WIDGET_TOOLKIT),beos) OSHELPER += nsMIMEInfoBeOS.cpp endif ifeq ($(MOZ_WIDGET_TOOLKIT),windows) OSHELPER += nsMIMEInfoWin.cpp Index: mozilla/uriloader/exthandler/unix/nsGNOMERegistry.cpp =================================================================== --- mozilla.orig/uriloader/exthandler/unix/nsGNOMERegistry.cpp 2007-04-04 18:47:48.000000000 +0200 +++ mozilla/uriloader/exthandler/unix/nsGNOMERegistry.cpp 2007-04-04 18:48:22.000000000 +0200 @@ -37,36 +37,36 @@ * ***** END LICENSE BLOCK ***** */ #include "nsGNOMERegistry.h" #include "prlink.h" #include "prmem.h" #include "nsString.h" #include "nsIComponentManager.h" #include "nsILocalFile.h" -#include "nsMIMEInfoImpl.h" +#include "nsMIMEInfoUnix.h" #include "nsAutoPtr.h" #include #include static PRLibrary *gconfLib; static PRLibrary *gnomeLib; static PRLibrary *vfsLib; typedef struct _GConfClient GConfClient; typedef struct _GnomeProgram GnomeProgram; typedef struct _GnomeModuleInfo GnomeModuleInfo; -typedef struct { +struct GnomeVFSMimeApplication { char *id; char *name; char *command; /* there is more here, but we don't need it */ -} GnomeVFSMimeApplication; +}; typedef GConfClient * (*_gconf_client_get_default_fn)(); typedef gchar * (*_gconf_client_get_string_fn)(GConfClient *, const char *, GError **); typedef gboolean (*_gconf_client_get_bool_fn)(GConfClient *, const char *, GError **); typedef gboolean (*_gnome_url_show_fn)(const char *, GError **); typedef const char * (*_gnome_vfs_mime_type_from_name_fn)(const char *); @@ -259,17 +259,17 @@ if (app) { CopyUTF8toUTF16(app, aDesc); g_free(app); } } -/* static */ already_AddRefed +/* static */ already_AddRefed nsGNOMERegistry::GetFromExtension(const char *aFileExt) { if (!gconfLib) return nsnull; // Get the MIME type from the extension, then call GetFromType to // fill in the MIMEInfo. @@ -281,27 +281,27 @@ const char *mimeType = _gnome_vfs_mime_type_from_name(fileExtToUse.get()); if (!strcmp(mimeType, "application/octet-stream")) return nsnull; return GetFromType(mimeType); } -/* static */ already_AddRefed +/* static */ already_AddRefed nsGNOMERegistry::GetFromType(const char *aMIMEType) { if (!gconfLib) return nsnull; GnomeVFSMimeApplication *handlerApp = _gnome_vfs_mime_get_default_application(aMIMEType); if (!handlerApp) return nsnull; - nsRefPtr mimeInfo = new nsMIMEInfoImpl(aMIMEType); + nsRefPtr mimeInfo = new nsMIMEInfoUnix(aMIMEType); NS_ENSURE_TRUE(mimeInfo, nsnull); // Get the list of extensions and append then to the mimeInfo. GList *extensions = _gnome_vfs_mime_get_extensions_list(aMIMEType); for (GList *extension = extensions; extension; extension = extension->next) mimeInfo->AppendExtension(nsDependentCString((const char *) extension->data)); _gnome_vfs_mime_extensions_list_free(extensions); @@ -315,21 +315,31 @@ gchar *nativeCommand = g_filename_from_utf8(handlerApp->command, -1, NULL, NULL, NULL); if (!nativeCommand) { NS_ERROR("Could not convert helper app command to filesystem encoding"); _gnome_vfs_mime_application_free(handlerApp); return nsnull; } - gchar *commandPath = g_find_program_in_path(nativeCommand); + gchar **argv; + gboolean res = g_shell_parse_argv(nativeCommand, NULL, &argv, NULL); + if (!res) { + NS_ERROR("Could not convert helper app command to filesystem encoding"); + _gnome_vfs_mime_application_free(handlerApp); + return nsnull; + } + + gchar *commandPath = g_find_program_in_path(argv[0]); g_free(nativeCommand); + g_strfreev(argv); if (!commandPath) { + NS_WARNING("could not find command in path"); _gnome_vfs_mime_application_free(handlerApp); return nsnull; } nsCOMPtr appFile; NS_NewNativeLocalFile(nsDependentCString(commandPath), PR_TRUE, getter_AddRefs(appFile)); if (appFile) { @@ -337,12 +347,12 @@ mimeInfo->SetDefaultDescription(NS_ConvertUTF8toUCS2(handlerApp->name)); mimeInfo->SetPreferredAction(nsIMIMEInfo::useSystemDefault); } g_free(commandPath); _gnome_vfs_mime_application_free(handlerApp); - nsMIMEInfoBase* retval; + nsMIMEInfoUnix* retval; NS_ADDREF((retval = mimeInfo)); return retval; } Index: mozilla/uriloader/exthandler/unix/nsGNOMERegistry.h =================================================================== --- mozilla.orig/uriloader/exthandler/unix/nsGNOMERegistry.h 2007-04-04 18:47:48.000000000 +0200 +++ mozilla/uriloader/exthandler/unix/nsGNOMERegistry.h 2007-04-04 18:48:22.000000000 +0200 @@ -30,29 +30,34 @@ * 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 nsGNOMERegistry_h__ +#define nsGNOMERegistry_h__ + #include "nsIURI.h" #include "nsCOMPtr.h" -class nsMIMEInfoBase; +class nsMIMEInfoUnix; class nsGNOMERegistry { public: static void Startup(); static PRBool HandlerExists(const char *aProtocolScheme); static nsresult LoadURL(nsIURI *aURL); static void GetAppDescForScheme(const nsACString& aScheme, nsAString& aDesc); - static already_AddRefed GetFromExtension(const char *aFileExt); + static already_AddRefed GetFromExtension(const char *aFileExt); - static already_AddRefed GetFromType(const char *aMIMEType); + static already_AddRefed GetFromType(const char *aMIMEType); }; + +#endif // nsGNOMERegistry_h__ Index: mozilla/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ mozilla/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp 2007-04-04 18:48:22.000000000 +0200 @@ -0,0 +1,197 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.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.org Code. + * + * The Initial Developer of the Original Code is + * Red Hat, Inc. + * Portions created by the Initial Developer are Copyright (C) 2005 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Christopher Aillon (Original author) + * + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsMIMEInfoUnix.h" +#include "prlink.h" +#include "prmem.h" +#include +#include + +static PRLibrary *gnomeLib; +static PRLibrary *vfsLib; + +typedef struct _GnomeProgram GnomeProgram; +typedef struct _GnomeModuleInfo GnomeModuleInfo; + +typedef enum { + GNOME_VFS_OK // there's more but we don't care about them. +} GnomeVFSResult; + +typedef GnomeVFSResult (*_gnome_vfs_mime_application_launch_fn) + (GnomeVFSMimeApplication *app, + GList *uris); +typedef void (*_gnome_vfs_mime_application_free_fn)(GnomeVFSMimeApplication *); +typedef GnomeVFSMimeApplication * (*_gnome_vfs_mime_application_copy_fn)(GnomeVFSMimeApplication *); +typedef GnomeProgram * (*_gnome_program_init_fn)(const char *, const char *, + const GnomeModuleInfo *, int, + char **, const char *, ...); +typedef const char * (*_gnome_vfs_mime_application_get_name_fn)(GnomeVFSMimeApplication *); +typedef const GnomeModuleInfo * (*_libgnome_module_info_get_fn)(); +typedef GnomeProgram * (*_gnome_program_get_fn)(); +typedef char * (*_gnome_vfs_make_uri_from_input_fn)(const char *); + +#define DECL_FUNC_PTR(func) static _##func##_fn _##func + +DECL_FUNC_PTR(gnome_vfs_mime_application_launch); +DECL_FUNC_PTR(gnome_vfs_mime_application_free); +DECL_FUNC_PTR(gnome_vfs_mime_application_copy); +DECL_FUNC_PTR(gnome_vfs_mime_application_get_name); +DECL_FUNC_PTR(gnome_program_init); +DECL_FUNC_PTR(gnome_program_get); +DECL_FUNC_PTR(libgnome_module_info_get); +DECL_FUNC_PTR(gnome_vfs_make_uri_from_input); + +static PRLibrary * +LoadVersionedLibrary(const char* libName, const char* libVersion) +{ + char *platformLibName = PR_GetLibraryName(nsnull, libName); + nsCAutoString versionLibName(platformLibName); + versionLibName.Append(libVersion); + PR_Free(platformLibName); + return PR_LoadLibrary(versionLibName.get()); +} + +static void +Cleanup() +{ + // Unload all libraries + if (gnomeLib) + PR_UnloadLibrary(gnomeLib); + if (vfsLib) + PR_UnloadLibrary(vfsLib); + + gnomeLib = vfsLib = nsnull; +} + +static void +InitGnomeVFS() +{ + static PRBool initialized = PR_FALSE; + + if (initialized) + return; + + #define ENSURE_LIB(lib) \ + PR_BEGIN_MACRO \ + if (!lib) { \ + Cleanup(); \ + return; \ + } \ + PR_END_MACRO + + #define GET_LIB_FUNCTION(lib, func, failure) \ + PR_BEGIN_MACRO \ + _##func = (_##func##_fn) PR_FindFunctionSymbol(lib##Lib, #func); \ + if (!_##func) { \ + failure; \ + } \ + PR_END_MACRO + + // Attempt to open libgnome + gnomeLib = LoadVersionedLibrary("gnome-2", ".0"); + ENSURE_LIB(gnomeLib); + + GET_LIB_FUNCTION(gnome, gnome_program_init, return Cleanup()); + GET_LIB_FUNCTION(gnome, libgnome_module_info_get, return Cleanup()); + GET_LIB_FUNCTION(gnome, gnome_program_get, return Cleanup()); + + // Attempt to open libgnomevfs + vfsLib = LoadVersionedLibrary("gnomevfs-2", ".0"); + ENSURE_LIB(vfsLib); + + GET_LIB_FUNCTION(vfs, gnome_vfs_mime_application_launch, /* do nothing */); + GET_LIB_FUNCTION(vfs, gnome_vfs_make_uri_from_input, return Cleanup()); + GET_LIB_FUNCTION(vfs, gnome_vfs_mime_application_get_name, return Cleanup()); + GET_LIB_FUNCTION(vfs, gnome_vfs_mime_application_free, return Cleanup()); + GET_LIB_FUNCTION(vfs, gnome_vfs_mime_application_copy, return Cleanup()); + + // Initialize GNOME, if it's not already initialized. It's not + // necessary to tell GNOME about our actual command line arguments. + + if (!_gnome_program_get()) { + char *argv[1] = { "gecko" }; + _gnome_program_init("Gecko", "1.0", _libgnome_module_info_get(), + 1, argv, NULL); + } + + // Note: after GNOME has been initialized, do not ever unload these + // libraries. They register atexit handlers, so if they are unloaded, we'll + // crash on exit. +} + +void +nsMIMEInfoUnix::SetDefaultGnomeVFSMimeApplication(GnomeVFSMimeApplication* app) +{ + if (_gnome_vfs_mime_application_copy && _gnome_vfs_mime_application_free) { + mDefaultVFSApplication = _gnome_vfs_mime_application_copy(app); + + mPreferredAction = nsIMIMEInfo::useSystemDefault; + + const gchar * name = _gnome_vfs_mime_application_get_name(mDefaultVFSApplication); + if (name) + mDefaultAppDescription = NS_ConvertUTF8toUCS2(name); + } +} + +nsMIMEInfoUnix::~nsMIMEInfoUnix() +{ + if (mDefaultVFSApplication) + _gnome_vfs_mime_application_free(mDefaultVFSApplication); +} + +nsresult +nsMIMEInfoUnix::LaunchDefaultWithFile(nsIFile* aFile) +{ + NS_ENSURE_ARG_POINTER(aFile); + + InitGnomeVFS(); + + if (_gnome_vfs_mime_application_launch && mDefaultVFSApplication) { + nsCAutoString nativePath; + aFile->GetNativePath(nativePath); + + gchar *uri = _gnome_vfs_make_uri_from_input(nativePath.get()); + + GList *uris = NULL; + uris = g_list_append(uris, uri); + + GnomeVFSResult result = _gnome_vfs_mime_application_launch(mDefaultVFSApplication, uris); + + g_free(uri); + g_list_free(uris); + + if (result != GNOME_VFS_OK) + return NS_ERROR_FAILURE; + + return NS_OK; + } + + if (!mDefaultApplication) + return NS_ERROR_FILE_NOT_FOUND; + + return LaunchWithIProcess(mDefaultApplication, aFile); +} + Index: mozilla/uriloader/exthandler/unix/nsMIMEInfoUnix.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ mozilla/uriloader/exthandler/unix/nsMIMEInfoUnix.h 2007-04-04 18:48:22.000000000 +0200 @@ -0,0 +1,48 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.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.org Code. + * + * The Initial Developer of the Original Code is + * Red Hat, Inc. + * Portions created by the Initial Developer are Copyright (C) 2005 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Christopher Aillon (Original author) + * + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsMimeInfoUnix_h__ +#define nsMimeInfoUnix_h__ + +#include "nsMIMEInfoImpl.h" + +struct GnomeVFSMimeApplication; + +class nsMIMEInfoUnix : public nsMIMEInfoImpl +{ +public: + nsMIMEInfoUnix(const char* aType = "") : nsMIMEInfoImpl(aType), mDefaultVFSApplication(nsnull) {} + virtual ~nsMIMEInfoUnix(); + + void SetDefaultGnomeVFSMimeApplication(GnomeVFSMimeApplication *app); + +protected: + virtual NS_HIDDEN_(nsresult) LaunchDefaultWithFile(nsIFile* aFile); + + GnomeVFSMimeApplication *mDefaultVFSApplication; +}; + +#endif // nsMimeInfoUnix_h__ Index: mozilla/uriloader/exthandler/unix/nsOSHelperAppService.cpp =================================================================== --- mozilla.orig/uriloader/exthandler/unix/nsOSHelperAppService.cpp 2007-04-04 18:47:48.000000000 +0200 +++ mozilla/uriloader/exthandler/unix/nsOSHelperAppService.cpp 2007-04-04 18:48:22.000000000 +0200 @@ -39,16 +39,17 @@ * ***** END LICENSE BLOCK ***** */ #include #include #include "nsOSHelperAppService.h" #ifdef MOZ_WIDGET_GTK2 #include "nsGNOMERegistry.h" +#include "nsMIMEInfoUnix.h" #endif #include "nsISupports.h" #include "nsString.h" #include "nsReadableUtils.h" #include "nsUnicharUtils.h" #include "nsXPIDLString.h" #include "nsIURL.h" #include "nsIFileStreams.h" @@ -1481,16 +1482,27 @@ already_AddRefed nsOSHelperAppService::GetFromType(const nsCString& aMIMEType) { // if the type is empty, return immediately if (aMIMEType.IsEmpty()) return nsnull; LOG(("Here we do a mimetype lookup for '%s'\n", aMIMEType.get())); +#ifdef MOZ_WIDGET_GTK2 + // Look in GNOME registry first since it is the preferred method in GNOME, + // should trump the mailcap entry + LOG(("Looking in GNOME registry\n")); + nsMIMEInfoBase *gnomeInfo = nsGNOMERegistry::GetFromType(aMIMEType.get()).get(); + if (gnomeInfo) { + LOG(("Got MIMEInfo from GNOME registry\n")); + return gnomeInfo; + } +#endif + // extract the major and minor types NS_ConvertASCIItoUTF16 mimeType(aMIMEType); nsAString::const_iterator start_iter, end_iter, majorTypeStart, majorTypeEnd, minorTypeStart, minorTypeEnd; mimeType.BeginReading(start_iter); mimeType.EndReading(end_iter); @@ -1518,30 +1530,16 @@ minorType, typeOptions, handler, mailcap_description, mozillaFlags, PR_TRUE); - if (handler.IsEmpty() && extensions.IsEmpty() && - mailcap_description.IsEmpty() && mime_types_description.IsEmpty()) { - // No useful data yet - -#ifdef MOZ_WIDGET_GTK2 - LOG(("Looking in GNOME registry\n")); - nsMIMEInfoBase *gnomeInfo = nsGNOMERegistry::GetFromType(aMIMEType.get()).get(); - if (gnomeInfo) { - LOG(("Got MIMEInfo from GNOME registry\n")); - return gnomeInfo; - } -#endif - } - if (handler.IsEmpty() && mailcap_description.IsEmpty()) { DoLookUpHandlerAndDescription(majorType, minorType, typeOptions, handler, mailcap_description, mozillaFlags, PR_FALSE);