tor-browser

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

detect-user-session-start.mjs (2861B)


      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 file,
      3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 import {
      6  actionCreators as ac,
      7  actionTypes as at,
      8 } from "../../common/Actions.mjs";
      9 import { perfService as perfSvc } from "./perf-service.mjs";
     10 
     11 const VISIBLE = "visible";
     12 const VISIBILITY_CHANGE_EVENT = "visibilitychange";
     13 
     14 export class DetectUserSessionStart {
     15  constructor(store, options = {}) {
     16    this._store = store;
     17    // Overrides for testing
     18    this.document = options.document || globalThis.document;
     19    this._perfService = options.perfService || perfSvc;
     20    this._onVisibilityChange = this._onVisibilityChange.bind(this);
     21  }
     22 
     23  /**
     24   * sendEventOrAddListener - Notify immediately if the page is already visible,
     25   *                    or else set up a listener for when visibility changes.
     26   *                    This is needed for accurate session tracking for telemetry,
     27   *                    because tabs are pre-loaded.
     28   */
     29  sendEventOrAddListener() {
     30    if (this.document.visibilityState === VISIBLE) {
     31      // If the document is already visible, to the user, send a notification
     32      // immediately that a session has started.
     33      this._sendEvent();
     34    } else {
     35      // If the document is not visible, listen for when it does become visible.
     36      this.document.addEventListener(
     37        VISIBILITY_CHANGE_EVENT,
     38        this._onVisibilityChange
     39      );
     40    }
     41  }
     42 
     43  /**
     44   * _sendEvent - Sends a message to the main process to indicate the current
     45   *              tab is now visible to the user, includes the
     46   *              visibility_event_rcvd_ts time in ms from the UNIX epoch.
     47   */
     48  _sendEvent() {
     49    this._perfService.mark("visibility_event_rcvd_ts");
     50 
     51    try {
     52      let visibility_event_rcvd_ts =
     53        this._perfService.getMostRecentAbsMarkStartByName(
     54          "visibility_event_rcvd_ts"
     55        );
     56 
     57      this._store.dispatch(
     58        ac.AlsoToMain({
     59          type: at.SAVE_SESSION_PERF_DATA,
     60          data: {
     61            visibility_event_rcvd_ts,
     62            window_inner_width: window.innerWidth,
     63            window_inner_height: window.innerHeight,
     64          },
     65        })
     66      );
     67    } catch (ex) {
     68      // If this failed, it's likely because the `privacy.resistFingerprinting`
     69      // pref is true.  We should at least not blow up.
     70    }
     71  }
     72 
     73  /**
     74   * _onVisibilityChange - If the visibility has changed to visible, sends a notification
     75   *                      and removes the event listener. This should only be called once per tab.
     76   */
     77  _onVisibilityChange() {
     78    if (this.document.visibilityState === VISIBLE) {
     79      this._sendEvent();
     80      this.document.removeEventListener(
     81        VISIBILITY_CHANGE_EVENT,
     82        this._onVisibilityChange
     83      );
     84    }
     85  }
     86 }