tor-browser

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

selector.js (3428B)


      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 {
      8  isNodeValid,
      9 } = require("resource://devtools/server/actors/highlighters/utils/markup.js");
     10 const {
     11  BoxModelHighlighter,
     12 } = require("resource://devtools/server/actors/highlighters/box-model.js");
     13 
     14 // How many maximum nodes can be highlighted at the same time by the SelectorHighlighter
     15 const MAX_HIGHLIGHTED_ELEMENTS = 100;
     16 
     17 /**
     18 * The SelectorHighlighter runs a given selector through querySelectorAll on the
     19 * document of the provided context node and then uses the BoxModelHighlighter
     20 * to highlight the matching nodes
     21 */
     22 class SelectorHighlighter {
     23  constructor(highlighterEnv, inspector) {
     24    this.highlighterEnv = highlighterEnv;
     25    this.inspector = inspector;
     26    this._highlighters = [];
     27  }
     28 
     29  /**
     30   * Show a BoxModelHighlighter on each node that matches a given selector.
     31   *
     32   * @param {DOMNode} node
     33   *        A context node used to get the document element on which to run
     34   *        querySelectorAll(). This node will not be highlighted.
     35   * @param {object} options
     36   *        Configuration options for SelectorHighlighter.
     37   *        All of the options for BoxModelHighlighter.show() are also valid here.
     38   * @param {string} options.selector
     39   *        Required. CSS selector used with querySelectorAll() to find matching elements.
     40   */
     41  async show(node, options = {}) {
     42    this.hide();
     43 
     44    if (!isNodeValid(node) || !options.selector) {
     45      return false;
     46    }
     47 
     48    let nodes = [];
     49 
     50    if (options.ruleActorID && this.inspector) {
     51      const pageStyle = await this.inspector.getPageStyle();
     52      const rule = pageStyle.getActorByID(options.ruleActorID);
     53      if (rule) {
     54        nodes = rule.rawRule.querySelectorAll(node.getRootNode());
     55      }
     56    } else {
     57      try {
     58        nodes = node.ownerDocument.querySelectorAll(options.selector);
     59      } catch (e) {
     60        // It's fine if the provided selector is invalid, `nodes` will be an empty array.
     61      }
     62    }
     63 
     64    // Prevent passing the `selector` option to BoxModelHighlighter
     65    delete options.selector;
     66 
     67    const promises = [];
     68    for (let i = 0; i < Math.min(nodes.length, MAX_HIGHLIGHTED_ELEMENTS); i++) {
     69      promises.push(this._showHighlighter(nodes[i], options));
     70    }
     71 
     72    await Promise.all(promises);
     73    return true;
     74  }
     75 
     76  /**
     77   * Create an instance of BoxModelHighlighter, wait for it to be ready
     78   * (see CanvasFrameAnonymousContentHelper.initialize()),
     79   * then show the highlighter on the given node with the given configuration options.
     80   *
     81   * @param  {DOMNode} node
     82   *         Node to be highlighted
     83   * @param  {object} options
     84   *         Configuration options for the BoxModelHighlighter
     85   * @return {Promise} Promise that resolves when the BoxModelHighlighter is ready
     86   */
     87  async _showHighlighter(node, options) {
     88    const highlighter = new BoxModelHighlighter(this.highlighterEnv);
     89    await highlighter.isReady;
     90 
     91    highlighter.show(node, options);
     92    this._highlighters.push(highlighter);
     93  }
     94 
     95  hide() {
     96    for (const highlighter of this._highlighters) {
     97      highlighter.destroy();
     98    }
     99    this._highlighters = [];
    100  }
    101 
    102  destroy() {
    103    this.hide();
    104    this.highlighterEnv = null;
    105  }
    106 }
    107 exports.SelectorHighlighter = SelectorHighlighter;