Source code

Revision control

Copy as Markdown

Other Tools

Test Info:

/* Any copyright is dedicated to the Public Domain.
"use strict";
const { AppConstants } = ChromeUtils.importESModule(
"resource://gre/modules/AppConstants.sys.mjs"
);
const { PlacesUtils } = ChromeUtils.importESModule(
"resource://gre/modules/PlacesUtils.sys.mjs"
);
const { PlacesTestUtils } = ChromeUtils.importESModule(
);
Assert.equal(AppConstants.platform, "win", "Is running under Windows");
const TASKBAR_SERVICE = Cc["@mozilla.org/windows-taskbar;1"].getService(
Ci.nsIWinTaskbar
);
Assert.ok(TASKBAR_SERVICE, "Got nsIWinTaskBar");
const JUMP_LIST_BUILDER = TASKBAR_SERVICE.createJumpListBuilder(
false /* aPrivateBrowsing */
);
Assert.ok(JUMP_LIST_BUILDER, "Got an nsIJumpListBuilder");
// The Windows Jump List favicon cache is in the profile directory, so let's
// make sure that a profile exists.
do_get_profile();
// See FaviconHelper::kJumpListCacheDir
const JUMP_LIST_CACHE_FOLDER = "jumpListCache";
const JUMP_LIST_CACHE_PATH = PathUtils.join(
PathUtils.profileDir,
JUMP_LIST_CACHE_FOLDER
);
const TEST_PAGE_URI = Services.io.newURI("https://widget.test");
const TEST_FAVICON_URI = Services.io.newURI(
`${TEST_PAGE_URI.spec}/favicon.ico`
);
const FAVICON_MIME_TYPE = "image/x-icon";
/**
* Clears the contents of the Windows Jump List favicon cache.
*
* @returns {Promise<undefined>}
*/
async function emptyFaviconCache() {
await IOUtils.remove(JUMP_LIST_CACHE_PATH, {
ignoreAbsent: true,
recursive: true,
});
await IOUtils.makeDirectory(JUMP_LIST_CACHE_PATH);
}
add_setup(async () => {
const FAVICON_BYTES = await IOUtils.read(do_get_file("favicon.ico").path);
Assert.ok(FAVICON_BYTES.length, "Was able to load the testing favicon.");
await PlacesTestUtils.addVisits(TEST_PAGE_URI);
let dataURL = await new Promise((resolve, reject) => {
let buffer = new Uint8ClampedArray(FAVICON_BYTES);
let blob = new Blob([buffer], { type: FAVICON_MIME_TYPE });
let reader = new FileReader();
reader.addEventListener("load", () => resolve(reader.result));
reader.addEventListener("error", reject);
reader.readAsDataURL(blob);
});
return new Promise(resolve => {
PlacesUtils.favicons.setFaviconForPage(
TEST_PAGE_URI,
TEST_FAVICON_URI,
Services.io.newURI(dataURL),
undefined,
resolve
);
});
});
/**
* Test that we can populate the Windows Jump List favicon cache with a known
* favicon from the favicon database.
*/
add_task(async function test_write_favicon_cache() {
// Let's make sure that the Windows Jump List favicon cache folder is empty
// to start.
await emptyFaviconCache();
let firstCallCachePath = await JUMP_LIST_BUILDER.obtainAndCacheFaviconAsync(
TEST_PAGE_URI
);
Assert.ok(firstCallCachePath, "Got a non-empty cache path");
Assert.ok(
await IOUtils.exists(firstCallCachePath),
"A file exists at the cache path"
);
let cacheBytes = await IOUtils.read(firstCallCachePath);
let sniffer = Cc["@mozilla.org/image/loader;1"].createInstance(
Ci.nsIContentSniffer
);
// Now test that if we re-request the same favicon, that we don't write the
// same favicon to disk - but continue to use the existing cached file.
Assert.equal(
sniffer.getMIMETypeFromContent(null, cacheBytes, cacheBytes.length),
FAVICON_MIME_TYPE,
"An image was written to the path."
);
let { lastModified } = await IOUtils.stat(firstCallCachePath);
let secondCallCachePath = await JUMP_LIST_BUILDER.obtainAndCacheFaviconAsync(
TEST_PAGE_URI
);
Assert.equal(
secondCallCachePath,
firstCallCachePath,
"Got back the same path the second time."
);
Assert.equal(
(await IOUtils.stat(secondCallCachePath)).lastModified,
lastModified,
"The file did not get written to again."
);
});
/**
* Test that if we request to cache a favicon that doesn't exist within the
* favicon database that we reject the Promise with a result code.
*/
add_task(async function test_invalid_favicon() {
// Let's make sure that the Windows Jump List favicon cache folder is empty
// to start.
await emptyFaviconCache();
await Assert.rejects(
JUMP_LIST_BUILDER.obtainAndCacheFaviconAsync(
Services.io.newURI("https://page.that.does.not.exist.com")
),
/NS_ERROR_FAILURE/
);
// And ensure that no favicons got written despite the error.
let { length: numberOfFavicons } = await IOUtils.getChildren(
JUMP_LIST_CACHE_PATH
);
Assert.equal(numberOfFavicons, 0, "No favicons were written");
});
/**
* Test that we will overwrite the favicon cache with a fresh copy if the cache
* has expired.
*/
add_task(async function test_expired_favicon_cache() {
// Let's make sure that the Windows Jump List favicon cache folder is empty
// to start.
await emptyFaviconCache();
let firstCallCachePath = await JUMP_LIST_BUILDER.obtainAndCacheFaviconAsync(
TEST_PAGE_URI
);
Assert.ok(firstCallCachePath, "Got a non-empty cache path");
Assert.ok(
await IOUtils.exists(firstCallCachePath),
"A file exists at the cache path"
);
// Now make it seem as if the favicon was last modified last week. That's
// definitely expired, since the actual expiry is when the icon is a day old.
let aWeekAgo = Date.now() - 86400 * 7; // 86400 seconds in a day, times 7 days.
await IOUtils.setModificationTime(firstCallCachePath, aWeekAgo);
let { lastModified } = await IOUtils.stat(firstCallCachePath);
let secondCallCachePath = await JUMP_LIST_BUILDER.obtainAndCacheFaviconAsync(
TEST_PAGE_URI
);
Assert.equal(
secondCallCachePath,
firstCallCachePath,
"Got back the same path the second time."
);
Assert.equal(
(await IOUtils.stat(secondCallCachePath)).lastModified,
lastModified,
"The file got overwritten."
);
});