Bug 1772264 - Part 2: Identifying a rich icon and passing down the info - r=mak

Differential Revision: https://phabricator.services.mozilla.com/D217109
This commit is contained in:
Yazan Al Macki
2024-09-04 08:38:10 +00:00
parent 6d4bd6d268
commit ac70c4c73b
9 changed files with 72 additions and 9 deletions

View File

@@ -113,6 +113,7 @@ export class LinkHandlerParent extends JSWindowActorParent {
iconURL,
canStoreIcon,
beforePageShow,
isRichIcon,
}
) {
let tab = gBrowser.getTabForBrowser(browser);
@@ -148,7 +149,9 @@ export class LinkHandlerParent extends JSWindowActorParent {
Services.io.newURI(pageURL),
Services.io.newURI(originalURL),
iconURI,
expiration && lazy.PlacesUtils.toPRTime(expiration)
expiration && lazy.PlacesUtils.toPRTime(expiration),
null,
isRichIcon
);
} catch (ex) {
console.error(ex);

View File

@@ -48,3 +48,35 @@ add_task(async function test_maskIcons() {
BrowserTestUtils.removeTab(tab);
});
add_task(async function test_richIconInfo_rich() {
const URL = ROOT + "file_rich_icon.html";
const EXPECTED_RICH_ICON = ROOT + "rich_moz_2.png";
let richIconPromise = waitForFaviconMessage(false, EXPECTED_RICH_ICON);
const tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, URL);
let richIcon = await richIconPromise;
is(richIcon.iconURL, EXPECTED_RICH_ICON, "should load rich icon");
ok(richIcon.isRichIcon, "isRichIcon flag should be passed for rich icons");
BrowserTestUtils.removeTab(tab);
});
add_task(async function test_richIconInfo_notRich() {
const URL = ROOT + "file_rich_icon.html";
const EXPECTED_ICON = ROOT + "moz.png";
let iconPromise = waitForFaviconMessage(true, EXPECTED_ICON);
const tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, URL);
let icon = await iconPromise;
is(icon.iconURL, EXPECTED_ICON, "should load icon");
ok(!icon.isRichIcon, "isRichIcon flag should be passed as false");
BrowserTestUtils.removeTab(tab);
});

View File

@@ -36,11 +36,13 @@ function waitForFaviconMessage(isTabIcon = undefined, expectedURL = undefined) {
iconURL: data.originalURL,
dataURL: data.iconURL,
canUseForTab: data.canUseForTab,
isRichIcon: data.isRichIcon,
});
} else {
reject({
iconURL: data.originalURL,
canUseForTab: data.canUseForTab,
isRichIcon: data.isRichIcon,
});
}
};

View File

