diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
commit | 43a97878ce14b72f0981164f87f2e35e14151312 (patch) | |
tree | 620249daf56c0258faa40cbdcf9cfba06de2a846 /toolkit/modules/BrowserTelemetryUtils.sys.mjs | |
parent | Initial commit. (diff) | |
download | firefox-upstream.tar.xz firefox-upstream.zip |
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'toolkit/modules/BrowserTelemetryUtils.sys.mjs')
-rw-r--r-- | toolkit/modules/BrowserTelemetryUtils.sys.mjs | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/toolkit/modules/BrowserTelemetryUtils.sys.mjs b/toolkit/modules/BrowserTelemetryUtils.sys.mjs new file mode 100644 index 0000000000..bacd32686d --- /dev/null +++ b/toolkit/modules/BrowserTelemetryUtils.sys.mjs @@ -0,0 +1,194 @@ +/* -*- mode: js; indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* 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 { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs"; + +const lazy = {}; + +// The maximum number of concurrently-loaded origins allowed in order to +// qualify for the Fission rollout experiment. +XPCOMUtils.defineLazyPreferenceGetter( + lazy, + "fissionExperimentMaxOrigins", + "fission.experiment.max-origins.origin-cap", + 30 +); +// The length of the sliding window during which a user must stay below +// the max origin cap. If the last time a user passed the max origin cap +// fell outside of this window, they will requalify for the experiment. +XPCOMUtils.defineLazyPreferenceGetter( + lazy, + "fissionExperimentSlidingWindowMS", + "fission.experiment.max-origins.sliding-window-ms", + 7 * 24 * 60 * 60 * 1000 +); +// The pref holding the current qaualification state of the user. If +// true, the user is currently qualified from the experiment. +const FISSION_EXPERIMENT_PREF_QUALIFIED = + "fission.experiment.max-origins.qualified"; +XPCOMUtils.defineLazyPreferenceGetter( + lazy, + "fissionExperimentQualified", + FISSION_EXPERIMENT_PREF_QUALIFIED, + false +); +// The pref holding the timestamp of the last time we saw an origin +// count below the cap while the user was not currently marked as +// qualified. +const FISSION_EXPERIMENT_PREF_LAST_QUALIFIED = + "fission.experiment.max-origins.last-qualified"; +XPCOMUtils.defineLazyPreferenceGetter( + lazy, + "fissionExperimentLastQualified", + FISSION_EXPERIMENT_PREF_LAST_QUALIFIED, + 0 +); +// The pref holding the timestamp of the last time we saw an origin +// count exceeding the cap. +const FISSION_EXPERIMENT_PREF_LAST_DISQUALIFIED = + "fission.experiment.max-origins.last-disqualified"; +XPCOMUtils.defineLazyPreferenceGetter( + lazy, + "fissionExperimentLastDisqualified", + FISSION_EXPERIMENT_PREF_LAST_DISQUALIFIED, + 0 +); + +export var BrowserTelemetryUtils = { + recordSiteOriginTelemetry(aWindows, aIsGeckoView) { + Services.tm.idleDispatchToMainThread(() => { + this._recordSiteOriginTelemetry(aWindows, aIsGeckoView); + }); + }, + + computeSiteOriginCount(aWindows, aIsGeckoView) { + // Geckoview and Desktop work differently. On desktop, aBrowser objects + // holds an array of tabs which we can use to get the <browser> objects. + // In Geckoview, it is apps' responsibility to keep track of the tabs, so + // there isn't an easy way for us to get the tabs. + let tabs = []; + if (aIsGeckoView) { + // To get all active windows; Each tab has its own window + tabs = aWindows; + } else { + for (const win of aWindows) { + tabs = tabs.concat(win.gBrowser.tabs); + } + } + + let topLevelBCs = []; + + for (const tab of tabs) { + let browser; + if (aIsGeckoView) { + browser = tab.browser; + } else { + browser = tab.linkedBrowser; + } + + if (browser.browsingContext) { + // This is the top level browsingContext + topLevelBCs.push(browser.browsingContext); + } + } + + return CanonicalBrowsingContext.countSiteOrigins(topLevelBCs); + }, + + _recordSiteOriginTelemetry(aWindows, aIsGeckoView) { + let currentTime = Date.now(); + + // default is 5 minutes + if (!this.min_interval) { + this.min_interval = Services.prefs.getIntPref( + "telemetry.number_of_site_origin.min_interval", + 300000 + ); + } + + let originCount = this.computeSiteOriginCount(aWindows, aIsGeckoView); + let histogram = Services.telemetry.getHistogramById( + "FX_NUMBER_OF_UNIQUE_SITE_ORIGINS_ALL_TABS" + ); + + // Discard the first load because most of the time the first load only has 1 + // tab and 1 window open, so it is useless to report it. + if (!this._lastRecordSiteOrigin) { + this._lastRecordSiteOrigin = currentTime; + } else if (currentTime >= this._lastRecordSiteOrigin + this.min_interval) { + this._lastRecordSiteOrigin = currentTime; + + histogram.add(originCount); + } + + // Update the Fission experiment qualification state based on the + // current origin count: + + // If we don't already have a last disqualification timestamp, look + // through the existing histogram values, and use the existing + // maximum value as the initial count. This will prevent us from + // enrolling users in the experiment if they have a history of + // exceeding our origin cap. + if (!this._checkedInitialExperimentQualification) { + this._checkedInitialExperimentQualification = true; + if ( + !Services.prefs.prefHasUserValue( + FISSION_EXPERIMENT_PREF_LAST_DISQUALIFIED + ) + ) { + for (let [bucketStr, entryCount] of Object.entries( + histogram.snapshot().values + )) { + let bucket = Number(bucketStr); + if (bucket > originCount && entryCount > 0) { + originCount = bucket; + } + } + Services.prefs.setIntPref(FISSION_EXPERIMENT_PREF_LAST_DISQUALIFIED, 0); + } + } + + let currentTimeSec = currentTime / 1000; + if (originCount < lazy.fissionExperimentMaxOrigins) { + let lastDisqualified = lazy.fissionExperimentLastDisqualified; + let lastQualified = lazy.fissionExperimentLastQualified; + + // If the last time we saw a qualifying origin count was earlier + // than the last time we say a disqualifying count, update any + // existing last disqualified timestamp to just before now, on the + // basis that our origin count has probably just fallen below the + // cap. + if (lastDisqualified > 0 && lastQualified <= lastDisqualified) { + Services.prefs.setIntPref( + FISSION_EXPERIMENT_PREF_LAST_DISQUALIFIED, + currentTimeSec - 1 + ); + } + + if (!lazy.fissionExperimentQualified) { + Services.prefs.setIntPref( + FISSION_EXPERIMENT_PREF_LAST_QUALIFIED, + currentTimeSec + ); + + // We have a qualifying origin count now. If the last time we were + // disqualified was prior to the start of our current sliding + // window, re-qualify the user. + if ( + currentTimeSec - lastDisqualified >= + lazy.fissionExperimentSlidingWindowMS / 1000 + ) { + Services.prefs.setBoolPref(FISSION_EXPERIMENT_PREF_QUALIFIED, true); + } + } + } else { + Services.prefs.setIntPref( + FISSION_EXPERIMENT_PREF_LAST_DISQUALIFIED, + currentTimeSec + ); + Services.prefs.setBoolPref(FISSION_EXPERIMENT_PREF_QUALIFIED, false); + } + }, +}; |