diff options
Diffstat (limited to 'browser/components/newtab/content-src/lib/detect-user-session-start.js')
-rw-r--r-- | browser/components/newtab/content-src/lib/detect-user-session-start.js | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/browser/components/newtab/content-src/lib/detect-user-session-start.js b/browser/components/newtab/content-src/lib/detect-user-session-start.js new file mode 100644 index 0000000000..43aa388967 --- /dev/null +++ b/browser/components/newtab/content-src/lib/detect-user-session-start.js @@ -0,0 +1,82 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import { + actionCreators as ac, + actionTypes as at, +} from "common/Actions.sys.mjs"; +import { perfService as perfSvc } from "content-src/lib/perf-service"; + +const VISIBLE = "visible"; +const VISIBILITY_CHANGE_EVENT = "visibilitychange"; + +export class DetectUserSessionStart { + constructor(store, options = {}) { + this._store = store; + // Overrides for testing + this.document = options.document || global.document; + this._perfService = options.perfService || perfSvc; + this._onVisibilityChange = this._onVisibilityChange.bind(this); + } + + /** + * sendEventOrAddListener - Notify immediately if the page is already visible, + * or else set up a listener for when visibility changes. + * This is needed for accurate session tracking for telemetry, + * because tabs are pre-loaded. + */ + sendEventOrAddListener() { + if (this.document.visibilityState === VISIBLE) { + // If the document is already visible, to the user, send a notification + // immediately that a session has started. + this._sendEvent(); + } else { + // If the document is not visible, listen for when it does become visible. + this.document.addEventListener( + VISIBILITY_CHANGE_EVENT, + this._onVisibilityChange + ); + } + } + + /** + * _sendEvent - Sends a message to the main process to indicate the current + * tab is now visible to the user, includes the + * visibility_event_rcvd_ts time in ms from the UNIX epoch. + */ + _sendEvent() { + this._perfService.mark("visibility_event_rcvd_ts"); + + try { + let visibility_event_rcvd_ts = + this._perfService.getMostRecentAbsMarkStartByName( + "visibility_event_rcvd_ts" + ); + + this._store.dispatch( + ac.AlsoToMain({ + type: at.SAVE_SESSION_PERF_DATA, + data: { visibility_event_rcvd_ts }, + }) + ); + } catch (ex) { + // If this failed, it's likely because the `privacy.resistFingerprinting` + // pref is true. We should at least not blow up. + } + } + + /** + * _onVisibilityChange - If the visibility has changed to visible, sends a notification + * and removes the event listener. This should only be called once per tab. + */ + _onVisibilityChange() { + if (this.document.visibilityState === VISIBLE) { + this._sendEvent(); + this.document.removeEventListener( + VISIBILITY_CHANGE_EVENT, + this._onVisibilityChange + ); + } + } +} |