Bug 808027 - Change favicons handling to be Bitmap-based (r=mfinkle)
authorLucas Rocha <lucasr@mozilla.com>
Mon, 05 Nov 2012 11:42:25 +0000
changeset 112296 a519a3f18f39e032b942e8eee1be8c6aedcb01ca
parent 112295 b91b1e93e3d406c587fe5af6bebea343780734d3
child 112297 4222b4c6a3e93ade8ae84c966d85cc9d3e9ea612
push id17507
push userlrocha@mozilla.com
push dateMon, 05 Nov 2012 11:42:59 +0000
treeherdermozilla-inbound@a519a3f18f39 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmfinkle
bugs808027
milestone19.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 808027 - Change favicons handling to be Bitmap-based (r=mfinkle)
mobile/android/base/AboutHomeContent.java
mobile/android/base/BrowserApp.java
mobile/android/base/BrowserToolbar.java
mobile/android/base/Favicons.java
mobile/android/base/GeckoApp.java
mobile/android/base/Tab.java
mobile/android/base/awesomebar/AllPagesTab.java
mobile/android/base/db/BrowserDB.java
mobile/android/base/db/LocalBrowserDB.java
--- a/mobile/android/base/AboutHomeContent.java
+++ b/mobile/android/base/AboutHomeContent.java
@@ -24,17 +24,16 @@ import android.content.Context;
 import android.content.Intent;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.database.Cursor;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.Canvas;
 import android.graphics.Color;
-import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.graphics.Path;
 import android.graphics.Paint;
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffXfermode;
 import android.graphics.RectF;
 import android.os.SystemClock;
 import android.text.SpannableString;
@@ -548,20 +547,20 @@ public class AboutHomeContent extends Sc
                                 if (mUriLoadCallback != null)
                                     mUriLoadCallback.callback(homepageUrl);
                             }
                         });
 
                         Favicons favicons = mActivity.getFavicons();
                         favicons.loadFavicon(pageUrl, iconUrl, true,
                                     new Favicons.OnFaviconLoadedListener() {
-                            public void onFaviconLoaded(String url, Drawable favicon) {
+                            public void onFaviconLoaded(String url, Bitmap favicon) {
                                 if (favicon != null) {
                                     ImageView icon = (ImageView) row.findViewById(R.id.addon_icon);
-                                    icon.setImageDrawable(favicon);
+                                    icon.setImageBitmap(favicon);
                                 }
                             }
                         });
 
                         mAddons.addItem(row);
                     }
 
                     mAddons.show();
