diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
commit | 2aa4a82499d4becd2284cdb482213d541b8804dd (patch) | |
tree | b80bf8bf13c3766139fbacc530efd0dd9d54394c /remote/targets/TargetList.jsm | |
parent | Initial commit. (diff) | |
download | firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip |
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | remote/targets/TargetList.jsm | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/remote/targets/TargetList.jsm b/remote/targets/TargetList.jsm new file mode 100644 index 0000000000..7117fbbee4 --- /dev/null +++ b/remote/targets/TargetList.jsm @@ -0,0 +1,173 @@ +/* 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"; + +var EXPORTED_SYMBOLS = ["TargetList"]; + +const { EventEmitter } = ChromeUtils.import( + "resource://gre/modules/EventEmitter.jsm" +); +const { TabTarget } = ChromeUtils.import( + "chrome://remote/content/targets/TabTarget.jsm" +); +const { MainProcessTarget } = ChromeUtils.import( + "chrome://remote/content/targets/MainProcessTarget.jsm" +); +const { TabObserver } = ChromeUtils.import( + "chrome://remote/content/observers/TargetObserver.jsm" +); + +class TargetList { + constructor() { + // Target ID -> Target + this._targets = new Map(); + + EventEmitter.decorate(this); + } + + /** + * Start listing and listening for all the debuggable targets + */ + async watchForTargets() { + await this.watchForTabs(); + } + + unwatchForTargets() { + this.unwatchForTabs(); + } + + /** + * Watch for all existing and new tabs being opened. + * So that we can create the related TabTarget instance for + * each of them. + */ + async watchForTabs() { + if (this.tabObserver) { + throw new Error("Targets is already watching for new tabs"); + } + this.tabObserver = new TabObserver({ registerExisting: true }); + this.tabObserver.on("open", async (eventName, tab) => { + const target = new TabTarget(this, tab.linkedBrowser); + this.registerTarget(target); + }); + this.tabObserver.on("close", (eventName, tab) => { + const browser = tab.linkedBrowser; + // Ignore the browsers that haven't had time to initialize. + if (!browser.browsingContext) { + return; + } + const target = this.getByBrowsingContext(browser.browsingContext.id); + if (target) { + this.destroyTarget(target); + } + }); + await this.tabObserver.start(); + } + + unwatchForTabs() { + if (this.tabObserver) { + this.tabObserver.stop(); + this.tabObserver = null; + } + } + + /** + * To be called right after instantiating a new Target instance. + * This will hold the new instance in the list and notify about + * its creation. + */ + registerTarget(target) { + this._targets.set(target.id, target); + this.emit("target-created", target); + } + + /** + * To be called when the debuggable target has been destroy. + * So that we can notify it no longer exists and disconnect + * all connecting made to debug it. + */ + destroyTarget(target) { + target.destructor(); + this._targets.delete(target.id); + this.emit("target-destroyed", target); + } + + /** + * Destroy all the registered target of all kinds. + * This will end up dropping all connections made to debug any of them. + */ + destructor() { + for (const target of this) { + this.destroyTarget(target); + } + this._targets.clear(); + if (this.mainProcessTarget) { + this.mainProcessTarget = null; + } + + this.unwatchForTargets(); + } + + get size() { + return this._targets.size; + } + + /** + * Get Target instance by target id + * + * @param {string} id + * Target id + * + * @return {Target} + */ + getById(id) { + return this._targets.get(id); + } + + /** + * Get Target instance by browsing context id + * + * @param {number} id + * browsing context id + * + * @return {Target} + */ + getByBrowsingContext(id) { + let rv; + for (const target of this._targets.values()) { + if (target.browsingContext && target.browsingContext.id === id) { + rv = target; + break; + } + } + return rv; + } + + /** + * Get the Target instance for the main process. + * This target is a singleton and only exposes a subset of domains. + */ + getMainProcessTarget() { + if (!this.mainProcessTarget) { + this.mainProcessTarget = new MainProcessTarget(this); + this.registerTarget(this.mainProcessTarget); + } + return this.mainProcessTarget; + } + + *[Symbol.iterator]() { + for (const target of this._targets.values()) { + yield target; + } + } + + toJSON() { + return [...this]; + } + + toString() { + return `[object TargetList ${this.size}]`; + } +} |