Bug 1180715 (2/4) - Provide a nsIFileURL interface for thumbnails. review=ttaubert

Use nsISubstitutingProtocolHandler to return a SubstitutingURL and to
resolve the thumbnail URL to the backing nsIFile.

Now the image loader code will realise that moz-page-thumb:// URLs are
backed by a file and will be able to use the file mtime to evaluate
whether the cached imgRequest has expired.

* Implement the nsISubstitutingProtocolHandler methods in the thumbnail
protocol handler. The resolveURI method does all the work, the other
methods are just stubs.

* moz-page-thumb:// is now an URL rather than an URI, so update the
signature accordingly.

* Add xpcshell-test to affirm that SubstitutingURL::EnsureFile()
resolves the backing file correctly.

* Adjust the mochitest to account for the one second granularity of the
mtime tracking.
This commit is contained in:
Oliver Henshaw 2015-10-20 10:45:32 +05:30
parent b9c6244413
commit 99a9fbf8cb
6 changed files with 95 additions and 5 deletions

View File

@ -158,7 +158,7 @@ this.PageThumbs = {
*/
getThumbnailURL: function PageThumbs_getThumbnailURL(aUrl) {
return this.scheme + "://" + this.staticHost +
"?url=" + encodeURIComponent(aUrl);
"/?url=" + encodeURIComponent(aUrl);
},
/**

View File

@ -10,7 +10,7 @@
*
* URL structure:
*
* moz-page-thumb://thumbnail?url=http%3A%2F%2Fwww.mozilla.org%2F
* moz-page-thumb://thumbnail/?url=http%3A%2F%2Fwww.mozilla.org%2F
*
* This URL requests an image for 'http://www.mozilla.org/'.
*/
@ -24,14 +24,17 @@ const Ci = Components.interfaces;
Cu.import("resource://gre/modules/PageThumbs.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/osfile.jsm", this);
XPCOMUtils.defineLazyModuleGetter(this, "Services",
"resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
"resource://gre/modules/FileUtils.jsm");
const SUBSTITUTING_URL_CID = "{dea9657c-18cf-4984-bde9-ccef5d8ab473}";
/**
* Implements the thumbnail protocol handler responsible for moz-page-thumb: URIs.
* Implements the thumbnail protocol handler responsible for moz-page-thumb: URLs.
*/
function Protocol() {
}
@ -68,7 +71,7 @@ Protocol.prototype = {
* @return The newly created URI.
*/
newURI: function Proto_newURI(aSpec, aOriginCharset) {
let uri = Cc["@mozilla.org/network/simple-uri;1"].createInstance(Ci.nsIURI);
let uri = Components.classesByID[SUBSTITUTING_URL_CID].createInstance(Ci.nsIURL);
uri.spec = aSpec;
return uri;
},
@ -98,8 +101,37 @@ Protocol.prototype = {
*/
allowPort: () => false,
// nsISubstitutingProtocolHandler methods
/*
* Substituting the scheme and host isn't enough, we also transform the path.
* So declare no-op implementations for (get|set|has)Substitution methods and
* do all the work in resolveURI.
*/
setSubstitution(root, baseURI) {},
getSubstitution(root) {
throw Cr.NS_ERROR_NOT_AVAILABLE;
},
hasSubstitution(root) {
return false;
},
resolveURI(resURI) {
if (resURI.host != PageThumbs.staticHost)
throw Cr.NS_ERROR_NOT_AVAILABLE;
let {url} = parseURI(resURI);
let path = PageThumbsStorage.getFilePathForURL(url);
return OS.Path.toFileURI(path);
},
// xpcom machinery
classID: Components.ID("{5a4ae9b5-f475-48ae-9dce-0b4c1d347884}"),
QueryInterface: XPCOMUtils.generateQI([Ci.nsIProtocolHandler])
QueryInterface: XPCOMUtils.generateQI([Ci.nsIProtocolHandler,
Ci.nsISubstitutingProtocolHandler])
};
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([Protocol]);

View File

@ -5,6 +5,7 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
XPCSHELL_TESTS_MANIFESTS += ['test/xpcshell.ini']
EXTRA_COMPONENTS += [
'BrowserPageThumbs.manifest',

View File

@ -88,6 +88,11 @@ function capIfStaleErrorResponseUpdateTest() {
yield addTab(URL);
yield captureAndCheckColor(0, 255, 0, "we have a green thumbnail");
// image cache entry timestamps have second resolution
// so make sure the second part of this test takes part in a different second.
yield wait(2000);
// update the thumbnail to be stale, then re-request it. The server will
// return a 400 response and a red thumbnail.
// The service should not save the thumbnail - so we (a) check the thumbnail
@ -119,6 +124,11 @@ function capIfStaleGoodResponseUpdateTest() {
let browser = gBrowser.selectedBrowser;
yield captureAndCheckColor(0, 255, 0, "we have a green thumbnail");
// image cache entry timestamps have second resolution
// so make sure the second part of this test takes part in a different second.
yield wait(2000);
// update the thumbnail to be stale, then re-request it. The server will
// return a 200 response and a red thumbnail - so that new thumbnail should
// end up captured.
@ -148,6 +158,11 @@ function regularCapErrorResponseUpdateTest() {
yield addTab(URL);
yield captureAndCheckColor(0, 255, 0, "we have a green thumbnail");
gBrowser.removeTab(gBrowser.selectedTab);
// image cache entry timestamps have second resolution
// so make sure the second part of this test takes part in a different second.
yield wait(2000);
// do it again - the server will return a 400, so the foreground service
// should not update it.
yield addTab(URL);
@ -162,6 +177,11 @@ function regularCapGoodResponseUpdateTest() {
yield addTab(URL);
yield captureAndCheckColor(0, 255, 0, "we have a green thumbnail");
gBrowser.removeTab(gBrowser.selectedTab);
// image cache entry timestamps have second resolution
// so make sure the second part of this test takes part in a different second.
yield wait(2000);
// do it again - the server will return a 200, so the foreground service
// should update it.
yield addTab(URL);

View File

@ -0,0 +1,31 @@
// tests to check that moz-page-thumb URLs correctly resolve as file:// URLS
"use strict";
const Cu = Components.utils;
const Cc = Components.classes;
const Cr = Components.results;
const Ci = Components.interfaces;
Cu.import("resource://gre/modules/Services.jsm");
// need profile so that PageThumbsStorage can resolve the path to the underlying file
do_get_profile();
function run_test() {
// first check the protocol handler implements the correct interface
let handler = Services.io.getProtocolHandler("moz-page-thumb");
ok(handler instanceof Ci.nsISubstitutingProtocolHandler,
"moz-page-thumb handler provides substituting interface");
// then check that the file URL resolution works
let uri = Services.io.newURI("moz-page-thumb://thumbnail/?url=http%3A%2F%2Fwww.mozilla.org%2F",
null, null);
ok(uri instanceof Ci.nsIFileURL, "moz-page-thumb:// is a FileURL");
ok(uri.file, "This moz-page-thumb:// object is backed by a file");
// and check that the error case works as specified
let bad = Services.io.newURI("moz-page-thumb://wronghost/?url=http%3A%2F%2Fwww.mozilla.org%2F",
null, null);
Assert.throws(() => handler.resolveURI(bad), /NS_ERROR_NOT_AVAILABLE/i,
"moz-page-thumb object with wrong host must not resolve to a file path");
}

View File

@ -0,0 +1,6 @@
[DEFAULT]
head =
tail =
[test_thumbnails_interfaces.js]
skip-if = os == 'b2g' || os == 'android' # xpcom interface not packaged