summaryrefslogtreecommitdiffstats
path: root/devtools/server/actors/targets/parent-process.js
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/server/actors/targets/parent-process.js')
-rw-r--r--devtools/server/actors/targets/parent-process.js165
1 files changed, 165 insertions, 0 deletions
diff --git a/devtools/server/actors/targets/parent-process.js b/devtools/server/actors/targets/parent-process.js
new file mode 100644
index 0000000000..8bd7f82a1d
--- /dev/null
+++ b/devtools/server/actors/targets/parent-process.js
@@ -0,0 +1,165 @@
+/* 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 the entire parent process.
+ *
+ * This actor extends BrowsingContextTargetActor.
+ * This actor is extended by WebExtensionTargetActor.
+ *
+ * See devtools/docs/backend/actor-hierarchy.md for more details.
+ */
+
+const { Ci } = require("chrome");
+const Services = require("Services");
+const { DevToolsServer } = require("devtools/server/devtools-server");
+const {
+ getChildDocShells,
+ BrowsingContextTargetActor,
+ browsingContextTargetPrototype,
+} = require("devtools/server/actors/targets/browsing-context");
+const makeDebugger = require("devtools/server/actors/utils/make-debugger");
+
+const { extend } = require("devtools/shared/extend");
+const {
+ parentProcessTargetSpec,
+} = require("devtools/shared/specs/targets/parent-process");
+const Targets = require("devtools/server/actors/targets/index");
+const TargetActorMixin = require("devtools/server/actors/targets/target-actor-mixin");
+
+/**
+ * Protocol.js expects only the prototype object, and does not maintain the prototype
+ * chain when it constructs the ActorClass. For this reason we are using `extend` to
+ * maintain the properties of BrowsingContextTargetActor.prototype
+ */
+const parentProcessTargetPrototype = extend({}, browsingContextTargetPrototype);
+
+/**
+ * Creates a target actor for debugging all the chrome content in the parent process.
+ * Most of the implementation is inherited from BrowsingContextTargetActor.
+ * ParentProcessTargetActor is a child of RootActor, it can be instantiated via
+ * RootActor.getProcess request. ParentProcessTargetActor exposes all target-scoped actors
+ * via its form() request, like BrowsingContextTargetActor.
+ *
+ * @param connection DevToolsServerConnection
+ * The connection to the client.
+ * @param window Window object (optional)
+ * If the upper class already knows against which window the actor should attach,
+ * it is passed as a constructor argument here.
+ */
+parentProcessTargetPrototype.initialize = function(connection, window) {
+ // Defines the default docshell selected for the target actor
+ if (!window) {
+ window = Services.wm.getMostRecentWindow(DevToolsServer.chromeWindowType);
+ }
+
+ // Default to any available top level window if there is no expected window
+ // eg when running ./mach run --chrome chrome://browser/content/aboutTabCrashed.xhtml --jsdebugger
+ if (!window) {
+ window = Services.wm.getMostRecentWindow(null);
+ }
+
+ // We really want _some_ window at least, so fallback to the hidden window if
+ // there's nothing else (such as during early startup).
+ if (!window) {
+ window = Services.appShell.hiddenDOMWindow;
+ }
+
+ BrowsingContextTargetActor.prototype.initialize.call(
+ this,
+ connection,
+ window.docShell
+ );
+
+ // This creates a Debugger instance for chrome debugging all globals.
+ this.makeDebugger = makeDebugger.bind(null, {
+ findDebuggees: dbg => dbg.findAllGlobals(),
+ shouldAddNewGlobalAsDebuggee: () => true,
+ });
+
+ // Ensure catching the creation of any new content docshell
+ this.watchNewDocShells = true;
+};
+
+parentProcessTargetPrototype.isRootActor = true;
+
+/**
+ * Getter for the list of all docshells in this targetActor
+ * @return {Array}
+ */
+Object.defineProperty(parentProcessTargetPrototype, "docShells", {
+ get: function() {
+ // Iterate over all top-level windows and all their docshells.
+ let docShells = [];
+ for (const { docShell } of Services.ww.getWindowEnumerator()) {
+ docShells = docShells.concat(getChildDocShells(docShell));
+ }
+
+ return docShells;
+ },
+});
+
+parentProcessTargetPrototype.observe = function(subject, topic, data) {
+ BrowsingContextTargetActor.prototype.observe.call(this, subject, topic, data);
+ if (!this.attached) {
+ return;
+ }
+
+ subject.QueryInterface(Ci.nsIDocShell);
+
+ if (topic == "chrome-webnavigation-create") {
+ this._onDocShellCreated(subject);
+ } else if (topic == "chrome-webnavigation-destroy") {
+ this._onDocShellDestroy(subject);
+ }
+};
+
+parentProcessTargetPrototype._attach = function() {
+ if (this.attached) {
+ return false;
+ }
+
+ BrowsingContextTargetActor.prototype._attach.call(this);
+
+ // Listen for any new/destroyed chrome docshell
+ Services.obs.addObserver(this, "chrome-webnavigation-create");
+ Services.obs.addObserver(this, "chrome-webnavigation-destroy");
+
+ // Iterate over all top-level windows.
+ for (const { docShell } of Services.ww.getWindowEnumerator()) {
+ if (docShell == this.docShell) {
+ continue;
+ }
+ this._progressListener.watch(docShell);
+ }
+ return undefined;
+};
+
+parentProcessTargetPrototype._detach = function() {
+ if (!this.attached) {
+ return false;
+ }
+
+ Services.obs.removeObserver(this, "chrome-webnavigation-create");
+ Services.obs.removeObserver(this, "chrome-webnavigation-destroy");
+
+ // Iterate over all top-level windows.
+ for (const { docShell } of Services.ww.getWindowEnumerator()) {
+ if (docShell == this.docShell) {
+ continue;
+ }
+ this._progressListener.unwatch(docShell);
+ }
+
+ return BrowsingContextTargetActor.prototype._detach.call(this);
+};
+
+exports.parentProcessTargetPrototype = parentProcessTargetPrototype;
+exports.ParentProcessTargetActor = TargetActorMixin(
+ Targets.TYPES.FRAME,
+ parentProcessTargetSpec,
+ parentProcessTargetPrototype
+);