142 lines
4.7 KiB
JavaScript
142 lines
4.7 KiB
JavaScript
/* 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";
|
|
|
|
const {
|
|
processDescriptorSpec,
|
|
} = require("resource://devtools/shared/specs/descriptors/process.js");
|
|
const {
|
|
WindowGlobalTargetFront,
|
|
} = require("resource://devtools/client/fronts/targets/window-global.js");
|
|
const {
|
|
ContentProcessTargetFront,
|
|
} = require("resource://devtools/client/fronts/targets/content-process.js");
|
|
const {
|
|
FrontClassWithSpec,
|
|
registerFront,
|
|
} = require("resource://devtools/shared/protocol.js");
|
|
const {
|
|
DescriptorMixin,
|
|
} = require("resource://devtools/client/fronts/descriptors/descriptor-mixin.js");
|
|
const DESCRIPTOR_TYPES = require("resource://devtools/client/fronts/descriptors/descriptor-types.js");
|
|
|
|
class ProcessDescriptorFront extends DescriptorMixin(
|
|
FrontClassWithSpec(processDescriptorSpec)
|
|
) {
|
|
constructor(client, targetFront, parentFront) {
|
|
super(client, targetFront, parentFront);
|
|
this._isParent = false;
|
|
this._processTargetFront = null;
|
|
this._targetFrontPromise = null;
|
|
}
|
|
|
|
descriptorType = DESCRIPTOR_TYPES.PROCESS;
|
|
|
|
form(json) {
|
|
this.id = json.id;
|
|
this._isParent = json.isParent;
|
|
this._isWindowlessParent = json.isWindowlessParent;
|
|
this.traits = json.traits || {};
|
|
}
|
|
|
|
async _createProcessTargetFront(form) {
|
|
let front = null;
|
|
// the request to getTarget may return a ContentProcessTargetActor or a
|
|
// ParentProcessTargetActor. In most cases getProcess(0) will return the
|
|
// main process target actor, which is a ParentProcessTargetActor, but
|
|
// not in xpcshell, which uses a ContentProcessTargetActor. So select
|
|
// the right front based on the actor ID.
|
|
if (form.actor.includes("parentProcessTarget")) {
|
|
// ParentProcessTargetActor doesn't have a specific front, instead it uses
|
|
// WindowGlobalTargetFront on the client side.
|
|
front = new WindowGlobalTargetFront(this._client, null, this);
|
|
} else {
|
|
front = new ContentProcessTargetFront(this._client, null, this);
|
|
}
|
|
// As these fronts aren't instantiated by protocol.js, we have to set their actor ID
|
|
// manually like that:
|
|
front.actorID = form.actor;
|
|
front.form(form);
|
|
|
|
// @backward-compat { version 84 } Older server don't send the processID in the form
|
|
if (!front.processID) {
|
|
front.processID = this.id;
|
|
}
|
|
|
|
this.manage(front);
|
|
return front;
|
|
}
|
|
|
|
/**
|
|
* This flag should be true for parent process descriptors of a regular
|
|
* browser instance, where you can expect the target to be associated with a
|
|
* window global.
|
|
*
|
|
* This will typically be true for the descriptor used by the Browser Toolbox
|
|
* or the Browser Console opened against a regular Firefox instance.
|
|
*
|
|
* On the contrary this will be false for parent process descriptors created
|
|
* for xpcshell debugging or for background task debugging.
|
|
*/
|
|
get isBrowserProcessDescriptor() {
|
|
return this._isParent && !this._isWindowlessParent;
|
|
}
|
|
|
|
get isParentProcessDescriptor() {
|
|
return this._isParent;
|
|
}
|
|
|
|
get isProcessDescriptor() {
|
|
return true;
|
|
}
|
|
|
|
getCachedTarget() {
|
|
return this._processTargetFront;
|
|
}
|
|
|
|
async getTarget() {
|
|
// Only return the cached Target if it is still alive.
|
|
if (this._processTargetFront && !this._processTargetFront.isDestroyed()) {
|
|
return this._processTargetFront;
|
|
}
|
|
// Otherwise, ensure that we don't try to spawn more than one Target by
|
|
// returning the pending promise
|
|
if (this._targetFrontPromise) {
|
|
return this._targetFrontPromise;
|
|
}
|
|
this._targetFrontPromise = (async () => {
|
|
let targetFront = null;
|
|
try {
|
|
const targetForm = await super.getTarget();
|
|
targetFront = await this._createProcessTargetFront(targetForm);
|
|
} catch (e) {
|
|
// This is likely to happen if we get a lot of events which drop previous
|
|
// processes.
|
|
console.log(
|
|
`Request to connect to ProcessDescriptor "${this.id}" failed: ${e}`
|
|
);
|
|
}
|
|
// Save the reference to the target only after the call to attach
|
|
// so that getTarget always returns the attached target in case of concurrent calls
|
|
this._processTargetFront = targetFront;
|
|
// clear the promise if we are finished so that we can re-connect if
|
|
// necessary
|
|
this._targetFrontPromise = null;
|
|
return targetFront;
|
|
})();
|
|
return this._targetFrontPromise;
|
|
}
|
|
|
|
destroy() {
|
|
if (this._processTargetFront) {
|
|
this._processTargetFront.destroy();
|
|
this._processTargetFront = null;
|
|
}
|
|
this._targetFrontPromise = null;
|
|
super.destroy();
|
|
}
|
|
}
|
|
|
|
exports.ProcessDescriptorFront = ProcessDescriptorFront;
|
|
registerFront(ProcessDescriptorFront);
|