summaryrefslogtreecommitdiffstats
path: root/toolkit/components/places/tests/favicons/test_replaceFaviconDataFromDataURL.js
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/places/tests/favicons/test_replaceFaviconDataFromDataURL.js')
-rw-r--r--toolkit/components/places/tests/favicons/test_replaceFaviconDataFromDataURL.js537
1 files changed, 537 insertions, 0 deletions
diff --git a/toolkit/components/places/tests/favicons/test_replaceFaviconDataFromDataURL.js b/toolkit/components/places/tests/favicons/test_replaceFaviconDataFromDataURL.js
new file mode 100644
index 0000000000..c1b83fc8a7
--- /dev/null
+++ b/toolkit/components/places/tests/favicons/test_replaceFaviconDataFromDataURL.js
@@ -0,0 +1,537 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/*
+ * Tests for replaceFaviconData()
+ */
+
+var iconsvc = PlacesUtils.favicons;
+
+var originalFavicon = {
+ file: do_get_file("favicon-normal16.png"),
+ uri: uri(do_get_file("favicon-normal16.png")),
+ data: readFileData(do_get_file("favicon-normal16.png")),
+ mimetype: "image/png",
+};
+
+var uniqueFaviconId = 0;
+function createFavicon(fileName) {
+ let tempdir = Services.dirsvc.get("TmpD", Ci.nsIFile);
+
+ // remove any existing file at the path we're about to copy to
+ let outfile = tempdir.clone();
+ outfile.append(fileName);
+ try {
+ outfile.remove(false);
+ } catch (e) {}
+
+ originalFavicon.file.copyToFollowingLinks(tempdir, fileName);
+
+ let stream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(
+ Ci.nsIFileOutputStream
+ );
+ stream.init(outfile, 0x02 | 0x08 | 0x10, 0o600, 0);
+
+ // append some data that sniffers/encoders will ignore that will distinguish
+ // the different favicons we'll create
+ uniqueFaviconId++;
+ let uniqueStr = "uid:" + uniqueFaviconId;
+ stream.write(uniqueStr, uniqueStr.length);
+ stream.close();
+
+ Assert.equal(outfile.leafName.substr(0, fileName.length), fileName);
+
+ return {
+ file: outfile,
+ uri: uri(outfile),
+ data: readFileData(outfile),
+ mimetype: "image/png",
+ };
+}
+
+function createDataURLForFavicon(favicon) {
+ return "data:" + favicon.mimetype + ";base64," + toBase64(favicon.data);
+}
+
+function checkCallbackSucceeded(
+ callbackMimetype,
+ callbackData,
+ sourceMimetype,
+ sourceData
+) {
+ Assert.equal(callbackMimetype, sourceMimetype);
+ Assert.ok(compareArrays(callbackData, sourceData));
+}
+
+function run_test() {
+ // check that the favicon loaded correctly
+ Assert.equal(originalFavicon.data.length, 286);
+ run_next_test();
+}
+
+add_task(async function test_replaceFaviconDataFromDataURL_validHistoryURI() {
+ info("test replaceFaviconDataFromDataURL for valid history uri");
+
+ let pageURI = uri("http://test1.bar/");
+ await PlacesTestUtils.addVisits(pageURI);
+
+ let favicon = createFavicon("favicon1.png");
+ iconsvc.replaceFaviconDataFromDataURL(
+ favicon.uri,
+ createDataURLForFavicon(favicon),
+ 0,
+ Services.scriptSecurityManager.getSystemPrincipal()
+ );
+
+ await new Promise(resolve => {
+ iconsvc.setAndFetchFaviconForPage(
+ pageURI,
+ favicon.uri,
+ true,
+ PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE,
+ function test_replaceFaviconDataFromDataURL_validHistoryURI_check(
+ aURI,
+ aDataLen,
+ aData,
+ aMimeType
+ ) {
+ checkCallbackSucceeded(
+ aMimeType,
+ aData,
+ favicon.mimetype,
+ favicon.data
+ );
+ checkFaviconDataForPage(
+ pageURI,
+ favicon.mimetype,
+ favicon.data,
+ function test_replaceFaviconDataFromDataURL_validHistoryURI_callback() {
+ favicon.file.remove(false);
+ resolve();
+ }
+ );
+ },
+ Services.scriptSecurityManager.getSystemPrincipal()
+ );
+ });
+
+ await PlacesUtils.history.clear();
+});
+
+add_task(
+ async function test_replaceFaviconDataFromDataURL_overrideDefaultFavicon() {
+ info(
+ "test replaceFaviconDataFromDataURL to override a later setAndFetchFaviconForPage"
+ );
+
+ let pageURI = uri("http://test2.bar/");
+ await PlacesTestUtils.addVisits(pageURI);
+
+ let firstFavicon = createFavicon("favicon2.png");
+ let secondFavicon = createFavicon("favicon3.png");
+
+ iconsvc.replaceFaviconDataFromDataURL(
+ firstFavicon.uri,
+ createDataURLForFavicon(secondFavicon),
+ 0,
+ Services.scriptSecurityManager.getSystemPrincipal()
+ );
+
+ await new Promise(resolve => {
+ iconsvc.setAndFetchFaviconForPage(
+ pageURI,
+ firstFavicon.uri,
+ true,
+ PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE,
+ function test_replaceFaviconDataFromDataURL_overrideDefaultFavicon_check(
+ aURI,
+ aDataLen,
+ aData,
+ aMimeType
+ ) {
+ checkCallbackSucceeded(
+ aMimeType,
+ aData,
+ secondFavicon.mimetype,
+ secondFavicon.data
+ );
+ checkFaviconDataForPage(
+ pageURI,
+ secondFavicon.mimetype,
+ secondFavicon.data,
+ function test_replaceFaviconDataFromDataURL_overrideDefaultFavicon_callback() {
+ firstFavicon.file.remove(false);
+ secondFavicon.file.remove(false);
+ resolve();
+ }
+ );
+ },
+ Services.scriptSecurityManager.getSystemPrincipal()
+ );
+ });
+
+ await PlacesUtils.history.clear();
+ }
+);
+
+add_task(async function test_replaceFaviconDataFromDataURL_replaceExisting() {
+ info(
+ "test replaceFaviconDataFromDataURL to override a previous setAndFetchFaviconForPage"
+ );
+
+ let pageURI = uri("http://test3.bar");
+ await PlacesTestUtils.addVisits(pageURI);
+
+ let firstFavicon = createFavicon("favicon4.png");
+ let secondFavicon = createFavicon("favicon5.png");
+
+ await new Promise(resolve => {
+ iconsvc.setAndFetchFaviconForPage(
+ pageURI,
+ firstFavicon.uri,
+ true,
+ PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE,
+ function test_replaceFaviconDataFromDataURL_replaceExisting_firstSet_check(
+ aURI,
+ aDataLen,
+ aData,
+ aMimeType
+ ) {
+ checkCallbackSucceeded(
+ aMimeType,
+ aData,
+ firstFavicon.mimetype,
+ firstFavicon.data
+ );
+ checkFaviconDataForPage(
+ pageURI,
+ firstFavicon.mimetype,
+ firstFavicon.data,
+ function test_replaceFaviconDataFromDataURL_replaceExisting_firstCallback() {
+ iconsvc.replaceFaviconDataFromDataURL(
+ firstFavicon.uri,
+ createDataURLForFavicon(secondFavicon),
+ 0,
+ Services.scriptSecurityManager.getSystemPrincipal()
+ );
+ checkFaviconDataForPage(
+ pageURI,
+ secondFavicon.mimetype,
+ secondFavicon.data,
+ function test_replaceFaviconDataFromDataURL_replaceExisting_secondCallback() {
+ firstFavicon.file.remove(false);
+ secondFavicon.file.remove(false);
+ resolve();
+ }
+ );
+ }
+ );
+ },
+ Services.scriptSecurityManager.getSystemPrincipal()
+ );
+ });
+
+ await PlacesUtils.history.clear();
+});
+
+add_task(async function test_replaceFaviconDataFromDataURL_unrelatedReplace() {
+ info("test replaceFaviconDataFromDataURL to not make unrelated changes");
+
+ let pageURI = uri("http://test4.bar/");
+ await PlacesTestUtils.addVisits(pageURI);
+
+ let favicon = createFavicon("favicon6.png");
+ let unrelatedFavicon = createFavicon("favicon7.png");
+
+ iconsvc.replaceFaviconDataFromDataURL(
+ unrelatedFavicon.uri,
+ createDataURLForFavicon(unrelatedFavicon),
+ 0,
+ Services.scriptSecurityManager.getSystemPrincipal()
+ );
+
+ await new Promise(resolve => {
+ iconsvc.setAndFetchFaviconForPage(
+ pageURI,
+ favicon.uri,
+ true,
+ PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE,
+ function test_replaceFaviconDataFromDataURL_unrelatedReplace_check(
+ aURI,
+ aDataLen,
+ aData,
+ aMimeType
+ ) {
+ checkCallbackSucceeded(
+ aMimeType,
+ aData,
+ favicon.mimetype,
+ favicon.data
+ );
+ checkFaviconDataForPage(
+ pageURI,
+ favicon.mimetype,
+ favicon.data,
+ function test_replaceFaviconDataFromDataURL_unrelatedReplace_callback() {
+ favicon.file.remove(false);
+ unrelatedFavicon.file.remove(false);
+ resolve();
+ }
+ );
+ },
+ Services.scriptSecurityManager.getSystemPrincipal()
+ );
+ });
+
+ await PlacesUtils.history.clear();
+});
+
+add_task(async function test_replaceFaviconDataFromDataURL_badInputs() {
+ info("test replaceFaviconDataFromDataURL to throw on bad inputs");
+
+ let favicon = createFavicon("favicon8.png");
+
+ let ex = null;
+ try {
+ iconsvc.replaceFaviconDataFromDataURL(
+ favicon.uri,
+ "",
+ 0,
+ Services.scriptSecurityManager.getSystemPrincipal()
+ );
+ } catch (e) {
+ ex = e;
+ } finally {
+ Assert.ok(!!ex);
+ }
+
+ ex = null;
+ try {
+ iconsvc.replaceFaviconDataFromDataURL(
+ null,
+ createDataURLForFavicon(favicon),
+ 0,
+ Services.scriptSecurityManager.getSystemPrincipal()
+ );
+ } catch (e) {
+ ex = e;
+ } finally {
+ Assert.ok(!!ex);
+ }
+
+ favicon.file.remove(false);
+
+ await PlacesUtils.history.clear();
+});
+
+add_task(async function test_replaceFaviconDataFromDataURL_twiceReplace() {
+ info("test replaceFaviconDataFromDataURL on multiple replacements");
+
+ let pageURI = uri("http://test5.bar/");
+ await PlacesTestUtils.addVisits(pageURI);
+
+ let firstFavicon = createFavicon("favicon9.png");
+ let secondFavicon = createFavicon("favicon10.png");
+
+ iconsvc.replaceFaviconDataFromDataURL(
+ firstFavicon.uri,
+ createDataURLForFavicon(firstFavicon),
+ 0,
+ Services.scriptSecurityManager.getSystemPrincipal()
+ );
+ iconsvc.replaceFaviconDataFromDataURL(
+ firstFavicon.uri,
+ createDataURLForFavicon(secondFavicon),
+ 0,
+ Services.scriptSecurityManager.getSystemPrincipal()
+ );
+
+ await new Promise(resolve => {
+ iconsvc.setAndFetchFaviconForPage(
+ pageURI,
+ firstFavicon.uri,
+ true,
+ PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE,
+ function test_replaceFaviconDataFromDataURL_twiceReplace_check(
+ aURI,
+ aDataLen,
+ aData,
+ aMimeType
+ ) {
+ checkCallbackSucceeded(
+ aMimeType,
+ aData,
+ secondFavicon.mimetype,
+ secondFavicon.data
+ );
+ checkFaviconDataForPage(
+ pageURI,
+ secondFavicon.mimetype,
+ secondFavicon.data,
+ function test_replaceFaviconDataFromDataURL_twiceReplace_callback() {
+ firstFavicon.file.remove(false);
+ secondFavicon.file.remove(false);
+ resolve();
+ }
+ );
+ },
+ Services.scriptSecurityManager.getSystemPrincipal()
+ );
+ });
+
+ await PlacesUtils.history.clear();
+});
+
+add_task(
+ async function test_replaceFaviconDataFromDataURL_afterRegularAssign() {
+ info("test replaceFaviconDataFromDataURL after replaceFaviconData");
+
+ let pageURI = uri("http://test6.bar/");
+ await PlacesTestUtils.addVisits(pageURI);
+
+ let firstFavicon = createFavicon("favicon11.png");
+ let secondFavicon = createFavicon("favicon12.png");
+
+ iconsvc.replaceFaviconData(
+ firstFavicon.uri,
+ firstFavicon.data,
+ firstFavicon.mimetype
+ );
+ iconsvc.replaceFaviconDataFromDataURL(
+ firstFavicon.uri,
+ createDataURLForFavicon(secondFavicon),
+ 0,
+ Services.scriptSecurityManager.getSystemPrincipal()
+ );
+
+ await new Promise(resolve => {
+ iconsvc.setAndFetchFaviconForPage(
+ pageURI,
+ firstFavicon.uri,
+ true,
+ PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE,
+ function test_replaceFaviconDataFromDataURL_afterRegularAssign_check(
+ aURI,
+ aDataLen,
+ aData,
+ aMimeType
+ ) {
+ checkCallbackSucceeded(
+ aMimeType,
+ aData,
+ secondFavicon.mimetype,
+ secondFavicon.data
+ );
+ checkFaviconDataForPage(
+ pageURI,
+ secondFavicon.mimetype,
+ secondFavicon.data,
+ function test_replaceFaviconDataFromDataURL_afterRegularAssign_callback() {
+ firstFavicon.file.remove(false);
+ secondFavicon.file.remove(false);
+ resolve();
+ }
+ );
+ },
+ Services.scriptSecurityManager.getSystemPrincipal()
+ );
+ });
+
+ await PlacesUtils.history.clear();
+ }
+);
+
+add_task(
+ async function test_replaceFaviconDataFromDataURL_beforeRegularAssign() {
+ info("test replaceFaviconDataFromDataURL before replaceFaviconData");
+
+ let pageURI = uri("http://test7.bar/");
+ await PlacesTestUtils.addVisits(pageURI);
+
+ let firstFavicon = createFavicon("favicon13.png");
+ let secondFavicon = createFavicon("favicon14.png");
+
+ iconsvc.replaceFaviconDataFromDataURL(
+ firstFavicon.uri,
+ createDataURLForFavicon(firstFavicon),
+ 0,
+ Services.scriptSecurityManager.getSystemPrincipal()
+ );
+ iconsvc.replaceFaviconData(
+ firstFavicon.uri,
+ secondFavicon.data,
+ secondFavicon.mimetype
+ );
+
+ await new Promise(resolve => {
+ iconsvc.setAndFetchFaviconForPage(
+ pageURI,
+ firstFavicon.uri,
+ true,
+ PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE,
+ function test_replaceFaviconDataFromDataURL_beforeRegularAssign_check(
+ aURI,
+ aDataLen,
+ aData,
+ aMimeType
+ ) {
+ checkCallbackSucceeded(
+ aMimeType,
+ aData,
+ secondFavicon.mimetype,
+ secondFavicon.data
+ );
+ checkFaviconDataForPage(
+ pageURI,
+ secondFavicon.mimetype,
+ secondFavicon.data,
+ function test_replaceFaviconDataFromDataURL_beforeRegularAssign_callback() {
+ firstFavicon.file.remove(false);
+ secondFavicon.file.remove(false);
+ resolve();
+ }
+ );
+ },
+ Services.scriptSecurityManager.getSystemPrincipal()
+ );
+ });
+
+ await PlacesUtils.history.clear();
+ }
+);
+
+/* toBase64 copied from image/test/unit/test_encoder_png.js */
+
+/* Convert data (an array of integers) to a Base64 string. */
+const toBase64Table =
+ // eslint-disable-next-line no-useless-concat
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + "0123456789+/";
+const base64Pad = "=";
+function toBase64(data) {
+ let result = "";
+ let length = data.length;
+ let i;
+ // Convert every three bytes to 4 ascii characters.
+ for (i = 0; i < length - 2; i += 3) {
+ result += toBase64Table[data[i] >> 2];
+ result += toBase64Table[((data[i] & 0x03) << 4) + (data[i + 1] >> 4)];
+ result += toBase64Table[((data[i + 1] & 0x0f) << 2) + (data[i + 2] >> 6)];
+ result += toBase64Table[data[i + 2] & 0x3f];
+ }
+
+ // Convert the remaining 1 or 2 bytes, pad out to 4 characters.
+ if (length % 3) {
+ i = length - (length % 3);
+ result += toBase64Table[data[i] >> 2];
+ if (length % 3 == 2) {
+ result += toBase64Table[((data[i] & 0x03) << 4) + (data[i + 1] >> 4)];
+ result += toBase64Table[(data[i + 1] & 0x0f) << 2];
+ result += base64Pad;
+ } else {
+ result += toBase64Table[(data[i] & 0x03) << 4];
+ result += base64Pad + base64Pad;
+ }
+ }
+
+ return result;
+}