Bug 1134537 - Only support GIO in Linux's nsIconChannel. r=seth

This commit is contained in:
Alex Henrie 2015-03-03 23:15:08 -07:00
parent f22da41d9f
commit 02784a8b7c
2 changed files with 1 additions and 311 deletions

View File

@ -10,17 +10,6 @@
#include "mozilla/Endian.h"
#include <algorithm>
#ifdef MOZ_ENABLE_GNOMEUI
// Older versions of these headers seem to be missing an extern "C"
extern "C" {
#include <libgnome/libgnome.h>
#include <libgnomeui/gnome-icon-theme.h>
#include <libgnomeui/gnome-icon-lookup.h>
#include <libgnomevfs/gnome-vfs-file-info.h>
#include <libgnomevfs/gnome-vfs-ops.h>
}
#endif
#ifdef MOZ_ENABLE_GIO
#include <gio/gio.h>
#endif
@ -43,41 +32,6 @@ NS_IMPL_ISUPPORTS(nsIconChannel,
nsIRequest,
nsIChannel)
#ifdef MOZ_ENABLE_GNOMEUI
// These let us have a soft dependency on libgnomeui rather than a hard one.
// These are just basically the prototypes of the functions in the libraries.
typedef char* (*_GnomeIconLookup_fn)(GtkIconTheme* icon_theme,
GnomeThumbnailFactory* thumbnail_factory,
const char* file_uri,
const char* custom_icon,
GnomeVFSFileInfo* file_info,
const char* mime_type,
GnomeIconLookupFlags flags,
GnomeIconLookupResultFlags* result);
typedef GnomeIconTheme* (*_GnomeIconThemeNew_fn)(void);
typedef int (*_GnomeInit_fn)(const char* app_id, const char* app_version,
int argc, char** argv,
const struct poptOption* options,
int flags, poptContext* return_ctx);
typedef GnomeProgram* (*_GnomeProgramGet_fn)(void);
typedef GnomeVFSResult (*_GnomeVFSGetFileInfo_fn)(const gchar* text_uri,
GnomeVFSFileInfo* info,
GnomeVFSFileInfoOptions options);
typedef void (*_GnomeVFSFileInfoClear_fn)(GnomeVFSFileInfo* info);
static PRLibrary* gLibGnomeUI = nullptr;
static PRLibrary* gLibGnome = nullptr;
static PRLibrary* gLibGnomeVFS = nullptr;
static bool gTriedToLoadGnomeLibs = false;
static _GnomeIconLookup_fn _gnome_icon_lookup = nullptr;
static _GnomeIconThemeNew_fn _gnome_icon_theme_new = nullptr;
static _GnomeInit_fn _gnome_init = nullptr;
static _GnomeProgramGet_fn _gnome_program_get = nullptr;
static _GnomeVFSGetFileInfo_fn _gnome_vfs_get_file_info = nullptr;
static _GnomeVFSFileInfoClear_fn _gnome_vfs_file_info_clear = nullptr;
#endif //MOZ_ENABLE_GNOMEUI
static nsresult
moz_gdk_pixbuf_to_channel(GdkPixbuf* aPixbuf, nsIURI* aURI,
nsIChannel** aChannel)
@ -162,9 +116,6 @@ moz_gdk_pixbuf_to_channel(GdkPixbuf* aPixbuf, nsIURI* aURI,
static GtkWidget* gProtoWindow = nullptr;
static GtkWidget* gStockImageWidget = nullptr;
#ifdef MOZ_ENABLE_GNOMEUI
static GnomeIconTheme* gIconTheme = nullptr;
#endif //MOZ_ENABLE_GNOMEUI
static void
ensure_stock_image_widget()
@ -183,100 +134,6 @@ ensure_stock_image_widget()
}
}
#ifdef MOZ_ENABLE_GNOMEUI
static nsresult
ensure_libgnomeui()
{
// Attempt to get the libgnomeui symbol references. We do it this way
// so that stock icons from Init() don't get held back by InitWithGnome()'s
// libgnomeui dependency.
if (!gTriedToLoadGnomeLibs) {
gLibGnomeUI = PR_LoadLibrary("libgnomeui-2.so.0");
if (!gLibGnomeUI) {
return NS_ERROR_NOT_AVAILABLE;
}
_gnome_init =
(_GnomeInit_fn)PR_FindFunctionSymbol(gLibGnomeUI,
"gnome_init_with_popt_table");
_gnome_icon_theme_new =
(_GnomeIconThemeNew_fn)PR_FindFunctionSymbol(gLibGnomeUI,
"gnome_icon_theme_new");
_gnome_icon_lookup =
(_GnomeIconLookup_fn)PR_FindFunctionSymbol(gLibGnomeUI,
"gnome_icon_lookup");
if (!_gnome_init || !_gnome_icon_theme_new || !_gnome_icon_lookup) {
PR_UnloadLibrary(gLibGnomeUI);
gLibGnomeUI = nullptr;
return NS_ERROR_NOT_AVAILABLE;
}
}
if (!gLibGnomeUI) {
return NS_ERROR_NOT_AVAILABLE;
}
return NS_OK;
}
static nsresult
ensure_libgnome()
{
if (!gTriedToLoadGnomeLibs) {
gLibGnome = PR_LoadLibrary("libgnome-2.so.0");
if (!gLibGnome) {
return NS_ERROR_NOT_AVAILABLE;
}
_gnome_program_get =
(_GnomeProgramGet_fn)PR_FindFunctionSymbol(gLibGnome,
"gnome_program_get");
if (!_gnome_program_get) {
PR_UnloadLibrary(gLibGnome);
gLibGnome = nullptr;
return NS_ERROR_NOT_AVAILABLE;
}
}
if (!gLibGnome) {
return NS_ERROR_NOT_AVAILABLE;
}
return NS_OK;
}
static nsresult
ensure_libgnomevfs()
{
if (!gTriedToLoadGnomeLibs) {
gLibGnomeVFS = PR_LoadLibrary("libgnomevfs-2.so.0");
if (!gLibGnomeVFS) {
return NS_ERROR_NOT_AVAILABLE;
}
_gnome_vfs_get_file_info =
(_GnomeVFSGetFileInfo_fn)PR_FindFunctionSymbol(gLibGnomeVFS,
"gnome_vfs_get_file_info");
_gnome_vfs_file_info_clear =
(_GnomeVFSFileInfoClear_fn)PR_FindFunctionSymbol(gLibGnomeVFS,
"gnome_vfs_file_"
"info_clear");
if (!_gnome_vfs_get_file_info || !_gnome_vfs_file_info_clear) {
PR_UnloadLibrary(gLibGnomeVFS);
gLibGnomeVFS = nullptr;
return NS_ERROR_NOT_AVAILABLE;
}
}
if (!gLibGnomeVFS) {
return NS_ERROR_NOT_AVAILABLE;
}
return NS_OK;
}
#endif //MOZ_ENABLE_GNOMEUI
static GtkIconSize
moz_gtk_icon_size(const char* name)
{
@ -307,7 +164,7 @@ moz_gtk_icon_size(const char* name)
return GTK_ICON_SIZE_MENU;
}
#if defined(MOZ_ENABLE_GNOMEUI) || defined(MOZ_ENABLE_GIO)
#ifdef MOZ_ENABLE_GIO
static int32_t
GetIconSize(nsIMozIconURI* aIconURI)
{
@ -346,149 +203,7 @@ ScaleIconBuf(GdkPixbuf** aBuf, int32_t iconSize)
}
return NS_OK;
}
#endif
#ifdef MOZ_ENABLE_GNOMEUI
nsresult
nsIconChannel::InitWithGnome(nsIMozIconURI* aIconURI)
{
nsresult rv;
if (NS_FAILED(ensure_libgnomeui()) || NS_FAILED(ensure_libgnome()) ||
NS_FAILED(ensure_libgnomevfs())) {
gTriedToLoadGnomeLibs = true;
return NS_ERROR_NOT_AVAILABLE;
}
gTriedToLoadGnomeLibs = true;
if (!_gnome_program_get()) {
// Get the brandShortName from the string bundle to pass to GNOME
// as the application name. This may be used for things such as
// the title of grouped windows in the panel.
nsCOMPtr<nsIStringBundleService> bundleService =
do_GetService(NS_STRINGBUNDLE_CONTRACTID);
NS_ASSERTION(bundleService, "String bundle service must be present!");
nsCOMPtr<nsIStringBundle> bundle;
bundleService->CreateBundle("chrome://branding/locale/brand.properties",
getter_AddRefs(bundle));
nsAutoString appName;
if (bundle) {
bundle->GetStringFromName(MOZ_UTF16("brandShortName"),
getter_Copies(appName));
} else {
NS_WARNING(
"brand.properties not present, using default application name");
appName.AssignLiteral(MOZ_UTF16("Gecko"));
}
char* empty[] = { "" };
_gnome_init(NS_ConvertUTF16toUTF8(appName).get(),
"1.0", 1, empty, nullptr, 0, nullptr);
}
uint32_t iconSize = GetIconSize(aIconURI);
nsAutoCString type;
aIconURI->GetContentType(type);
GnomeVFSFileInfo fileInfo = {0};
fileInfo.refcount = 1; // In case some GnomeVFS function addrefs and
// releases it
nsAutoCString spec;
nsCOMPtr<nsIURL> url;
rv = aIconURI->GetIconURL(getter_AddRefs(url));
if (url) {
url->GetAsciiSpec(spec);
// Only ask gnome-vfs for a GnomeVFSFileInfo for file: uris, to avoid a
// network request
bool isFile;
if (NS_SUCCEEDED(url->SchemeIs("file", &isFile)) && isFile) {
_gnome_vfs_get_file_info(spec.get(), &fileInfo,
GNOME_VFS_FILE_INFO_DEFAULT);
}
else {
// The filename we get is UTF-8-compatible, which matches gnome
// expectations.
// See also:
// http://lists.gnome.org/archives/gnome-vfs-list/2004-March/msg00049.html
// "Whenever we can detect the charset used for the URI type we try to
// convert it to/from utf8 automatically inside gnome-vfs."
// I'll interpret that as "otherwise, this field is random junk".
nsAutoCString name;
url->GetFileName(name);
fileInfo.name = g_strdup(name.get());
if (!type.IsEmpty()) {
fileInfo.valid_fields = GNOME_VFS_FILE_INFO_FIELDS_MIME_TYPE;
fileInfo.mime_type = g_strdup(type.get());
}
}
}
if (type.IsEmpty()) {
nsCOMPtr<nsIMIMEService> ms(do_GetService("@mozilla.org/mime;1"));
if (ms) {
nsAutoCString fileExt;
aIconURI->GetFileExtension(fileExt);
if (!fileExt.IsEmpty()) {
ms->GetTypeFromExtension(fileExt, type);
}
}
}
// Get the icon theme
if (!gIconTheme) {
gIconTheme = _gnome_icon_theme_new();
if (!gIconTheme) {
_gnome_vfs_file_info_clear(&fileInfo);
return NS_ERROR_NOT_AVAILABLE;
}
}
char* name = _gnome_icon_lookup(gIconTheme, nullptr, spec.get(), nullptr,
&fileInfo, type.get(),
GNOME_ICON_LOOKUP_FLAGS_NONE, nullptr);
_gnome_vfs_file_info_clear(&fileInfo);
if (!name) {
return NS_ERROR_NOT_AVAILABLE;
}
// Get the default theme associated with the screen
// Do NOT free.
GtkIconTheme* theme = gtk_icon_theme_get_default();
if (!theme) {
g_free(name);
return NS_ERROR_UNEXPECTED;
}
GError* err = nullptr;
GdkPixbuf* buf = gtk_icon_theme_load_icon(theme, name, iconSize,
(GtkIconLookupFlags)0, &err);
g_free(name);
if (!buf) {
if (err) {
g_error_free(err);
}
return NS_ERROR_UNEXPECTED;
}
rv = ScaleIconBuf(&buf, iconSize);
NS_ENSURE_SUCCESS(rv, rv);
rv = moz_gdk_pixbuf_to_channel(buf, aIconURI,
getter_AddRefs(mRealChannel));
g_object_unref(buf);
return rv;
}
#endif // MOZ_ENABLE_GNOMEUI
#ifdef MOZ_ENABLE_GIO
nsresult
nsIconChannel::InitWithGIO(nsIMozIconURI* aIconURI)
{
@ -594,14 +309,10 @@ nsIconChannel::Init(nsIURI* aURI)
nsAutoCString stockIcon;
iconURI->GetStockIcon(stockIcon);
if (stockIcon.IsEmpty()) {
#ifdef MOZ_ENABLE_GNOMEUI
return InitWithGnome(iconURI);
#else
#ifdef MOZ_ENABLE_GIO
return InitWithGIO(iconURI);
#else
return NS_ERROR_NOT_AVAILABLE;
#endif
#endif
}
@ -710,23 +421,4 @@ nsIconChannel::Shutdown() {
gProtoWindow = nullptr;
gStockImageWidget = nullptr;
}
#ifdef MOZ_ENABLE_GNOMEUI
if (gIconTheme) {
g_object_unref(G_OBJECT(gIconTheme));
gIconTheme = nullptr;
}
gTriedToLoadGnomeLibs = false;
if (gLibGnomeUI) {
PR_UnloadLibrary(gLibGnomeUI);
gLibGnomeUI = nullptr;
}
if (gLibGnome) {
PR_UnloadLibrary(gLibGnome);
gLibGnome = nullptr;
}
if (gLibGnomeVFS) {
PR_UnloadLibrary(gLibGnomeVFS);
gLibGnomeVFS = nullptr;
}
#endif //MOZ_ENABLE_GNOMEUI
}

View File

@ -37,8 +37,6 @@ class nsIconChannel MOZ_FINAL : public nsIChannel
/// Will always be non-null after a successful Init.
nsCOMPtr<nsIChannel> mRealChannel;
/// Called by Init if we need to use the gnomeui library.
nsresult InitWithGnome(nsIMozIconURI* aURI);
nsresult InitWithGIO(nsIMozIconURI* aIconURI);
};