summaryrefslogtreecommitdiffstats
path: root/browser/actors/LinkHandlerParent.sys.mjs
diff options
context:
space:
mode:
Diffstat (limited to 'browser/actors/LinkHandlerParent.sys.mjs')
-rw-r--r--browser/actors/LinkHandlerParent.sys.mjs156
1 files changed, 156 insertions, 0 deletions
diff --git a/browser/actors/LinkHandlerParent.sys.mjs b/browser/actors/LinkHandlerParent.sys.mjs
new file mode 100644
index 0000000000..b720fddb30
--- /dev/null
+++ b/browser/actors/LinkHandlerParent.sys.mjs
@@ -0,0 +1,156 @@
+/* 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/. */
+
+const lazy = {};
+
+ChromeUtils.defineESModuleGetters(lazy, {
+ PlacesUIUtils: "resource:///modules/PlacesUIUtils.sys.mjs",
+});
+
+let gTestListeners = new Set();
+
+export 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;
+ }
+
+ 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);
+ }
+ 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) {
+ console.error(ex);
+ return;
+ }
+ if (iconURI.scheme != "data") {
+ try {
+ Services.scriptSecurityManager.checkLoadURIWithPrincipal(
+ browser.contentPrincipal,
+ iconURI,
+ Services.scriptSecurityManager.ALLOW_CHROME
+ );
+ } catch (ex) {
+ return;
+ }
+ }
+ if (canStoreIcon) {
+ try {
+ lazy.PlacesUIUtils.loadFavicon(
+ browser,
+ Services.scriptSecurityManager.getSystemPrincipal(),
+ Services.io.newURI(pageURL),
+ Services.io.newURI(originalURL),
+ expiration,
+ iconURI
+ );
+ } catch (ex) {
+ console.error(ex);
+ }
+ }
+
+ if (canUseForTab) {
+ gBrowser.setIcon(tab, iconURL, originalURL);
+ }
+ }
+}