Backed out 2 changesets (bug 1911489) for causing build bustages @ FaviconHelpers.cpp CLOSED TREE

Backed out changeset 1f24313b74af (bug 1911489)
Backed out changeset 6badc2766d0f (bug 1911489)
This commit is contained in:
Sandor Molnar
2024-10-08 00:22:13 +03:00
parent 92076e16a7
commit d8c8b45c5a
28 changed files with 338 additions and 303 deletions

View File

@@ -137,15 +137,14 @@ export class LinkHandlerParent extends JSWindowActorParent {
} }
if (canStoreIcon) { if (canStoreIcon) {
try { try {
lazy.PlacesUtils.favicons lazy.PlacesUtils.favicons.setFaviconForPage(
.setFaviconForPage( Services.io.newURI(pageURL),
Services.io.newURI(pageURL), Services.io.newURI(originalURL),
Services.io.newURI(originalURL), iconURI,
iconURI, expiration && lazy.PlacesUtils.toPRTime(expiration),
expiration && lazy.PlacesUtils.toPRTime(expiration), null,
isRichIcon isRichIcon
) );
.catch(console.error);
} catch (ex) { } catch (ex) {
console.error(ex); console.error(ex);
} }

View File

@@ -23,7 +23,15 @@ add_task(async function test_notificationClose() {
let dataURL = makeURI( let dataURL = makeURI(
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVQI12P4//8/AAX+Av7czFnnAAAAAElFTkSuQmCC" "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVQI12P4//8/AAX+Av7czFnnAAAAAElFTkSuQmCC"
); );
await PlacesTestUtils.setFaviconForPage(notificationURI, dataURL, dataURL); await new Promise(resolve => {
PlacesUtils.favicons.setFaviconForPage(
notificationURI,
dataURL,
dataURL,
null,
resolve
);
});
await BrowserTestUtils.withNewTab( await BrowserTestUtils.withNewTab(
{ {

View File

@@ -247,13 +247,11 @@ DistributionCustomizer.prototype = {
if (item.icon && item.iconData) { if (item.icon && item.iconData) {
try { try {
lazy.PlacesUtils.favicons lazy.PlacesUtils.favicons.setFaviconForPage(
.setFaviconForPage( Services.io.newURI(item.link),
Services.io.newURI(item.link), Services.io.newURI(item.icon),
Services.io.newURI(item.icon), Services.io.newURI(item.iconData)
Services.io.newURI(item.iconData) );
)
.catch(console.error);
} catch (e) { } catch (e) {
console.error(e); console.error(e);
} }

View File

@@ -211,13 +211,11 @@ function setFaviconForBookmark(bookmark) {
return; return;
} }
lazy.PlacesUtils.favicons lazy.PlacesUtils.favicons.setFaviconForPage(
.setFaviconForPage( bookmark.URL.URI,
bookmark.URL.URI, Services.io.newURI("fake-favicon-uri:" + bookmark.URL.href),
Services.io.newURI("fake-favicon-uri:" + bookmark.URL.href), bookmark.Favicon.URI
bookmark.Favicon.URI );
)
.catch(lazy.log.error);
} }
// Cache of folder names to guids to be used by the getParentGuid // Cache of folder names to guids to be used by the getParentGuid

View File

@@ -886,6 +886,8 @@ class MigrationUtils {
); );
for (let faviconDataItem of favicons) { for (let faviconDataItem of favicons) {
let dataURL;
try { try {
// getMIMETypeFromContent throws error if could not get the mime type // getMIMETypeFromContent throws error if could not get the mime type
// from the data. // from the data.
@@ -895,7 +897,7 @@ class MigrationUtils {
faviconDataItem.faviconData.length faviconDataItem.faviconData.length
); );
let dataURL = await new Promise((resolve, reject) => { dataURL = await new Promise((resolve, reject) => {
let buffer = new Uint8ClampedArray(faviconDataItem.faviconData); let buffer = new Uint8ClampedArray(faviconDataItem.faviconData);
let blob = new Blob([buffer], { type: mimeType }); let blob = new Blob([buffer], { type: mimeType });
let reader = new FileReader(); let reader = new FileReader();
@@ -907,16 +909,15 @@ class MigrationUtils {
let fakeFaviconURI = Services.io.newURI( let fakeFaviconURI = Services.io.newURI(
"fake-favicon-uri:" + faviconDataItem.uri.spec "fake-favicon-uri:" + faviconDataItem.uri.spec
); );
lazy.PlacesUtils.favicons lazy.PlacesUtils.favicons.setFaviconForPage(
.setFaviconForPage( faviconDataItem.uri,
faviconDataItem.uri, fakeFaviconURI,
fakeFaviconURI, Services.io.newURI(dataURL)
Services.io.newURI(dataURL) );
)
.catch(console.warn);
} catch (e) { } catch (e) {
// Even if error happens for favicon, continue the process. // Even if error happens for favicon, continue the process.
console.warn(e); console.warn(e);
continue;
} }
} }
} }

View File

@@ -129,15 +129,11 @@ export class FaviconFeed {
const redirectedUri = Services.io.newURI(lastVisit.url); const redirectedUri = Services.io.newURI(lastVisit.url);
const iconInfo = await this.getFaviconInfo(redirectedUri); const iconInfo = await this.getFaviconInfo(redirectedUri);
if (iconInfo?.faviconSize >= MIN_FAVICON_SIZE) { if (iconInfo?.faviconSize >= MIN_FAVICON_SIZE) {
try { lazy.PlacesUtils.favicons.copyFavicons(
lazy.PlacesUtils.favicons.copyFavicons( redirectedUri,
redirectedUri, Services.io.newURI(url),
Services.io.newURI(url), lazy.PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE
lazy.PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE );
);
} catch (ex) {
console.error(`Failed to copy favicon [${ex}]`);
}
} }
} }
} }
@@ -200,9 +196,11 @@ export class FaviconFeed {
try { try {
// If the given faviconURI is data URL, set it as is. // If the given faviconURI is data URL, set it as is.
if (faviconURI.schemeIs("data")) { if (faviconURI.schemeIs("data")) {
lazy.PlacesUtils.favicons lazy.PlacesUtils.favicons.setFaviconForPage(
.setFaviconForPage(pageURI, faviconURI, faviconURI) pageURI,
.catch(console.error); faviconURI,
faviconURI
);
return; return;
} }
@@ -215,13 +213,11 @@ export class FaviconFeed {
} }
// Otherwise, fetch from network. // Otherwise, fetch from network.
lazy.PlacesUtils.favicons lazy.PlacesUtils.favicons.setFaviconForPage(
.setFaviconForPage( pageURI,
pageURI, faviconURI,
faviconURI, await this.getFaviconDataURLFromNetwork(faviconURI)
await this.getFaviconDataURLFromNetwork(faviconURI) );
)
.catch(console.error);
} catch (ex) { } catch (ex) {
console.error(`Failed to set favicon for page:${ex}`); console.error(`Failed to set favicon for page:${ex}`);
} }

View File

@@ -95,7 +95,7 @@ add_task(async function test_fetchIcon_with_valid_favicon() {
.resolves({ domain: TEST_DOMAIN, image_url: TEST_FAVICON_URL.spec }); .resolves({ domain: TEST_DOMAIN, image_url: TEST_FAVICON_URL.spec });
info("Setup valid favicon data in DB"); info("Setup valid favicon data in DB");
await PlacesUtils.favicons.setFaviconForPage( PlacesUtils.favicons.setFaviconForPage(
TEST_PAGE_URL, TEST_PAGE_URL,
TEST_FAVICON_URL, TEST_FAVICON_URL,
TEST_SVG_DATA_URL TEST_SVG_DATA_URL
@@ -166,7 +166,7 @@ add_task(async function test_fetchIconFromRedirects_with_valid_favicon() {
]); ]);
info("Setup valid favicon data in DB"); info("Setup valid favicon data in DB");
await PlacesUtils.favicons.setFaviconForPage( PlacesUtils.favicons.setFaviconForPage(
TEST_PAGE_URL, TEST_PAGE_URL,
TEST_FAVICON_URL, TEST_FAVICON_URL,
TEST_SVG_DATA_URL TEST_SVG_DATA_URL

View File

@@ -41,8 +41,7 @@ add_task(async function () {
parentGuid: PlacesUtils.bookmarks.toolbarGuid, parentGuid: PlacesUtils.bookmarks.toolbarGuid,
}); });
registerCleanupFunction(async function () { registerCleanupFunction(async function () {
await PlacesUtils.bookmarks.eraseEverything(); await PlacesUtils.bookmarks.remove(bm);
await PlacesUtils.history.clear();
}); });
// The icon is read asynchronously from the network, we don't have an easy way // The icon is read asynchronously from the network, we don't have an easy way
@@ -60,7 +59,15 @@ add_task(async function () {
info("Sidebar: " + sidebarShot1); info("Sidebar: " + sidebarShot1);
let dataURL = await PlacesTestUtils.getFaviconDataURLFromNetwork(ICON_URI); let dataURL = await PlacesTestUtils.getFaviconDataURLFromNetwork(ICON_URI);
await PlacesTestUtils.setFaviconForPage(PAGE_URI, ICON_URI, dataURL); await new Promise(resolve => {
PlacesUtils.favicons.setFaviconForPage(
PAGE_URI,
ICON_URI,
dataURL,
null,
resolve
);
});
let dataURLInDB = await PlacesTestUtils.getFaviconDataURLFromDB(ICON_URI); let dataURLInDB = await PlacesTestUtils.getFaviconDataURLFromDB(ICON_URI);
Assert.ok(dataURLInDB.equals(dataURL), "Succesfully set the icon"); Assert.ok(dataURLInDB.equals(dataURL), "Succesfully set the icon");

View File

@@ -827,7 +827,7 @@ BookmarkImporter.prototype = {
bookmark => bookmark.type == PlacesUtils.bookmarks.TYPE_BOOKMARK bookmark => bookmark.type == PlacesUtils.bookmarks.TYPE_BOOKMARK
).length; ).length;
insertFaviconsForTree(tree); insertFaviconsForTree(tree).catch(console.warn);
} }
return bookmarkCount; return bookmarkCount;
}, },
@@ -1080,7 +1080,7 @@ BookmarkExporter.prototype = {
* *
* @param {Object} node The bookmark node for icons to be inserted. * @param {Object} node The bookmark node for icons to be inserted.
*/ */
function insertFaviconForNode(node) { async function insertFaviconForNode(node) {
if (!node.icon && !node.iconUri) { if (!node.icon && !node.iconUri) {
// No favicon information. // No favicon information.
return; return;
@@ -1093,14 +1093,19 @@ function insertFaviconForNode(node) {
return; return;
} }
PlacesUtils.favicons let result = await new Promise(resolve => {
.setFaviconForPage( PlacesUtils.favicons.setFaviconForPage(
Services.io.newURI(node.url), Services.io.newURI(node.url),
// Use iconUri otherwise create a fake favicon URI to use (FIXME: bug 523932) // Use iconUri otherwise create a fake favicon URI to use (FIXME: bug 523932)
Services.io.newURI(node.iconUri ?? "fake-favicon-uri:" + node.url), Services.io.newURI(node.iconUri ?? "fake-favicon-uri:" + node.url),
faviconDataURI faviconDataURI,
) null,
.catch(console.error); resolve
);
});
if (!Components.isSuccessCode(result)) {
throw new Error("Failed to call setFaviconForPage():", node.url);
}
} catch (ex) { } catch (ex) {
console.error("Failed to import favicon data:", ex); console.error("Failed to import favicon data:", ex);
} }
@@ -1115,12 +1120,12 @@ function insertFaviconForNode(node) {
* *
* @param {Object} nodeTree The bookmark node tree for icons to be inserted. * @param {Object} nodeTree The bookmark node tree for icons to be inserted.
*/ */
function insertFaviconsForTree(nodeTree) { async function insertFaviconsForTree(nodeTree) {
insertFaviconForNode(nodeTree); await insertFaviconForNode(nodeTree);
if (nodeTree.children) { if (nodeTree.children) {
for (let child of nodeTree.children) { for (let child of nodeTree.children) {
insertFaviconsForTree(child); await insertFaviconsForTree(child);
} }
} }
} }

View File

@@ -291,7 +291,7 @@ BookmarkImporter.prototype = {
).length; ).length;
// Now add any favicons. // Now add any favicons.
insertFaviconsForTree(node); insertFaviconsForTree(node).catch(console.warn);
} }
return bookmarkCount; return bookmarkCount;
}, },
@@ -498,7 +498,7 @@ function translateTreeTypes(node) {
* *
* @param {Object} node The bookmark node for icons to be inserted. * @param {Object} node The bookmark node for icons to be inserted.
*/ */
function insertFaviconForNode(node) { async function insertFaviconForNode(node) {
if (!node.icon && !node.iconUri) { if (!node.icon && !node.iconUri) {
// No favicon information. // No favicon information.
return; return;
@@ -511,14 +511,19 @@ function insertFaviconForNode(node) {
return; return;
} }
PlacesUtils.favicons let result = await new Promise(resolve => {
.setFaviconForPage( PlacesUtils.favicons.setFaviconForPage(
Services.io.newURI(node.url), Services.io.newURI(node.url),
// Use iconUri otherwise create a fake favicon URI to use (FIXME: bug 523932) // Use iconUri otherwise create a fake favicon URI to use (FIXME: bug 523932)
Services.io.newURI(node.iconUri ?? "fake-favicon-uri:" + node.url), Services.io.newURI(node.iconUri ?? "fake-favicon-uri:" + node.url),
faviconDataURI faviconDataURI,
) null,
.catch(console.error); resolve
);
});
if (!Components.isSuccessCode(result)) {
throw new Error("Failed to call setFaviconForPage():", node.url);
}
} catch (ex) { } catch (ex) {
console.error("Failed to import favicon data:", ex); console.error("Failed to import favicon data:", ex);
} }
@@ -533,12 +538,12 @@ function insertFaviconForNode(node) {
* *
* @param {Object} nodeTree The bookmark node tree for icons to be inserted. * @param {Object} nodeTree The bookmark node tree for icons to be inserted.
*/ */
function insertFaviconsForTree(nodeTree) { async function insertFaviconsForTree(nodeTree) {
insertFaviconForNode(nodeTree); await insertFaviconForNode(nodeTree);
if (nodeTree.children) { if (nodeTree.children) {
for (let child of nodeTree.children) { for (let child of nodeTree.children) {
insertFaviconsForTree(child); await insertFaviconsForTree(child);
} }
} }
} }

View File

@@ -649,10 +649,10 @@ AsyncAssociateIconToPage::Run() {
AsyncSetIconForPage::AsyncSetIconForPage(const IconData& aIcon, AsyncSetIconForPage::AsyncSetIconForPage(const IconData& aIcon,
const PageData& aPage, const PageData& aPage,
dom::Promise* aPromise) PlacesCompletionCallback* aCallback)
: Runnable("places::AsyncSetIconForPage"), : Runnable("places::AsyncSetIconForPage"),
mPromise(new nsMainThreadPtrHolder<dom::Promise>( mCallback(new nsMainThreadPtrHolder<PlacesCompletionCallback>(
"AsyncSetIconForPage::Promise", aPromise, false)), "AsyncSetIconForPage::mCallback", aCallback, false)),
mIcon(aIcon), mIcon(aIcon),
mPage(aPage) {} mPage(aPage) {}
@@ -665,14 +665,13 @@ AsyncSetIconForPage::Run() {
nsresult rv = NS_OK; nsresult rv = NS_OK;
auto guard = MakeScopeExit([&]() { auto guard = MakeScopeExit([&]() {
NS_DispatchToMainThread(NS_NewRunnableFunction( if (mCallback) {
"AsyncSetIconForPage::Promise", [rv, promise = std::move(mPromise)]() { NS_DispatchToMainThread(
if (NS_SUCCEEDED(rv)) { NS_NewRunnableFunction("AsyncSetIconForPage::Callback",
promise->MaybeResolveWithUndefined(); [rv, callback = std::move(mCallback)]() {
} else { (void)callback->Complete(rv);
promise->MaybeReject(rv); }));
} }
}));
}); });
// Fetch the page data. // Fetch the page data.

View File

@@ -14,6 +14,7 @@
#include "nsThreadUtils.h" #include "nsThreadUtils.h"
#include "nsProxyRelease.h" #include "nsProxyRelease.h"
#include "imgLoader.h" #include "imgLoader.h"
#include "PlacesCompletionCallback.h"
class nsIPrincipal; class nsIPrincipal;
@@ -147,14 +148,14 @@ class AsyncSetIconForPage final : public Runnable {
* Icon to be associated. * Icon to be associated.
* @param aPage * @param aPage
* Page to which associate the icon. * Page to which associate the icon.
* @param aPromise * @param aCallback
* Promise that returns the result. * Function to be called when the associate process finishes.
*/ */
AsyncSetIconForPage(const IconData& aIcon, const PageData& aPage, AsyncSetIconForPage(const IconData& aIcon, const PageData& aPage,
dom::Promise* aPromise); PlacesCompletionCallback* aCallback);
private: private:
nsMainThreadPtrHandle<dom::Promise> mPromise; nsMainThreadPtrHandle<PlacesCompletionCallback> mCallback;
IconData mIcon; IconData mIcon;
PageData mPage; PageData mPage;
}; };

View File

@@ -0,0 +1,19 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsISupports.idl"
[scriptable, function, uuid(ea26627b-d21a-4f97-b2d0-f8df7be24808)]
interface PlacesCompletionCallback : nsISupports {
/**
* Indicates that the event this callback was passed in for has completed.
*
* @param status
* The status of the call. Generally NS_OK if the operation
* completed successfully.
*/
void complete(in nsresult status);
};

View File

@@ -23,6 +23,7 @@ if CONFIG["MOZ_PLACES"]:
"nsINavBookmarksService.idl", "nsINavBookmarksService.idl",
"nsIPlacesPreviewsHelperService.idl", "nsIPlacesPreviewsHelperService.idl",
"nsITaggingService.idl", "nsITaggingService.idl",
"PlacesCompletionCallback.idl",
] ]
EXPORTS.mozilla.places = [ EXPORTS.mozilla.places = [

View File

@@ -14,6 +14,7 @@
*/ */
#include "nsFaviconService.h" #include "nsFaviconService.h"
#include "PlacesCompletionCallback.h"
#include "nsNavHistory.h" #include "nsNavHistory.h"
#include "nsPlacesMacros.h" #include "nsPlacesMacros.h"
@@ -223,41 +224,24 @@ void nsFaviconService::ClearImageCache(nsIURI* aImageURI) {
} }
NS_IMETHODIMP NS_IMETHODIMP
nsFaviconService::SetFaviconForPage(nsIURI* aPageURI, nsIURI* aFaviconURI, nsFaviconService::SetFaviconForPage(
nsIURI* aDataURL, PRTime aExpiration = 0, nsIURI* aPageURI, nsIURI* aFaviconURI, nsIURI* aDataURL,
bool isRichIcon = false, PRTime aExpiration = 0, PlacesCompletionCallback* aCallback = nullptr,
JSContext* aContext = nullptr, bool isRichIcon = false) {
Promise** aPromise = nullptr) {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
NS_ENSURE_ARG(aPageURI); NS_ENSURE_ARG(aPageURI);
NS_ENSURE_ARG(aFaviconURI); NS_ENSURE_ARG(aFaviconURI);
NS_ENSURE_ARG(aDataURL); NS_ENSURE_ARG(aDataURL);
MOZ_DIAGNOSTIC_ASSERT(aDataURL->SchemeIs("data")); MOZ_DIAGNOSTIC_ASSERT(aDataURL->SchemeIs("data"));
ErrorResult result;
RefPtr<Promise> promise =
Promise::Create(xpc::CurrentNativeGlobal(aContext), result);
if (NS_WARN_IF(result.Failed())) {
return result.StealNSResult();
}
nsresult rv = NS_OK;
auto guard = MakeScopeExit([&]() {
if (NS_SUCCEEDED(rv)) {
promise->MaybeResolveWithUndefined();
promise.forget(aPromise);
}
});
if (!aDataURL->SchemeIs("data")) { if (!aDataURL->SchemeIs("data")) {
return (rv = NS_ERROR_INVALID_ARG); return NS_ERROR_INVALID_ARG;
} }
NS_ENSURE_ARG(canStoreIconForPage(aPageURI)); NS_ENSURE_ARG(canStoreIconForPage(aPageURI));
if (AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed)) { if (AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed)) {
return (rv = NS_OK); return NS_OK;
} }
PRTime now = PR_Now(); PRTime now = PR_Now();
@@ -266,6 +250,14 @@ nsFaviconService::SetFaviconForPage(nsIURI* aPageURI, nsIURI* aFaviconURI,
aExpiration = now + MAX_FAVICON_EXPIRATION; aExpiration = now + MAX_FAVICON_EXPIRATION;
} }
// Use the data: protocol handler to convert the data.
nsresult rv = NS_OK;
auto guard = MakeScopeExit([&]() {
if (aCallback) {
aCallback->Complete(rv);
}
});
nsCOMPtr<nsIIOService> ioService = do_GetIOService(&rv); nsCOMPtr<nsIIOService> ioService = do_GetIOService(&rv);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIProtocolHandler> protocolHandler; nsCOMPtr<nsIProtocolHandler> protocolHandler;
@@ -403,7 +395,7 @@ nsFaviconService::SetFaviconForPage(nsIURI* aPageURI, nsIURI* aFaviconURI,
} }
RefPtr<AsyncSetIconForPage> event = RefPtr<AsyncSetIconForPage> event =
new AsyncSetIconForPage(icon, page, promise); new AsyncSetIconForPage(icon, page, aCallback);
RefPtr<Database> DB = Database::GetDatabase(); RefPtr<Database> DB = Database::GetDatabase();
if (MOZ_UNLIKELY(!DB)) { if (MOZ_UNLIKELY(!DB)) {
return (rv = NS_ERROR_UNEXPECTED); return (rv = NS_ERROR_UNEXPECTED);
@@ -412,7 +404,6 @@ nsFaviconService::SetFaviconForPage(nsIURI* aPageURI, nsIURI* aFaviconURI,
DB->DispatchToAsyncThread(event); DB->DispatchToAsyncThread(event);
guard.release(); guard.release();
promise.forget(aPromise);
return NS_OK; return NS_OK;
} }

View File

@@ -9,6 +9,7 @@ interface nsIURI;
interface nsIPrincipal; interface nsIPrincipal;
interface mozIPlacesPendingOperation; interface mozIPlacesPendingOperation;
interface nsIFaviconDataCallback; interface nsIFaviconDataCallback;
interface PlacesCompletionCallback;
[scriptable, uuid(e81e0b0c-b9f1-4c2e-8f3c-b809933cf73c)] [scriptable, uuid(e81e0b0c-b9f1-4c2e-8f3c-b809933cf73c)]
interface nsIFaviconService : nsISupports interface nsIFaviconService : nsISupports
@@ -105,18 +106,21 @@ interface nsIFaviconService : nsISupports
* Until this time, we won't try to load it again. * Until this time, we won't try to load it again.
* If this argument is omitted, the expiration defaults to * If this argument is omitted, the expiration defaults to
* 7 days (FaviconHelpers::MAX_FAVICON_EXPIRATION) from now. * 7 days (FaviconHelpers::MAX_FAVICON_EXPIRATION) from now.
* * @param [optional] aCallback
* @return Promise that is resolved/rejected when finishing the process. * Once we're done setting and/or fetching the favicon, we invoke this
* callback.
* *
* @throws NS_ERROR_FILE_TOO_BIG if the icon is excessively large and can not * @throws NS_ERROR_FILE_TOO_BIG if the icon is excessively large and can not
* be optimized internally. * be optimized internally.
*
* @see PlacesCompletionCallback in PlacesCompletionCallback.idl.
*/ */
[implicit_jscontext, must_use] void setFaviconForPage(
Promise setFaviconForPage(
in nsIURI aPageURI, in nsIURI aPageURI,
in nsIURI aFaviconURI, in nsIURI aFaviconURI,
in nsIURI aDataURL, in nsIURI aDataURL,
[optional] in PRTime aExpiration, [optional] in PRTime aExpiration,
[optional] in PlacesCompletionCallback aCallback,
[optional] in boolean isRichIcon [optional] in boolean isRichIcon
); );

View File

@@ -143,7 +143,19 @@ export var PlacesTestUtils = Object.freeze({
} }
faviconPromises.push( faviconPromises.push(
lazy.PlacesUtils.favicons.setFaviconForPage(uri, faviconURI, faviconURI) new Promise((resolve, reject) => {
try {
lazy.PlacesUtils.favicons.setFaviconForPage(
uri,
faviconURI,
faviconURI,
null,
resolve
);
} catch (ex) {
reject(ex);
}
})
); );
} }
await Promise.all(faviconPromises); await Promise.all(faviconPromises);
@@ -167,17 +179,30 @@ export var PlacesTestUtils = Object.freeze({
expiration = 0, expiration = 0,
isRichIcon = false isRichIcon = false
) { ) {
return lazy.PlacesUtils.favicons.setFaviconForPage( return new Promise((resolve, reject) => {
pageURI instanceof Ci.nsIURI ? pageURI : Services.io.newURI(pageURI), lazy.PlacesUtils.favicons.setFaviconForPage(
faviconURI instanceof Ci.nsIURI pageURI instanceof Ci.nsIURI ? pageURI : Services.io.newURI(pageURI),
? faviconURI faviconURI instanceof Ci.nsIURI
: Services.io.newURI(faviconURI), ? faviconURI
faviconDataURL instanceof Ci.nsIURI : Services.io.newURI(faviconURI),
? faviconDataURL faviconDataURL instanceof Ci.nsIURI
: Services.io.newURI(faviconDataURL), ? faviconDataURL
expiration, : Services.io.newURI(faviconDataURL),
isRichIcon expiration,
); status => {
if (Components.isSuccessCode(status)) {
resolve(status);
} else {
reject(
new Error(
`Failed to process setFaviconForPage(): status code = ${status}`
)
);
}
},
isRichIcon
);
});
}, },
/** /**

View File

@@ -16,11 +16,7 @@ add_setup(() => {
add_task(async function test_storing_a_normal_16x16_icon() { add_task(async function test_storing_a_normal_16x16_icon() {
const PAGE_URL = Services.io.newURI("http://places.test"); const PAGE_URL = Services.io.newURI("http://places.test");
await PlacesTestUtils.addVisits(PAGE_URL); await PlacesTestUtils.addVisits(PAGE_URL);
await PlacesUtils.favicons.setFaviconForPage( await setFavicon(PAGE_URL, SMALLPNG_DATA_URI);
PAGE_URL,
SMALLPNG_DATA_URI,
SMALLPNG_DATA_URI
);
// Now set expiration to 0 and change the payload. // Now set expiration to 0 and change the payload.
info("Set expiration to 0 and replace favicon data"); info("Set expiration to 0 and replace favicon data");
@@ -36,10 +32,18 @@ add_task(async function test_storing_a_normal_16x16_icon() {
); );
info("Refresh favicon"); info("Refresh favicon");
await PlacesUtils.favicons.setFaviconForPage( await setFavicon(PAGE_URL, SMALLPNG_DATA_URI);
PAGE_URL,
SMALLPNG_DATA_URI,
SMALLPNG_DATA_URI
);
await compareFavicons("page-icon:" + PAGE_URL.spec, SMALLPNG_DATA_URI); await compareFavicons("page-icon:" + PAGE_URL.spec, SMALLPNG_DATA_URI);
}); });
async function setFavicon(pageURL, faviconDataURL) {
await new Promise(resolve => {
PlacesUtils.favicons.setFaviconForPage(
pageURL,
faviconDataURL,
faviconDataURL,
null,
resolve
);
});
}

View File

@@ -19,7 +19,15 @@ add_task(async function test_normal() {
await PlacesTestUtils.addVisits(pageURI); await PlacesTestUtils.addVisits(pageURI);
await PlacesUtils.favicons.setFaviconForPage(pageURI, FAVICON_URI, dataURL); await new Promise(resolve => {
PlacesUtils.favicons.setFaviconForPage(
pageURI,
FAVICON_URI,
dataURL,
null,
resolve
);
});
await new Promise(resolve => { await new Promise(resolve => {
PlacesUtils.favicons.getFaviconDataForPage( PlacesUtils.favicons.getFaviconDataForPage(

View File

@@ -7,11 +7,16 @@ add_task(async function test_normal() {
let pageURI = NetUtil.newURI("http://example.com/normal"); let pageURI = NetUtil.newURI("http://example.com/normal");
await PlacesTestUtils.addVisits(pageURI); await PlacesTestUtils.addVisits(pageURI);
await PlacesTestUtils.setFaviconForPage(
pageURI, await new Promise(resolve => {
SMALLPNG_DATA_URI, PlacesUtils.favicons.setFaviconForPage(
SMALLPNG_DATA_URI pageURI,
); SMALLPNG_DATA_URI,
SMALLPNG_DATA_URI,
null,
resolve
);
});
await new Promise(resolve => { await new Promise(resolve => {
PlacesUtils.favicons.getFaviconDataForPage( PlacesUtils.favicons.getFaviconDataForPage(

View File

@@ -94,11 +94,15 @@ add_task(async function test_twiceReplace() {
let secondFavicon = await createFavicon("favicon10.png"); let secondFavicon = await createFavicon("favicon10.png");
let firstFaviconDataURL = await createDataURLForFavicon(firstFavicon); let firstFaviconDataURL = await createDataURLForFavicon(firstFavicon);
await PlacesUtils.favicons.setFaviconForPage( await new Promise(resolve => {
pageURI, PlacesUtils.favicons.setFaviconForPage(
firstFavicon.uri, pageURI,
firstFaviconDataURL firstFavicon.uri,
); firstFaviconDataURL,
null,
resolve
);
});
await doTestSetFaviconForPage({ await doTestSetFaviconForPage({
pageURI, pageURI,
@@ -153,35 +157,17 @@ add_task(async function test_invalidPageURI() {
await PlacesTestUtils.addVisits(uri("http://example.com/")); await PlacesTestUtils.addVisits(uri("http://example.com/"));
let favicon = await createFavicon("favicon-invalidPageURI.png"); let favicon = await createFavicon("favicon-invalidPageURI.png");
const TEST_DATA = [ for (let invalidURI of [null, "", "http://example.com"]) {
{
pageURI: null,
expected: "NS_ERROR_ILLEGAL_VALUE",
},
{
pageURI: "",
expected: "NS_ERROR_XPC_BAD_CONVERT_JS",
},
{
pageURI: "http://example.com",
expected: "NS_ERROR_XPC_BAD_CONVERT_JS",
},
];
for (let { pageURI, expected } of TEST_DATA) {
try { try {
info(`Invalid page URI test for [${pageURI}]`); info(`Invalid page URI test for [${invalidURI}]`);
await PlacesUtils.favicons.setFaviconForPage( PlacesUtils.favicons.setFaviconForPage(
pageURI, invalidURI,
favicon.uri, favicon.uri,
await createDataURLForFavicon(favicon) await createDataURLForFavicon(favicon)
); );
Assert.ok(false, "Error should happened"); Assert.ok(false, "Error should happened");
} catch (e) { } catch (e) {
Assert.equal( Assert.ok(true, `Expected error happend [${e.message}]`);
e.name,
expected,
`Expected error happened for [${pageURI}]`
);
} }
} }
}); });
@@ -191,36 +177,17 @@ add_task(async function test_invalidFaviconURI() {
await PlacesTestUtils.addVisits(pageURI); await PlacesTestUtils.addVisits(pageURI);
let favicon = await createFavicon("favicon-invalidFaviconURI.png"); let favicon = await createFavicon("favicon-invalidFaviconURI.png");
const TEST_DATA = [ for (let invalidURI of [null, "", favicon.uri.spec]) {
{
faviconURI: null,
expected: "NS_ERROR_ILLEGAL_VALUE",
},
{
faviconURI: "",
expected: "NS_ERROR_XPC_BAD_CONVERT_JS",
},
{
faviconURI: "favicon.uri.spec",
expected: "NS_ERROR_XPC_BAD_CONVERT_JS",
},
];
for (let { faviconURI, expected } of TEST_DATA) {
try { try {
info(`Invalid favicon URI test for [${faviconURI}]`); info(`Invalid favicon URI test for [${invalidURI}]`);
await PlacesUtils.favicons.setFaviconForPage( PlacesUtils.favicons.setFaviconForPage(
pageURI, pageURI,
faviconURI, invalidURI,
await createDataURLForFavicon(favicon) await createDataURLForFavicon(favicon)
); );
Assert.ok(false, "Error should happened"); Assert.ok(false, "Error should happened");
} catch (e) { } catch (e) {
Assert.equal( Assert.ok(true, `Expected error happend [${e.message}]`);
e.name,
expected,
`Expected error happened for [${faviconURI}]`
);
} }
} }
}); });
@@ -230,67 +197,23 @@ add_task(async function test_invalidFaviconDataURI() {
await PlacesTestUtils.addVisits(pageURI); await PlacesTestUtils.addVisits(pageURI);
let faviconURI = uri("http://example.com/favicon.svg"); let faviconURI = uri("http://example.com/favicon.svg");
const TEST_DATA = [ for (let invalidURI of [
{ null,
faviconDataURI: null, "",
expected: "NS_ERROR_ILLEGAL_VALUE", "data:text/plain;base64,SGVsbG8sIFdvcmxkIQ==",
}, // nsIFaviconService::MAX_FAVICON_BUFFER_SIZE = 65536
{ uri(`data:image/svg+xml;utf8,<svg><text>${Array(65536)}</text></svg>`),
faviconDataURI: "", ]) {
expected: "NS_ERROR_XPC_BAD_CONVERT_JS",
},
{
faviconDataURI: "data:text/plain;base64,SGVsbG8sIFdvcmxkIQ==",
expected: "NS_ERROR_XPC_BAD_CONVERT_JS",
},
{
// nsIFaviconService::MAX_FAVICON_BUFFER_SIZE = 65536
faviconDataURI: uri(
`data:image/svg+xml;utf8,<svg><text>${Array(65536)}</text></svg>`
),
expected: "NS_ERROR_FILE_TOO_BIG",
},
];
for (let { faviconDataURI, expected } of TEST_DATA) {
try { try {
info(`Invalid favicon data URI test for [${faviconDataURI}]`); info(`Invalid favicon data URI test for [${invalidURI}]`);
await PlacesUtils.favicons.setFaviconForPage( PlacesUtils.favicons.setFaviconForPage(pageURI, faviconURI, invalidURI);
pageURI,
faviconURI,
faviconDataURI
);
Assert.ok(false, "Error should happened"); Assert.ok(false, "Error should happened");
} catch (e) { } catch (e) {
Assert.equal( Assert.ok(true, `Expected error happend [${e.message}]`);
e.name,
expected,
`Expected error happened for [${faviconDataURI}]`
);
} }
} }
}); });
// Error handled by this test will fire from AsyncSetIconForPage Runnable.
add_task(async function test_noVisitData() {
let pageURI = uri("http://test1.bar/");
let favicon = await createFavicon("favicon1.png");
try {
await PlacesUtils.favicons.setFaviconForPage(
pageURI,
favicon.uri,
await createDataURLForFavicon(favicon)
);
Assert.ok(false, "Error should happened");
} catch (e) {
Assert.equal(e.name, "NS_ERROR_NOT_AVAILABLE", "Expected error happened");
}
await IOUtils.remove(favicon.file.path);
await PlacesUtils.history.clear();
});
add_task(async function test_sameHostRedirect() { add_task(async function test_sameHostRedirect() {
// Add a bookmarked page that redirects to another page, set a favicon on the // Add a bookmarked page that redirects to another page, set a favicon on the
// latter and check the former gets it too, if they are in the same host. // latter and check the former gets it too, if they are in the same host.
@@ -313,7 +236,7 @@ add_task(async function test_sameHostRedirect() {
events.some(e => e.url == srcUrl && e.faviconUrl == SMALLPNG_DATA_URI.spec) events.some(e => e.url == srcUrl && e.faviconUrl == SMALLPNG_DATA_URI.spec)
); );
await PlacesUtils.favicons.setFaviconForPage( PlacesUtils.favicons.setFaviconForPage(
Services.io.newURI(destUrl), Services.io.newURI(destUrl),
SMALLPNG_DATA_URI, SMALLPNG_DATA_URI,
SMALLPNG_DATA_URI SMALLPNG_DATA_URI
@@ -374,14 +297,18 @@ async function doTestSetFaviconForPage({
expectedFaviconData, expectedFaviconData,
expectedFaviconMimeType, expectedFaviconMimeType,
}) { }) {
let result = await PlacesUtils.favicons.setFaviconForPage( let result = await new Promise(resolve => {
pageURI, PlacesUtils.favicons.setFaviconForPage(
faviconURI, pageURI,
dataURL faviconURI,
); dataURL,
null,
resolve
);
});
info("Check the result of setFaviconForPage"); info("Check the result of setFaviconForPage");
Assert.equal(result, null, "If succeeded, the promise has no data"); Assert.equal(result, 0);
await new Promise(resolve => { await new Promise(resolve => {
checkFaviconDataForPage( checkFaviconDataForPage(
@@ -423,9 +350,8 @@ add_task(async function test_pageURIProtocols() {
"https://example.com/", "https://example.com/",
]; ];
for (let pageURI of invalidPageURIs) { for (let pageURI of invalidPageURIs) {
await PlacesTestUtils.addBookmarkWithDetails({ uri: pageURI });
try { try {
await PlacesUtils.favicons.setFaviconForPage( PlacesUtils.favicons.setFaviconForPage(
uri(pageURI), uri(pageURI),
favicon.uri, favicon.uri,
await createDataURLForFavicon(favicon) await createDataURLForFavicon(favicon)
@@ -434,12 +360,10 @@ add_task(async function test_pageURIProtocols() {
} catch (e) { } catch (e) {
Assert.ok(true, `Expected error [${e.message}]`); Assert.ok(true, `Expected error [${e.message}]`);
} }
await PlacesUtils.bookmarks.eraseEverything();
} }
for (let pageURI of validPageURIs) { for (let pageURI of validPageURIs) {
await PlacesTestUtils.addBookmarkWithDetails({ uri: pageURI });
try { try {
await PlacesUtils.favicons.setFaviconForPage( PlacesUtils.favicons.setFaviconForPage(
uri(pageURI), uri(pageURI),
favicon.uri, favicon.uri,
await createDataURLForFavicon(favicon) await createDataURLForFavicon(favicon)
@@ -448,6 +372,5 @@ add_task(async function test_pageURIProtocols() {
} catch (e) { } catch (e) {
Assert.ok(false, `Unexpected error [${e.message}]`); Assert.ok(false, `Unexpected error [${e.message}]`);
} }
await PlacesUtils.bookmarks.eraseEverything();
} }
}); });

View File

@@ -8,11 +8,15 @@ add_task(async function () {
visitDate: Date.now() * 1000, visitDate: Date.now() * 1000,
}); });
await PlacesUtils.favicons.setFaviconForPage( await new Promise(resolve => {
PAGEURI, PlacesUtils.favicons.setFaviconForPage(
SMALLSVG_DATA_URI, PAGEURI,
SMALLSVG_DATA_URI SMALLSVG_DATA_URI,
); SMALLSVG_DATA_URI,
null,
resolve
);
});
await new Promise(resolve => { await new Promise(resolve => {
PlacesUtils.favicons.getFaviconDataForPage( PlacesUtils.favicons.getFaviconDataForPage(

View File

@@ -758,7 +758,15 @@ async function setFaviconForPage(page, icon, forceReload = true) {
dataURL = await PlacesTestUtils.getFaviconDataURLFromNetwork(iconURI); dataURL = await PlacesTestUtils.getFaviconDataURLFromNetwork(iconURI);
} }
await PlacesUtils.favicons.setFaviconForPage(pageURI, iconURI, dataURL); await new Promise(resolve => {
PlacesUtils.favicons.setFaviconForPage(
pageURI,
iconURI,
dataURL,
null,
resolve
);
});
} }
function getFaviconUrlForPage(page, width = 0) { function getFaviconUrlForPage(page, width = 0) {

View File

@@ -281,11 +281,16 @@ add_task(async function test_error_cases() {
add_task(async function test_orphans() { add_task(async function test_orphans() {
let uri = NetUtil.newURI("http://moz.org/"); let uri = NetUtil.newURI("http://moz.org/");
await PlacesTestUtils.addVisits({ uri }); await PlacesTestUtils.addVisits({ uri });
await PlacesTestUtils.setFaviconForPage(
uri, await new Promise(resolve => {
SMALLPNG_DATA_URI, PlacesUtils.favicons.setFaviconForPage(
SMALLPNG_DATA_URI uri,
); SMALLPNG_DATA_URI,
SMALLPNG_DATA_URI,
null,
resolve
);
});
// Also create a root icon. // Also create a root icon.
let faviconURI = Services.io.newURI(uri.spec + "favicon.ico"); let faviconURI = Services.io.newURI(uri.spec + "favicon.ico");

View File

@@ -377,11 +377,16 @@ add_task(async function test_error_cases() {
add_task(async function test_orphans() { add_task(async function test_orphans() {
let uri = NetUtil.newURI("http://moz.org/"); let uri = NetUtil.newURI("http://moz.org/");
await PlacesTestUtils.addVisits({ uri }); await PlacesTestUtils.addVisits({ uri });
await PlacesTestUtils.setFaviconForPage(
uri, await new Promise(resolve => {
SMALLPNG_DATA_URI, PlacesUtils.favicons.setFaviconForPage(
SMALLPNG_DATA_URI uri,
); SMALLPNG_DATA_URI,
SMALLPNG_DATA_URI,
null,
resolve
);
});
await PlacesUtils.history.update({ await PlacesUtils.history.update({
url: uri, url: uri,

View File

@@ -2610,11 +2610,15 @@ tests.push({
}); });
PlacesUtils.tagging.tagURI(this._uri1, ["testtag"]); PlacesUtils.tagging.tagURI(this._uri1, ["testtag"]);
await PlacesUtils.favicons.setFaviconForPage( await new Promise(resolve => {
this._uri2, PlacesUtils.favicons.setFaviconForPage(
SMALLPNG_DATA_URI, this._uri2,
SMALLPNG_DATA_URI SMALLPNG_DATA_URI,
); SMALLPNG_DATA_URI,
null,
resolve
);
});
await PlacesUtils.keywords.insert({ await PlacesUtils.keywords.insert({
url: this._uri1.spec, url: this._uri1.spec,
keyword: "testkeyword", keyword: "testkeyword",

View File

@@ -235,11 +235,15 @@ add_task(async function test_import_chromefavicon() {
let dataURL = await PlacesTestUtils.getFaviconDataURLFromNetwork( let dataURL = await PlacesTestUtils.getFaviconDataURLFromNetwork(
CHROME_FAVICON_URI CHROME_FAVICON_URI
); );
await PlacesTestUtils.setFaviconForPage( await new Promise(resolve => {
PAGE_URI, PlacesUtils.favicons.setFaviconForPage(
CHROME_FAVICON_URI, PAGE_URI,
dataURL CHROME_FAVICON_URI,
); dataURL,
null,
resolve
);
});
let data = await new Promise(resolve => { let data = await new Promise(resolve => {
PlacesUtils.favicons.getFaviconDataForPage( PlacesUtils.favicons.getFaviconDataForPage(
@@ -267,11 +271,15 @@ add_task(async function test_import_chromefavicon() {
let dataURL_2 = await PlacesTestUtils.getFaviconDataURLFromNetwork( let dataURL_2 = await PlacesTestUtils.getFaviconDataURLFromNetwork(
CHROME_FAVICON_URI_2 CHROME_FAVICON_URI_2
); );
await PlacesTestUtils.setFaviconForPage( await new Promise(resolve => {
PAGE_URI, PlacesUtils.favicons.setFaviconForPage(
CHROME_FAVICON_URI_2, PAGE_URI,
dataURL_2 CHROME_FAVICON_URI_2,
); dataURL_2,
null,
resolve
);
});
info("import from html"); info("import from html");
await PlacesUtils.bookmarks.eraseEverything(); await PlacesUtils.bookmarks.eraseEverything();

View File

@@ -68,11 +68,15 @@ add_setup(async () => {
reader.readAsDataURL(blob); reader.readAsDataURL(blob);
}); });
await PlacesUtils.favicons.setFaviconForPage( return new Promise(resolve => {
TEST_PAGE_URI, PlacesUtils.favicons.setFaviconForPage(
TEST_FAVICON_URI, TEST_PAGE_URI,
Services.io.newURI(dataURL) TEST_FAVICON_URI,
); Services.io.newURI(dataURL),
undefined,
resolve
);
});
}); });
/** /**