tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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);