tor-browser

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

screenshot-content.js (4955B)


      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 { Actor } = require("resource://devtools/shared/protocol.js");
      7 const {
      8  screenshotContentSpec,
      9 } = require("resource://devtools/shared/specs/screenshot-content.js");
     10 
     11 const { LocalizationHelper } = require("resource://devtools/shared/l10n.js");
     12 const STRINGS_URI = "devtools/shared/locales/screenshot.properties";
     13 const L10N = new LocalizationHelper(STRINGS_URI);
     14 loader.lazyRequireGetter(
     15  this,
     16  ["getCurrentZoom", "getRect"],
     17  "resource://devtools/shared/layout/utils.js",
     18  true
     19 );
     20 
     21 exports.ScreenshotContentActor = class ScreenshotContentActor extends Actor {
     22  constructor(conn, targetActor) {
     23    super(conn, screenshotContentSpec);
     24    this.targetActor = targetActor;
     25  }
     26 
     27  _getRectForNode(node) {
     28    const originWindow = this.targetActor.ignoreSubFrames
     29      ? node.ownerGlobal
     30      : node.ownerGlobal.top;
     31    return getRect(originWindow, node, node.ownerGlobal);
     32  }
     33 
     34  /**
     35   * Retrieve some window-related information that will be passed to the parent process
     36   * to actually generate the screenshot.
     37   *
     38   * @param {object} args
     39   * @param {boolean} args.fullpage: Should the screenshot be the height of the whole page
     40   * @param {string} args.selector: A CSS selector for the element we should take the
     41   *                 screenshot of. The function will return true for the `error` property
     42   *                 if the screenshot does not match any element.
     43   * @param {string} args.nodeActorID: The actorID of the node actor matching the element
     44   *                 we should take the screenshot of.
     45   * @returns {object} An object with the following properties:
     46   *          - error {Boolean}: Set to true if an issue was encountered that prevents
     47   *            taking the screenshot
     48   *          - messages {Array<Object{text, level}>}: An array of objects representing
     49   *            the messages emitted throught the process and their level.
     50   *          - windowDpr {Number}: Value of window.devicePixelRatio
     51   *          - windowZoom {Number}: The page current zoom level
     52   *          - rect {Object}: Object with left, top, width and height properties
     53   *            representing the rect **inside the browser element** that should be rendered.
     54   *            For screenshot of the current viewport, we return null, as expected by the
     55   *            `drawSnapshot` API.
     56   */
     57  prepareCapture({ fullpage, selector, nodeActorID }) {
     58    const { window } = this.targetActor;
     59    // Use the override if set, note that the override is not returned by
     60    // devicePixelRatio on privileged code, see bug 1759962.
     61    //
     62    // FIXME(bug 1760711): Whether zoom is included in devicePixelRatio depends
     63    // on whether there's an override, this is a bit suspect.
     64    const windowDpr =
     65      window.browsingContext.top.overrideDPPX || window.devicePixelRatio;
     66    const windowZoom = getCurrentZoom(window);
     67    const messages = [];
     68 
     69    // If we're going to take the current view of the page, we don't need to compute a rect,
     70    // since it's the default behaviour of drawSnapshot.
     71    if (!fullpage && !selector && !nodeActorID) {
     72      return {
     73        rect: null,
     74        messages,
     75        windowDpr,
     76        windowZoom,
     77      };
     78    }
     79 
     80    let left;
     81    let top;
     82    let width;
     83    let height;
     84 
     85    if (fullpage) {
     86      // We don't want to render the scrollbars
     87      const winUtils = window.windowUtils;
     88      const scrollbarHeight = {};
     89      const scrollbarWidth = {};
     90      winUtils.getScrollbarSize(false, scrollbarWidth, scrollbarHeight);
     91 
     92      left = 0;
     93      top = 0;
     94      width =
     95        window.innerWidth +
     96        window.scrollMaxX -
     97        window.scrollMinX -
     98        scrollbarWidth.value;
     99      height =
    100        window.innerHeight +
    101        window.scrollMaxY -
    102        window.scrollMinY -
    103        scrollbarHeight.value;
    104    } else if (selector) {
    105      const node = window.document.querySelector(selector);
    106 
    107      if (!node) {
    108        messages.push({
    109          level: "warn",
    110          text: L10N.getFormatStr("screenshotNoSelectorMatchWarning", selector),
    111        });
    112 
    113        return {
    114          error: true,
    115          messages,
    116        };
    117      }
    118 
    119      ({ left, top, width, height } = this._getRectForNode(node));
    120    } else if (nodeActorID) {
    121      const nodeActor = this.conn.getActor(nodeActorID);
    122      if (!nodeActor) {
    123        messages.push({
    124          level: "error",
    125          text: `Screenshot actor failed to find Node actor for '${nodeActorID}'`,
    126        });
    127 
    128        return {
    129          error: true,
    130          messages,
    131        };
    132      }
    133 
    134      ({ left, top, width, height } = this._getRectForNode(nodeActor.rawNode));
    135    }
    136 
    137    return {
    138      windowDpr,
    139      windowZoom,
    140      rect: { left, top, width, height },
    141      messages,
    142    };
    143  }
    144 };