mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-04 13:07:52 +00:00
Bug 1602189: If the app manifest provides no icons use those provided by the page where available. r=Gijs
Makes the LinkHandler cache its most recent seen icons so that we can retrieve them when the app manifest doesn't provide any (generally only when there is no manifest at all). Differential Revision: https://phabricator.services.mozilla.com/D56291 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
117107b7d4
commit
ecb4d2fcb7
@ -39,12 +39,13 @@ class LinkHandlerParent extends JSWindowActorParent {
|
||||
let win = browser.ownerGlobal;
|
||||
|
||||
let gBrowser = win.gBrowser;
|
||||
if (!gBrowser) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (aMsg.name) {
|
||||
case "Link:LoadingIcon":
|
||||
if (!gBrowser) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aMsg.data.canUseForTab) {
|
||||
let tab = gBrowser.getTabForBrowser(browser);
|
||||
if (tab.hasAttribute("busy")) {
|
||||
@ -56,12 +57,27 @@ class LinkHandlerParent extends JSWindowActorParent {
|
||||
break;
|
||||
|
||||
case "Link:SetIcon":
|
||||
// Cache the most recent icon and rich icon locally.
|
||||
if (aMsg.data.canUseForTab) {
|
||||
this.icon = aMsg.data;
|
||||
} else {
|
||||
this.richIcon = aMsg.data;
|
||||
}
|
||||
|
||||
if (!gBrowser) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.setIconFromLink(gBrowser, browser, aMsg.data);
|
||||
|
||||
this.notifyTestListeners("SetIcon", aMsg.data);
|
||||
break;
|
||||
|
||||
case "Link:SetFailedIcon":
|
||||
if (!gBrowser) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aMsg.data.canUseForTab) {
|
||||
this.clearPendingIcon(gBrowser, browser);
|
||||
}
|
||||
@ -70,6 +86,10 @@ class LinkHandlerParent extends JSWindowActorParent {
|
||||
break;
|
||||
|
||||
case "Link:AddSearch":
|
||||
if (!gBrowser) {
|
||||
return;
|
||||
}
|
||||
|
||||
let tab = gBrowser.getTabForBrowser(browser);
|
||||
if (!tab) {
|
||||
break;
|
||||
|
60
browser/components/ssb/ImageTools.jsm
Normal file
60
browser/components/ssb/ImageTools.jsm
Normal file
@ -0,0 +1,60 @@
|
||||
/* 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/. */
|
||||
|
||||
var EXPORTED_SYMBOLS = ["ImageTools"];
|
||||
|
||||
const { XPCOMUtils } = ChromeUtils.import(
|
||||
"resource://gre/modules/XPCOMUtils.jsm"
|
||||
);
|
||||
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
"NetUtil",
|
||||
"resource://gre/modules/NetUtil.jsm"
|
||||
);
|
||||
XPCOMUtils.defineLazyServiceGetter(
|
||||
this,
|
||||
"ImgTools",
|
||||
"@mozilla.org/image/tools;1",
|
||||
Ci.imgITools
|
||||
);
|
||||
|
||||
const ImageTools = {
|
||||
/**
|
||||
* Given a data URI decodes the data into an object with "type" which is the
|
||||
* found mimetype and "container" which is an imgIContainer.
|
||||
*
|
||||
* @param {nsIURI} dataURI the URI to load.
|
||||
* @return {Promise<object>} the image info.
|
||||
*/
|
||||
loadImage(dataURI) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!dataURI.schemeIs("data")) {
|
||||
reject(new Error("Should only be loading data URIs."));
|
||||
return;
|
||||
}
|
||||
|
||||
let channel = NetUtil.newChannel({
|
||||
uri: dataURI,
|
||||
loadUsingSystemPrincipal: true,
|
||||
});
|
||||
|
||||
ImgTools.decodeImageFromChannelAsync(
|
||||
dataURI,
|
||||
channel,
|
||||
(container, status) => {
|
||||
if (Components.isSuccessCode(status)) {
|
||||
resolve({
|
||||
type: channel.contentType,
|
||||
container,
|
||||
});
|
||||
} else {
|
||||
reject(Components.Exception("Failed to load image.", status));
|
||||
}
|
||||
},
|
||||
null
|
||||
);
|
||||
});
|
||||
},
|
||||
};
|
@ -38,6 +38,7 @@ XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
ManifestProcessor: "resource://gre/modules/ManifestProcessor.jsm",
|
||||
KeyValueService: "resource://gre/modules/kvstore.jsm",
|
||||
OS: "resource://gre/modules/osfile.jsm",
|
||||
ImageTools: "resource:///modules/ssb/ImageTools.jsm",
|
||||
});
|
||||
|
||||
/**
|
||||
@ -106,6 +107,36 @@ function manifestForURI(uri) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an IconResource from the LinkHandler data.
|
||||
*
|
||||
* @param {object} iconData the data from the LinkHandler actor.
|
||||
* @return {Promise<IconResource>} an icon resource.
|
||||
*/
|
||||
async function getIconResource(iconData) {
|
||||
// This should be a data url so no network traffic.
|
||||
let imageData = await ImageTools.loadImage(
|
||||
Services.io.newURI(iconData.iconURL)
|
||||
);
|
||||
if (imageData.container.type == Ci.imgIContainer.TYPE_VECTOR) {
|
||||
return {
|
||||
src: iconData.iconURL,
|
||||
purpose: ["any"],
|
||||
type: imageData.type,
|
||||
sizes: ["any"],
|
||||
};
|
||||
}
|
||||
|
||||
// TODO: For ico files we should find all the available sizes: Bug 1604285.
|
||||
|
||||
return {
|
||||
src: iconData.iconURL,
|
||||
purpose: ["any"],
|
||||
type: imageData.type,
|
||||
sizes: [`${imageData.container.width}x${imageData.container.height}`],
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an app manifest for a site loaded in a browser element.
|
||||
*
|
||||
@ -151,6 +182,25 @@ async function buildManifestForBrowser(browser) {
|
||||
})
|
||||
)).filter(icon => icon);
|
||||
|
||||
// If the site provided no icons then try to use the normal page icons.
|
||||
if (!manifest.icons.length) {
|
||||
let linkHandler = browser.browsingContext.currentWindowGlobal.getActor(
|
||||
"LinkHandler"
|
||||
);
|
||||
|
||||
for (let icon of [linkHandler.icon, linkHandler.richIcon]) {
|
||||
if (!icon) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
manifest.icons.push(await getIconResource(icon));
|
||||
} catch (e) {
|
||||
console.warn(`Failed to load icon resource ${icon.originalURL}`, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return manifest;
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,10 @@ EXTRA_JS_MODULES += [
|
||||
'SiteSpecificBrowserService.jsm',
|
||||
]
|
||||
|
||||
EXTRA_JS_MODULES.ssb += [
|
||||
'ImageTools.jsm',
|
||||
]
|
||||
|
||||
FINAL_TARGET_FILES.actors += [
|
||||
'SiteSpecificBrowserChild.jsm',
|
||||
'SiteSpecificBrowserParent.jsm',
|
||||
|
Loading…
x
Reference in New Issue
Block a user