tor-browser

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

watcher.js (7123B)


      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 { watcherSpec } = require("resource://devtools/shared/specs/watcher.js");
      7 const {
      8  FrontClassWithSpec,
      9  registerFront,
     10 } = require("resource://devtools/shared/protocol.js");
     11 
     12 loader.lazyRequireGetter(
     13  this,
     14  "WindowGlobalTargetFront",
     15  "resource://devtools/client/fronts/targets/window-global.js",
     16  true
     17 );
     18 loader.lazyRequireGetter(
     19  this,
     20  "ContentProcessTargetFront",
     21  "resource://devtools/client/fronts/targets/content-process.js",
     22  true
     23 );
     24 loader.lazyRequireGetter(
     25  this,
     26  "WorkerTargetFront",
     27  "resource://devtools/client/fronts/targets/worker.js",
     28  true
     29 );
     30 loader.lazyRequireGetter(
     31  this,
     32  "ContentScriptTargetFront",
     33  "resource://devtools/client/fronts/targets/content-script.js",
     34  true
     35 );
     36 
     37 class WatcherFront extends FrontClassWithSpec(watcherSpec) {
     38  constructor(client, targetFront, parentFront) {
     39    super(client, targetFront, parentFront);
     40 
     41    this._onTargetAvailable = this._onTargetAvailable.bind(this);
     42    this._onTargetDestroyed = this._onTargetDestroyed.bind(this);
     43 
     44    // Convert form, which is just JSON object to Fronts for these two events
     45    this.on("target-available-form", this._onTargetAvailable);
     46    this.on("target-destroyed-form", this._onTargetDestroyed);
     47  }
     48 
     49  form(json) {
     50    this.actorID = json.actor;
     51    this.traits = json.traits;
     52  }
     53 
     54  _onTargetAvailable(form) {
     55    let front;
     56    if (form.actor.includes("/contentProcessTarget")) {
     57      front = new ContentProcessTargetFront(this.conn, null, this);
     58    } else if (form.actor.includes("/workerTarget")) {
     59      front = new WorkerTargetFront(this.conn, null, this);
     60    } else if (form.actor.includes("/contentScriptTarget")) {
     61      front = new ContentScriptTargetFront(this.conn, null, this);
     62    } else {
     63      front = new WindowGlobalTargetFront(this.conn, null, this);
     64    }
     65    front.actorID = form.actor;
     66    front.form(form);
     67    this.manage(front);
     68    this.emit("target-available", front);
     69  }
     70 
     71  _onTargetDestroyed(form, options = {}) {
     72    const front = this._getTargetFront(form);
     73 
     74    // When server side target switching is off,
     75    // the watcher may notify us about the top level target destruction a bit late.
     76    // The descriptor (`this.parentFront`) already switched to the new target.
     77    // Missing `target-destroyed` isn't critical when target switching is off
     78    // as `TargetCommand.switchToTarget` will end calling `TargetCommand.onTargetDestroyed` for all
     79    // existing targets.
     80    // https://searchfox.org/mozilla-central/rev/af8e5d37fd56be90ccddae2203e7b875d3f3ae87/devtools/shared/commands/target/target-command.js#166-173
     81    if (front) {
     82      this.emit("target-destroyed", front, options);
     83    }
     84  }
     85 
     86  _getTargetFront(form) {
     87    let front = this.getActorByID(form.actor);
     88    // For top level target, the target will be a child of the descriptor front,
     89    // which happens to be the parent front of the watcher.
     90    if (!front) {
     91      front = this.parentFront.getActorByID(form.actor);
     92    }
     93    return front;
     94  }
     95 
     96  /**
     97   * Retrieve the already existing WindowGlobalTargetFront for the parent
     98   * BrowsingContext of the given BrowsingContext ID.
     99   */
    100  async getParentWindowGlobalTarget(browsingContextID) {
    101    const id = await this.getParentBrowsingContextID(browsingContextID);
    102    if (!id) {
    103      return null;
    104    }
    105    return this.getWindowGlobalTarget(id);
    106  }
    107 
    108  /**
    109   * Memoized getter for the "blackboxing" actor
    110   */
    111  async getBlackboxingActor() {
    112    if (!this._blackboxingActor) {
    113      this._blackboxingActor = await super.getBlackboxingActor();
    114    }
    115    return this._blackboxingActor;
    116  }
    117  /**
    118   * Memoized getter for the "breakpoint-list" actor
    119   */
    120  async getBreakpointListActor() {
    121    if (!this._breakpointListActor) {
    122      this._breakpointListActor = await super.getBreakpointListActor();
    123    }
    124    return this._breakpointListActor;
    125  }
    126 
    127  /**
    128   * Memoized getter for the "target-configuration" actor
    129   */
    130  async getTargetConfigurationActor() {
    131    if (!this._targetConfigurationActor) {
    132      this._targetConfigurationActor =
    133        await super.getTargetConfigurationActor();
    134    }
    135    return this._targetConfigurationActor;
    136  }
    137 
    138  /**
    139   * Memoized getter for the "thread-configuration" actor
    140   */
    141  async getThreadConfigurationActor() {
    142    if (!this._threadConfigurationActor) {
    143      this._threadConfigurationActor =
    144        await super.getThreadConfigurationActor();
    145    }
    146    return this._threadConfigurationActor;
    147  }
    148 
    149  /**
    150   * For a given BrowsingContext ID, return the already existing WindowGlobalTargetFront
    151   */
    152  async getWindowGlobalTarget(id) {
    153    // First scan the watcher children as the watcher manages all the targets
    154    for (const front of this.poolChildren()) {
    155      if (front.browsingContextID == id) {
    156        return front;
    157      }
    158    }
    159    // But the top level target will be created by the Descriptor.getTarget() method
    160    // and so be hosted in the Descriptor's pool.
    161    // The parent front of the WatcherActor happens to be the Descriptor Actor.
    162    // This code could go away or be simplified if the Descriptor starts fetch all
    163    // the targets, including the top level one via the Watcher. i.e. drop Descriptor.getTarget().
    164    const topLevelTarget = await this.parentFront.getTarget();
    165    if (topLevelTarget?.browsingContextID == id) {
    166      return topLevelTarget;
    167    }
    168 
    169    // If we could not find a window global target for the provided id, the
    170    // window global might not be the topmost one of a given process (isProcessRoot == true).
    171    // For now we only create targets for the top window global of each process,
    172    // so we recursively check the parent browsing context ids
    173    // until we find a valid target.
    174    const parentBrowsingContextID = await this.getParentBrowsingContextID(id);
    175    if (parentBrowsingContextID && parentBrowsingContextID !== id) {
    176      return this.getWindowGlobalTarget(parentBrowsingContextID);
    177    }
    178 
    179    return null;
    180  }
    181 
    182  getWindowGlobalTargetByInnerWindowId(innerWindowId) {
    183    for (const front of this.poolChildren()) {
    184      if (front.innerWindowId == innerWindowId) {
    185        return front;
    186      }
    187    }
    188    // Use getCachedTarget in order to have a fully synchronous method
    189    // as the callsite in ResourceCommand benefit from being synchronous.
    190    // Here we care only about already existing resource and do not need to
    191    // wait for the next target to come.
    192    const topLevelTarget = this.parentFront.getCachedTarget();
    193    if (topLevelTarget?.innerWindowId == innerWindowId) {
    194      return topLevelTarget;
    195    }
    196    console.error("Unable to find target with innerWindowId:" + innerWindowId);
    197    return null;
    198  }
    199 
    200  /**
    201   * Memoized getter for the "networkParent" actor
    202   */
    203  async getNetworkParentActor() {
    204    if (!this._networkParentActor) {
    205      this._networkParentActor = await super.getNetworkParentActor();
    206    }
    207    return this._networkParentActor;
    208  }
    209 }
    210 registerFront(WatcherFront);