tor-browser

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

sources.js (3448B)


      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 
      5 "use strict";
      6 
      7 const Targets = require("resource://devtools/server/actors/targets/index.js");
      8 
      9 const {
     10  STATES: THREAD_STATES,
     11 } = require("resource://devtools/server/actors/thread.js");
     12 
     13 /**
     14 * Start watching for all JS sources related to a given Target Actor.
     15 * This will notify about existing sources, but also the ones created in future.
     16 *
     17 * @param TargetActor targetActor
     18 *        The target actor from which we should observe sources
     19 * @param Object options
     20 *        Dictionary object with following attributes:
     21 *        - onAvailable: mandatory function
     22 *          This will be called for each resource.
     23 */
     24 class SourceWatcher {
     25  constructor() {
     26    this.onNewSource = this.onNewSource.bind(this);
     27  }
     28 
     29  async watch(targetActor, { onAvailable }) {
     30    // The Browser Toolbox uses the Content Process target's Thread actor to debug all scripts
     31    // running into a given process. This includes WindowGlobal scripts.
     32    // Because of this, and in such configuration, we have to ignore the WindowGlobal targets.
     33    if (
     34      targetActor.sessionContext.type == "all" &&
     35      !targetActor.sessionContext.enableWindowGlobalThreadActors &&
     36      targetActor.targetType === Targets.TYPES.FRAME &&
     37      targetActor.typeName != "parentProcessTarget"
     38    ) {
     39      return;
     40    }
     41 
     42    const { threadActor } = targetActor;
     43    this.sourcesManager = targetActor.sourcesManager;
     44    this.onAvailable = onAvailable;
     45 
     46    threadActor.attach({});
     47 
     48    // Disable `ThreadActor.newSource` RDP event in order to avoid unnecessary traffic
     49    threadActor.disableNewSourceEvents();
     50 
     51    threadActor.sourcesManager.on("newSource", this.onNewSource);
     52 
     53    // For WindowGlobal, Content process and Service Worker targets,
     54    // the thread actor is fully managed by the server codebase.
     55    // For these targets, the actor should be "attached" (initialized) right away in order
     56    // to start observing the sources.
     57    //
     58    // For regular and shared Workers, the thread actor is still managed by the client.
     59    // The client will call `attach` (bug 1691986) later, which will also resume worker execution.
     60    const isTargetCreation = threadActor.state == THREAD_STATES.DETACHED;
     61    const { targetType } = targetActor;
     62    if (
     63      isTargetCreation &&
     64      targetType != Targets.TYPES.WORKER &&
     65      targetType != Targets.TYPES.SHARED_WORKER
     66    ) {
     67      await threadActor.attach({});
     68    }
     69 
     70    // Before fetching all sources, process existing ones.
     71    // The ThreadActor is already up and running before this code runs
     72    // and have sources already registered and for which newSource event already fired.
     73    const sources = [];
     74    for (const sourceActor of threadActor.sourcesManager.iter()) {
     75      const resource = sourceActor.form();
     76      sources.push(resource);
     77    }
     78    onAvailable(sources);
     79 
     80    // Requesting all sources should end up emitting newSource on threadActor.sourcesManager
     81    threadActor.addAllSources();
     82  }
     83 
     84  /**
     85   * Stop watching for sources
     86   */
     87  destroy() {
     88    if (this.sourcesManager) {
     89      this.sourcesManager.off("newSource", this.onNewSource);
     90    }
     91  }
     92 
     93  onNewSource(source) {
     94    const resource = source.form();
     95    this.onAvailable([resource]);
     96  }
     97 }
     98 
     99 module.exports = SourceWatcher;