Bug 870100 (part 1) - regenerate stale page thumbnails on demand, and send notification when done. r=adw

This commit is contained in:
Mark Hammond 2013-06-24 14:32:32 -04:00
parent 5a9a006392
commit 9236afae00
4 changed files with 94 additions and 1 deletions

View File

@ -17,6 +17,11 @@ const LATEST_STORAGE_VERSION = 3;
const EXPIRATION_MIN_CHUNK_SIZE = 50;
const EXPIRATION_INTERVAL_SECS = 3600;
// If a request for a thumbnail comes in and we find one that is "stale"
// (or don't find one at all) we automatically queue a request to generate a
// new one.
const MAX_THUMBNAIL_AGE_SECS = 172800; // 2 days == 60*60*24*2 == 172800 secs.
/**
* Name of the directory in the profile that contains the thumbnails.
*/
@ -180,6 +185,26 @@ this.PageThumbs = {
"?url=" + encodeURIComponent(aUrl);
},
/**
* Checks if an existing thumbnail for the specified URL is either missing
* or stale, and if so, queues a background request to capture it. That
* capture process will send a notification via the observer service on
* capture, so consumers should watch for such observations if they want to
* be notified of an updated thumbnail.
*/
captureIfStale: function PageThumbs_captureIfStale(aUrl) {
let filePath = PageThumbsStorage.getFilePathForURL(aUrl);
PageThumbsWorker.post("isFileRecent", [filePath, MAX_THUMBNAIL_AGE_SECS]
).then(result => {
if (!result.ok) {
// Sadly there is currently a circular dependency between this module
// and BackgroundPageThumbs, so do the import locally.
let BPT = Cu.import("resource://gre/modules/BackgroundPageThumbs.jsm", {}).BackgroundPageThumbs;
BPT.capture(aUrl);
}
});
},
/**
* Captures a thumbnail for the given window.
* @param aWindow The DOM window to capture a thumbnail from.
@ -310,6 +335,7 @@ this.PageThumbs = {
Services.telemetry.getHistogramById("FX_THUMBNAILS_STORE_TIME_MS")
.add(new Date() - telemetryStoreTime);
Services.obs.notifyObservers(null, "page-thumbnail:create", aFinalURL);
// We've been redirected. Create a copy of the current thumbnail for
// the redirect source. We need to do this because:
//
@ -321,8 +347,10 @@ this.PageThumbs = {
// 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 (aFinalURL != aOriginalURL)
if (aFinalURL != aOriginalURL) {
yield PageThumbsStorage.copy(aFinalURL, aOriginalURL);
Services.obs.notifyObservers(null, "page-thumbnail:create", aOriginalURL);
}
});
},

View File

@ -53,6 +53,20 @@ self.onmessage = function onmessage(msg) {
let Agent = {
// Checks if the specified file exists and has an age less than as
// specifed (in seconds).
isFileRecent: function Agent_isFileRecent(path, maxAge) {
try {
let stat = OS.File.stat(path);
let maxDate = new Date();
maxDate.setSeconds(maxDate.getSeconds() - maxAge);
return stat.lastModificationDate > maxDate;
} catch (ex if ex instanceof OS.File.Error) {
// file doesn't exist (or can't be stat'd) - must be stale.
return false;
}
},
remove: function Agent_removeFile(path) {
try {
OS.File.remove(path);

View File

@ -20,6 +20,7 @@ MOCHITEST_BROWSER_FILES := \
browser_thumbnails_storage_migrate3.js \
browser_thumbnails_bug726727.js \
browser_thumbnails_bug727765.js \
browser_thumbnails_update.js \
head.js \
background_red.html \
background_red_scroll.html \

View File

@ -0,0 +1,50 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* These tests check the auto-update facility of the thumbnail service.
*/
let numNotifications = 0;
const URL = "data:text/html;charset=utf-8,<body%20bgcolor=ff0000></body>";
function observe(subject, topic, data) {
is(topic, "page-thumbnail:create", "got expected topic");
is(data, URL, "data is our test URL");
if (++numNotifications == 2) {
// This is the final notification and signals test success...
Services.obs.removeObserver(observe, "page-thumbnail:create");
next();
}
}
function runTests() {
Services.obs.addObserver(observe, "page-thumbnail:create", false);
// Create a tab with a red background.
yield addTab(URL);
let browser = gBrowser.selectedBrowser;
// Capture the screenshot.
PageThumbs.captureAndStore(browser, function () {
// We've got a capture so should have seen the observer.
is(numNotifications, 1, "got notification of item being created.");
// The capture is now "fresh" - so requesting the URL should not cause
// a new capture.
PageThumbs.captureIfStale(URL);
is(numNotifications, 1, "still only 1 notification of item being created.");
// Now we will go behind the back of the thumbnail service and change the
// mtime of the file to be in the past.
let fname = PageThumbsStorage.getFilePathForURL(URL);
let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
file.initWithPath(fname);
ok(file.exists(), fname + " doesn't exist");
// Set it as very stale...
file.lastModifiedTime = Date.now() - 1000000000;
// Ask for it to be updated.
PageThumbs.captureIfStale(URL);
// But it's async, so wait - our observer above will call next() when
// the notification comes.
});
yield undefined; // wait for callbacks to call 'next'...
}