diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
commit | 43a97878ce14b72f0981164f87f2e35e14151312 (patch) | |
tree | 620249daf56c0258faa40cbdcf9cfba06de2a846 /devtools/server/actors/targets/content-process.js | |
parent | Initial commit. (diff) | |
download | firefox-43a97878ce14b72f0981164f87f2e35e14151312.tar.xz firefox-43a97878ce14b72f0981164f87f2e35e14151312.zip |
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'devtools/server/actors/targets/content-process.js')
-rw-r--r-- | devtools/server/actors/targets/content-process.js | 257 |
1 files changed, 257 insertions, 0 deletions
diff --git a/devtools/server/actors/targets/content-process.js b/devtools/server/actors/targets/content-process.js new file mode 100644 index 0000000000..b783542fe1 --- /dev/null +++ b/devtools/server/actors/targets/content-process.js @@ -0,0 +1,257 @@ +/* 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"; + +/* + * Target actor for all resources in a content process of Firefox (chrome sandboxes, frame + * scripts, documents, etc.) + * + * See devtools/docs/backend/actor-hierarchy.md for more details. + */ + +const { ThreadActor } = require("resource://devtools/server/actors/thread.js"); +const { + WebConsoleActor, +} = require("resource://devtools/server/actors/webconsole.js"); +const makeDebugger = require("resource://devtools/server/actors/utils/make-debugger.js"); +const { Pool } = require("resource://devtools/shared/protocol.js"); +const { assert } = require("resource://devtools/shared/DevToolsUtils.js"); +const { + SourcesManager, +} = require("resource://devtools/server/actors/utils/sources-manager.js"); +const { Actor } = require("resource://devtools/shared/protocol.js"); +const { + contentProcessTargetSpec, +} = require("resource://devtools/shared/specs/targets/content-process.js"); +const Targets = require("resource://devtools/server/actors/targets/index.js"); +const Resources = require("resource://devtools/server/actors/resources/index.js"); +const TargetActorMixin = require("resource://devtools/server/actors/targets/target-actor-mixin.js"); +const { TargetActorRegistry } = ChromeUtils.importESModule( + "resource://devtools/server/actors/targets/target-actor-registry.sys.mjs" +); + +loader.lazyRequireGetter( + this, + "WorkerDescriptorActorList", + "resource://devtools/server/actors/worker/worker-descriptor-actor-list.js", + true +); +loader.lazyRequireGetter( + this, + "MemoryActor", + "resource://devtools/server/actors/memory.js", + true +); + +const ContentProcessTargetActor = TargetActorMixin( + Targets.TYPES.PROCESS, + contentProcessTargetSpec, + { + initialize(connection, { isXpcShellTarget = false, sessionContext } = {}) { + Actor.prototype.initialize.call(this, connection); + this.conn = connection; + this.threadActor = null; + this.isXpcShellTarget = isXpcShellTarget; + this.sessionContext = sessionContext; + + // Use a see-everything debugger + this.makeDebugger = makeDebugger.bind(null, { + findDebuggees: dbg => dbg.findAllGlobals(), + shouldAddNewGlobalAsDebuggee: global => true, + }); + + const sandboxPrototype = { + get tabs() { + return Array.from( + Services.ww.getWindowEnumerator(), + win => win.docShell.messageManager + ); + }, + }; + + // Scope into which the webconsole executes: + // A sandbox with chrome privileges with a `tabs` getter. + const systemPrincipal = Cc[ + "@mozilla.org/systemprincipal;1" + ].createInstance(Ci.nsIPrincipal); + const sandbox = Cu.Sandbox(systemPrincipal, { + sandboxPrototype, + wantGlobalProperties: ["ChromeUtils"], + }); + this._consoleScope = sandbox; + + this._workerList = null; + this._workerDescriptorActorPool = null; + this._onWorkerListChanged = this._onWorkerListChanged.bind(this); + + // Try to destroy the Content Process Target when the content process shuts down. + // The parent process can't communicate during shutdown as the communication channel + // is already down (message manager or JS Window Actor API). + // So that we have to observe to some event fired from this process. + // While such cleanup doesn't sound ultimately necessary (the process will be completely destroyed) + // mochitests are asserting that there is no leaks during process shutdown. + // Do not override destroy as Protocol.js may override it when calling destroy, + // and we won't be able to call removeObserver correctly. + this.destroyObserver = this.destroy.bind(this); + Services.obs.addObserver(this.destroyObserver, "xpcom-shutdown"); + if (this.isXpcShellTarget) { + TargetActorRegistry.registerXpcShellTargetActor(this); + } + }, + + get isRootActor() { + return true; + }, + + get url() { + return undefined; + }, + + get window() { + return this._consoleScope; + }, + + get sourcesManager() { + if (!this._sourcesManager) { + assert( + this.threadActor, + "threadActor should exist when creating SourcesManager." + ); + this._sourcesManager = new SourcesManager(this.threadActor); + } + return this._sourcesManager; + }, + + /* + * Return a Debugger instance or create one if there is none yet + */ + get dbg() { + if (!this._dbg) { + this._dbg = this.makeDebugger(); + } + return this._dbg; + }, + + form() { + if (!this._consoleActor) { + this._consoleActor = new WebConsoleActor(this.conn, this); + this.manage(this._consoleActor); + } + + if (!this.threadActor) { + this.threadActor = new ThreadActor(this, null); + this.manage(this.threadActor); + } + if (!this.memoryActor) { + this.memoryActor = new MemoryActor(this.conn, this); + this.manage(this.memoryActor); + } + + return { + actor: this.actorID, + consoleActor: this._consoleActor.actorID, + isXpcShellTarget: this.isXpcShellTarget, + memoryActor: this.memoryActor.actorID, + processID: Services.appinfo.processID, + remoteType: Services.appinfo.remoteType, + threadActor: this.threadActor.actorID, + + traits: { + networkMonitor: false, + // See trait description in browsing-context.js + supportsTopLevelTargetFlag: false, + }, + }; + }, + + ensureWorkerList() { + if (!this._workerList) { + this._workerList = new WorkerDescriptorActorList(this.conn, {}); + } + return this._workerList; + }, + + listWorkers() { + return this.ensureWorkerList() + .getList() + .then(actors => { + const pool = new Pool(this.conn, "workers"); + for (const actor of actors) { + pool.manage(actor); + } + + // Do not destroy the pool before transfering ownership to the newly created + // pool, so that we do not accidentally destroy actors that are still in use. + if (this._workerDescriptorActorPool) { + this._workerDescriptorActorPool.destroy(); + } + + this._workerDescriptorActorPool = pool; + this._workerList.onListChanged = this._onWorkerListChanged; + + return { + from: this.actorID, + workers: actors, + }; + }); + }, + + _onWorkerListChanged() { + this.conn.send({ from: this.actorID, type: "workerListChanged" }); + this._workerList.onListChanged = null; + }, + + pauseMatchingServiceWorkers(request) { + this.ensureWorkerList().workerPauser.setPauseServiceWorkers( + request.origin + ); + }, + + destroy() { + // Avoid reentrancy. We will destroy the Transport when emitting "destroyed", + // which will force destroying all actors. + if (this.destroying) { + return; + } + this.destroying = true; + + // Unregistering watchers first is important + // otherwise you might have leaks reported when running browser_browser_toolbox_netmonitor.js in debug builds + Resources.unwatchAllResources(this); + + this.emit("destroyed"); + + Actor.prototype.destroy.call(this); + + if (this.threadActor) { + this.threadActor = null; + } + + // Tell the live lists we aren't watching any more. + if (this._workerList) { + this._workerList.destroy(); + this._workerList = null; + } + + if (this._sourcesManager) { + this._sourcesManager.destroy(); + this._sourcesManager = null; + } + + if (this._dbg) { + this._dbg.disable(); + this._dbg = null; + } + + Services.obs.removeObserver(this.destroyObserver, "xpcom-shutdown"); + + if (this.isXpcShellTarget) { + TargetActorRegistry.unregisterXpcShellTargetActor(this); + } + }, + } +); + +exports.ContentProcessTargetActor = ContentProcessTargetActor; |