From 8dd16259287f58f9273002717ec4d27e97127719 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 12 Jun 2024 07:43:14 +0200 Subject: Merging upstream version 127.0. Signed-off-by: Daniel Baumann --- .../places/tests/PlacesTestUtils.sys.mjs | 37 ++ .../components/places/tests/browser/browser.toml | 12 + .../tests/browser/browser_visituri_restriction.js | 227 +++++++++ .../browser/browser_visituri_restriction_origin.js | 92 ++++ toolkit/components/places/tests/browser/head.js | 77 +++ .../places/tests/chrome/test_cached_favicon.xhtml | 15 +- .../tests/expiration/test_debug_expiration.js | 16 +- .../places/tests/favicons/head_favicons.js | 87 +++- .../favicons/test_cached-favicon_mime_type.js | 20 +- .../tests/favicons/test_expire_on_new_icons.js | 38 +- .../tests/favicons/test_favicons_conversions.js | 37 +- .../tests/favicons/test_favicons_protocols_ref.js | 17 +- .../tests/favicons/test_getFaviconDataForPage.js | 16 +- .../tests/favicons/test_getFaviconURLForPage.js | 16 +- .../places/tests/favicons/test_heavy_favicon.js | 4 +- .../tests/favicons/test_incremental_vacuum.js | 7 +- .../places/tests/favicons/test_multiple_frames.js | 12 +- .../tests/favicons/test_page-icon_protocol.js | 44 +- .../tests/favicons/test_replaceFaviconData.js | 395 --------------- .../favicons/test_replaceFaviconDataFromDataURL.js | 537 --------------------- .../places/tests/favicons/test_root_icons.js | 67 ++- .../tests/favicons/test_setFaviconForPage.js | 245 ++++++++++ .../components/places/tests/favicons/xpcshell.toml | 6 +- .../places/tests/gtest/places_test_harness_tail.h | 8 +- toolkit/components/places/tests/head_common.js | 37 +- .../components/places/tests/history/test_remove.js | 15 +- .../places/tests/unit/test_PlacesQuery_history.js | 33 ++ 27 files changed, 962 insertions(+), 1155 deletions(-) create mode 100644 toolkit/components/places/tests/browser/browser_visituri_restriction.js create mode 100644 toolkit/components/places/tests/browser/browser_visituri_restriction_origin.js delete mode 100644 toolkit/components/places/tests/favicons/test_replaceFaviconData.js delete mode 100644 toolkit/components/places/tests/favicons/test_replaceFaviconDataFromDataURL.js create mode 100644 toolkit/components/places/tests/favicons/test_setFaviconForPage.js (limited to 'toolkit/components/places/tests') diff --git a/toolkit/components/places/tests/PlacesTestUtils.sys.mjs b/toolkit/components/places/tests/PlacesTestUtils.sys.mjs index 4e459d2e32..97dda6367f 100644 --- a/toolkit/components/places/tests/PlacesTestUtils.sys.mjs +++ b/toolkit/components/places/tests/PlacesTestUtils.sys.mjs @@ -156,6 +156,43 @@ export var PlacesTestUtils = Object.freeze({ await Promise.all(faviconPromises); }, + /* + * Helper function to call PlacesUtils.favicons.setFaviconForPage() and waits + * finishing setting. This function throws an error if the status of + * PlacesUtils.favicons.setFaviconForPage() is not success. + * + * @param {string or nsIURI} pageURI + * @param {string or nsIURI} faviconURI + * @param {string or nsIURI} faviconDataURL + * @param {Number} [optional] expiration + * @return {Promise} waits for finishing setting + */ + setFaviconForPage(pageURI, faviconURI, faviconDataURL, expiration = 0) { + return new Promise((resolve, reject) => { + lazy.PlacesUtils.favicons.setFaviconForPage( + pageURI instanceof Ci.nsIURI ? pageURI : Services.io.newURI(pageURI), + faviconURI instanceof Ci.nsIURI + ? faviconURI + : Services.io.newURI(faviconURI), + faviconDataURL instanceof Ci.nsIURI + ? faviconDataURL + : Services.io.newURI(faviconDataURL), + expiration, + status => { + if (Components.isSuccessCode(status)) { + resolve(status); + } else { + reject( + new Error( + `Failed to process setFaviconForPage(): status code = ${status}` + ) + ); + } + } + ); + }); + }, + /** * Clears any favicons stored in the database. */ diff --git a/toolkit/components/places/tests/browser/browser.toml b/toolkit/components/places/tests/browser/browser.toml index b7d688c980..aceee48f24 100644 --- a/toolkit/components/places/tests/browser/browser.toml +++ b/toolkit/components/places/tests/browser/browser.toml @@ -117,3 +117,15 @@ support-files = [ "favicon.html", "final.html", ] + +["browser_visituri_restriction.js"] +skip-if = [ + "verify", + "os == 'linux' && (asan || tsan)", # Bug 1891145 +] + +["browser_visituri_restriction_origin.js"] +skip-if = [ + "verify", + "os == 'linux' && (asan || tsan)", # Bug 1891145 +] diff --git a/toolkit/components/places/tests/browser/browser_visituri_restriction.js b/toolkit/components/places/tests/browser/browser_visituri_restriction.js new file mode 100644 index 0000000000..2af41e6f51 --- /dev/null +++ b/toolkit/components/places/tests/browser/browser_visituri_restriction.js @@ -0,0 +1,227 @@ +/** + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +"use strict"; + +const TEST_PAGE = `data:text/html, + https://example.com + http://example.com + https://www.example.com + https://example.org`; + +add_setup(async function () { + await SpecialPowers.pushPrefEnv({ + set: [ + // Enable restriction feature. + ["places.history.floodingPrevention.enabled", true], + // Restrict from the second visit. + ["places.history.floodingPrevention.restrictionCount", 1], + ["places.history.floodingPrevention.restrictionExpireSeconds", 4], + // Not apply flooding prevention until some seconds elapse after user + // interaction begins. + [ + "places.history.floodingPrevention.maxSecondsFromLastUserInteraction", + 4, + ], + // To enable UserActivation by EventUtils.synthesizeMouseAtCenter() in + // ContentTask.spawn() in synthesizeVisitByUser(). + ["test.events.async.enabled", true], + ], + }); + await clearHistoryAndHistoryCache(); +}); + +add_task(async function basic() { + await BrowserTestUtils.withNewTab( + { gBrowser, url: TEST_PAGE }, + async browser => { + info("Sanity check"); + await assertLinkVisitedStatus(browser, "https://example.com/", { + visitCount: 0, + isVisited: false, + }); + await assertLinkVisitedStatus(browser, "https://example.com/", { + visitCount: 0, + isVisited: false, + }); + await assertLinkVisitedStatus(browser, "https://www.example.com/", { + visitCount: 0, + isVisited: false, + }); + await assertLinkVisitedStatus(browser, "https://example.org/", { + visitCount: 0, + isVisited: false, + }); + + info("Visit https://example.com/ by user"); + await synthesizeVisitByUser(browser, "https://example.com/"); + await assertLinkVisitedStatus(browser, "https://example.com/", { + visitCount: 1, + isVisited: true, + }); + + info( + "Visit https://example.com/ by script within maxSecondsFromLastUserInteraction" + ); + await synthesizeVisitByScript(browser, "https://example.com/"); + await synthesizeVisitByScript(browser, "https://example.com/"); + await assertLinkVisitedStatus(browser, "https://example.com/", { + visitCount: 3, + isVisited: true, + }); + + await waitForPrefSeconds("maxSecondsFromLastUserInteraction"); + + info( + "Visit https://example.com/ by script without maxSecondsFromLastUserInteraction" + ); + await synthesizeVisitByScript(browser, "https://example.com/"); + await assertLinkVisitedStatus(browser, "https://example.com/", { + visitCount: 4, + isVisited: true, + }); + + info("Visit again, but it should be restricted"); + await synthesizeVisitByScript(browser, "https://example.com/"); + await assertLinkVisitedStatus(browser, "https://example.com/", { + visitCount: 4, + isVisited: true, + }); + + info("Check other"); + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + await assertLinkVisitedStatus(browser, "http://example.com/", { + visitCount: 0, + isVisited: false, + }); + await assertLinkVisitedStatus(browser, "https://www.example.com/", { + visitCount: 0, + isVisited: false, + }); + await assertLinkVisitedStatus(browser, "https://example.org/", { + visitCount: 0, + isVisited: false, + }); + } + ); + + await clearHistoryAndHistoryCache(); +}); + +add_task(async function expireRestriction() { + await BrowserTestUtils.withNewTab( + { gBrowser, url: TEST_PAGE }, + async browser => { + info("Visit https://example.com/ by user"); + await synthesizeVisitByUser(browser, "https://example.com/"); + await assertLinkVisitedStatus(browser, "https://example.com/", { + visitCount: 1, + isVisited: true, + }); + + info( + "Visit https://example.com/ by script within maxSecondsFromLastUserInteraction" + ); + await synthesizeVisitByScript(browser, "https://example.com/"); + await synthesizeVisitByScript(browser, "https://example.com/"); + await assertLinkVisitedStatus(browser, "https://example.com/", { + visitCount: 3, + isVisited: true, + }); + + await waitForPrefSeconds("maxSecondsFromLastUserInteraction"); + + info( + "Visit https://example.com/ by script without maxSecondsFromLastUserInteraction" + ); + await synthesizeVisitByScript(browser, "https://example.com/"); + await assertLinkVisitedStatus(browser, "https://example.com/", { + visitCount: 4, + isVisited: true, + }); + + await waitForPrefSeconds("restrictionExpireSeconds"); + + info("Visit again, it should not be restricted"); + await synthesizeVisitByScript(browser, "https://example.com/"); + await assertLinkVisitedStatus(browser, "https://example.com/", { + visitCount: 5, + isVisited: true, + }); + } + ); + + await clearHistoryAndHistoryCache(); +}); + +add_task(async function userInputAlwaysAcceptable() { + await BrowserTestUtils.withNewTab( + { gBrowser, url: TEST_PAGE }, + async browser => { + info("Visit by user"); + await synthesizeVisitByUser(browser, "https://example.com/"); + await assertLinkVisitedStatus(browser, "https://example.com/", { + visitCount: 1, + isVisited: true, + }); + await synthesizeVisitByUser(browser, "https://example.com/"); + await assertLinkVisitedStatus(browser, "https://example.com/", { + visitCount: 2, + isVisited: true, + }); + + await waitForPrefSeconds("maxSecondsFromLastUserInteraction"); + + info("Visit by user input"); + await synthesizeVisitByUser(browser, "https://example.com/"); + await assertLinkVisitedStatus(browser, "https://example.com/", { + visitCount: 3, + isVisited: true, + }); + await synthesizeVisitByUser(browser, "https://example.com/"); + await assertLinkVisitedStatus(browser, "https://example.com/", { + visitCount: 4, + isVisited: true, + }); + } + ); + + await clearHistoryAndHistoryCache(); +}); + +add_task(async function disable() { + await SpecialPowers.pushPrefEnv({ + set: [["places.history.floodingPrevention.enabled", false]], + }); + + await BrowserTestUtils.withNewTab( + { gBrowser, url: TEST_PAGE }, + async browser => { + info("Any visits are stored"); + for (let i = 0; i < 3; i++) { + await synthesizeVisitByScript(browser, "https://example.com/"); + await assertLinkVisitedStatus(browser, "https://example.com/", { + visitCount: i + 1, + isVisited: true, + }); + } + } + ); + + await clearHistoryAndHistoryCache(); +}); + +async function waitForPrefSeconds(pref) { + info(`Wait until elapsing ${pref}`); + return new Promise(r => + // eslint-disable-next-line mozilla/no-arbitrary-setTimeout + setTimeout( + r, + Services.prefs.getIntPref(`places.history.floodingPrevention.${pref}`) * + 1000 + + 100 + ) + ); +} diff --git a/toolkit/components/places/tests/browser/browser_visituri_restriction_origin.js b/toolkit/components/places/tests/browser/browser_visituri_restriction_origin.js new file mode 100644 index 0000000000..ee691c79e8 --- /dev/null +++ b/toolkit/components/places/tests/browser/browser_visituri_restriction_origin.js @@ -0,0 +1,92 @@ +/** + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +"use strict"; + +const TEST_PAGE = `data:text/html, + https://example.com + http://example.com + https://www.example.com + https://example.org`; + +add_setup(async function () { + await SpecialPowers.pushPrefEnv({ + set: [ + // Enable restriction feature. + ["places.history.floodingPrevention.enabled", true], + // Restrict from the second visit. + ["places.history.floodingPrevention.restrictionCount", 1], + // Stop expiring. + ["places.history.floodingPrevention.restrictionExpireSeconds", 100], + // Always appply flooding preveition. + [ + "places.history.floodingPrevention.maxSecondsFromLastUserInteraction", + 0, + ], + // To enable UserActivation by EventUtils.synthesizeMouseAtCenter() in ContentTask.spawn() in synthesizeVisitByUser(). + ["test.events.async.enabled", true], + ], + }); +}); + +add_task(async function same_origin_but_other() { + await BrowserTestUtils.withNewTab( + { gBrowser, url: TEST_PAGE }, + async browser => { + info("Sanity check"); + await assertLinkVisitedStatus(browser, "https://example.com/", { + visitCount: 0, + isVisited: false, + }); + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + await assertLinkVisitedStatus(browser, "http://example.com/", { + visitCount: 0, + isVisited: false, + }); + await assertLinkVisitedStatus(browser, "https://www.example.com/", { + visitCount: 0, + isVisited: false, + }); + await assertLinkVisitedStatus(browser, "https://example.org/", { + visitCount: 0, + isVisited: false, + }); + + info("Visit https://example.com/ by user"); + await synthesizeVisitByUser(browser, "https://example.com/"); + await assertLinkVisitedStatus(browser, "https://example.com/", { + visitCount: 1, + isVisited: true, + }); + + info("Visit others by Scripts"); + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + await synthesizeVisitByScript(browser, "http://example.com/"); + await synthesizeVisitByScript(browser, "https://www.example.com/"); + await synthesizeVisitByScript(browser, "https://example.org/"); + + info("Check the status"); + await assertLinkVisitedStatus(browser, "https://example.com/", { + visitCount: 1, + isVisited: true, + }); + // eslint-disable-next-line @microsoft/sdl/no-insecure-url + await assertLinkVisitedStatus(browser, "http://example.com/", { + visitCount: 0, + isVisited: true, + }); + await assertLinkVisitedStatus(browser, "https://www.example.com/", { + visitCount: 0, + isVisited: true, + }); + await assertLinkVisitedStatus(browser, "https://example.org/", { + visitCount: 1, + isVisited: true, + }); + } + ); + + await clearHistoryAndHistoryCache(); +}); diff --git a/toolkit/components/places/tests/browser/head.js b/toolkit/components/places/tests/browser/head.js index b1b916ee29..da40a832c6 100644 --- a/toolkit/components/places/tests/browser/head.js +++ b/toolkit/components/places/tests/browser/head.js @@ -17,3 +17,80 @@ function whenNewWindowLoaded(aOptions, aCallback) { BrowserTestUtils.waitForNewWindow().then(aCallback); OpenBrowserWindow(aOptions); } + +async function clearHistoryAndHistoryCache() { + await PlacesUtils.history.clear(); + // Clear HistoryRestiction cache as well. + Cc["@mozilla.org/browser/history;1"] + .getService(Ci.mozIAsyncHistory) + .clearCache(); +} + +async function synthesizeVisitByUser(browser, url) { + let onNewTab = BrowserTestUtils.waitForNewTab(browser.ownerGlobal.gBrowser); + // We intentionally turn off this a11y check, because the following click is + // purposefully sent on an arbitrary web content that is not expected to be + // tested by itself with the browser mochitests, therefore this rule check + // shall be ignored by a11y_checks suite. + AccessibilityUtils.setEnv({ mustHaveAccessibleRule: false }); + await ContentTask.spawn(browser, [url], async ([href]) => { + EventUtils.synthesizeMouseAtCenter( + content.document.querySelector(`a[href='${href}'`), + {}, + content + ); + }); + AccessibilityUtils.resetEnv(); + let tab = await onNewTab; + BrowserTestUtils.removeTab(tab); +} + +async function synthesizeVisitByScript(browser, url) { + let onNewTab = BrowserTestUtils.waitForNewTab(browser.ownerGlobal.gBrowser); + AccessibilityUtils.setEnv({ mustHaveAccessibleRule: false }); + await ContentTask.spawn(browser, [url], async ([href]) => { + let a = content.document.querySelector(`a[href='${href}'`); + a.click(); + }); + AccessibilityUtils.resetEnv(); + let tab = await onNewTab; + BrowserTestUtils.removeTab(tab); +} + +async function assertLinkVisitedStatus( + browser, + url, + { visitCount: expectedVisitCount, isVisited: expectedVisited } +) { + await BrowserTestUtils.waitForCondition(async () => { + let visitCount = + (await PlacesTestUtils.getDatabaseValue("moz_places", "visit_count", { + url, + })) ?? 0; + + if (visitCount != expectedVisitCount) { + return false; + } + + Assert.equal(visitCount, expectedVisitCount, "The visit count is correct"); + return true; + }); + + await ContentTask.spawn( + browser, + [url, expectedVisited], + async ([href, visited]) => { + // ElementState::VISITED + const VISITED_STATE = 1 << 18; + await ContentTaskUtils.waitForCondition(() => { + let isVisited = !!( + content.InspectorUtils.getContentState( + content.document.querySelector(`a[href='${href}']`) + ) & VISITED_STATE + ); + return isVisited == visited; + }); + } + ); + Assert.ok(true, "The visited state is corerct"); +} diff --git a/toolkit/components/places/tests/chrome/test_cached_favicon.xhtml b/toolkit/components/places/tests/chrome/test_cached_favicon.xhtml index f7e7f4f1d8..1046574bdf 100644 --- a/toolkit/components/places/tests/chrome/test_cached_favicon.xhtml +++ b/toolkit/components/places/tests/chrome/test_cached_favicon.xhtml @@ -104,19 +104,12 @@ function test() // icon with a page explicitly in order for it to be visible through // the protocol. info("Replace favicon data"); - var systemPrincipal = Cc["@mozilla.org/systemprincipal;1"] - .createInstance(Ci.nsIPrincipal); - PlacesUtils.favicons.replaceFaviconDataFromDataURL( - Services.io.newURI(tests[1].url), - tests[1].expectedIcon, - (Date.now() + 86400) * 1000, - systemPrincipal); - info("Set favicon data"); - PlacesUtils.favicons.setAndFetchFaviconForPage( + PlacesUtils.favicons.setFaviconForPage( Services.io.newURI("https://example.com/favicon_annotations"), Services.io.newURI(tests[1].url), - true, PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE, null, - systemPrincipal); + Services.io.newURI(tests[1].expectedIcon), + (Date.now() + 86400) * 1000, + ); // And start our test process. loadNextTest(); diff --git a/toolkit/components/places/tests/expiration/test_debug_expiration.js b/toolkit/components/places/tests/expiration/test_debug_expiration.js index 204295d46c..22657e6b24 100644 --- a/toolkit/components/places/tests/expiration/test_debug_expiration.js +++ b/toolkit/components/places/tests/expiration/test_debug_expiration.js @@ -356,13 +356,7 @@ add_task(async function test_expire_icons() { } if (entry.icon) { - PlacesUtils.favicons.replaceFaviconDataFromDataURL( - Services.io.newURI(entry.icon), - dataUrl, - 0, - Services.scriptSecurityManager.getSystemPrincipal() - ); - await PlacesTestUtils.addFavicons(new Map([[entry.page, entry.icon]])); + await PlacesTestUtils.setFaviconForPage(entry.page, entry.icon, dataUrl); Assert.equal( await getFaviconUrlForPage(entry.page), entry.icon, @@ -380,13 +374,7 @@ add_task(async function test_expire_icons() { } if (entry.root) { - PlacesUtils.favicons.replaceFaviconDataFromDataURL( - Services.io.newURI(entry.root), - dataUrl, - 0, - Services.scriptSecurityManager.getSystemPrincipal() - ); - await PlacesTestUtils.addFavicons(new Map([[entry.page, entry.root]])); + await PlacesTestUtils.setFaviconForPage(entry.page, entry.root, dataUrl); } if (entry.iconExpired) { diff --git a/toolkit/components/places/tests/favicons/head_favicons.js b/toolkit/components/places/tests/favicons/head_favicons.js index afd2c4924f..73dd2a61ed 100644 --- a/toolkit/components/places/tests/favicons/head_favicons.js +++ b/toolkit/components/places/tests/favicons/head_favicons.js @@ -15,6 +15,9 @@ const systemPrincipal = Services.scriptSecurityManager.getSystemPrincipal(); +// Used in createFavicon(). +let uniqueFaviconId = 0; + /** * Checks that the favicon for the given page matches the provided data. * @@ -24,6 +27,7 @@ const systemPrincipal = Services.scriptSecurityManager.getSystemPrincipal(); * Expected MIME type of the icon, for example "image/png". * @param aExpectedData * Expected icon data, expressed as an array of byte values. + * If set null, skip the test for the favicon data. * @param aCallback * This function is called after the check finished. */ @@ -37,7 +41,9 @@ function checkFaviconDataForPage( aPageURI, async function (aURI, aDataLen, aData, aMimeType) { Assert.equal(aExpectedMimeType, aMimeType); - Assert.ok(compareArrays(aExpectedData, aData)); + if (aExpectedData) { + Assert.ok(compareArrays(aExpectedData, aData)); + } await check_guid_for_uri(aPageURI); aCallback(); } @@ -76,3 +82,82 @@ function promiseFaviconChanged(aExpectedPageURI, aExpectedFaviconURI) { }); }); } + +/** + * Create favicon file to temp directory. + * + * @param {string} aFileName + * File name that will be created in temp directory. + * @returns {object} + * { + * file: nsIFile, + * uri: nsIURI, + * data: byte Array, + * mimetype: String, + * } + */ +async function createFavicon(aFileName) { + // Copy the favicon file we have to the specified file in temp directory. + let originalFaviconFile = do_get_file("favicon-normal16.png"); + let tempDir = Services.dirsvc.get("TmpD", Ci.nsIFile); + let faviconFile = tempDir.clone(); + faviconFile.append(aFileName); + await IOUtils.copy(originalFaviconFile.path, faviconFile.path); + + // Append some data that sniffers/encoders will ignore that will distinguish + // the different favicons we'll create. + let stream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance( + Ci.nsIFileOutputStream + ); + const WRONLY_PERMISSION = 0o600; + stream.init( + faviconFile, + FileUtils.MODE_WRONLY | FileUtils.MODE_APPEND, + WRONLY_PERMISSION, + 0 + ); + uniqueFaviconId++; + let uniqueStr = "uid:" + uniqueFaviconId; + stream.write(uniqueStr, uniqueStr.length); + stream.close(); + + Assert.equal(faviconFile.leafName.substr(0, aFileName.length), aFileName); + + return { + file: faviconFile, + uri: uri(faviconFile), + data: readFileData(faviconFile), + mimeType: "image/png", + }; +} + +/** + * Create nsIURI for given favicon object. + * + * @param {object} aFavicon + * Favicon object created by createFavicon(). + * @returns {nsIURI} + */ +async function createDataURLForFavicon(aFavicon) { + let dataURL = await toDataURL(aFavicon.data, aFavicon.mimeType); + return uri(dataURL); +} + +/** + * Create data URL string from given byte array and type. + * + * @param {Array} data + * Byte array. + * @param {string} type + * The type of this data. + * @returns {string} + */ +function toDataURL(data, type) { + let blob = new Blob([new Uint8Array(data)], { type }); + return new Promise((resolve, reject) => { + let reader = new FileReader(); + reader.addEventListener("load", () => resolve(reader.result)); + reader.addEventListener("error", reject); + reader.readAsDataURL(blob); + }); +} diff --git a/toolkit/components/places/tests/favicons/test_cached-favicon_mime_type.js b/toolkit/components/places/tests/favicons/test_cached-favicon_mime_type.js index c1f6689a70..52eb81ae85 100644 --- a/toolkit/components/places/tests/favicons/test_cached-favicon_mime_type.js +++ b/toolkit/components/places/tests/favicons/test_cached-favicon_mime_type.js @@ -68,14 +68,12 @@ add_task(async function () { info("Test that the content type of a favicon we add is correct."); let testURI = uri("http://mozilla.org/"); // Add the data before opening - PlacesUtils.favicons.replaceFaviconDataFromDataURL( + await PlacesTestUtils.addVisits(testURI); + await PlacesTestUtils.setFaviconForPage( + testURI, testIconURI, - testFaviconData, - 0, - systemPrincipal + testFaviconData ); - await PlacesTestUtils.addVisits(testURI); - await setFaviconForPage(testURI, testIconURI); // Open the channel let channel = NetUtil.newChannel({ uri: PlacesUtils.favicons.getFaviconLinkForIcon(testIconURI).spec, @@ -120,14 +118,12 @@ add_task(async function test_userpass() { CACHED_ICON_NORMAL, CACHED_ICON_USERPASS, ]) { - PlacesUtils.favicons.replaceFaviconDataFromDataURL( + await PlacesTestUtils.addVisits(pageURI); + await PlacesTestUtils.setFaviconForPage( + pageURI, iconURI, - testFaviconData, - 0, - systemPrincipal + testFaviconData ); - await PlacesTestUtils.addVisits(pageURI); - await setFaviconForPage(pageURI, iconURI); // Open the channel let channel = NetUtil.newChannel({ diff --git a/toolkit/components/places/tests/favicons/test_expire_on_new_icons.js b/toolkit/components/places/tests/favicons/test_expire_on_new_icons.js index d5a7c42ba3..f0089d737b 100644 --- a/toolkit/components/places/tests/favicons/test_expire_on_new_icons.js +++ b/toolkit/components/places/tests/favicons/test_expire_on_new_icons.js @@ -28,23 +28,23 @@ add_task(async function test_expire_associated() { ]; for (let icon of favicons) { - let data = readFileData(do_get_file(icon.name)); - PlacesUtils.favicons.replaceFaviconData( - NetUtil.newURI(TEST_URL + icon.name), - data, + let dataURL = await readFileDataAsDataURL( + do_get_file(icon.name), icon.mimeType ); - await setFaviconForPage(TEST_URL, TEST_URL + icon.name); + await PlacesTestUtils.setFaviconForPage( + TEST_URL, + TEST_URL + icon.name, + dataURL + ); if (icon.expired) { await expireIconRelationsForPage(TEST_URL); // Add the same icon to another page. - PlacesUtils.favicons.replaceFaviconData( - NetUtil.newURI(TEST_URL + icon.name), - data, - icon.mimeType, - icon.expire + await PlacesTestUtils.setFaviconForPage( + TEST_URL2, + TEST_URL + icon.name, + dataURL ); - await setFaviconForPage(TEST_URL2, TEST_URL + icon.name); } } @@ -88,13 +88,7 @@ add_task(async function test_expire_root() { // Insert an expired icon. let iconURI = NetUtil.newURI(pageURI.spec + "favicon-normal16.png"); - PlacesUtils.favicons.replaceFaviconDataFromDataURL( - iconURI, - SMALLPNG_DATA_URI.spec, - 0, - systemPrincipal - ); - await setFaviconForPage(pageURI, iconURI); + await PlacesTestUtils.setFaviconForPage(pageURI, iconURI, SMALLPNG_DATA_URI); Assert.equal( await countEntries("moz_icons_to_pages"), 1, @@ -105,13 +99,11 @@ add_task(async function test_expire_root() { // Now insert a new root icon. let rootIconURI = NetUtil.newURI(pageURI.spec + "favicon.ico"); - PlacesUtils.favicons.replaceFaviconDataFromDataURL( + await PlacesTestUtils.setFaviconForPage( + pageURI, rootIconURI, - SMALLPNG_DATA_URI.spec, - 0, - systemPrincipal + SMALLPNG_DATA_URI ); - await setFaviconForPage(pageURI, rootIconURI); // Only the root icon should have survived. Assert.equal( diff --git a/toolkit/components/places/tests/favicons/test_favicons_conversions.js b/toolkit/components/places/tests/favicons/test_favicons_conversions.js index 28a0fffb7f..dd8a35c5ac 100644 --- a/toolkit/components/places/tests/favicons/test_favicons_conversions.js +++ b/toolkit/components/places/tests/favicons/test_favicons_conversions.js @@ -43,29 +43,24 @@ async function checkFaviconDataConversion( }); let faviconURI = NetUtil.newURI("http://places.test/icon/" + aFileName); let fileData = readFileOfLength(aFileName, aFileLength); + let fileDataURL = await fileDataToDataURL(fileData, aFileMimeType); + await PlacesTestUtils.setFaviconForPage( + pageURI.spec, + faviconURI.spec, + fileDataURL + ); - PlacesUtils.favicons.replaceFaviconData(faviconURI, fileData, aFileMimeType); await new Promise(resolve => { - PlacesUtils.favicons.setAndFetchFaviconForPage( - pageURI, - faviconURI, - true, - PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE, - (aURI, aDataLen, aData, aMimeType) => { - if (!aExpectConversion) { - Assert.ok(compareArrays(aData, fileData)); - Assert.equal(aMimeType, aFileMimeType); - } else { - if (!aVaryOnWindows || !isWindows) { - let expectedFile = do_get_file("expected-" + aFileName + ".png"); - Assert.ok(compareArrays(aData, readFileData(expectedFile))); - } - Assert.equal(aMimeType, "image/png"); - } - resolve(); - }, - Services.scriptSecurityManager.getSystemPrincipal() - ); + if (!aExpectConversion) { + checkFaviconDataForPage(pageURI, aFileMimeType, fileData, resolve); + } else if (!aVaryOnWindows || !isWindows) { + let expectedFile = do_get_file("expected-" + aFileName + ".png"); + let expectedData = readFileData(expectedFile); + checkFaviconDataForPage(pageURI, "image/png", expectedData, resolve); + } else { + // Not check the favicon data. + checkFaviconDataForPage(pageURI, "image/png", null, resolve); + } }); } diff --git a/toolkit/components/places/tests/favicons/test_favicons_protocols_ref.js b/toolkit/components/places/tests/favicons/test_favicons_protocols_ref.js index aa0241a3d2..4d359f7307 100644 --- a/toolkit/components/places/tests/favicons/test_favicons_protocols_ref.js +++ b/toolkit/components/places/tests/favicons/test_favicons_protocols_ref.js @@ -9,21 +9,16 @@ const ICON32_URL = "http://places.test/favicon-normal32.png"; add_task(async function () { await PlacesTestUtils.addVisits(PAGE_URL); // Add 2 differently sized favicons for this page. - - let data = readFileData(do_get_file("favicon-normal16.png")); - PlacesUtils.favicons.replaceFaviconData( - Services.io.newURI(ICON16_URL), - data, + let dataURL16 = await readFileDataAsDataURL( + do_get_file("favicon-normal16.png"), "image/png" ); - await setFaviconForPage(PAGE_URL, ICON16_URL); - data = readFileData(do_get_file("favicon-normal32.png")); - PlacesUtils.favicons.replaceFaviconData( - Services.io.newURI(ICON32_URL), - data, + await PlacesTestUtils.setFaviconForPage(PAGE_URL, ICON16_URL, dataURL16); + let dataURL32 = await readFileDataAsDataURL( + do_get_file("favicon-normal32.png"), "image/png" ); - await setFaviconForPage(PAGE_URL, ICON32_URL); + await PlacesTestUtils.setFaviconForPage(PAGE_URL, ICON32_URL, dataURL32); const PAGE_ICON_URL = "page-icon:" + PAGE_URL; diff --git a/toolkit/components/places/tests/favicons/test_getFaviconDataForPage.js b/toolkit/components/places/tests/favicons/test_getFaviconDataForPage.js index 80f498f33f..8c6fb0a2bb 100644 --- a/toolkit/components/places/tests/favicons/test_getFaviconDataForPage.js +++ b/toolkit/components/places/tests/favicons/test_getFaviconDataForPage.js @@ -60,12 +60,8 @@ add_task(async function test_fallback() { info("Set icon for the root"); await PlacesTestUtils.addVisits(ROOT_URL); let data = readFileData(do_get_file("favicon-normal16.png")); - PlacesUtils.favicons.replaceFaviconData( - NetUtil.newURI(ROOT_ICON_URL), - data, - "image/png" - ); - await setFaviconForPage(ROOT_URL, ROOT_ICON_URL); + let dataURL = await fileDataToDataURL(data, "image/png"); + await PlacesTestUtils.setFaviconForPage(ROOT_URL, ROOT_ICON_URL, dataURL); info("check fallback icons"); await new Promise(resolve => { @@ -96,12 +92,8 @@ add_task(async function test_fallback() { info("Now add a proper icon for the page"); await PlacesTestUtils.addVisits(SUBPAGE_URL); let data32 = readFileData(do_get_file("favicon-normal32.png")); - PlacesUtils.favicons.replaceFaviconData( - NetUtil.newURI(ICON32_URL), - data32, - "image/png" - ); - await setFaviconForPage(SUBPAGE_URL, ICON32_URL); + let dataURL32 = await fileDataToDataURL(data32, "image/png"); + await PlacesTestUtils.setFaviconForPage(SUBPAGE_URL, ICON32_URL, dataURL32); info("check no fallback icons"); await new Promise(resolve => { diff --git a/toolkit/components/places/tests/favicons/test_getFaviconURLForPage.js b/toolkit/components/places/tests/favicons/test_getFaviconURLForPage.js index e8f459cb08..3fa11ae6c0 100644 --- a/toolkit/components/places/tests/favicons/test_getFaviconURLForPage.js +++ b/toolkit/components/places/tests/favicons/test_getFaviconURLForPage.js @@ -57,13 +57,11 @@ add_task(async function test_fallback() { info("Set icon for the root"); await PlacesTestUtils.addVisits(ROOT_URL); - let data = readFileData(do_get_file("favicon-normal16.png")); - PlacesUtils.favicons.replaceFaviconData( - NetUtil.newURI(ROOT_ICON_URL), - data, + let dataURL = await readFileDataAsDataURL( + do_get_file("favicon-normal16.png"), "image/png" ); - await setFaviconForPage(ROOT_URL, ROOT_ICON_URL); + await PlacesTestUtils.setFaviconForPage(ROOT_URL, ROOT_ICON_URL, dataURL); info("check fallback icons"); Assert.equal( @@ -79,13 +77,11 @@ add_task(async function test_fallback() { info("Now add a proper icon for the page"); await PlacesTestUtils.addVisits(SUBPAGE_URL); - let data32 = readFileData(do_get_file("favicon-normal32.png")); - PlacesUtils.favicons.replaceFaviconData( - NetUtil.newURI(ICON32_URL), - data32, + let dataURL32 = await readFileDataAsDataURL( + do_get_file("favicon-normal32.png"), "image/png" ); - await setFaviconForPage(SUBPAGE_URL, ICON32_URL); + await PlacesTestUtils.setFaviconForPage(SUBPAGE_URL, ICON32_URL, dataURL32); info("check no fallback icons"); Assert.equal( diff --git a/toolkit/components/places/tests/favicons/test_heavy_favicon.js b/toolkit/components/places/tests/favicons/test_heavy_favicon.js index 09adcaf6fa..4541de9bff 100644 --- a/toolkit/components/places/tests/favicons/test_heavy_favicon.js +++ b/toolkit/components/places/tests/favicons/test_heavy_favicon.js @@ -26,8 +26,8 @@ add_task(async function () { let pageURI = uri("http://foo.bar/"); await PlacesTestUtils.addVisits(pageURI); - PlacesUtils.favicons.replaceFaviconData(icon.uri, icon.data, icon.mimetype); - await setFaviconForPage(pageURI, icon.uri); + let dataURI = await fileDataToDataURL(icon.data, icon.mimetype); + await PlacesTestUtils.setFaviconForPage(pageURI.spec, icon.uri.spec, dataURI); Assert.equal( await getFaviconUrlForPage(pageURI), icon.uri.spec, diff --git a/toolkit/components/places/tests/favicons/test_incremental_vacuum.js b/toolkit/components/places/tests/favicons/test_incremental_vacuum.js index ab93121d47..2c1a5ad3f9 100644 --- a/toolkit/components/places/tests/favicons/test_incremental_vacuum.js +++ b/toolkit/components/places/tests/favicons/test_incremental_vacuum.js @@ -16,10 +16,9 @@ add_task(async function () { let url = "http://foo.bar/"; await PlacesTestUtils.addVisits(url); for (let i = 0; i < 10; ++i) { - let iconUri = NetUtil.newURI("http://mozilla.org/" + i); - let data = readFileData(icon.file); - PlacesUtils.favicons.replaceFaviconData(iconUri, data, icon.mimetype); - await setFaviconForPage(url, iconUri); + let iconUri = "http://mozilla.org/" + i; + let dataURL = await readFileDataAsDataURL(icon.file, icon.mimetype); + await PlacesTestUtils.setFaviconForPage(url, iconUri, dataURL); } let promise = TestUtils.topicObserved("places-favicons-expired"); diff --git a/toolkit/components/places/tests/favicons/test_multiple_frames.js b/toolkit/components/places/tests/favicons/test_multiple_frames.js index 5c7f585715..a6aae572de 100644 --- a/toolkit/components/places/tests/favicons/test_multiple_frames.js +++ b/toolkit/components/places/tests/favicons/test_multiple_frames.js @@ -14,9 +14,15 @@ add_task(async function () { let faviconURI = NetUtil.newURI("http://places.test/icon/favicon-multi.ico"); // Fake window. let win = { devicePixelRatio: 1.0 }; - let icoData = readFileData(do_get_file("favicon-multi.ico")); - PlacesUtils.favicons.replaceFaviconData(faviconURI, icoData, "image/x-icon"); - await setFaviconForPage(pageURI, faviconURI); + let icoDataURL = await readFileDataAsDataURL( + do_get_file("favicon-multi.ico"), + "image/x-icon" + ); + await PlacesTestUtils.setFaviconForPage( + pageURI.spec, + faviconURI.spec, + icoDataURL + ); for (let size of [16, 32, 64]) { let file = do_get_file(`favicon-multi-frame${size}.png`); diff --git a/toolkit/components/places/tests/favicons/test_page-icon_protocol.js b/toolkit/components/places/tests/favicons/test_page-icon_protocol.js index 287484868f..2241dec990 100644 --- a/toolkit/components/places/tests/favicons/test_page-icon_protocol.js +++ b/toolkit/components/places/tests/favicons/test_page-icon_protocol.js @@ -76,25 +76,12 @@ var gFavicon; add_task(async function setup() { await PlacesTestUtils.addVisits(TEST_URI); - - PlacesUtils.favicons.replaceFaviconDataFromDataURL( + await PlacesTestUtils.setFaviconForPage( + TEST_URI, ICON_URI, ICON_DATAURL, - (Date.now() + 8640000) * 1000, - Services.scriptSecurityManager.getSystemPrincipal() + (Date.now() + 8640000) * 1000 ); - - await new Promise(resolve => { - PlacesUtils.favicons.setAndFetchFaviconForPage( - TEST_URI, - ICON_URI, - false, - PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE, - resolve, - Services.scriptSecurityManager.getSystemPrincipal() - ); - }); - gDefaultFavicon = await fetchIconForSpec( PlacesUtils.favicons.defaultFavicon.spec ); @@ -133,13 +120,11 @@ add_task(async function subpage_url_fallback() { add_task(async function svg_icon() { let faviconURI = NetUtil.newURI("http://places.test/favicon.svg"); - PlacesUtils.favicons.replaceFaviconDataFromDataURL( + await PlacesTestUtils.setFaviconForPage( + TEST_URI, faviconURI, - SMALLSVG_DATA_URI.spec, - 0, - Services.scriptSecurityManager.getSystemPrincipal() + SMALLSVG_DATA_URI ); - await setFaviconForPage(TEST_URI, faviconURI); let svgIcon = await fetchIconForSpec(SMALLSVG_DATA_URI.spec); info(svgIcon.contentType); let pageIcon = await fetchIconForSpec("page-icon:" + TEST_URI.spec); @@ -270,23 +255,8 @@ add_task(async function test_with_user_pass() { for (const { pageURI, iconURI } of testData) { for (const loadingIconURISpec of [PAGE_ICON_NORMAL, PAGE_ICON_USERPASS]) { - PlacesUtils.favicons.replaceFaviconDataFromDataURL( - iconURI, - ICON_DATAURL, - 0, - systemPrincipal - ); await PlacesTestUtils.addVisits(pageURI); - await new Promise(resolve => { - PlacesUtils.favicons.setAndFetchFaviconForPage( - pageURI, - iconURI, - false, - PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE, - resolve, - Services.scriptSecurityManager.getSystemPrincipal() - ); - }); + await PlacesTestUtils.setFaviconForPage(pageURI, iconURI, ICON_DATAURL); let { data, contentType } = await fetchIconForSpec(loadingIconURISpec); Assert.equal(contentType, gFavicon.contentType); diff --git a/toolkit/components/places/tests/favicons/test_replaceFaviconData.js b/toolkit/components/places/tests/favicons/test_replaceFaviconData.js deleted file mode 100644 index 2e9835eaa9..0000000000 --- a/toolkit/components/places/tests/favicons/test_replaceFaviconData.js +++ /dev/null @@ -1,395 +0,0 @@ -/* 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 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_replaceFaviconData_validHistoryURI() { - info("test replaceFaviconData for valid history uri"); - - let pageURI = uri("http://test1.bar/"); - await PlacesTestUtils.addVisits(pageURI); - - let favicon = createFavicon("favicon1.png"); - - iconsvc.replaceFaviconData(favicon.uri, favicon.data, favicon.mimetype); - - await new Promise(resolve => { - iconsvc.setAndFetchFaviconForPage( - pageURI, - favicon.uri, - true, - PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE, - function test_replaceFaviconData_validHistoryURI_check( - aURI, - aDataLen, - aData, - aMimeType - ) { - dump("GOT " + aMimeType + "\n"); - checkCallbackSucceeded( - aMimeType, - aData, - favicon.mimetype, - favicon.data - ); - checkFaviconDataForPage( - pageURI, - favicon.mimetype, - favicon.data, - function test_replaceFaviconData_validHistoryURI_callback() { - favicon.file.remove(false); - resolve(); - } - ); - }, - systemPrincipal - ); - }); - - await PlacesUtils.history.clear(); -}); - -add_task(async function test_replaceFaviconData_overrideDefaultFavicon() { - info("test replaceFaviconData 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.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_replaceFaviconData_overrideDefaultFavicon_check( - aURI, - aDataLen, - aData, - aMimeType - ) { - checkCallbackSucceeded( - aMimeType, - aData, - secondFavicon.mimetype, - secondFavicon.data - ); - checkFaviconDataForPage( - pageURI, - secondFavicon.mimetype, - secondFavicon.data, - function test_replaceFaviconData_overrideDefaultFavicon_callback() { - firstFavicon.file.remove(false); - secondFavicon.file.remove(false); - resolve(); - } - ); - }, - systemPrincipal - ); - }); - - await PlacesUtils.history.clear(); -}); - -add_task(async function test_replaceFaviconData_replaceExisting() { - info( - "test replaceFaviconData 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_replaceFaviconData_replaceExisting_firstSet_check( - aURI, - aDataLen, - aData, - aMimeType - ) { - checkCallbackSucceeded( - aMimeType, - aData, - firstFavicon.mimetype, - firstFavicon.data - ); - checkFaviconDataForPage( - pageURI, - firstFavicon.mimetype, - firstFavicon.data, - function test_replaceFaviconData_overrideDefaultFavicon_firstCallback() { - iconsvc.replaceFaviconData( - firstFavicon.uri, - secondFavicon.data, - secondFavicon.mimetype - ); - PlacesTestUtils.promiseAsyncUpdates().then(() => { - checkFaviconDataForPage( - pageURI, - secondFavicon.mimetype, - secondFavicon.data, - function test_replaceFaviconData_overrideDefaultFavicon_secondCallback() { - firstFavicon.file.remove(false); - secondFavicon.file.remove(false); - resolve(); - }, - systemPrincipal - ); - }); - } - ); - }, - systemPrincipal - ); - }); - - await PlacesUtils.history.clear(); -}); - -add_task(async function test_replaceFaviconData_unrelatedReplace() { - info("test replaceFaviconData 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.replaceFaviconData( - unrelatedFavicon.uri, - unrelatedFavicon.data, - unrelatedFavicon.mimetype - ); - - await new Promise(resolve => { - iconsvc.setAndFetchFaviconForPage( - pageURI, - favicon.uri, - true, - PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE, - function test_replaceFaviconData_unrelatedReplace_check( - aURI, - aDataLen, - aData, - aMimeType - ) { - checkCallbackSucceeded( - aMimeType, - aData, - favicon.mimetype, - favicon.data - ); - checkFaviconDataForPage( - pageURI, - favicon.mimetype, - favicon.data, - function test_replaceFaviconData_unrelatedReplace_callback() { - favicon.file.remove(false); - unrelatedFavicon.file.remove(false); - resolve(); - } - ); - }, - systemPrincipal - ); - }); - - await PlacesUtils.history.clear(); -}); - -add_task(async function test_replaceFaviconData_badInputs() { - info("test replaceFaviconData to throw on bad inputs"); - let icon = createFavicon("favicon8.png"); - - Assert.throws( - () => iconsvc.replaceFaviconData(icon.uri, icon.data, ""), - /NS_ERROR_ILLEGAL_VALUE/ - ); - Assert.throws( - () => iconsvc.replaceFaviconData(icon.uri, icon.data, "not-an-image"), - /NS_ERROR_ILLEGAL_VALUE/ - ); - Assert.throws( - () => iconsvc.replaceFaviconData(null, icon.data, icon.mimetype), - /NS_ERROR_ILLEGAL_VALUE/ - ); - Assert.throws( - () => iconsvc.replaceFaviconData(icon.uri, [], icon.mimetype), - /NS_ERROR_ILLEGAL_VALUE/ - ); - Assert.throws( - () => iconsvc.replaceFaviconData(icon.uri, null, icon.mimetype), - /NS_ERROR_XPC_CANT_CONVERT_PRIMITIVE_TO_ARRAY/ - ); - - icon.file.remove(false); - await PlacesUtils.history.clear(); -}); - -add_task(async function test_replaceFaviconData_twiceReplace() { - info("test replaceFaviconData on multiple replacements"); - - let pageURI = uri("http://test5.bar/"); - await PlacesTestUtils.addVisits(pageURI); - - let firstFavicon = createFavicon("favicon9.png"); - let secondFavicon = createFavicon("favicon10.png"); - - iconsvc.replaceFaviconData( - firstFavicon.uri, - firstFavicon.data, - firstFavicon.mimetype - ); - 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_replaceFaviconData_twiceReplace_check( - aURI, - aDataLen, - aData, - aMimeType - ) { - checkCallbackSucceeded( - aMimeType, - aData, - secondFavicon.mimetype, - secondFavicon.data - ); - checkFaviconDataForPage( - pageURI, - secondFavicon.mimetype, - secondFavicon.data, - function test_replaceFaviconData_twiceReplace_callback() { - firstFavicon.file.remove(false); - secondFavicon.file.remove(false); - resolve(); - }, - systemPrincipal - ); - }, - systemPrincipal - ); - }); - - await PlacesUtils.history.clear(); -}); - -add_task(async function test_replaceFaviconData_rootOverwrite() { - info("test replaceFaviconData doesn't overwrite root = 1"); - - async function getRootValue(url) { - let db = await PlacesUtils.promiseDBConnection(); - let rows = await db.execute( - "SELECT root FROM moz_icons WHERE icon_url = :url", - { url } - ); - return rows[0].getResultByName("root"); - } - - const PAGE_URL = "http://rootoverwrite.bar/"; - let pageURI = Services.io.newURI(PAGE_URL); - const ICON_URL = "http://rootoverwrite.bar/favicon.ico"; - let iconURI = Services.io.newURI(ICON_URL); - - await PlacesTestUtils.addVisits(pageURI); - - let icon = createFavicon("favicon9.png"); - PlacesUtils.favicons.replaceFaviconData(iconURI, icon.data, icon.mimetype); - await PlacesTestUtils.addFavicons(new Map([[PAGE_URL, ICON_URL]])); - - Assert.equal(await getRootValue(ICON_URL), 1, "Check root == 1"); - let icon2 = createFavicon("favicon10.png"); - PlacesUtils.favicons.replaceFaviconData(iconURI, icon2.data, icon2.mimetype); - // replaceFaviconData doesn't have a callback, but we must wait its updated. - await PlacesTestUtils.promiseAsyncUpdates(); - Assert.equal(await getRootValue(ICON_URL), 1, "Check root did not change"); - - await PlacesUtils.history.clear(); -}); diff --git a/toolkit/components/places/tests/favicons/test_replaceFaviconDataFromDataURL.js b/toolkit/components/places/tests/favicons/test_replaceFaviconDataFromDataURL.js deleted file mode 100644 index c1b83fc8a7..0000000000 --- a/toolkit/components/places/tests/favicons/test_replaceFaviconDataFromDataURL.js +++ /dev/null @@ -1,537 +0,0 @@ -/* 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; -} diff --git a/toolkit/components/places/tests/favicons/test_root_icons.js b/toolkit/components/places/tests/favicons/test_root_icons.js index f0487cc162..5a101ed6a6 100644 --- a/toolkit/components/places/tests/favicons/test_root_icons.js +++ b/toolkit/components/places/tests/favicons/test_root_icons.js @@ -9,13 +9,11 @@ add_task(async function () { let pageURI = NetUtil.newURI("http://www.places.test/page/"); await PlacesTestUtils.addVisits(pageURI); let faviconURI = NetUtil.newURI("http://www.places.test/favicon.ico"); - PlacesUtils.favicons.replaceFaviconDataFromDataURL( + await PlacesTestUtils.setFaviconForPage( + pageURI, faviconURI, - SMALLPNG_DATA_URI.spec, - 0, - systemPrincipal + SMALLPNG_DATA_URI ); - await setFaviconForPage(pageURI, faviconURI); // Sanity checks. Assert.equal(await getFaviconUrlForPage(pageURI), faviconURI.spec); @@ -70,22 +68,18 @@ add_task(async function test_removePagesByTimeframe() { // Add a normal icon to the most recent page. let faviconURI = NetUtil.newURI(`${BASE_URL}/page/favicon.ico`); - PlacesUtils.favicons.replaceFaviconDataFromDataURL( + await PlacesTestUtils.setFaviconForPage( + pageURI, faviconURI, - SMALLSVG_DATA_URI.spec, - 0, - systemPrincipal + SMALLSVG_DATA_URI ); - await setFaviconForPage(pageURI, faviconURI); // Add a root icon to the most recent page. let rootIconURI = NetUtil.newURI(`${BASE_URL}/favicon.ico`); - PlacesUtils.favicons.replaceFaviconDataFromDataURL( + await PlacesTestUtils.setFaviconForPage( + pageURI, rootIconURI, - SMALLPNG_DATA_URI.spec, - 0, - systemPrincipal + SMALLPNG_DATA_URI ); - await setFaviconForPage(pageURI, rootIconURI); // Sanity checks. Assert.equal( @@ -141,13 +135,11 @@ add_task(async function test_different_host() { let pageURI = NetUtil.newURI("http://places.test/page/"); await PlacesTestUtils.addVisits(pageURI); let faviconURI = NetUtil.newURI("http://mozilla.test/favicon.ico"); - PlacesUtils.favicons.replaceFaviconDataFromDataURL( + await PlacesTestUtils.setFaviconForPage( + pageURI, faviconURI, - SMALLPNG_DATA_URI.spec, - 0, - systemPrincipal + SMALLPNG_DATA_URI ); - await setFaviconForPage(pageURI, faviconURI); Assert.equal( await getFaviconUrlForPage(pageURI), @@ -166,16 +158,25 @@ add_task(async function test_different_host() { add_task(async function test_same_size() { // Add two icons with the same size, one is a root icon. Check that the // non-root icon is preferred when a smaller size is requested. - let data = readFileData(do_get_file("favicon-normal32.png")); + let dataURL = await readFileDataAsDataURL( + do_get_file("favicon-normal32.png"), + "image/png" + ); let pageURI = NetUtil.newURI("http://new_places.test/page/"); await PlacesTestUtils.addVisits(pageURI); let faviconURI = NetUtil.newURI("http://new_places.test/favicon.ico"); - PlacesUtils.favicons.replaceFaviconData(faviconURI, data, "image/png"); - await setFaviconForPage(pageURI, faviconURI); + await PlacesTestUtils.setFaviconForPage( + pageURI.spec, + faviconURI.spec, + dataURL + ); faviconURI = NetUtil.newURI("http://new_places.test/another_icon.ico"); - PlacesUtils.favicons.replaceFaviconData(faviconURI, data, "image/png"); - await setFaviconForPage(pageURI, faviconURI); + await PlacesTestUtils.setFaviconForPage( + pageURI.spec, + faviconURI.spec, + dataURL + ); Assert.equal( await getFaviconUrlForPage(pageURI, 20), @@ -207,13 +208,7 @@ add_task(async function test_root_on_different_host() { // Root favicon for TEST_URL1. const ICON_URL = "http://places1.test/favicon.ico"; let iconURI = NetUtil.newURI(ICON_URL); - PlacesUtils.favicons.replaceFaviconDataFromDataURL( - iconURI, - SMALLPNG_DATA_URI.spec, - 0, - systemPrincipal - ); - await setFaviconForPage(pageURI1, iconURI); + await PlacesTestUtils.setFaviconForPage(pageURI1, iconURI, SMALLPNG_DATA_URI); Assert.equal(await getRootValue(ICON_URL), 1, "Check root == 1"); Assert.equal( await getFaviconUrlForPage(pageURI1, 16), @@ -222,13 +217,7 @@ add_task(async function test_root_on_different_host() { ); // Same favicon for TEST_URL2. - PlacesUtils.favicons.replaceFaviconDataFromDataURL( - iconURI, - SMALLPNG_DATA_URI.spec, - 0, - systemPrincipal - ); - await setFaviconForPage(pageURI2, iconURI); + await PlacesTestUtils.setFaviconForPage(pageURI2, iconURI, SMALLPNG_DATA_URI); Assert.equal(await getRootValue(ICON_URL), 1, "Check root == 1"); Assert.equal( await getFaviconUrlForPage(pageURI2, 16), diff --git a/toolkit/components/places/tests/favicons/test_setFaviconForPage.js b/toolkit/components/places/tests/favicons/test_setFaviconForPage.js new file mode 100644 index 0000000000..22364e5410 --- /dev/null +++ b/toolkit/components/places/tests/favicons/test_setFaviconForPage.js @@ -0,0 +1,245 @@ +/* Any copyright is dedicated to the Public Domain. + * https://creativecommons.org/publicdomain/zero/1.0/ */ + +/* + * Tests for setFaviconForPage() + */ + +add_task(async function test_validHistoryURI() { + let pageURI = uri("http://test1.bar/"); + await PlacesTestUtils.addVisits(pageURI); + + let favicon = await createFavicon("favicon1.png"); + + await doTestSetFaviconForPage({ + pageURI, + faviconURI: favicon.uri, + dataURL: await createDataURLForFavicon(favicon), + expectedFaviconData: favicon.data, + expectedFaviconMimeType: favicon.mimeType, + }); + + await IOUtils.remove(favicon.file.path); + await PlacesUtils.history.clear(); +}); + +add_task(async function test_overrideDefaultFavicon() { + let pageURI = uri("http://test2.bar/"); + await PlacesTestUtils.addVisits(pageURI); + + let firstFavicon = await createFavicon("favicon2.png"); + let secondFavicon = await createFavicon("favicon3.png"); + + await doTestSetFaviconForPage({ + pageURI, + faviconURI: firstFavicon.uri, + dataURL: await createDataURLForFavicon(secondFavicon), + expectedFaviconData: secondFavicon.data, + expectedFaviconMimeType: secondFavicon.mimeType, + }); + + await IOUtils.remove(firstFavicon.file.path); + await IOUtils.remove(secondFavicon.file.path); + await PlacesUtils.history.clear(); +}); + +add_task(async function test_replaceExisting() { + let pageURI = uri("http://test3.bar"); + await PlacesTestUtils.addVisits(pageURI); + + let firstFavicon = await createFavicon("favicon4.png"); + let secondFavicon = await createFavicon("favicon5.png"); + + await new Promise(resolve => { + PlacesUtils.favicons.setAndFetchFaviconForPage( + pageURI, + firstFavicon.uri, + true, + PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE, + function test_replaceExisting_firstSet_check( + aURI, + aDataLen, + aData, + aMimeType + ) { + Assert.equal(aMimeType, firstFavicon.mimeType); + Assert.ok(compareArrays(aData, firstFavicon.data)); + checkFaviconDataForPage( + pageURI, + firstFavicon.mimeType, + firstFavicon.data, + resolve + ); + }, + Services.scriptSecurityManager.getSystemPrincipal() + ); + }); + + await doTestSetFaviconForPage({ + pageURI, + faviconURI: firstFavicon.uri, + dataURL: await createDataURLForFavicon(secondFavicon), + expectedFaviconData: secondFavicon.data, + expectedFaviconMimeType: secondFavicon.mimeType, + }); + + await IOUtils.remove(firstFavicon.file.path); + await IOUtils.remove(secondFavicon.file.path); + await PlacesUtils.history.clear(); +}); + +add_task(async function test_twiceReplace() { + let pageURI = uri("http://test5.bar/"); + await PlacesTestUtils.addVisits(pageURI); + + let firstFavicon = await createFavicon("favicon9.png"); + let secondFavicon = await createFavicon("favicon10.png"); + + let firstFaviconDataURL = await createDataURLForFavicon(firstFavicon); + await new Promise(resolve => { + PlacesUtils.favicons.setFaviconForPage( + pageURI, + firstFavicon.uri, + firstFaviconDataURL, + null, + resolve + ); + }); + + await doTestSetFaviconForPage({ + pageURI, + faviconURI: firstFavicon.uri, + dataURL: await createDataURLForFavicon(secondFavicon), + expectedFaviconData: secondFavicon.data, + expectedFaviconMimeType: secondFavicon.mimeType, + }); + + await IOUtils.remove(firstFavicon.file.path); + await IOUtils.remove(secondFavicon.file.path); + await PlacesUtils.history.clear(); +}); + +add_task(async function test_userpass() { + let pageURI = uri("http://user:pass@test1.bar/"); + await PlacesTestUtils.addVisits(pageURI); + + let favicon = await createFavicon("favicon1.png"); + let faviconURI = uri("http://user:pass@test1.bar/favicon1.png"); + + await doTestSetFaviconForPage({ + pageURI, + faviconURI, + dataURL: await createDataURLForFavicon(favicon), + expectedFaviconData: favicon.data, + expectedFaviconMimeType: favicon.mimeType, + }); + + await IOUtils.remove(favicon.file.path); + await PlacesUtils.history.clear(); +}); + +add_task(async function test_svg() { + let pageURI = uri("http://example.com/"); + await PlacesTestUtils.addVisits(pageURI); + + const svgContent = ""; + + await doTestSetFaviconForPage({ + pageURI, + faviconURI: uri("http://example.com/favicon.svg"), + dataURL: uri(`data:image/svg+xml;utf8,${svgContent}`), + expectedFaviconData: Array.from(new TextEncoder().encode(svgContent)), + expectedFaviconMimeType: "image/svg+xml", + }); + + await PlacesUtils.history.clear(); +}); + +add_task(async function test_invalidPageURI() { + await PlacesTestUtils.addVisits(uri("http://example.com/")); + let favicon = await createFavicon("favicon-invalidPageURI.png"); + + for (let invalidURI of [null, "", "http://example.com"]) { + try { + info(`Invalid page URI test for [${invalidURI}]`); + PlacesUtils.favicons.setFaviconForPage( + invalidURI, + favicon.uri, + await createDataURLForFavicon(favicon) + ); + Assert.ok(false, "Error should happened"); + } catch (e) { + Assert.ok(true, `Expected error happend [${e.message}]`); + } + } +}); + +add_task(async function test_invalidFaviconURI() { + let pageURI = uri("http://example.com/"); + await PlacesTestUtils.addVisits(pageURI); + let favicon = await createFavicon("favicon-invalidFaviconURI.png"); + + for (let invalidURI of [null, "", favicon.uri.spec]) { + try { + info(`Invalid favicon URI test for [${invalidURI}]`); + PlacesUtils.favicons.setFaviconForPage( + pageURI, + invalidURI, + await createDataURLForFavicon(favicon) + ); + Assert.ok(false, "Error should happened"); + } catch (e) { + Assert.ok(true, `Expected error happend [${e.message}]`); + } + } +}); + +add_task(async function test_invalidFaviconDataURI() { + let pageURI = uri("http://example.com/"); + await PlacesTestUtils.addVisits(pageURI); + let favicon = createFavicon("favicon-invalidFaviconDataURI.png"); + + for (let invalidURI of [ + null, + "", + "data:text/plain;base64,SGVsbG8sIFdvcmxkIQ==", + ]) { + try { + info(`Invalid favicon data URI test for [${invalidURI}]`); + PlacesUtils.favicons.setFaviconForPage(pageURI, favicon.uri, invalidURI); + Assert.ok(false, "Error should happened"); + } catch (e) { + Assert.ok(true, `Expected error happend [${e.message}]`); + } + } +}); + +async function doTestSetFaviconForPage({ + pageURI, + faviconURI, + dataURL, + expectedFaviconData, + expectedFaviconMimeType, +}) { + let result = await new Promise(resolve => { + PlacesUtils.favicons.setFaviconForPage( + pageURI, + faviconURI, + dataURL, + null, + resolve + ); + }); + + info("Check the result of setFaviconForPage"); + Assert.equal(result, 0); + + await new Promise(resolve => { + checkFaviconDataForPage( + pageURI, + expectedFaviconMimeType, + expectedFaviconData, + resolve + ); + }); +} diff --git a/toolkit/components/places/tests/favicons/xpcshell.toml b/toolkit/components/places/tests/favicons/xpcshell.toml index 997aa48e0b..2716e72fda 100644 --- a/toolkit/components/places/tests/favicons/xpcshell.toml +++ b/toolkit/components/places/tests/favicons/xpcshell.toml @@ -57,10 +57,6 @@ support-files = [ ["test_query_result_favicon_changed_on_child.js"] -["test_replaceFaviconData.js"] - -["test_replaceFaviconDataFromDataURL.js"] - ["test_root_icons.js"] ["test_setAndFetchFaviconForPage.js"] @@ -69,4 +65,6 @@ support-files = [ ["test_setAndFetchFaviconForPage_redirects.js"] +["test_setFaviconForPage.js"] + ["test_svg_favicon.js"] diff --git a/toolkit/components/places/tests/gtest/places_test_harness_tail.h b/toolkit/components/places/tests/gtest/places_test_harness_tail.h index 0464d14e0d..27de44eaa9 100644 --- a/toolkit/components/places/tests/gtest/places_test_harness_tail.h +++ b/toolkit/components/places/tests/gtest/places_test_harness_tail.h @@ -20,7 +20,7 @@ class RunNextTest : public mozilla::Runnable { public: RunNextTest() : mozilla::Runnable("RunNextTest") {} NS_IMETHOD Run() override { - NS_ASSERTION(NS_IsMainThread(), "Not running on the main thread?"); + MOZ_RELEASE_ASSERT(NS_IsMainThread(), "Not running on the main thread?"); if (gTestsIndex < int(mozilla::ArrayLength(gTests))) { do_test_pending(); Test& test = gTests[gTestsIndex++]; @@ -47,7 +47,7 @@ void run_next_test() { int gPendingTests = 0; void do_test_pending() { - NS_ASSERTION(NS_IsMainThread(), "Not running on the main thread?"); + MOZ_RELEASE_ASSERT(NS_IsMainThread(), "Not running on the main thread?"); if (kDebugRunNextTest) { printf_stderr("do_test_pending()\n"); MozWalkTheStack(stderr); @@ -56,8 +56,8 @@ void do_test_pending() { } void do_test_finished() { - NS_ASSERTION(NS_IsMainThread(), "Not running on the main thread?"); - NS_ASSERTION(gPendingTests > 0, "Invalid pending test count!"); + MOZ_RELEASE_ASSERT(NS_IsMainThread(), "Not running on the main thread?"); + MOZ_RELEASE_ASSERT(gPendingTests > 0, "Invalid pending test count!"); gPendingTests--; } diff --git a/toolkit/components/places/tests/head_common.js b/toolkit/components/places/tests/head_common.js index d7a465786e..22d89db139 100644 --- a/toolkit/components/places/tests/head_common.js +++ b/toolkit/components/places/tests/head_common.js @@ -169,7 +169,6 @@ function readFileData(aFile) { } return bytes; } - /** * Reads the data from the named file, verifying the expected file length. * @@ -186,6 +185,42 @@ function readFileOfLength(aFileName, aExpectedLength) { return data; } +/** + * Reads the data from the specified nsIFile, then returns it as data URL. + * + * @param file + * The nsIFile to read from. + * @param mimeType + * The mime type of the file content. + * @return Promise that retunes data URL. + */ +async function readFileDataAsDataURL(file, mimeType) { + const data = readFileData(file); + return fileDataToDataURL(data, mimeType); +} + +/** + * Converts the given data to the data URL. + * + * @param data + * The file data. + * @param mimeType + * The mime type of the file content. + * @return Promise that retunes data URL. + */ +async function fileDataToDataURL(data, mimeType) { + const dataURL = await new Promise(resolve => { + const buffer = new Uint8ClampedArray(data); + const blob = new Blob([buffer], { type: mimeType }); + const reader = new FileReader(); + reader.onload = e => { + resolve(e.target.result); + }; + reader.readAsDataURL(blob); + }); + return dataURL; +} + /** * Returns the base64-encoded version of the given string. This function is * similar to window.btoa, but is available to xpcshell tests also. diff --git a/toolkit/components/places/tests/history/test_remove.js b/toolkit/components/places/tests/history/test_remove.js index c018a996f3..8c469b5930 100644 --- a/toolkit/components/places/tests/history/test_remove.js +++ b/toolkit/components/places/tests/history/test_remove.js @@ -292,20 +292,7 @@ add_task(async function test_orphans() { ); // Also create a root icon. let faviconURI = Services.io.newURI(uri.spec + "favicon.ico"); - PlacesUtils.favicons.replaceFaviconDataFromDataURL( - faviconURI, - SMALLPNG_DATA_URI.spec, - 0, - Services.scriptSecurityManager.getSystemPrincipal() - ); - PlacesUtils.favicons.setAndFetchFaviconForPage( - uri, - faviconURI, - true, - PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE, - null, - Services.scriptSecurityManager.getSystemPrincipal() - ); + await PlacesTestUtils.setFaviconForPage(uri, faviconURI, SMALLPNG_DATA_URI); await PlacesUtils.history.update({ url: uri, diff --git a/toolkit/components/places/tests/unit/test_PlacesQuery_history.js b/toolkit/components/places/tests/unit/test_PlacesQuery_history.js index 9546e03730..24a046bcdc 100644 --- a/toolkit/components/places/tests/unit/test_PlacesQuery_history.js +++ b/toolkit/components/places/tests/unit/test_PlacesQuery_history.js @@ -3,6 +3,10 @@ http://creativecommons.org/publicdomain/zero/1.0/ */ "use strict"; +const { sinon } = ChromeUtils.importESModule( + "resource://testing-common/Sinon.sys.mjs" +); + const { PlacesQuery } = ChromeUtils.importESModule( "resource://gre/modules/PlacesQuery.sys.mjs" ); @@ -243,3 +247,32 @@ add_task(async function test_search_visits() { await PlacesUtils.history.clear(); }); + +add_task(async function test_search_interrupt() { + const { promise, reject } = Promise.withResolvers(); + const mockDatabase = { + executeCached: async (_, { query }) => { + if (query === "First Query") { + // Simulate a slow-running query which runs long enough to be + // interrupted by the next one. + await promise; + } + return []; + }, + interrupt: () => reject("interrupt() was called."), + }; + const stub = sinon + .stub(PlacesUtils, "promiseLargeCacheDBConnection") + .resolves(mockDatabase); + + const promiseFirstQuery = placesQuery.searchHistory("First Query"); + const promiseSecondQuery = placesQuery.searchHistory("Second Query"); + await Assert.rejects( + promiseFirstQuery, + /interrupt/, + "The first query was interrupted." + ); + ok(await promiseSecondQuery, "The second query resolved normally."); + + stub.restore(); +}); -- cgit v1.2.3