/* 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/. */ import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs"; const lazy = {}; XPCOMUtils.defineLazyModuleGetters(lazy, { AboutNewTab: "resource:///modules/AboutNewTab.jsm", ASRouter: "resource://activity-stream/lib/ASRouter.jsm", }); // A mapping of loaded new tab pages, where the mapping is: // browser -> { actor, browser, browsingContext, portID, url, loaded } let gLoadedTabs = new Map(); export class AboutNewTabParent extends JSWindowActorParent { static get loadedTabs() { return gLoadedTabs; } getTabDetails(message) { let browsingContext = message.target.browsingContext; let browser = browsingContext.top.embedderElement; return browser ? gLoadedTabs.get(browser) : null; } handleEvent(event) { if (event.type == "SwapDocShells") { let oldBrowser = this.browsingContext.top.embedderElement; let newBrowser = event.detail; let tabDetails = gLoadedTabs.get(oldBrowser); if (tabDetails) { tabDetails.browser = newBrowser; gLoadedTabs.delete(oldBrowser); gLoadedTabs.set(newBrowser, tabDetails); oldBrowser.removeEventListener("SwapDocShells", this); newBrowser.addEventListener("SwapDocShells", this); } } } async receiveMessage(message) { switch (message.name) { case "AboutNewTabVisible": await lazy.ASRouter.waitForInitialized; lazy.ASRouter.sendTriggerMessage({ browser: this.browsingContext.top.embedderElement, // triggerId and triggerContext id: "defaultBrowserCheck", context: { source: "newtab" }, }); break; case "Init": { let actor = message.target; let browsingContext = actor.browsingContext; let browser = browsingContext.top.embedderElement; if (!browser) { return; } let tabDetails = { actor, browser, browsingContext, portID: message.data.portID, url: message.data.url, }; gLoadedTabs.set(browser, tabDetails); browser.addEventListener("SwapDocShells", this); browser.addEventListener("EndSwapDocShells", this); this.notifyActivityStreamChannel("onNewTabInit", message, tabDetails); break; } case "Load": this.notifyActivityStreamChannel("onNewTabLoad", message); break; case "Unload": { let tabDetails = this.getTabDetails(message); if (!tabDetails) { // When closing a tab, the embedderElement can already be disconnected, so // an a backup, look up the tab details by browsing context. tabDetails = this.getByBrowsingContext( message.target.browsingContext ); } if (!tabDetails) { return; } tabDetails.browser.removeEventListener("EndSwapDocShells", this); gLoadedTabs.delete(tabDetails.browser); this.notifyActivityStreamChannel("onNewTabUnload", message, tabDetails); break; } case "ActivityStream:ContentToMain": this.notifyActivityStreamChannel("onMessage", message); break; } } notifyActivityStreamChannel(name, message, tabDetails) { if (!tabDetails) { tabDetails = this.getTabDetails(message); if (!tabDetails) { return; } } let channel = this.getChannel(); if (!channel) { return; } let messageToSend = { target: message.target, data: message.data || {}, }; channel[name](messageToSend, tabDetails); } getByBrowsingContext(expectedBrowsingContext) { for (let tabDetails of AboutNewTabParent.loadedTabs.values()) { if (tabDetails.browsingContext === expectedBrowsingContext) { return tabDetails; } } return null; } getChannel() { return lazy.AboutNewTab.activityStream?.store?.getMessageChannel(); } }