Bug 705911 - [Page Thumbnails] Save screenshots of redirecting sites; r=dao

This commit is contained in:
Tim Taubert 2012-03-23 19:12:43 +01:00
parent 67144f3d55
commit d25f887da9
6 changed files with 160 additions and 16 deletions

View File

@ -110,6 +110,9 @@ let PageThumbs = {
*/
captureAndStore: function PageThumbs_captureAndStore(aBrowser, aCallback) {
let url = aBrowser.currentURI.spec;
let channel = aBrowser.docShell.currentDocumentChannel;
let originalURL = channel.originalURI.spec;
this.capture(aBrowser.contentWindow, function (aInputStream) {
let telemetryStoreTime = new Date();
@ -117,6 +120,20 @@ let PageThumbs = {
if (aSuccessful) {
Services.telemetry.getHistogramById("FX_THUMBNAILS_STORE_TIME_MS")
.add(new Date() - telemetryStoreTime);
// We've been redirected. Create a copy of the current thumbnail for
// the redirect source. We need to do this because:
//
// 1) Users can drag any kind of links onto the newtab page. If those
// links redirect to a different URL then we want to be able to
// provide thumbnails for both of them.
//
// 2) The newtab page should actually display redirect targets, only.
// Because of bug 559175 this information can get lost when using
// Sync and therefore also redirect sources appear on the newtab
// page. We also want thumbnails for those.
if (url != originalURL)
PageThumbsCache._copy(url, originalURL);
}
if (aCallback)
@ -206,6 +223,54 @@ let PageThumbsCache = {
this._openCacheEntry(aKey, Ci.nsICache.ACCESS_WRITE, aCallback);
},
/**
* Copies an existing cache entry's data to a new cache entry.
* @param aSourceKey The key that contains the data to copy.
* @param aTargetKey The key that will be the copy of aSourceKey's data.
*/
_copy: function Cache_copy(aSourceKey, aTargetKey) {
let sourceEntry, targetEntry, waitingCount = 2;
function finish() {
if (sourceEntry)
sourceEntry.close();
if (targetEntry)
targetEntry.close();
}
function copyDataWhenReady() {
if (--waitingCount > 0)
return;
if (!sourceEntry || !targetEntry) {
finish();
return;
}
let inputStream = sourceEntry.openInputStream(0);
let outputStream = targetEntry.openOutputStream(0);
// Copy the image data to a new entry.
NetUtil.asyncCopy(inputStream, outputStream, function (aResult) {
if (Components.isSuccessCode(aResult))
targetEntry.markValid();
finish();
});
}
this.getReadEntry(aSourceKey, function (aSourceEntry) {
sourceEntry = aSourceEntry;
copyDataWhenReady();
});
this.getWriteEntry(aTargetKey, function (aTargetEntry) {
targetEntry = aTargetEntry;
copyDataWhenReady();
});
},
/**
* Opens the cache entry identified by the given key.
* @param aKey The key identifying the desired cache entry.

View File

@ -13,8 +13,11 @@ include $(topsrcdir)/config/rules.mk
_BROWSER_FILES = \
browser_thumbnails_capture.js \
browser_thumbnails_redirect.js \
browser_thumbnails_bug726727.js \
head.js \
background_red.html \
background_red_redirect.sjs \
$(NULL)
libs:: $(_BROWSER_FILES)

View File

@ -0,0 +1,3 @@
<html>
<body bgcolor=ff0000></body>
</html>

View File

@ -0,0 +1,10 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
function handleRequest(aRequest, aResponse) {
// Set HTTP Status.
aResponse.setStatusLine(aRequest.httpVersion, 301, "Moved Permanently");
// Set redirect URI.
aResponse.setHeader("Location", "http://mochi.test:8888/browser/browser/components/thumbnails/test/background_red.html");
}

View File

@ -0,0 +1,51 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
const URL = "http://mochi.test:8888/browser/browser/components/thumbnails/" +
"test/background_red_redirect.sjs";
let cacheService = Cc["@mozilla.org/network/cache-service;1"]
.getService(Ci.nsICacheService);
/**
* These tests ensure that we save and provide thumbnails for redirecting sites.
*/
function runTests() {
// Kick off history by loading a tab first or the test fails in single mode.
yield addTab(URL);
gBrowser.removeTab(gBrowser.selectedTab);
// Create a tab, redirecting to a page with a red background.
yield addTab(URL);
yield captureAndCheckColor(255, 0, 0, "we have a red thumbnail");
// Wait until the referrer's thumbnail's cache entry has been written.
yield whenCacheEntryExists(URL);
yield checkThumbnailColor(URL, 255, 0, 0, "referrer has a red thumbnail");
}
function whenCacheEntryExists(aKey) {
let callback = next;
checkCacheEntryExists(aKey, function (aExists) {
if (!aExists)
callback = function () whenCacheEntryExists(aKey);
executeSoon(callback);
});
}
function checkCacheEntryExists(aKey, aCallback) {
PageThumbsCache.getReadEntry(aKey, function (aEntry) {
let inputStream = aEntry && aEntry.openInputStream(0);
let exists = inputStream && inputStream.available();
if (inputStream)
inputStream.close();
if (aEntry)
aEntry.close();
aCallback(exists);
});
}

View File

@ -98,26 +98,38 @@ function captureAndCheckColor(aRed, aGreen, aBlue, aMessage) {
// Capture the screenshot.
PageThumbs.captureAndStore(browser, function () {
let width = 100, height = 100;
let thumb = PageThumbs.getThumbnailURL(browser.currentURI.spec, width, height);
checkThumbnailColor(browser.currentURI.spec, aRed, aGreen, aBlue, aMessage);
});
}
getXULDocument(function (aDocument) {
let htmlns = "http://www.w3.org/1999/xhtml";
let img = aDocument.createElementNS(htmlns, "img");
img.setAttribute("src", thumb);
/**
* Retrieve a thumbnail from the cache and compare its pixel color values.
* @param aURL The URL of the thumbnail's page.
* @param aRed The red component's intensity.
* @param aGreen The green component's intensity.
* @param aBlue The blue component's intensity.
* @param aMessage The info message to print when comparing the pixel color.
*/
function checkThumbnailColor(aURL, aRed, aGreen, aBlue, aMessage) {
let width = 100, height = 100;
let thumb = PageThumbs.getThumbnailURL(aURL, width, height);
whenLoaded(img, function () {
let canvas = aDocument.createElementNS(htmlns, "canvas");
canvas.setAttribute("width", width);
canvas.setAttribute("height", height);
getXULDocument(function (aDocument) {
let htmlns = "http://www.w3.org/1999/xhtml";
let img = aDocument.createElementNS(htmlns, "img");
img.setAttribute("src", thumb);
// Draw the image to a canvas and compare the pixel color values.
let ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, width, height);
checkCanvasColor(ctx, aRed, aGreen, aBlue, aMessage);
whenLoaded(img, function () {
let canvas = aDocument.createElementNS(htmlns, "canvas");
canvas.setAttribute("width", width);
canvas.setAttribute("height", height);
next();
});
// Draw the image to a canvas and compare the pixel color values.
let ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, width, height);
checkCanvasColor(ctx, aRed, aGreen, aBlue, aMessage);
next();
});
});
}