@@ -549,6 +549,7 @@ class IconLoader {
canStoreIcon:
iconInfo.beforePageShow && iconInfo.iconUri.schemeIs("data"),
beforePageShow: iconInfo.beforePageShow,
isRichIcon: iconInfo.isRichIcon,
});
return;
}
@@ -571,6 +572,7 @@ class IconLoader {
iconURL: dataURL,
canStoreIcon,
beforePageShow: iconInfo.beforePageShow,
isRichIcon: iconInfo.isRichIcon,
});
} catch (e) {
if (e.result != Cr.NS_BINDING_ABORTED) {

View File

@@ -206,8 +206,9 @@ nsresult SetIconInfo(const RefPtr<Database>& aDB, IconData& aIcon,
nsCOMPtr<mozIStorageStatement> insertStmt = aDB->GetStatement(
"INSERT INTO moz_icons "
"(icon_url, fixed_icon_url_hash, width, root, expire_ms, data) "
"VALUES (:url, hash(fixup_url(:url)), :width, :root, :expire, :data) ");
"(icon_url, fixed_icon_url_hash, width, root, expire_ms, data, flags) "
"VALUES (:url, hash(fixup_url(:url)), :width, :root, :expire, :data, "
":flags) ");
NS_ENSURE_STATE(insertStmt);
// ReplaceFaviconData may replace data for an already existing icon, and in
// that case it won't have the page uri at hand, thus it can't tell if the
@@ -216,7 +217,8 @@ nsresult SetIconInfo(const RefPtr<Database>& aDB, IconData& aIcon,
"UPDATE moz_icons SET width = :width, "
"expire_ms = :expire, "
"data = :data, "
"root = (root OR :root) "
"root = (root OR :root), "
"flags = :flags "
"WHERE id = :id ");
NS_ENSURE_STATE(updateStmt);
@@ -249,6 +251,8 @@ nsresult SetIconInfo(const RefPtr<Database>& aDB, IconData& aIcon,
rv = updateStmt->BindBlobByName("data"_ns, TO_INTBUFFER(payload.data),
payload.data.Length());
NS_ENSURE_SUCCESS(rv, rv);
rv = updateStmt->BindInt32ByName("flags"_ns, aIcon.flags);
NS_ENSURE_SUCCESS(rv, rv);
rv = updateStmt->Execute();
NS_ENSURE_SUCCESS(rv, rv);
// Set the new payload id.
@@ -268,6 +272,8 @@ nsresult SetIconInfo(const RefPtr<Database>& aDB, IconData& aIcon,
rv = insertStmt->BindBlobByName("data"_ns, TO_INTBUFFER(payload.data),
payload.data.Length());
NS_ENSURE_SUCCESS(rv, rv);
rv = insertStmt->BindInt32ByName("flags"_ns, aIcon.flags);
NS_ENSURE_SUCCESS(rv, rv);
rv = insertStmt->Execute();
NS_ENSURE_SUCCESS(rv, rv);
// Set the new payload id.

View File

@@ -74,7 +74,8 @@ struct IconData {
: expiration(0),
fetchMode(FETCH_NEVER),
status(ICON_STATUS_UNKNOWN),
rootIcon(0) {}
rootIcon(0),
flags(0) {}
nsCString spec;
nsCString host;
@@ -83,6 +84,8 @@ struct IconData {
uint16_t status; // This is a bitset, see ICON_STATUS_* defines above.
uint8_t rootIcon;
CopyableTArray<IconPayload> payloads;
uint16_t flags; // This is a bitset, see ICONDATA_FLAGS_* defines
// in toolkit/components/places/nsIFaviconService.idl.
};
/**

View File

@@ -215,7 +215,8 @@ void nsFaviconService::ClearImageCache(nsIURI* aImageURI) {
NS_IMETHODIMP
nsFaviconService::SetFaviconForPage(
nsIURI* aPageURI, nsIURI* aFaviconURI, nsIURI* aDataURL,
PRTime aExpiration = 0, PlacesCompletionCallback* aCallback = nullptr) {
PRTime aExpiration = 0, PlacesCompletionCallback* aCallback = nullptr,
bool isRichIcon = false) {
MOZ_ASSERT(NS_IsMainThread());
NS_ENSURE_ARG(aPageURI);
NS_ENSURE_ARG(aFaviconURI);
@@ -331,6 +332,9 @@ nsFaviconService::SetFaviconForPage(
icon.expiration = aExpiration;
icon.status = ICON_STATUS_CACHED;
icon.fetchMode = FETCH_NEVER;
if (isRichIcon) {
icon.flags |= ICONDATA_FLAGS_RICH;
}
rv = faviconURI->GetSpec(icon.spec);
NS_ENSURE_SUCCESS(rv, rv);
// URIs can arguably lack a host.

View File

@@ -19,6 +19,9 @@ interface nsIFaviconService : nsISupports
// The favicon is being loaded from a non-private browsing window
const unsigned long FAVICON_LOAD_NON_PRIVATE = 2;
// Defines values for icon flags.
const unsigned short ICONDATA_FLAGS_RICH = 1 << 0;
/**
* The limit in bytes of the size of favicons in memory and passed via the
* favicon protocol.
@@ -172,7 +175,8 @@ interface nsIFaviconService : nsISupports
in nsIURI aFaviconURI,
in nsIURI aDataURL,
[optional] in PRTime aExpiration,
[optional] in PlacesCompletionCallback aCallback
[optional] in PlacesCompletionCallback aCallback,
[optional] in boolean isRichIcon
);
/**

View File

@@ -167,7 +167,13 @@ export var PlacesTestUtils = Object.freeze({
* @param {Number} [optional] expiration
* @return {Promise} waits for finishing setting
*/
setFaviconForPage(pageURI, faviconURI, faviconDataURL, expiration = 0) {
setFaviconForPage(
pageURI,
faviconURI,
faviconDataURL,
expiration = 0,
isRichIcon = false
) {
return new Promise((resolve, reject) => {
lazy.PlacesUtils.favicons.setFaviconForPage(
pageURI instanceof Ci.nsIURI ? pageURI : Services.io.newURI(pageURI),
@@ -188,7 +194,8 @@ export var PlacesTestUtils = Object.freeze({
)
);
}
}
},
isRichIcon
);
});
},