diff --git a/mobile/android/base/tests/robocop.ini b/mobile/android/base/tests/robocop.ini
index 58c99b15773e..81a485119ff0 100644
--- a/mobile/android/base/tests/robocop.ini
+++ b/mobile/android/base/tests/robocop.ini
@@ -19,6 +19,7 @@
[testFormHistory]
[testBrowserProvider]
[testSearchSuggestions]
+[testThumbnails]
# [testPermissions] # see bug 757475
# [testJarReader] # see bug 738890
diff --git a/mobile/android/base/tests/robocop_404.sjs b/mobile/android/base/tests/robocop_404.sjs
new file mode 100644
index 000000000000..10e1c4945efc
--- /dev/null
+++ b/mobile/android/base/tests/robocop_404.sjs
@@ -0,0 +1,28 @@
+/**
+ * Used with testThumbnails.
+ * On the first visit, the page is green.
+ * On subsequent visits, the page is red.
+ */
+
+function handleRequest(request, response) {
+ let type = request.queryString.match(/^type=(.*)$/)[1];
+ let state = "thumbnails." + type;
+ let color = "#0f0";
+ let status = 200;
+
+ if (getState(state)) {
+ color = "#f00";
+ if (type == "do404")
+ status = 404;
+ } else {
+ setState(state, "1");
+ }
+
+ response.setStatusLine(request.httpVersion, status, null);
+ response.setHeader("Content-Type", "text/html", false);
+ response.setHeader("Cache-Control", "no-cache", false);
+ response.write('');
+ response.write('
' + type + '');
+ response.write('');
+ response.write('');
+}
diff --git a/mobile/android/base/tests/testThumbnails.java.in b/mobile/android/base/tests/testThumbnails.java.in
new file mode 100644
index 000000000000..34d905b04b4e
--- /dev/null
+++ b/mobile/android/base/tests/testThumbnails.java.in
@@ -0,0 +1,99 @@
+#filter substitution
+package @ANDROID_PACKAGE_NAME@.tests;
+
+import @ANDROID_PACKAGE_NAME@.*;
+import android.app.Activity;
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.graphics.drawable.BitmapDrawable;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+/**
+ * Test for thumbnail updates.
+ * - loads 2 pages, each of which yield an HTTP 200
+ * - verifies thumbnails are updated for both pages
+ * - loads pages again; first page yields HTTP 200, second yields HTTP 404
+ * - verifies thumbnail is updated for HTTP 200, but not HTTP 404
+ */
+public class testThumbnails extends BaseTest {
+ private int mTopSitesId;
+ private int mThumbnailId;
+ private int mTitleId;
+
+ @Override
+ protected int getTestType() {
+ return TEST_MOCHITEST;
+ }
+
+ public void testThumbnails() {
+ mTopSitesId = mDriver.findElement(getActivity(), "top_sites_grid").getId();
+ mThumbnailId = mDriver.findElement(getActivity(), "thumbnail").getId();
+ mTitleId = mDriver.findElement(getActivity(), "title").getId();
+
+ final String site1Url = getAbsoluteUrl("/robocop/robocop_404.sjs?type=changeColor");
+ final String site2Url = getAbsoluteUrl("/robocop/robocop_404.sjs?type=do404");
+ final String site1Title = "changeColor";
+ final String site2Title = "do404";
+
+ // the session snapshot runnable is run 500ms after document stop. a
+ // 3000ms delay gives us 2.5 seconds to take the screenshot, which
+ // should be plenty of time, even on slow devices
+ final int thumbnailDelay = 3000;
+
+ mActions.expectGeckoEvent("Gecko:Ready").blockForEvent();
+
+ // load sites; both will return HTTP 200 with a green background
+ loadUrl(site1Url);
+ mSolo.sleep(thumbnailDelay);
+ loadUrl(site2Url);
+ mSolo.sleep(thumbnailDelay);
+ loadUrl("about:home");
+ waitForTest(new ThumbnailTest(site1Title, Color.GREEN), 5000);
+ mAsserter.is(getTopSiteThumbnailColor(site1Title), Color.GREEN, "Top site thumbnail updated for HTTP 200");
+ waitForTest(new ThumbnailTest(site2Title, Color.GREEN), 5000);
+ mAsserter.is(getTopSiteThumbnailColor(site2Title), Color.GREEN, "Top site thumbnail updated for HTTP 200");
+
+ // load sites again; both will have red background, and do404 will return HTTP 404
+ loadUrl(site1Url);
+ mSolo.sleep(thumbnailDelay);
+ loadUrl(site2Url);
+ mSolo.sleep(thumbnailDelay);
+ loadUrl("about:home");
+ waitForTest(new ThumbnailTest(site1Title, Color.RED), 5000);
+ mAsserter.is(getTopSiteThumbnailColor(site1Title), Color.RED, "Top site thumbnail updated for HTTP 200");
+ waitForTest(new ThumbnailTest(site2Title, Color.GREEN), 5000);
+ mAsserter.is(getTopSiteThumbnailColor(site2Title), Color.GREEN, "Top site thumbnail not updated for HTTP 404");
+ }
+
+ private class ThumbnailTest implements BooleanTest {
+ private String mTitle;
+ private int mColor;
+
+ public ThumbnailTest(String title, int color) {
+ mTitle = title;
+ mColor = color;
+ }
+
+ public boolean test() {
+ return getTopSiteThumbnailColor(mTitle) == mColor;
+ }
+ }
+
+ private int getTopSiteThumbnailColor(String title) {
+ ViewGroup topSites = (ViewGroup) getActivity().findViewById(mTopSitesId);
+ final int childCount = topSites.getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ View child = topSites.getChildAt(i);
+ TextView titleView = (TextView) child.findViewById(mTitleId);
+ if (titleView.getText().equals(title)) {
+ ImageView thumbnailView = (ImageView) child.findViewById(mThumbnailId);
+ Bitmap thumbnail = ((BitmapDrawable) thumbnailView.getDrawable()).getBitmap();
+ return thumbnail.getPixel(0, 0);
+ }
+ }
+ return -1;
+ }
+}