gecko-dev/browser/actors/LinkHandlerParent.jsm
Dave Townsend ecb4d2fcb7 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
2019-12-16 19:57:00 +00:00

171 lines
3.8 KiB
JavaScript

/* 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/. */
"use strict";
const EXPORTED_SYMBOLS = ["LinkHandlerParent"];
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
ChromeUtils.defineModuleGetter(
this,
"PlacesUIUtils",
"resource:///modules/PlacesUIUtils.jsm"
);
let gTestListeners = new Set();
class LinkHandlerParent extends JSWindowActorParent {
static addListenerForTests(listener) {
gTestListeners.add(listener);
}
static removeListenerForTests(listener) {
gTestListeners.delete(listener);
}
receiveMessage(aMsg) {
let browser = this.browsingContext.top.embedderElement;
if (!browser) {
return;
}
if (browser.outerBrowser) {
// Responsive design mode check
browser = browser.outerBrowser;
}
let win = browser.ownerGlobal;
let gBrowser = win.gBrowser;
switch (aMsg.name) {
case "Link:LoadingIcon":
if (!gBrowser) {
return;
}
if (aMsg.data.canUseForTab) {
let tab = gBrowser.getTabForBrowser(browser);
if (tab.hasAttribute("busy")) {
tab.setAttribute("pendingicon", "true");
}
}
this.notifyTestListeners("LoadingIcon", aMsg.data);
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);
}
this.notifyTestListeners("SetFailedIcon", aMsg.data);
break;
case "Link:AddSearch":
if (!gBrowser) {
return;
}
let tab = gBrowser.getTabForBrowser(browser);
if (!tab) {
break;
}
if (win.BrowserSearch) {
win.BrowserSearch.addEngine(
browser,
aMsg.data.engine,
Services.io.newURI(aMsg.data.url)
);
}
break;
}
}
notifyTestListeners(name, data) {
for (let listener of gTestListeners) {
listener(name, data);
}
}
clearPendingIcon(gBrowser, aBrowser) {
let tab = gBrowser.getTabForBrowser(aBrowser);
tab.removeAttribute("pendingicon");
}
setIconFromLink(
gBrowser,
browser,
{ pageURL, originalURL, canUseForTab, expiration, iconURL, canStoreIcon }
) {
let tab = gBrowser.getTabForBrowser(browser);
if (!tab) {
return;
}
if (canUseForTab) {
this.clearPendingIcon(gBrowser, browser);
}
let iconURI;
try {
iconURI = Services.io.newURI(iconURL);
} catch (ex) {
Cu.reportError(ex);
return;
}
if (iconURI.scheme != "data") {
try {
Services.scriptSecurityManager.checkLoadURIWithPrincipal(
browser.contentPrincipal,
iconURI,
Services.scriptSecurityManager.ALLOW_CHROME
);
} catch (ex) {
return;
}
}
if (canStoreIcon) {
try {
PlacesUIUtils.loadFavicon(
browser,
Services.scriptSecurityManager.getSystemPrincipal(),
Services.io.newURI(pageURL),
Services.io.newURI(originalURL),
expiration,
iconURI
);
} catch (ex) {
Cu.reportError(ex);
}
}
if (canUseForTab) {
gBrowser.setIcon(tab, iconURL, originalURL);
}
}
}