bug 711543 - Get thumbnail images of tabs loaded in the background, and display them in the tab menu r=mfinkle
--- 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);