tor-browser

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

PageDataChild.sys.mjs (3035B)


      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 import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
      6 
      7 const lazy = {};
      8 
      9 ChromeUtils.defineESModuleGetters(lazy, {
     10  PageDataSchema:
     11    "moz-src:///browser/components/pagedata/PageDataSchema.sys.mjs",
     12  PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.sys.mjs",
     13 });
     14 
     15 // We defer any attempt to check for page data for a short time after a page
     16 // loads to allow JS to operate.
     17 XPCOMUtils.defineLazyPreferenceGetter(
     18  lazy,
     19  "READY_DELAY",
     20  "browser.pagedata.readyDelay",
     21  500
     22 );
     23 
     24 /**
     25 * The actor responsible for monitoring a page for page data.
     26 */
     27 export class PageDataChild extends JSWindowActorChild {
     28  #isContentWindowPrivate = true;
     29  /**
     30   * Used to debounce notifications about a page being ready.
     31   *
     32   * @type {Timer | null}
     33   */
     34  #deferTimer = null;
     35 
     36  /**
     37   * Called when the actor is created for a new page.
     38   */
     39  actorCreated() {
     40    this.#isContentWindowPrivate =
     41      lazy.PrivateBrowsingUtils.isContentWindowPrivate(this.contentWindow);
     42  }
     43 
     44  /**
     45   * Called when the page is destroyed.
     46   */
     47  didDestroy() {
     48    if (this.#deferTimer) {
     49      this.#deferTimer.cancel();
     50    }
     51  }
     52 
     53  /**
     54   * Called when the page has signalled it is done loading. This signal is
     55   * debounced by READY_DELAY.
     56   */
     57  #deferReady() {
     58    if (!this.#deferTimer) {
     59      this.#deferTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
     60    }
     61 
     62    // If the timer was already running this re-starts it.
     63    this.#deferTimer.initWithCallback(
     64      () => {
     65        this.#deferTimer = null;
     66        this.sendAsyncMessage("PageData:DocumentReady", {
     67          url: this.document.documentURI,
     68        });
     69      },
     70      lazy.READY_DELAY,
     71      Ci.nsITimer.TYPE_ONE_SHOT_LOW_PRIORITY
     72    );
     73  }
     74 
     75  /**
     76   * Called when a message is received from the parent process.
     77   *
     78   * @param {ReceiveMessageArgument} msg
     79   *   The received message.
     80   *
     81   * @returns {Promise | undefined}
     82   *   A promise for the requested data or undefined if no data was requested.
     83   */
     84  receiveMessage(msg) {
     85    if (this.#isContentWindowPrivate) {
     86      return undefined;
     87    }
     88 
     89    switch (msg.name) {
     90      case "PageData:CheckLoaded":
     91        // The service just started in the parent. Check if this document is
     92        // already loaded.
     93        if (this.document.readystate == "complete") {
     94          this.#deferReady();
     95        }
     96        break;
     97      case "PageData:Collect":
     98        return lazy.PageDataSchema.collectPageData(this.document);
     99    }
    100 
    101    return undefined;
    102  }
    103 
    104  /**
    105   * DOM event handler.
    106   *
    107   * @param {Event} event
    108   *   The DOM event.
    109   */
    110  handleEvent(event) {
    111    if (this.#isContentWindowPrivate) {
    112      return;
    113    }
    114 
    115    switch (event.type) {
    116      case "DOMContentLoaded":
    117      case "pageshow":
    118        this.#deferReady();
    119        break;
    120    }
    121  }
    122 }