summaryrefslogtreecommitdiffstats
path: root/browser/components/newtab/content-src/lib/detect-user-session-start.js
diff options
context:
space:
mode:
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.js82
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
+ );
+ }
+ }
+}