LCOV - code coverage report
Current view: directory - image/decoders/icon/gtk - nsIconChannel.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 257 8 3.1 %
Date: 2012-06-02 Functions: 14 1 7.1 %

       1                 : /* vim:set ts=2 sw=2 sts=2 cin et: */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is the Mozilla icon channel for gnome.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * Christian Biesinger <cbiesinger@web.de>.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 2004
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *  Nils Maier <MaierMan@web.de>
      24                 :  *
      25                 :  * Alternatively, the contents of this file may be used under the terms of
      26                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      27                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      28                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      29                 :  * of those above. If you wish to allow use of your version of this file only
      30                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      31                 :  * use your version of this file under the terms of the MPL, indicate your
      32                 :  * decision by deleting the provisions above and replace them with the notice
      33                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      34                 :  * the provisions above, a recipient may use your version of this file under
      35                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      36                 :  *
      37                 :  * ***** END LICENSE BLOCK ***** */
      38                 : 
      39                 : #include <stdlib.h>
      40                 : #include <unistd.h>
      41                 : 
      42                 : #ifdef MOZ_ENABLE_GNOMEUI
      43                 : // Older versions of these headers seem to be missing an extern "C"
      44                 : extern "C" {
      45                 : #include <libgnome/libgnome.h>
      46                 : #include <libgnomeui/gnome-icon-theme.h>
      47                 : #include <libgnomeui/gnome-icon-lookup.h>
      48                 : 
      49                 : #include <libgnomevfs/gnome-vfs-file-info.h>
      50                 : #include <libgnomevfs/gnome-vfs-ops.h>
      51                 : }
      52                 : #endif
      53                 : #ifdef MOZ_ENABLE_GIO
      54                 : #include <gio/gio.h>
      55                 : #endif
      56                 : 
      57                 : #include <gtk/gtk.h>
      58                 : 
      59                 : #include "nsIMIMEService.h"
      60                 : 
      61                 : #include "nsIStringBundle.h"
      62                 : 
      63                 : #include "nsNetUtil.h"
      64                 : #include "nsIURL.h"
      65                 : #include "prlink.h"
      66                 : 
      67                 : #include "mozilla/Util.h" // for DebugOnly
      68                 : 
      69                 : #include "nsIconChannel.h"
      70                 : 
      71               0 : NS_IMPL_ISUPPORTS2(nsIconChannel,
      72                 :                    nsIRequest,
      73                 :                    nsIChannel)
      74                 : 
      75                 : #ifdef MOZ_ENABLE_GNOMEUI
      76                 : // These let us have a soft dependency on libgnomeui rather than a hard one. These are just basically the prototypes
      77                 : // of the functions in the libraries.
      78                 : typedef char* (*_GnomeIconLookup_fn)(GtkIconTheme *icon_theme, GnomeThumbnailFactory *thumbnail_factory,
      79                 :                                      const char *file_uri, const char *custom_icon, GnomeVFSFileInfo *file_info,
      80                 :                                      const char *mime_type, GnomeIconLookupFlags flags, GnomeIconLookupResultFlags *result);
      81                 : typedef GnomeIconTheme* (*_GnomeIconThemeNew_fn)(void);
      82                 : typedef int (*_GnomeInit_fn)(const char *app_id, const char *app_version, int argc, char **argv, const struct poptOption *options,
      83                 :                              int flags, poptContext *return_ctx);
      84                 : typedef GnomeProgram* (*_GnomeProgramGet_fn)(void);
      85                 : typedef GnomeVFSResult (*_GnomeVFSGetFileInfo_fn)(const gchar *text_uri, GnomeVFSFileInfo *info, GnomeVFSFileInfoOptions options);
      86                 : typedef void (*_GnomeVFSFileInfoClear_fn)(GnomeVFSFileInfo *info);
      87                 : 
      88                 : static PRLibrary* gLibGnomeUI = nsnull;
      89                 : static PRLibrary* gLibGnome = nsnull;
      90                 : static PRLibrary* gLibGnomeVFS = nsnull;
      91                 : static bool gTriedToLoadGnomeLibs = false;
      92                 : 
      93                 : static _GnomeIconLookup_fn _gnome_icon_lookup = nsnull;
      94                 : static _GnomeIconThemeNew_fn _gnome_icon_theme_new = nsnull;
      95                 : static _GnomeInit_fn _gnome_init = nsnull;
      96                 : static _GnomeProgramGet_fn _gnome_program_get = nsnull;
      97                 : static _GnomeVFSGetFileInfo_fn _gnome_vfs_get_file_info = nsnull;
      98                 : static _GnomeVFSFileInfoClear_fn _gnome_vfs_file_info_clear = nsnull;
      99                 : #endif //MOZ_ENABLE_GNOMEUI
     100                 : 
     101                 : static nsresult
     102               0 : moz_gdk_pixbuf_to_channel(GdkPixbuf* aPixbuf, nsIURI *aURI,
     103                 :                           nsIChannel **aChannel)
     104                 : {
     105               0 :   int width = gdk_pixbuf_get_width(aPixbuf);
     106               0 :   int height = gdk_pixbuf_get_height(aPixbuf);
     107               0 :   NS_ENSURE_TRUE(height < 256 && width < 256 && height > 0 && width > 0 &&
     108                 :                  gdk_pixbuf_get_colorspace(aPixbuf) == GDK_COLORSPACE_RGB &&
     109                 :                  gdk_pixbuf_get_bits_per_sample(aPixbuf) == 8 &&
     110                 :                  gdk_pixbuf_get_has_alpha(aPixbuf) &&
     111                 :                  gdk_pixbuf_get_n_channels(aPixbuf) == 4,
     112                 :                  NS_ERROR_UNEXPECTED);
     113                 : 
     114               0 :   const int n_channels = 4;
     115               0 :   gsize buf_size = 2 + n_channels * height * width;
     116               0 :   PRUint8 * const buf = (PRUint8*)NS_Alloc(buf_size);
     117               0 :   NS_ENSURE_TRUE(buf, NS_ERROR_OUT_OF_MEMORY);
     118               0 :   PRUint8 *out = buf;
     119                 : 
     120               0 :   *(out++) = width;
     121               0 :   *(out++) = height;
     122                 : 
     123               0 :   const guchar * const pixels = gdk_pixbuf_get_pixels(aPixbuf);
     124               0 :   int rowextra = gdk_pixbuf_get_rowstride(aPixbuf) - width * n_channels;
     125                 : 
     126                 :   // encode the RGB data and the A data
     127               0 :   const guchar * in = pixels;
     128               0 :   for (int y = 0; y < height; ++y, in += rowextra) {
     129               0 :     for (int x = 0; x < width; ++x) {
     130               0 :       PRUint8 r = *(in++);
     131               0 :       PRUint8 g = *(in++);
     132               0 :       PRUint8 b = *(in++);
     133               0 :       PRUint8 a = *(in++);
     134                 : #define DO_PREMULTIPLY(c_) PRUint8(PRUint16(c_) * PRUint16(a) / PRUint16(255))
     135                 : #ifdef IS_LITTLE_ENDIAN
     136               0 :       *(out++) = DO_PREMULTIPLY(b);
     137               0 :       *(out++) = DO_PREMULTIPLY(g);
     138               0 :       *(out++) = DO_PREMULTIPLY(r);
     139               0 :       *(out++) = a;
     140                 : #else
     141                 :       *(out++) = a;
     142                 :       *(out++) = DO_PREMULTIPLY(r);
     143                 :       *(out++) = DO_PREMULTIPLY(g);
     144                 :       *(out++) = DO_PREMULTIPLY(b);
     145                 : #endif
     146                 : #undef DO_PREMULTIPLY
     147                 :     }
     148                 :   }
     149                 : 
     150               0 :   NS_ASSERTION(out == buf + buf_size, "size miscalculation");
     151                 : 
     152                 :   nsresult rv;
     153                 :   nsCOMPtr<nsIStringInputStream> stream =
     154               0 :     do_CreateInstance("@mozilla.org/io/string-input-stream;1", &rv);
     155               0 :   NS_ENSURE_SUCCESS(rv, rv);
     156                 : 
     157               0 :   rv = stream->AdoptData((char*)buf, buf_size);
     158               0 :   NS_ENSURE_SUCCESS(rv, rv);
     159                 : 
     160                 :   rv = NS_NewInputStreamChannel(aChannel, aURI, stream,
     161               0 :                                 NS_LITERAL_CSTRING("image/icon"));
     162               0 :   return rv;
     163                 : }
     164                 : 
     165                 : static GtkWidget *gProtoWindow = nsnull;
     166                 : static GtkWidget *gStockImageWidget = nsnull;
     167                 : #ifdef MOZ_ENABLE_GNOMEUI
     168                 : static GnomeIconTheme *gIconTheme = nsnull;
     169                 : #endif //MOZ_ENABLE_GNOMEUI
     170                 : 
     171                 : static void
     172               0 : ensure_stock_image_widget()
     173                 : {
     174                 :   // Only the style of the GtkImage needs to be used, but the widget is kept
     175                 :   // to track dynamic style changes.
     176               0 :   if (!gProtoWindow) {
     177               0 :     gProtoWindow = gtk_window_new(GTK_WINDOW_POPUP);
     178               0 :     GtkWidget* protoLayout = gtk_fixed_new();
     179               0 :     gtk_container_add(GTK_CONTAINER(gProtoWindow), protoLayout);
     180                 : 
     181               0 :     gStockImageWidget = gtk_image_new();
     182               0 :     gtk_container_add(GTK_CONTAINER(protoLayout), gStockImageWidget);
     183                 : 
     184               0 :     gtk_widget_ensure_style(gStockImageWidget);
     185                 :   }
     186               0 : }
     187                 : 
     188                 : #ifdef MOZ_ENABLE_GNOMEUI
     189                 : static nsresult
     190               0 : ensure_libgnomeui()
     191                 : {
     192                 :   // Attempt to get the libgnomeui symbol references. We do it this way so that stock icons from Init()
     193                 :   // don't get held back by InitWithGnome()'s libgnomeui dependency.
     194               0 :   if (!gTriedToLoadGnomeLibs) {
     195               0 :     gLibGnomeUI = PR_LoadLibrary("libgnomeui-2.so.0");
     196               0 :     if (!gLibGnomeUI)
     197               0 :       return NS_ERROR_NOT_AVAILABLE;
     198                 : 
     199               0 :     _gnome_init = (_GnomeInit_fn)PR_FindFunctionSymbol(gLibGnomeUI, "gnome_init_with_popt_table");
     200               0 :     _gnome_icon_theme_new = (_GnomeIconThemeNew_fn)PR_FindFunctionSymbol(gLibGnomeUI, "gnome_icon_theme_new");
     201               0 :     _gnome_icon_lookup = (_GnomeIconLookup_fn)PR_FindFunctionSymbol(gLibGnomeUI, "gnome_icon_lookup");
     202                 : 
     203               0 :     if (!_gnome_init || !_gnome_icon_theme_new || !_gnome_icon_lookup) {
     204               0 :       PR_UnloadLibrary(gLibGnomeUI);
     205               0 :       gLibGnomeUI = nsnull;
     206               0 :       return NS_ERROR_NOT_AVAILABLE;
     207                 :     }
     208                 :   }
     209                 : 
     210               0 :   if (!gLibGnomeUI)
     211               0 :     return NS_ERROR_NOT_AVAILABLE;
     212                 : 
     213               0 :   return NS_OK;
     214                 : }
     215                 : 
     216                 : static nsresult
     217               0 : ensure_libgnome()
     218                 : {
     219               0 :   if (!gTriedToLoadGnomeLibs) {
     220               0 :     gLibGnome = PR_LoadLibrary("libgnome-2.so.0");
     221               0 :     if (!gLibGnome)
     222               0 :       return NS_ERROR_NOT_AVAILABLE;
     223                 : 
     224               0 :     _gnome_program_get = (_GnomeProgramGet_fn)PR_FindFunctionSymbol(gLibGnome, "gnome_program_get");
     225               0 :     if (!_gnome_program_get) {
     226               0 :       PR_UnloadLibrary(gLibGnome);
     227               0 :       gLibGnome = nsnull;
     228               0 :       return NS_ERROR_NOT_AVAILABLE;
     229                 :     }
     230                 :   }
     231                 : 
     232               0 :   if (!gLibGnome)
     233               0 :     return NS_ERROR_NOT_AVAILABLE;
     234                 : 
     235               0 :   return NS_OK;
     236                 : }
     237                 : 
     238                 : static nsresult
     239               0 : ensure_libgnomevfs()
     240                 : {
     241               0 :   if (!gTriedToLoadGnomeLibs) {
     242               0 :     gLibGnomeVFS = PR_LoadLibrary("libgnomevfs-2.so.0");
     243               0 :     if (!gLibGnomeVFS)
     244               0 :       return NS_ERROR_NOT_AVAILABLE;
     245                 : 
     246               0 :     _gnome_vfs_get_file_info = (_GnomeVFSGetFileInfo_fn)PR_FindFunctionSymbol(gLibGnomeVFS, "gnome_vfs_get_file_info");
     247               0 :     _gnome_vfs_file_info_clear = (_GnomeVFSFileInfoClear_fn)PR_FindFunctionSymbol(gLibGnomeVFS, "gnome_vfs_file_info_clear");
     248               0 :     if (!_gnome_vfs_get_file_info || !_gnome_vfs_file_info_clear) {
     249               0 :       PR_UnloadLibrary(gLibGnomeVFS);
     250               0 :       gLibGnomeVFS = nsnull;
     251               0 :       return NS_ERROR_NOT_AVAILABLE;
     252                 :     }
     253                 :   }
     254                 : 
     255               0 :   if (!gLibGnomeVFS)
     256               0 :     return NS_ERROR_NOT_AVAILABLE;
     257                 : 
     258               0 :   return NS_OK;
     259                 : }
     260                 : #endif //MOZ_ENABLE_GNOMEUI
     261                 : 
     262                 : static GtkIconSize
     263               0 : moz_gtk_icon_size(const char *name)
     264                 : {
     265               0 :   if (strcmp(name, "button") == 0)
     266               0 :     return GTK_ICON_SIZE_BUTTON;
     267                 : 
     268               0 :   if (strcmp(name, "menu") == 0)
     269               0 :     return GTK_ICON_SIZE_MENU;
     270                 : 
     271               0 :   if (strcmp(name, "toolbar") == 0)
     272               0 :     return GTK_ICON_SIZE_LARGE_TOOLBAR;
     273                 : 
     274               0 :   if (strcmp(name, "toolbarsmall") == 0)
     275               0 :     return GTK_ICON_SIZE_SMALL_TOOLBAR;
     276                 : 
     277               0 :   if (strcmp(name, "dnd") == 0)
     278               0 :     return GTK_ICON_SIZE_DND;
     279                 : 
     280               0 :   if (strcmp(name, "dialog") == 0)
     281               0 :     return GTK_ICON_SIZE_DIALOG;
     282                 : 
     283               0 :   return GTK_ICON_SIZE_MENU;
     284                 : }
     285                 : 
     286                 : #if defined(MOZ_ENABLE_GNOMEUI) || defined(MOZ_ENABLE_GIO)
     287                 : static PRInt32
     288               0 : GetIconSize(nsIMozIconURI *aIconURI)
     289                 : {
     290               0 :   nsCAutoString iconSizeString;
     291                 : 
     292               0 :   aIconURI->GetIconSize(iconSizeString);
     293               0 :   if (iconSizeString.IsEmpty()) {
     294                 :     PRUint32 size;
     295               0 :     mozilla::DebugOnly<nsresult> rv = aIconURI->GetImageSize(&size);
     296               0 :     NS_ASSERTION(NS_SUCCEEDED(rv), "GetImageSize failed");
     297               0 :     return size; 
     298                 :   } else {
     299                 :     int size;
     300                 : 
     301               0 :     GtkIconSize icon_size = moz_gtk_icon_size(iconSizeString.get());
     302               0 :     gtk_icon_size_lookup(icon_size, &size, NULL);
     303               0 :     return size;
     304                 :   }
     305                 : }
     306                 : 
     307                 : /* Scale icon buffer to preferred size */
     308                 : static nsresult
     309               0 : ScaleIconBuf(GdkPixbuf **aBuf, PRInt32 iconSize)
     310                 : {
     311                 :   // Scale buffer only if width or height differ from preferred size
     312               0 :   if (gdk_pixbuf_get_width(*aBuf)  != iconSize &&
     313               0 :       gdk_pixbuf_get_height(*aBuf) != iconSize) {
     314                 :     GdkPixbuf *scaled = gdk_pixbuf_scale_simple(*aBuf, iconSize, iconSize,
     315               0 :                                                 GDK_INTERP_BILINEAR);
     316                 :     // replace original buffer by scaled
     317               0 :     g_object_unref(*aBuf);
     318               0 :     *aBuf = scaled;
     319               0 :     if (!scaled)
     320               0 :       return NS_ERROR_OUT_OF_MEMORY;
     321                 :   }
     322               0 :   return NS_OK;
     323                 : }
     324                 : #endif
     325                 : 
     326                 : #ifdef MOZ_ENABLE_GNOMEUI
     327                 : nsresult
     328               0 : nsIconChannel::InitWithGnome(nsIMozIconURI *aIconURI)
     329                 : {
     330                 :   nsresult rv;
     331                 : 
     332               0 :   if (NS_FAILED(ensure_libgnomeui()) || NS_FAILED(ensure_libgnome()) || NS_FAILED(ensure_libgnomevfs())) {
     333               0 :     gTriedToLoadGnomeLibs = true;
     334               0 :     return NS_ERROR_NOT_AVAILABLE;
     335                 :   }
     336                 : 
     337               0 :   gTriedToLoadGnomeLibs = true;
     338                 : 
     339               0 :   if (!_gnome_program_get()) {
     340                 :     // Get the brandShortName from the string bundle to pass to GNOME
     341                 :     // as the application name.  This may be used for things such as
     342                 :     // the title of grouped windows in the panel.
     343                 :     nsCOMPtr<nsIStringBundleService> bundleService = 
     344               0 :       do_GetService(NS_STRINGBUNDLE_CONTRACTID);
     345                 : 
     346               0 :     NS_ASSERTION(bundleService, "String bundle service must be present!");
     347                 : 
     348               0 :     nsCOMPtr<nsIStringBundle> bundle;
     349               0 :     bundleService->CreateBundle("chrome://branding/locale/brand.properties",
     350               0 :                                 getter_AddRefs(bundle));
     351               0 :     nsAutoString appName;
     352                 : 
     353               0 :     if (bundle) {
     354               0 :       bundle->GetStringFromName(NS_LITERAL_STRING("brandShortName").get(),
     355               0 :                                 getter_Copies(appName));
     356                 :     } else {
     357               0 :       NS_WARNING("brand.properties not present, using default application name");
     358               0 :       appName.Assign(NS_LITERAL_STRING("Gecko"));
     359                 :     }
     360                 : 
     361               0 :     char* empty[] = { "" };
     362               0 :     _gnome_init(NS_ConvertUTF16toUTF8(appName).get(), "1.0", 1, empty, NULL, 0, NULL);
     363                 :   }
     364                 : 
     365               0 :   PRUint32 iconSize = GetIconSize(aIconURI);
     366               0 :   nsCAutoString type;
     367               0 :   aIconURI->GetContentType(type);
     368                 : 
     369               0 :   GnomeVFSFileInfo fileInfo = {0};
     370               0 :   fileInfo.refcount = 1; // In case some GnomeVFS function addrefs and releases it
     371                 : 
     372               0 :   nsCAutoString spec;
     373               0 :   nsCOMPtr<nsIURL> url;
     374               0 :   rv = aIconURI->GetIconURL(getter_AddRefs(url));
     375               0 :   if (url) {
     376               0 :     url->GetAsciiSpec(spec);
     377                 :     // Only ask gnome-vfs for a GnomeVFSFileInfo for file: uris, to avoid a
     378                 :     // network request
     379                 :     bool isFile;
     380               0 :     if (NS_SUCCEEDED(url->SchemeIs("file", &isFile)) && isFile) {
     381               0 :       _gnome_vfs_get_file_info(spec.get(), &fileInfo, GNOME_VFS_FILE_INFO_DEFAULT);
     382                 :     }
     383                 :     else {
     384                 :       // The filename we get is UTF-8-compatible, which matches gnome expectations.
     385                 :       // See also: http://lists.gnome.org/archives/gnome-vfs-list/2004-March/msg00049.html
     386                 :       // "Whenever we can detect the charset used for the URI type we try to
     387                 :       //  convert it to/from utf8 automatically inside gnome-vfs."
     388                 :       // I'll interpret that as "otherwise, this field is random junk".
     389               0 :       nsCAutoString name;
     390               0 :       url->GetFileName(name);
     391               0 :       fileInfo.name = g_strdup(name.get());
     392                 : 
     393               0 :       if (!type.IsEmpty()) {
     394               0 :         fileInfo.valid_fields = GNOME_VFS_FILE_INFO_FIELDS_MIME_TYPE;
     395               0 :         fileInfo.mime_type = g_strdup(type.get());
     396                 :       }
     397                 :     }
     398                 :   }
     399                 : 
     400               0 :   if (type.IsEmpty()) {
     401               0 :     nsCOMPtr<nsIMIMEService> ms(do_GetService("@mozilla.org/mime;1"));
     402               0 :     if (ms) {
     403               0 :       nsCAutoString fileExt;
     404               0 :       aIconURI->GetFileExtension(fileExt);
     405               0 :       if (!fileExt.IsEmpty()) {
     406               0 :         ms->GetTypeFromExtension(fileExt, type);
     407                 :       }
     408                 :     }
     409                 :   }
     410                 :   // Get the icon theme
     411               0 :   if (!gIconTheme) {
     412               0 :     gIconTheme = _gnome_icon_theme_new();
     413                 : 
     414               0 :     if (!gIconTheme) {
     415               0 :       _gnome_vfs_file_info_clear(&fileInfo);
     416               0 :       return NS_ERROR_NOT_AVAILABLE;
     417                 :     }
     418                 :   }
     419                 : 
     420                 :   char* name = _gnome_icon_lookup(gIconTheme, NULL, spec.get(), NULL, &fileInfo,
     421                 :                                   type.get(), GNOME_ICON_LOOKUP_FLAGS_NONE,
     422               0 :                                   NULL);
     423                 : 
     424               0 :   _gnome_vfs_file_info_clear(&fileInfo);
     425               0 :   if (!name)
     426               0 :     return NS_ERROR_NOT_AVAILABLE;
     427                 :   
     428                 :   // Get the default theme associated with the screen
     429                 :   // Do NOT free.
     430               0 :   GtkIconTheme *theme = gtk_icon_theme_get_default();
     431               0 :   if (!theme) {
     432               0 :     g_free(name);
     433               0 :     return NS_ERROR_UNEXPECTED;
     434                 :   }
     435                 : 
     436               0 :   GError *err = nsnull;
     437               0 :   GdkPixbuf* buf = gtk_icon_theme_load_icon(theme, name, iconSize, (GtkIconLookupFlags)0, &err);
     438               0 :   g_free(name);
     439                 : 
     440               0 :   if (!buf) {
     441               0 :     if (err)
     442               0 :       g_error_free(err);
     443               0 :     return NS_ERROR_UNEXPECTED;
     444                 :   }
     445                 : 
     446               0 :   rv = ScaleIconBuf(&buf, iconSize);
     447               0 :   NS_ENSURE_SUCCESS(rv, rv);
     448                 : 
     449                 :   rv = moz_gdk_pixbuf_to_channel(buf, aIconURI,
     450               0 :                                  getter_AddRefs(mRealChannel));
     451               0 :   g_object_unref(buf);
     452               0 :   return rv;
     453                 : }
     454                 : #endif // MOZ_ENABLE_GNOMEUI
     455                 : 
     456                 : #ifdef MOZ_ENABLE_GIO
     457                 : nsresult
     458                 : nsIconChannel::InitWithGIO(nsIMozIconURI *aIconURI)
     459                 : {
     460                 :   nsresult rv;
     461                 : 
     462                 :   GIcon *icon = NULL;
     463                 :   nsCOMPtr<nsIURL> fileURI;
     464                 : 
     465                 :   // Read icon content
     466                 :   aIconURI->GetIconURL(getter_AddRefs(fileURI));
     467                 : 
     468                 :   // Get icon for file specified by URI
     469                 :   if (fileURI) {
     470                 :     bool isFile;
     471                 :     nsCAutoString spec;
     472                 :     fileURI->GetAsciiSpec(spec);
     473                 :     if (NS_SUCCEEDED(fileURI->SchemeIs("file", &isFile)) && isFile) {
     474                 :       GFile *file = g_file_new_for_uri(spec.get());
     475                 :       GFileInfo *fileInfo = g_file_query_info(file,
     476                 :                                               G_FILE_ATTRIBUTE_STANDARD_ICON,
     477                 :                                               G_FILE_QUERY_INFO_NONE, NULL, NULL);
     478                 :       g_object_unref(file);
     479                 :       if (fileInfo) {
     480                 :         // icon from g_content_type_get_icon doesn't need unref
     481                 :         icon = g_file_info_get_icon(fileInfo);
     482                 :         if (icon)
     483                 :           g_object_ref(icon);
     484                 :         g_object_unref(fileInfo);
     485                 :       }
     486                 :     }
     487                 :   }
     488                 :   
     489                 :   // Try to get icon by using MIME type
     490                 :   if (!icon) {
     491                 :     nsCAutoString type;
     492                 :     aIconURI->GetContentType(type);
     493                 :     // Try to get MIME type from file extension by using nsIMIMEService
     494                 :     if (type.IsEmpty()) {
     495                 :       nsCOMPtr<nsIMIMEService> ms(do_GetService("@mozilla.org/mime;1"));
     496                 :       if (ms) {
     497                 :         nsCAutoString fileExt;
     498                 :         aIconURI->GetFileExtension(fileExt);
     499                 :         ms->GetTypeFromExtension(fileExt, type);
     500                 :       }
     501                 :     }
     502                 :     char *ctype = NULL; // character representation of content type
     503                 :     if (!type.IsEmpty()) {
     504                 :       ctype = g_content_type_from_mime_type(type.get());
     505                 :     }
     506                 :     if (ctype) {
     507                 :       icon = g_content_type_get_icon(ctype);
     508                 :       g_free(ctype);
     509                 :     }
     510                 :   }
     511                 : 
     512                 :   // Get default icon theme
     513                 :   GtkIconTheme *iconTheme = gtk_icon_theme_get_default();  
     514                 :   GtkIconInfo *iconInfo = NULL;
     515                 :   // Get icon size
     516                 :   PRInt32 iconSize = GetIconSize(aIconURI);
     517                 : 
     518                 :   if (icon) {
     519                 :     NS_SUCCEEDED(rv);
     520                 : 
     521                 :     // Use icon and theme to get GtkIconInfo
     522                 :     iconInfo = gtk_icon_theme_lookup_by_gicon(iconTheme,
     523                 :                                               icon, iconSize,
     524                 :                                               (GtkIconLookupFlags)0);
     525                 :     g_object_unref(icon);
     526                 :   }
     527                 :   
     528                 :   if (!iconInfo) {
     529                 :     // Mozilla's mimetype lookup failed. Try the "unknown" icon.
     530                 :     iconInfo = gtk_icon_theme_lookup_icon(iconTheme,
     531                 :                                           "unknown", iconSize,
     532                 :                                           (GtkIconLookupFlags)0);
     533                 :     if (!iconInfo) {
     534                 :       return NS_ERROR_NOT_AVAILABLE;
     535                 :     }
     536                 :   }
     537                 :   
     538                 :   // Create a GdkPixbuf buffer containing icon and scale it
     539                 :   GdkPixbuf* buf = gtk_icon_info_load_icon(iconInfo, NULL);
     540                 :   gtk_icon_info_free(iconInfo);
     541                 :   if (!buf) {
     542                 :     return NS_ERROR_UNEXPECTED;
     543                 :   }
     544                 :   
     545                 :   rv = ScaleIconBuf(&buf, iconSize);
     546                 :   NS_ENSURE_SUCCESS(rv, rv);
     547                 : 
     548                 :   rv = moz_gdk_pixbuf_to_channel(buf, aIconURI,
     549                 :                                  getter_AddRefs(mRealChannel));
     550                 :   g_object_unref(buf);
     551                 :   return rv;
     552                 : }
     553                 : #endif // MOZ_ENABLE_GIO
     554                 : 
     555                 : nsresult
     556               0 : nsIconChannel::Init(nsIURI* aURI)
     557                 : {
     558               0 :   nsCOMPtr<nsIMozIconURI> iconURI = do_QueryInterface(aURI);
     559               0 :   NS_ASSERTION(iconURI, "URI is not an nsIMozIconURI");
     560                 : 
     561               0 :   nsCAutoString stockIcon;
     562               0 :   iconURI->GetStockIcon(stockIcon);
     563               0 :   if (stockIcon.IsEmpty()) {
     564                 : #ifdef MOZ_ENABLE_GNOMEUI
     565               0 :     return InitWithGnome(iconURI);
     566                 : #else 
     567                 : #ifdef MOZ_ENABLE_GIO
     568                 :     return InitWithGIO(iconURI);
     569                 : #else
     570                 :     return NS_ERROR_NOT_AVAILABLE;
     571                 : #endif
     572                 : #endif
     573                 :   }
     574                 : 
     575                 :   // Search for stockIcon
     576               0 :   nsCAutoString iconSizeString;
     577               0 :   iconURI->GetIconSize(iconSizeString);
     578                 : 
     579               0 :   nsCAutoString iconStateString;
     580               0 :   iconURI->GetIconState(iconStateString);
     581                 : 
     582               0 :   GtkIconSize icon_size = moz_gtk_icon_size(iconSizeString.get());
     583               0 :   GtkStateType state = iconStateString.EqualsLiteral("disabled") ?
     584               0 :     GTK_STATE_INSENSITIVE : GTK_STATE_NORMAL;
     585                 : 
     586                 :   // First lookup the icon by stock id and text direction.
     587               0 :   GtkTextDirection direction = GTK_TEXT_DIR_NONE;
     588               0 :   if (StringEndsWith(stockIcon, NS_LITERAL_CSTRING("-ltr"))) {
     589               0 :     direction = GTK_TEXT_DIR_LTR;
     590               0 :   } else if (StringEndsWith(stockIcon, NS_LITERAL_CSTRING("-rtl"))) {
     591               0 :     direction = GTK_TEXT_DIR_RTL;
     592                 :   }
     593                 : 
     594               0 :   bool forceDirection = direction != GTK_TEXT_DIR_NONE;
     595               0 :   nsCAutoString stockID;
     596               0 :   bool useIconName = false;
     597               0 :   if (!forceDirection) {
     598               0 :     direction = gtk_widget_get_default_direction();
     599               0 :     stockID = stockIcon;
     600                 :   } else {
     601                 :     // GTK versions < 2.22 use icon names from concatenating stock id with
     602                 :     // -(rtl|ltr), which is how the moz-icon stock name is interpreted here.
     603               0 :     stockID = Substring(stockIcon, 0, stockIcon.Length() - 4);
     604                 :     // However, if we lookup bidi icons by the stock name, then GTK versions
     605                 :     // >= 2.22 will use a bidi lookup convention that most icon themes do not
     606                 :     // yet follow.  Therefore, we first check to see if the theme supports the
     607                 :     // old icon name as this will have bidi support (if found).
     608               0 :     GtkIconTheme *icon_theme = gtk_icon_theme_get_default();
     609                 :     // Micking what gtk_icon_set_render_icon does with sizes, though it's not
     610                 :     // critical as icons will be scaled to suit size.  It just means we follow
     611                 :     // the same pathes and so share caches.
     612                 :     gint width, height;
     613               0 :     if (gtk_icon_size_lookup(icon_size, &width, &height)) {
     614               0 :       gint size = NS_MIN(width, height);
     615                 :       // We use gtk_icon_theme_lookup_icon() without
     616                 :       // GTK_ICON_LOOKUP_USE_BUILTIN instead of gtk_icon_theme_has_icon() so
     617                 :       // we don't pick up fallback icons added by distributions for backward
     618                 :       // compatibility.
     619                 :       GtkIconInfo *icon =
     620                 :         gtk_icon_theme_lookup_icon(icon_theme, stockIcon.get(),
     621               0 :                                    size, (GtkIconLookupFlags)0);
     622               0 :       if (icon) {
     623               0 :         useIconName = true;
     624               0 :         gtk_icon_info_free(icon);
     625                 :       }
     626                 :     }
     627                 :   }
     628                 : 
     629               0 :   ensure_stock_image_widget();
     630               0 :   GtkStyle *style = gtk_widget_get_style(gStockImageWidget);
     631               0 :   GtkIconSet *icon_set = NULL;
     632               0 :   if (!useIconName) {
     633               0 :     icon_set = gtk_style_lookup_icon_set(style, stockID.get());
     634                 :   }
     635                 : 
     636               0 :   if (!icon_set) {
     637                 :     // Either we have choosen icon-name lookup for a bidi icon, or stockIcon is
     638                 :     // not a stock id so we assume it is an icon name.
     639               0 :     useIconName = true;
     640                 :     // Creating a GtkIconSet is a convenient way to allow the style to
     641                 :     // render the icon, possibly with variations suitable for insensitive
     642                 :     // states.
     643               0 :     icon_set = gtk_icon_set_new();
     644               0 :     GtkIconSource *icon_source = gtk_icon_source_new();
     645                 :     
     646               0 :     gtk_icon_source_set_icon_name(icon_source, stockIcon.get());
     647               0 :     gtk_icon_set_add_source(icon_set, icon_source);
     648               0 :     gtk_icon_source_free(icon_source);
     649                 :   }
     650                 : 
     651                 :   GdkPixbuf *icon =
     652                 :     gtk_icon_set_render_icon (icon_set, style, direction, state,
     653               0 :                               icon_size, gStockImageWidget, NULL);
     654               0 :   if (useIconName) {
     655               0 :     gtk_icon_set_unref(icon_set);
     656                 :   }
     657                 : 
     658                 :   // According to documentation, gtk_icon_set_render_icon() never returns
     659                 :   // NULL, but it does return NULL when we have the problem reported here:
     660                 :   // https://bugzilla.gnome.org/show_bug.cgi?id=629878#c13
     661               0 :   if (!icon)
     662               0 :     return NS_ERROR_NOT_AVAILABLE;
     663                 :   
     664                 :   nsresult rv = moz_gdk_pixbuf_to_channel(icon, iconURI,
     665               0 :                                           getter_AddRefs(mRealChannel));
     666                 : 
     667               0 :   g_object_unref(icon);
     668                 : 
     669               0 :   return rv;
     670                 : }
     671                 : 
     672                 : void
     673            1419 : nsIconChannel::Shutdown() {
     674            1419 :   if (gProtoWindow) {
     675               0 :     gtk_widget_destroy(gProtoWindow);
     676               0 :     gProtoWindow = nsnull;
     677               0 :     gStockImageWidget = nsnull;
     678                 :   }
     679                 : #ifdef MOZ_ENABLE_GNOMEUI
     680            1419 :   if (gIconTheme) {
     681               0 :     g_object_unref(G_OBJECT(gIconTheme));
     682               0 :     gIconTheme = nsnull;
     683                 :   }
     684            1419 :   gTriedToLoadGnomeLibs = false;
     685            1419 :   if (gLibGnomeUI) {
     686               0 :     PR_UnloadLibrary(gLibGnomeUI);
     687               0 :     gLibGnomeUI = nsnull;
     688                 :   }
     689            1419 :   if (gLibGnome) {
     690               0 :     PR_UnloadLibrary(gLibGnome);
     691               0 :     gLibGnome = nsnull;
     692                 :   }
     693            1419 :   if (gLibGnomeVFS) {
     694               0 :     PR_UnloadLibrary(gLibGnomeVFS);
     695               0 :     gLibGnomeVFS = nsnull;
     696                 :   }
     697                 : #endif //MOZ_ENABLE_GNOMEUI
     698            1419 : }

Generated by: LCOV version 1.7