tor-browser

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

viewport-size.js (6326B)


      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  setIgnoreLayoutChanges,
      9 } = require("resource://devtools/shared/layout/utils.js");
     10 const {
     11  CanvasFrameAnonymousContentHelper,
     12 } = require("resource://devtools/server/actors/highlighters/utils/markup.js");
     13 
     14 /**
     15 * The ViewportSizeHighlighter is a class that displays the viewport
     16 * width and height on a small overlay on the top right edge of the page
     17 * while the rulers are turned on. This class is also extended by ViewportSizeOnResizeHighlighter,
     18 * which is used to show the viewport information when the rulers aren't displayed.
     19 */
     20 class ViewportSizeHighlighter {
     21  /**
     22   *
     23   * @param {HighlighterEnvironment} highlighterEnv
     24   * @param {InspectorActor} parent
     25   * @param {object} options
     26   * @param {number} options.hideTimeout: An optional number. When passed, the viewport
     27   *        information will automatically hide after {hideTimeout} ms.
     28   * @param {string} options.extraCls: An extra class to add to the infobar container.
     29   * @param {boolean} options.waitForDocumentToLoad: Option that will be passed to
     30   *        CanvasFrameAnonymousContentHelper. Defaults to true
     31   */
     32  constructor(highlighterEnv, parent, options = {}) {
     33    this.env = highlighterEnv;
     34    this.parent = parent;
     35 
     36    this.extraCls = options?.extraCls;
     37    this.hideTimeout = options?.hideTimeout;
     38 
     39    this.markup = new CanvasFrameAnonymousContentHelper(
     40      highlighterEnv,
     41      this._buildMarkup.bind(this),
     42      {
     43        contentRootHostClassName: "devtools-highlighter-viewport-size",
     44        waitForDocumentToLoad: options?.waitForDocumentToLoad ?? true,
     45      }
     46    );
     47    this._onPageResize = this._onPageResize.bind(this);
     48    this.isReady = this.markup.initialize();
     49 
     50    const { pageListenerTarget } = highlighterEnv;
     51    pageListenerTarget.addEventListener("pagehide", this);
     52  }
     53 
     54  /**
     55   * Static getter that indicates that BoxModelHighlighter supports
     56   * highlighting in XUL windows.
     57   */
     58  static get XULSupported() {
     59    return true;
     60  }
     61 
     62  get isFadingViewportHighlighter() {
     63    return this.hideTimeout !== undefined;
     64  }
     65 
     66  _buildMarkup() {
     67    const container = this.markup.createNode({
     68      attributes: { class: "highlighter-container" },
     69    });
     70 
     71    this.markup.createNode({
     72      parent: container,
     73      attributes: {
     74        id: "viewport-size-highlighter-viewport-infobar-container",
     75        class:
     76          "viewport-size-highlighter-viewport-infobar-container" +
     77          (this.extraCls ? " " + this.extraCls : ""),
     78        position: "top",
     79        hidden: "true",
     80      },
     81    });
     82 
     83    return container;
     84  }
     85 
     86  handleEvent(event) {
     87    switch (event.type) {
     88      case "pagehide":
     89        // If a page hide event is triggered for current window's highlighter, hide the
     90        // highlighter.
     91        if (event.target.defaultView === this.env.window) {
     92          this.destroy();
     93        }
     94        break;
     95    }
     96  }
     97 
     98  _update() {
     99    const { window } = this.env;
    100 
    101    setIgnoreLayoutChanges(true);
    102    this.updateViewportInfobar();
    103    setIgnoreLayoutChanges(false, window.document.documentElement);
    104  }
    105 
    106  updateViewportInfobar() {
    107    const { window } = this.env;
    108    const { innerHeight, innerWidth } = window;
    109    const infobarId = "viewport-size-highlighter-viewport-infobar-container";
    110    const textContent = innerWidth + "px \u00D7 " + innerHeight + "px";
    111    this.markup.getElement(infobarId).setTextContent(textContent);
    112  }
    113 
    114  destroy() {
    115    if (this._destroyed) {
    116      return;
    117    }
    118    this._destroyed = true;
    119 
    120    if (
    121      this.isFadingViewportHighlighter &&
    122      this.parent.highlightersState?.fadingViewportSizeHiglighter
    123    ) {
    124      this.parent.highlightersState.fadingViewportSizeHiglighter = null;
    125    }
    126 
    127    this.hide();
    128 
    129    const { pageListenerTarget } = this.env;
    130 
    131    if (pageListenerTarget) {
    132      pageListenerTarget.removeEventListener("pagehide", this);
    133    }
    134 
    135    this.markup.destroy();
    136 
    137    this.env = null;
    138    this.parent = null;
    139    this.markup = null;
    140    this.isReady = null;
    141  }
    142 
    143  show() {
    144    // pagehide may destroy this custom highlighter before its parent Highlighters class
    145    if (this._destroyed) {
    146      return false;
    147    }
    148 
    149    const { pageListenerTarget } = this.env;
    150    pageListenerTarget.addEventListener("resize", this._onPageResize);
    151    if (this.isFadingViewportHighlighter) {
    152      this.parent.highlightersState.fadingViewportSizeHiglighter = this;
    153    } else {
    154      // If this is handling the regular viewport highlighter (i.e. we want to show rulers)
    155      // hide the viewport on resize highlighter we might have.
    156      if (this.parent.highlightersState.fadingViewportSizeHiglighter) {
    157        this.parent.highlightersState.fadingViewportSizeHiglighter.hide();
    158      }
    159 
    160      // show infobar so that it's not hidden after re-enabling rulers
    161      this._showInfobarContainer();
    162      this._update();
    163    }
    164 
    165    return true;
    166  }
    167 
    168  _onPageResize() {
    169    const { window } = this.env;
    170    if (this.isFadingViewportHighlighter) {
    171      window.clearTimeout(this.resizeTimer);
    172    }
    173    this._showInfobarContainer();
    174    this._update();
    175 
    176    if (this.isFadingViewportHighlighter) {
    177      this.resizeTimer = window.setTimeout(() => {
    178        this._hideInfobarContainer();
    179      }, this.hideTimeout);
    180    }
    181  }
    182 
    183  _showInfobarContainer() {
    184    this.markup.removeAttributeForElement(
    185      "viewport-size-highlighter-viewport-infobar-container",
    186      "hidden"
    187    );
    188  }
    189 
    190  hide() {
    191    const { pageListenerTarget, window } = this.env;
    192    pageListenerTarget.removeEventListener("resize", this._onPageResize);
    193    this._hideInfobarContainer();
    194    if (this.isFadingViewportHighlighter) {
    195      window.clearTimeout(this.resizeTimer);
    196    } else if (this.parent.highlightersState?.fadingViewportSizeHiglighter) {
    197      // Re-set the viewport on resize highlighter when hiding the rulers
    198      this.parent.highlightersState.fadingViewportSizeHiglighter.show();
    199    }
    200  }
    201 
    202  _hideInfobarContainer() {
    203    this.markup.setAttributeForElement(
    204      "viewport-size-highlighter-viewport-infobar-container",
    205      "hidden",
    206      "true"
    207    );
    208  }
    209 }
    210 exports.ViewportSizeHighlighter = ViewportSizeHighlighter;