process.js (4802B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 "use strict"; 5 6 const { 7 processDescriptorSpec, 8 } = require("resource://devtools/shared/specs/descriptors/process.js"); 9 const { 10 WindowGlobalTargetFront, 11 } = require("resource://devtools/client/fronts/targets/window-global.js"); 12 const { 13 ContentProcessTargetFront, 14 } = require("resource://devtools/client/fronts/targets/content-process.js"); 15 const { 16 FrontClassWithSpec, 17 registerFront, 18 } = require("resource://devtools/shared/protocol.js"); 19 const { 20 DescriptorMixin, 21 } = require("resource://devtools/client/fronts/descriptors/descriptor-mixin.js"); 22 const DESCRIPTOR_TYPES = require("resource://devtools/client/fronts/descriptors/descriptor-types.js"); 23 24 class ProcessDescriptorFront extends DescriptorMixin( 25 FrontClassWithSpec(processDescriptorSpec) 26 ) { 27 constructor(client, targetFront, parentFront) { 28 super(client, targetFront, parentFront); 29 this._isParent = false; 30 this._processTargetFront = null; 31 this._targetFrontPromise = null; 32 } 33 34 descriptorType = DESCRIPTOR_TYPES.PROCESS; 35 36 form(json) { 37 this.id = json.id; 38 this._isParent = json.isParent; 39 this._isWindowlessParent = json.isWindowlessParent; 40 this.traits = json.traits || {}; 41 } 42 43 async _createProcessTargetFront(form) { 44 let front = null; 45 // the request to getTarget may return a ContentProcessTargetActor or a 46 // ParentProcessTargetActor. In most cases getProcess(0) will return the 47 // main process target actor, which is a ParentProcessTargetActor, but 48 // not in xpcshell, which uses a ContentProcessTargetActor. So select 49 // the right front based on the actor ID. 50 if (form.actor.includes("parentProcessTarget")) { 51 // ParentProcessTargetActor doesn't have a specific front, instead it uses 52 // WindowGlobalTargetFront on the client side. 53 front = new WindowGlobalTargetFront(this._client, null, this); 54 } else { 55 front = new ContentProcessTargetFront(this._client, null, this); 56 } 57 // As these fronts aren't instantiated by protocol.js, we have to set their actor ID 58 // manually like that: 59 front.actorID = form.actor; 60 front.form(form); 61 62 // @backward-compat { version 84 } Older server don't send the processID in the form 63 if (!front.processID) { 64 front.processID = this.id; 65 } 66 67 this.manage(front); 68 return front; 69 } 70 71 /** 72 * This flag should be true for parent process descriptors of a regular 73 * browser instance, where you can expect the target to be associated with a 74 * window global. 75 * 76 * This will typically be true for the descriptor used by the Browser Toolbox 77 * or the Browser Console opened against a regular Firefox instance. 78 * 79 * On the contrary this will be false for parent process descriptors created 80 * for xpcshell debugging or for background task debugging. 81 */ 82 get isBrowserProcessDescriptor() { 83 return this._isParent && !this._isWindowlessParent; 84 } 85 86 get isParentProcessDescriptor() { 87 return this._isParent; 88 } 89 90 get isProcessDescriptor() { 91 return true; 92 } 93 94 getCachedTarget() { 95 return this._processTargetFront; 96 } 97 98 async getTarget() { 99 // Only return the cached Target if it is still alive. 100 if (this._processTargetFront && !this._processTargetFront.isDestroyed()) { 101 return this._processTargetFront; 102 } 103 // Otherwise, ensure that we don't try to spawn more than one Target by 104 // returning the pending promise 105 if (this._targetFrontPromise) { 106 return this._targetFrontPromise; 107 } 108 this._targetFrontPromise = (async () => { 109 let targetFront = null; 110 try { 111 const targetForm = await super.getTarget(); 112 targetFront = await this._createProcessTargetFront(targetForm); 113 } catch (e) { 114 // This is likely to happen if we get a lot of events which drop previous 115 // processes. 116 console.log( 117 `Request to connect to ProcessDescriptor "${this.id}" failed: ${e}` 118 ); 119 } 120 // Save the reference to the target only after the call to attach 121 // so that getTarget always returns the attached target in case of concurrent calls 122 this._processTargetFront = targetFront; 123 // clear the promise if we are finished so that we can re-connect if 124 // necessary 125 this._targetFrontPromise = null; 126 return targetFront; 127 })(); 128 return this._targetFrontPromise; 129 } 130 131 destroy() { 132 if (this._processTargetFront) { 133 this._processTargetFront.destroy(); 134 this._processTargetFront = null; 135 } 136 this._targetFrontPromise = null; 137 super.destroy(); 138 } 139 } 140 141 registerFront(ProcessDescriptorFront);