bug 711543 - Get thumbnail images of tabs loaded in the background, and display them in the tab menu r=mfinkle
authorBrad Lassey <blassey@mozilla.com>
Mon, 16 Jan 2012 22:23:04 -0500
changeset 85997 5f522d3446578d5db2a2fc63bf32a2f43cdfc5f3
parent 85996 095649e65552b1ab61c63d81539f8b295effda42
child 85998 2f3527e85663a3eefca078c7696d4b4a7c6b464b
push idunknown
push userunknown
push dateunknown
reviewersmfinkle
bugs711543
milestone12.0a1
bug 711543 - Get thumbnail images of tabs loaded in the background, and display them in the tab menu r=mfinkle
mobile/android/base/GeckoApp.java
mobile/android/base/Tab.java
mobile/android/base/Tabs.java
mobile/android/base/TabsTray.java
--- a/mobile/android/base/GeckoApp.java
+++ b/mobile/android/base/GeckoApp.java
@@ -586,44 +586,54 @@ abstract public class GeckoApp
                     return;
 
                 ViewportMetrics viewportMetrics = mSoftwareLayerClient.getGeckoViewportMetrics();
                 if (viewportMetrics != null)
                     mLastViewport = viewportMetrics.toJSON();
 
                 mLastUri = lastHistoryEntry.mUri;
                 mLastTitle = lastHistoryEntry.mTitle;
-                Bitmap bitmap = mSoftwareLayerClient.getBitmap();
+                getAndProcessThumbnailForTab(tab);
+            }
+        }
+    }
+
+    void getAndProcessThumbnailForTab(Tab tab) {
+        Bitmap bitmap = null;
+        if (Tabs.getInstance().isSelectedTab(tab))
+            bitmap = mSoftwareLayerClient.getBitmap();
 
-                if (bitmap != null) {
-                    ByteArrayOutputStream bos = new ByteArrayOutputStream();
-                    bitmap.compress(Bitmap.CompressFormat.PNG, 0, bos);
-                    processThumbnail(tab, bitmap, bos.toByteArray());
-                } else {
-                    mLastScreen = null;
-                    GeckoAppShell.sendEventToGecko(
-                        new GeckoEvent("Tab:Screenshot", 
-                                       "{\"width\": \"" + mSoftwareLayerClient.getWidth() + "\", " +
-                                       "\"height\": \"" + mSoftwareLayerClient.getHeight() + "\", " +
-                                       "\"tabID\": \"" + tab.getId() + "\" }"));
-                }
-            }
+        if (bitmap != null) {
+            ByteArrayOutputStream bos = new ByteArrayOutputStream();
+            bitmap.compress(Bitmap.CompressFormat.PNG, 0, bos);
+            processThumbnail(tab, bitmap, bos.toByteArray());
+        } else {
+            mLastScreen = null;
+            GeckoAppShell.sendEventToGecko(
+                new GeckoEvent("Tab:Screenshot", 
+                               "{\"width\": \"" + mSoftwareLayerClient.getWidth() + "\", " +
+                               "\"height\": \"" + mSoftwareLayerClient.getHeight() + "\", " +
+                               "\"tabID\": \"" + tab.getId() + "\" }"));
         }
     }
     
     void processThumbnail(Tab thumbnailTab, Bitmap bitmap, byte[] compressed) {
         if (Tabs.getInstance().isSelectedTab(thumbnailTab))
             mLastScreen = compressed;
         if (thumbnailTab.getURL().equals("about:home")) {
             thumbnailTab.updateThumbnail(null);
             return;
         }
-        if (bitmap == null)
-            bitmap = BitmapFactory.decodeByteArray(compressed, 0, compressed.length);
-        thumbnailTab.updateThumbnail(bitmap);
+        try {
+            if (bitmap == null)
+                bitmap = BitmapFactory.decodeByteArray(compressed, 0, compressed.length);
+            thumbnailTab.updateThumbnail(bitmap);
+        } catch (OutOfMemoryError ome) {
+            Log.w(LOGTAG, "decoding byte array ran out of memory", ome);
+        }
     }
 
     private void maybeCancelFaviconLoad(Tab tab) {
         long faviconLoadId = tab.getFaviconLoadId();
 
         if (faviconLoadId == Favicons.NOT_LOADING)
             return;
 
--- a/mobile/android/base/Tab.java
+++ b/mobile/android/base/Tab.java
@@ -140,16 +140,17 @@ public final class Tab {
         return mFavicon;
     }
 
     public Drawable getThumbnail() {
         return mThumbnail;
     }
 
     public void updateThumbnail(final Bitmap b) {
+        final Tab tab = this;
         GeckoAppShell.getHandler().post(new Runnable() {
             public void run() {
                 if (sMinDim == 0) {
                     DisplayMetrics metrics = new DisplayMetrics();
                     GeckoApp.mAppContext.getWindowManager().getDefaultDisplay().getMetrics(metrics);
                     sMinDim = Math.min(metrics.widthPixels / 3, metrics.heightPixels / 2);
                     sDensity = metrics.density;
                 }
@@ -165,16 +166,21 @@ public final class Tab {
                         cropped.recycle();
                     } catch (OutOfMemoryError oom) {
                         Log.e(LOGTAG, "Unable to create/scale bitmap", oom);
                         mThumbnail = null;
                     }
                 } else {
                     mThumbnail = null;
                 }
+                GeckoApp.mAppContext.mMainHandler.post(new Runnable() {
+                    public void run() {
+                        GeckoApp.mAppContext.onTabsChanged(tab);
+                    }
+                });
             }
         });
     }
 
     public String getFaviconURL() {
         return mFaviconUrl;
     }
 
--- a/mobile/android/base/Tabs.java
+++ b/mobile/android/base/Tabs.java
@@ -211,9 +211,15 @@ public class Tabs implements GeckoEventL
                     event = event.substring("SessionHistory:".length());
                     tab.handleSessionHistoryMessage(event, message);
                 }
             }
         } catch (Exception e) { 
             Log.i(LOGTAG, "handleMessage throws " + e + " for message: " + event);
         }
     }
+
+    public void refreshThumbnails() {
+        Iterator<Tab> iterator = tabs.values().iterator();
+        while (iterator.hasNext())
+            GeckoApp.mAppContext.getAndProcessThumbnailForTab(iterator.next());
+    }
 }
--- a/mobile/android/base/TabsTray.java
+++ b/mobile/android/base/TabsTray.java
@@ -90,16 +90,17 @@ public class TabsTray extends Activity i
         
         LinearLayout container = (LinearLayout) findViewById(R.id.container);
         container.setOnClickListener(new Button.OnClickListener() {
             public void onClick(View v) {
                 finishActivity();
             }
         });
 
+        Tabs.getInstance().refreshThumbnails();
         GeckoApp.registerOnTabsChangedListener(this);
         onTabsChanged(null);
     }
 
     @Override
     public void onDestroy() {
         super.onDestroy();
         GeckoApp.unregisterOnTabsChangedListener(this);