tor-browser

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

changes.js (3686B)


      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 { Actor } = require("resource://devtools/shared/protocol.js");
      8 const { changesSpec } = require("resource://devtools/shared/specs/changes.js");
      9 
     10 /**
     11 * The ChangesActor stores a stack of changes made by devtools on
     12 * the document in the associated tab.
     13 */
     14 class ChangesActor extends Actor {
     15  /**
     16   * Create a ChangesActor.
     17   *
     18   * @param {DevToolsServerConnection} conn
     19   *    The server connection.
     20   * @param {TargetActor} targetActor
     21   *    The top-level Actor for this tab.
     22   */
     23  constructor(conn, targetActor) {
     24    super(conn, changesSpec);
     25    this.targetActor = targetActor;
     26 
     27    this.onTrackChange = this.pushChange.bind(this);
     28    this.onWillNavigate = this.onWillNavigate.bind(this);
     29 
     30    this.targetActor.on("track-css-change", this.onTrackChange);
     31    this.targetActor.on("will-navigate", this.onWillNavigate);
     32 
     33    this.changes = [];
     34  }
     35 
     36  destroy() {
     37    // Stop trying to emit RDP event on destruction.
     38    this._changesHaveBeenRequested = false;
     39    this.clearChanges();
     40    this.targetActor.off("will-navigate", this.onWillNavigate);
     41    this.targetActor.off("track-css-change", this.onTrackChange);
     42    super.destroy();
     43  }
     44 
     45  start() {
     46    /**
     47     * This function currently does nothing and returns nothing. It exists only
     48     * so that the client can trigger the creation of the ChangesActor through
     49     * the front, without triggering side effects, and with a sensible semantic
     50     * meaning.
     51     */
     52  }
     53 
     54  changeCount() {
     55    return this.changes.length;
     56  }
     57 
     58  change(index) {
     59    if (index >= 0 && index < this.changes.length) {
     60      // Return a copy of the change at index.
     61      return Object.assign({}, this.changes[index]);
     62    }
     63    // No change at that index -- return undefined.
     64    return undefined;
     65  }
     66 
     67  allChanges() {
     68    /**
     69     * This function is called by all change event consumers on the client
     70     * to get their initial state synchronized with the ChangesActor. We
     71     * set a flag when this function is called so we know that it's worthwhile
     72     * to send events.
     73     */
     74    this._changesHaveBeenRequested = true;
     75    return this.changes.slice();
     76  }
     77 
     78  /**
     79   * Handler for "will-navigate" event from the browsing context. The event is fired for
     80   * the host page and any nested resources, like iframes. The list of changes should be
     81   * cleared only when the host page navigates, ignoring any of its iframes.
     82   *
     83   * TODO: Clear changes made within sources in iframes when they navigate. Bug 1513940
     84   *
     85   * @param {object} eventData
     86   *        Event data with these properties:
     87   *        {
     88   *          window: Object      // Window DOM object of the event source page
     89   *          isTopLevel: Boolean // true if the host page will navigate
     90   *          newURI: String      // URI towards which the page will navigate
     91   *          request: Object     // Request data.
     92   *        }
     93   */
     94  onWillNavigate(eventData) {
     95    if (eventData.isTopLevel) {
     96      this.clearChanges();
     97    }
     98  }
     99 
    100  pushChange(change) {
    101    this.changes.push(change);
    102    if (this._changesHaveBeenRequested) {
    103      this.emit("add-change", change);
    104    }
    105  }
    106 
    107  popChange() {
    108    const change = this.changes.pop();
    109    if (this._changesHaveBeenRequested) {
    110      this.emit("remove-change", change);
    111    }
    112    return change;
    113  }
    114 
    115  clearChanges() {
    116    this.changes.length = 0;
    117    if (this._changesHaveBeenRequested) {
    118      this.emit("clear-changes");
    119    }
    120  }
    121 }
    122 
    123 exports.ChangesActor = ChangesActor;