@@ -585,26 +584,26 @@ public class AboutHomeContent extends Sc
             public void onTabRead(final SessionTab tab) {
                 final String url = tab.getSelectedUrl();
                 // don't show last tabs for about:home
                 if (url.equals("about:home")) {
                     return;
                 }
 
                 ContentResolver resolver = mActivity.getContentResolver();
-                final BitmapDrawable favicon = BrowserDB.getFaviconForUrl(resolver, url);
+                final Bitmap favicon = BrowserDB.getFaviconForUrl(resolver, url);
                 lastTabUrlsList.add(url);
 
                 AboutHomeContent.this.post(new Runnable() {
                     public void run() {
                         View container = mInflater.inflate(R.layout.abouthome_last_tabs_row, mLastTabs.getItemsContainer(), false);
                         ((TextView) container.findViewById(R.id.last_tab_title)).setText(tab.getSelectedTitle());
                         ((TextView) container.findViewById(R.id.last_tab_url)).setText(tab.getSelectedUrl());
                         if (favicon != null) {
-                            ((ImageView) container.findViewById(R.id.last_tab_favicon)).setImageDrawable(favicon);
+                            ((ImageView) container.findViewById(R.id.last_tab_favicon)).setImageBitmap(favicon);
                         }
 
                         container.setOnClickListener(new View.OnClickListener() {
                             public void onClick(View v) {
                                 Tabs.getInstance().loadUrlInTab(url);
                             }
                         });
 
--- a/mobile/android/base/BrowserApp.java
+++ b/mobile/android/base/BrowserApp.java
@@ -577,17 +577,17 @@ abstract public class BrowserApp extends
 
     /* Favicon methods */
     private void loadFavicon(final Tab tab) {
         maybeCancelFaviconLoad(tab);
 
         long id = getFavicons().loadFavicon(tab.getURL(), tab.getFaviconURL(), !tab.isPrivate(),
                         new Favicons.OnFaviconLoadedListener() {
 
-            public void onFaviconLoaded(String pageUrl, Drawable favicon) {
+            public void onFaviconLoaded(String pageUrl, Bitmap favicon) {
                 // Leave favicon UI untouched if we failed to load the image
                 // for some reason.
                 if (favicon == null)
                     return;
 
                 // The tab might be pointing to another URL by the time the
                 // favicon is finally loaded, in which case we simply ignore it.
                 if (!tab.getURL().equals(pageUrl))
--- a/mobile/android/base/BrowserToolbar.java
+++ b/mobile/android/base/BrowserToolbar.java
@@ -2,16 +2,17 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko;
 
 import android.content.Context;
 import android.graphics.Color;
+import android.graphics.Bitmap;
 import android.graphics.drawable.AnimationDrawable;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.graphics.Rect;
 import android.os.Build;
 import android.os.Handler;
 import android.os.SystemClock;
 import android.text.TextUtils;
@@ -673,22 +674,22 @@ public class BrowserToolbar implements V
         // the "Enter Search or Address" placeholder text
         if (tab != null && "about:home".equals(tab.getURL()))
             title = null;
 
         mTitle.setText(title);
         mAwesomeBar.setContentDescription(title != null ? title : mTitle.getHint());
     }
 
-    public void setFavicon(Drawable image) {
+    public void setFavicon(Bitmap image) {
         if (Tabs.getInstance().getSelectedTab().getState() == Tab.STATE_LOADING)
             return;
 
         if (image != null)
-            mFavicon.setImageDrawable(image);
+            mFavicon.setImageBitmap(image);
         else
             mFavicon.setImageResource(R.drawable.favicon);
     }
     
     public void setSecurityMode(String mode) {
         mShowSiteSecurity = true;
 
         if (mode.equals(SiteIdentityPopup.IDENTIFIED)) {
--- a/mobile/android/base/Favicons.java
+++ b/mobile/android/base/Favicons.java
@@ -16,16 +16,17 @@ import org.apache.http.entity.BufferedHt
 import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.Context;
 import android.database.Cursor;
 import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteOpenHelper;
 import android.database.sqlite.SQLiteQueryBuilder;
 import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.net.http.AndroidHttpClient;
 import android.os.AsyncTask;
 import android.util.Log;
 
 import java.io.InputStream;
 import java.net.MalformedURLException;
@@ -43,22 +44,22 @@ public class Favicons {
 
     public static final long NOT_LOADING = 0;
 
     private Context mContext;
     private DatabaseHelper mDbHelper;
 
     private Map<Long,LoadFaviconTask> mLoadTasks;
     private long mNextFaviconLoadId;
-    private LruCache<String, Drawable> mFaviconsCache;
+    private LruCache<String, Bitmap> mFaviconsCache;
     private static final String USER_AGENT = GeckoApp.mAppContext.getDefaultUAString();
     private AndroidHttpClient mHttpClient;
 
     public interface OnFaviconLoadedListener {
-        public void onFaviconLoaded(String url, Drawable favicon);
+        public void onFaviconLoaded(String url, Bitmap favicon);
     }
 
     private class DatabaseHelper extends SQLiteOpenHelper {
         private static final String DATABASE_NAME = "favicon_urls.db";
         private static final String TABLE_NAME = "favicon_urls";
         private static final int DATABASE_VERSION = 1;
 
         private static final String COLUMN_ID = "_id";
@@ -139,34 +140,33 @@ public class Favicons {
 
         mContext = context;
         mDbHelper = new DatabaseHelper(context);
 
         mLoadTasks = Collections.synchronizedMap(new HashMap<Long,LoadFaviconTask>());
         mNextFaviconLoadId = 0;
 
         // Create a favicon memory cache that have up to 1mb of size
-        mFaviconsCache = new LruCache<String, Drawable>(1024 * 1024) {
+        mFaviconsCache = new LruCache<String, Bitmap>(1024 * 1024) {
             @Override
-            protected int sizeOf(String url, Drawable image) {
-                Bitmap bitmap = ((BitmapDrawable) image).getBitmap();
-                return bitmap.getRowBytes() * bitmap.getHeight();
+            protected int sizeOf(String url, Bitmap image) {
+                return image.getRowBytes() * image.getHeight();
             }
         };
     }
 
     private synchronized AndroidHttpClient getHttpClient() {
         if (mHttpClient != null)
             return mHttpClient;
 
         mHttpClient = AndroidHttpClient.newInstance(USER_AGENT);
         return mHttpClient;
     }
 
-    private void dispatchResult(final String pageUrl, final Drawable image,
+    private void dispatchResult(final String pageUrl, final Bitmap image,
             final OnFaviconLoadedListener listener) {
         if (pageUrl != null && image != null)
             putFaviconInMemCache(pageUrl, image);
 
         // We want to always run the listener on UI thread
         GeckoAppShell.getMainHandler().post(new Runnable() {
             public void run() {
                 if (listener != null)
@@ -184,37 +184,37 @@ public class Favicons {
 
         // Handle the case where page url is empty
         if (pageUrl == null || pageUrl.length() == 0) {
             dispatchResult(null, null, listener);
             return -1;
         }
 
         // Check if favicon is mem cached
-        Drawable image = getFaviconFromMemCache(pageUrl);
+        Bitmap image = getFaviconFromMemCache(pageUrl);
         if (image != null) {
             dispatchResult(pageUrl, image, listener);
             return -1;
         }
 
         LoadFaviconTask task = new LoadFaviconTask(pageUrl, faviconUrl, persist, listener);
 
         long taskId = task.getId();
         mLoadTasks.put(taskId, task);
 
         task.execute();
 
         return taskId;
     }
 
-    public Drawable getFaviconFromMemCache(String pageUrl) {
+    public Bitmap getFaviconFromMemCache(String pageUrl) {
         return mFaviconsCache.get(pageUrl);
     }
 
-    public void putFaviconInMemCache(String pageUrl, Drawable image) {
+    public void putFaviconInMemCache(String pageUrl, Bitmap image) {
         mFaviconsCache.put(pageUrl, image);
     }
 
     public void clearMemCache() {
         mFaviconsCache.evictAll();
     }
 
     public boolean cancelFaviconLoad(long taskId) {
@@ -249,17 +249,17 @@ public class Favicons {
                 long taskId = iter.next();
                 cancelFaviconLoad(taskId);
             }
         }
         if (mHttpClient != null)
             mHttpClient.close();
     }
 
-    private class LoadFaviconTask extends AsyncTask<Void, Void, BitmapDrawable> {
+    private class LoadFaviconTask extends AsyncTask<Void, Void, Bitmap> {
         private long mId;
         private String mPageUrl;
         private String mFaviconUrl;
         private OnFaviconLoadedListener mListener;
         private boolean mPersist;
 
         public LoadFaviconTask(String pageUrl, String faviconUrl, boolean persist,
                 OnFaviconLoadedListener listener) {
@@ -269,43 +269,42 @@ public class Favicons {
 
             mPageUrl = pageUrl;
             mFaviconUrl = faviconUrl;
             mListener = listener;
             mPersist = persist;
         }
 
         // Runs in background thread
-        private BitmapDrawable loadFaviconFromDb() {
+        private Bitmap loadFaviconFromDb() {
             ContentResolver resolver = mContext.getContentResolver();
-            BitmapDrawable favicon = BrowserDB.getFaviconForUrl(resolver, mPageUrl);
-
-            return favicon;
+            return BrowserDB.getFaviconForUrl(resolver, mPageUrl);
         }
 
         // Runs in background thread
-        private void saveFaviconToDb(BitmapDrawable favicon) {
+        private void saveFaviconToDb(Bitmap favicon) {
             if (!mPersist) {
                 return;
             }
 
             // since the Async task can run this on any number of threads in the
             // pool, we need to protect against inserting the same url twice
             synchronized(mDbHelper) {
                 ContentResolver resolver = mContext.getContentResolver();
                 BrowserDB.updateFaviconForUrl(resolver, mPageUrl, favicon);
 
                 mDbHelper.setFaviconUrlForPageUrl(mPageUrl, mFaviconUrl);
             }
         }
 
         // Runs in background thread
-        private BitmapDrawable downloadFavicon(URL faviconUrl) {
+        private Bitmap downloadFavicon(URL faviconUrl) {
             if (mFaviconUrl.startsWith("jar:jar:")) {
-                return GeckoJarReader.getBitmapDrawable(mContext.getResources(), mFaviconUrl);
+                BitmapDrawable d = GeckoJarReader.getBitmapDrawable(mContext.getResources(), mFaviconUrl);
+                return d.getBitmap();
             }
 
             URI uri;
             try {
                 uri = faviconUrl.toURI();
             } catch (URISyntaxException e) {
                 Log.d(LOGTAG, "Could not get URI for favicon");
                 return null;
@@ -313,33 +312,33 @@ public class Favicons {
 
             // only get favicons for HTTP/HTTPS
             String scheme = uri.getScheme();
             if (!"http".equals(scheme) && !"https".equals(scheme))
                 return null;
 
             // skia decoder sometimes returns null; workaround is to use BufferedHttpEntity
             // http://groups.google.com/group/android-developers/browse_thread/thread/171b8bf35dbbed96/c3ec5f45436ceec8?lnk=raot 
-            BitmapDrawable image = null;
+            Bitmap image = null;
             try {
                 HttpGet request = new HttpGet(faviconUrl.toURI());
                 HttpEntity entity = getHttpClient().execute(request).getEntity();
                 BufferedHttpEntity bufferedEntity = new BufferedHttpEntity(entity);
                 InputStream contentStream = bufferedEntity.getContent();
-                image = (BitmapDrawable) Drawable.createFromStream(contentStream, "src");
+                image = BitmapFactory.decodeStream(contentStream);
             } catch (Exception e) {
                 Log.e(LOGTAG, "Error reading favicon", e);
             }
 
             return image;
         }
 
         @Override
-        protected BitmapDrawable doInBackground(Void... unused) {
-            BitmapDrawable image = null;
+        protected Bitmap doInBackground(Void... unused) {
+            Bitmap image = null;
 
             if (isCancelled())
                 return null;
 
             URL faviconUrl = null;
 
             // Handle the case of malformed favicon URL
             try {
@@ -377,17 +376,17 @@ public class Favicons {
             if (image != null) {
                 saveFaviconToDb(image);
             }
 
             return image;
         }
 
         @Override
-        protected void onPostExecute(final BitmapDrawable image) {
+        protected void onPostExecute(final Bitmap image) {
             mLoadTasks.remove(mId);
             dispatchResult(mPageUrl, image, mListener);
         }
 
         @Override
         protected void onCancelled() {
             mLoadTasks.remove(mId);
 
--- a/mobile/android/base/GeckoApp.java
+++ b/mobile/android/base/GeckoApp.java
@@ -41,17 +41,16 @@ import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.content.pm.Signature;
 import android.content.res.Configuration;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.Color;
 import android.graphics.PointF;
 import android.graphics.Rect;
-import android.graphics.drawable.BitmapDrawable;
 import android.hardware.Sensor;
 import android.hardware.SensorEvent;
 import android.hardware.SensorEventListener;
 import android.location.Location;
 import android.location.LocationListener;
 import android.net.Uri;
 import android.os.Build;
 import android.os.Bundle;
@@ -2741,19 +2740,19 @@ abstract public class GeckoApp
                 }
                 return true;
             }
             case R.id.add_to_launcher: {
                 Tab tab = Tabs.getInstance().getSelectedTab();
                 if (tab != null) {
                     String url = tab.getURL();
                     String title = tab.getDisplayTitle();
-                    BitmapDrawable favicon = (BitmapDrawable)(tab.getFavicon());
+                    Bitmap favicon = tab.getFavicon();
                     if (url != null && title != null) {
-                        GeckoAppShell.createShortcut(title, url, url, favicon == null ? null : favicon.getBitmap(), "");
+                        GeckoAppShell.createShortcut(title, url, url, favicon == null ? null : favicon, "");
                     }
                 }
                 return true;
             }
         }
         return false;
     }
 
--- a/mobile/android/base/Tab.java
+++ b/mobile/android/base/Tab.java
@@ -36,17 +36,17 @@ import java.util.regex.Pattern;
 public class Tab {
     private static final String LOGTAG = "GeckoTab";
 
     private static Pattern sColorPattern;
     private final int mId;
     private long mLastUsed;
     private String mUrl;
     private String mTitle;
-    private Drawable mFavicon;
+    private Bitmap mFavicon;
     private String mFaviconUrl;
     private int mFaviconSize;
     private JSONObject mIdentityData;
     private boolean mReaderEnabled;
     private BitmapDrawable mThumbnail;
     private int mHistoryIndex;
     private int mHistorySize;
     private int mParentId;
@@ -142,17 +142,17 @@ public class Tab {
     public String getDisplayTitle() {
         if (mTitle != null && mTitle.length() > 0) {
             return mTitle;
         }
 
         return mUrl;
     }
 
-    public Drawable getFavicon() {
+    public Bitmap getFavicon() {
         return mFavicon;
     }
 
     public Drawable getThumbnail() {
         return mThumbnail;
     }
 
     synchronized public ByteBuffer getThumbnailBuffer() {
@@ -320,17 +320,17 @@ public class Tab {
     public void setFaviconLoadId(long faviconLoadId) {
         mFaviconLoadId = faviconLoadId;
     }
 
     public long getFaviconLoadId() {
         return mFaviconLoadId;
     }
 
-    public void updateFavicon(Drawable favicon) {
+    public void updateFavicon(Bitmap favicon) {
         mFavicon = favicon;
     }
 
     public synchronized void updateFaviconURL(String faviconUrl, int size) {
         // If we already have an "any" sized icon, don't update the icon.
         if (mFaviconSize == -1)
             return;
 
--- a/mobile/android/base/awesomebar/AllPagesTab.java
+++ b/mobile/android/base/awesomebar/AllPagesTab.java
@@ -17,17 +17,16 @@ import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
 
 import android.app.Activity;
 import android.content.Context;
 import android.database.Cursor;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
-import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.AsyncTask;
 import android.os.Handler;
 import android.os.Message;
 import android.os.SystemClock;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.animation.AccelerateInterpolator;
@@ -264,21 +263,20 @@ public class AllPagesTab extends Awesome
             String keyword = null;
             int keywordCol = mCursor.getColumnIndex(URLColumns.KEYWORD);
             if (keywordCol != -1)
                 keyword = mCursor.getString(keywordCol);
 
             final String url = mCursor.getString(mCursor.getColumnIndexOrThrow(URLColumns.URL));
 
             Favicons favicons = GeckoApp.mAppContext.getFavicons();
-            Drawable faviconDrawable = favicons.getFaviconFromMemCache(url);
+            Bitmap bitmap = favicons.getFaviconFromMemCache(url);
             byte[] favicon = null;
 
-            if (faviconDrawable != null) {
-                Bitmap bitmap = ((BitmapDrawable) faviconDrawable).getBitmap();
+            if (bitmap != null) {
                 ByteArrayOutputStream stream = new ByteArrayOutputStream();
                 bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
                 favicon = stream.toByteArray();
             }
 
             return new ContextMenuSubject(id, url, favicon,
                                           mCursor.getString(mCursor.getColumnIndexOrThrow(URLColumns.TITLE)),
                                           keyword,
@@ -777,18 +775,17 @@ public class AllPagesTab extends Awesome
                 final byte[] b = c.getBlob(c.getColumnIndexOrThrow(Images.FAVICON));
                 if (b == null)
                     continue;
 
                 Bitmap favicon = BitmapFactory.decodeByteArray(b, 0, b.length);
                 if (favicon == null)
                     continue;
 
-                Drawable faviconDrawable = new BitmapDrawable(getResources(), favicon);
-                favicons.putFaviconInMemCache(url, faviconDrawable);
+                favicons.putFaviconInMemCache(url, favicon);
             } while (c.moveToNext());
         } finally {
             if (c != null)
                 c.close();
         }
     }
 
     private void loadFaviconsForCurrentResults() {
@@ -808,17 +805,17 @@ public class AllPagesTab extends Awesome
                 postUpdateFavicons();
             }
         }).execute();
     }
 
     private void displayFavicon(AwesomeEntryViewHolder viewHolder) {
         final String url = viewHolder.urlView.getText().toString();
         Favicons favicons = GeckoApp.mAppContext.getFavicons();
-        viewHolder.faviconView.setImageDrawable(favicons.getFaviconFromMemCache(url));
+        viewHolder.faviconView.setImageBitmap(favicons.getFaviconFromMemCache(url));
     }
 
     private void updateFavicons() {
         ListView listView = (ListView) mView;
         for (int i = 0; i < listView.getChildCount(); i++) {
             final View view = listView.getChildAt(i);
             final Object tag = view.getTag();
 
--- a/mobile/android/base/db/BrowserDB.java
+++ b/mobile/android/base/db/BrowserDB.java
@@ -5,16 +5,17 @@
 
 package org.mozilla.gecko.db;
 
 import org.mozilla.gecko.db.BrowserContract.ExpirePriority;
 
 import android.content.ContentResolver;
 import android.database.ContentObserver;
 import android.database.Cursor;
+import android.graphics.Bitmap;
 import android.graphics.drawable.BitmapDrawable;
 
 import java.util.List;
 
 public class BrowserDB {
     public static String ABOUT_PAGES_URL_FILTER = "about:%";
 
     public static interface URLColumns {
@@ -68,21 +69,21 @@ public class BrowserDB {
         public void removeBookmarksWithURL(ContentResolver cr, String uri);
 
         public void updateBookmark(ContentResolver cr, int id, String uri, String title, String keyword);
 
         public void addReadingListItem(ContentResolver cr, String title, String uri);
 
         public void removeReadingListItemWithURL(ContentResolver cr, String uri);
 
-        public BitmapDrawable getFaviconForUrl(ContentResolver cr, String uri);
+        public Bitmap getFaviconForUrl(ContentResolver cr, String uri);
 
         public Cursor getFaviconsForUrls(ContentResolver cr, List<String> urls);
 
-        public void updateFaviconForUrl(ContentResolver cr, String uri, BitmapDrawable favicon);
+        public void updateFaviconForUrl(ContentResolver cr, String uri, Bitmap favicon);
 
         public void updateThumbnailForUrl(ContentResolver cr, String uri, BitmapDrawable thumbnail);
 
         public byte[] getThumbnailForUrl(ContentResolver cr, String uri);
 
         public Cursor getThumbnailsForUrls(ContentResolver cr, List<String> urls);
 
         public void removeThumbnails(ContentResolver cr);
@@ -185,25 +186,25 @@ public class BrowserDB {
     public static void addReadingListItem(ContentResolver cr, String title, String uri) {
         sDb.addReadingListItem(cr, title, uri);
     }
 
     public static void removeReadingListItemWithURL(ContentResolver cr, String uri) {
         sDb.removeReadingListItemWithURL(cr, uri);
     }
 
-    public static BitmapDrawable getFaviconForUrl(ContentResolver cr, String uri) {
+    public static Bitmap getFaviconForUrl(ContentResolver cr, String uri) {
         return sDb.getFaviconForUrl(cr, uri);
     }
 
     public static Cursor getFaviconsForUrls(ContentResolver cr, List<String> urls) {
         return sDb.getFaviconsForUrls(cr, urls);
     }
 
-    public static void updateFaviconForUrl(ContentResolver cr, String uri, BitmapDrawable favicon) {
+    public static void updateFaviconForUrl(ContentResolver cr, String uri, Bitmap favicon) {
         sDb.updateFaviconForUrl(cr, uri, favicon);
     }
 
     public static void updateThumbnailForUrl(ContentResolver cr, String uri, BitmapDrawable thumbnail) {
         sDb.updateThumbnailForUrl(cr, uri, thumbnail);
     }
 
     public static byte[] getThumbnailForUrl(ContentResolver cr, String uri) {
--- a/mobile/android/base/db/LocalBrowserDB.java
+++ b/mobile/android/base/db/LocalBrowserDB.java
@@ -621,17 +621,17 @@ public class LocalBrowserDB implements B
         values.put(Bookmarks.KEYWORD, keyword);
 
         cr.update(mBookmarksUriWithProfile,
                   values,
                   Bookmarks._ID + " = ?",
                   new String[] { String.valueOf(id) });
     }
 
-    public BitmapDrawable getFaviconForUrl(ContentResolver cr, String uri) {
+    public Bitmap getFaviconForUrl(ContentResolver cr, String uri) {
         Cursor c = cr.query(mImagesUriWithProfile,
                             new String[] { Images.FAVICON },
                             Images.URL + " = ?",
                             new String[] { uri },
                             null);
 
         if (!c.moveToFirst()) {
             c.close();
@@ -641,18 +641,17 @@ public class LocalBrowserDB implements B
         int faviconIndex = c.getColumnIndexOrThrow(Images.FAVICON);
 
         byte[] b = c.getBlob(faviconIndex);
         c.close();
 
         if (b == null)
             return null;
 
-        Bitmap bitmap = BitmapFactory.decodeByteArray(b, 0, b.length);
-        return new BitmapDrawable(bitmap);
+        return BitmapFactory.decodeByteArray(b, 0, b.length);
     }
 
     public Cursor getFaviconsForUrls(ContentResolver cr, List<String> urls) {
         StringBuffer selection = new StringBuffer();
         String[] selectionArgs = new String[urls.size()];
 
         for (int i = 0; i < urls.size(); i++) {
           final String url = urls.get(i);
@@ -667,23 +666,19 @@ public class LocalBrowserDB implements B
         return cr.query(mImagesUriWithProfile,
                         new String[] { Images.URL, Images.FAVICON },
                         selection.toString(),
                         selectionArgs,
                         null);
     }
 
     public void updateFaviconForUrl(ContentResolver cr, String uri,
-            BitmapDrawable favicon) {
-        Bitmap bitmap = favicon.getBitmap();
-        if (bitmap == null)
-            return;
-
+            Bitmap favicon) {
         ByteArrayOutputStream stream = new ByteArrayOutputStream();
-        bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
+        favicon.compress(Bitmap.CompressFormat.PNG, 100, stream);
 
         ContentValues values = new ContentValues();
         values.put(Images.FAVICON, stream.toByteArray());
         values.put(Images.URL, uri);
 
         // Restore deleted record if possible
         values.put(Images.IS_DELETED, 0);