diff options
Diffstat (limited to 'browser/actors/AboutNewTabParent.sys.mjs')
-rw-r--r-- | browser/actors/AboutNewTabParent.sys.mjs | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/browser/actors/AboutNewTabParent.sys.mjs b/browser/actors/AboutNewTabParent.sys.mjs new file mode 100644 index 0000000000..27d5f82c0c --- /dev/null +++ b/browser/actors/AboutNewTabParent.sys.mjs @@ -0,0 +1,148 @@ +/* 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(); + } +} |