1
0
Fork 0
firefox/toolkit/components/telemetry/dap/DAPVisitCounter.sys.mjs
Daniel Baumann 5e9a113729
Adding upstream version 140.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
2025-06-25 09:37:52 +02:00

159 lines
5.1 KiB
JavaScript

/* 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 { DAPReportController, Task } from "./DAPReportController.sys.mjs";
let lazy = {};
ChromeUtils.defineLazyGetter(lazy, "logConsole", function () {
return console.createInstance({
prefix: "DAPVisitCounter",
maxLogLevelPref: "toolkit.telemetry.dap.logLevel",
});
});
ChromeUtils.defineESModuleGetters(lazy, {
NimbusFeatures: "resource://nimbus/ExperimentAPI.sys.mjs",
PlacesUtils: "resource://gre/modules/PlacesUtils.sys.mjs",
});
export const DAPVisitCounter = new (class {
counters = null;
dapReportContoller = null;
async startup() {
if (
Services.startup.isInOrBeyondShutdownPhase(
Ci.nsIAppStartup.SHUTDOWN_PHASE_APPSHUTDOWNCONFIRMED
)
) {
lazy.logConsole.warn(
"DAPVisitCounter startup not possible due to shutdown."
);
return;
}
const placesTypes = ["page-visited", "history-cleared", "page-removed"];
const placesListener = async events => {
for (const event of events) {
// Prioritizing data deletion.
switch (event.type) {
case "history-cleared":
case "page-removed": {
await this.dapReportContoller.deleteState();
break;
}
case "page-visited": {
// Even using the event.hidden flag there mayb be some double counting
// here. It would have to be fixed in the Places API.
if (!event.hidden) {
for (const counter of this.counters) {
for (const pattern of counter.patterns) {
if (pattern.matches(event.url)) {
lazy.logConsole.debug(`${pattern.pattern} matched!`);
await this.dapReportContoller.recordMeasurement(
counter.experiment.task_id,
counter.experiment.bucket
);
}
}
}
}
}
}
}
};
lazy.NimbusFeatures.dapTelemetry.onUpdate(async () => {
if (this.counters !== null) {
await this.dapReportContoller.cleanup(30 * 1000, "nimbus-update");
this.counters = null;
this.dapReportContoller = null;
}
// Clear registered calllbacks
lazy.PlacesUtils.observers.removeListener(placesTypes, placesListener);
// If we have an active Nimbus configuration, register this DAPVisitCounter.
if (
lazy.NimbusFeatures.dapTelemetry.getVariable("enabled") &&
lazy.NimbusFeatures.dapTelemetry.getVariable("visitCountingEnabled")
) {
this.initialize_counters();
lazy.PlacesUtils.observers.addListener(placesTypes, placesListener);
/*
Intentionally not adding AsyncShutdown.appShutdownConfirmed.addBlocker.
Attempting to send a report on shutdown causes a NetworkError which
ultimately result in a lost report. Since the pending report is
persisted, it will be submitted on the next start.
*/
let tasks = {};
for (const counter of this.counters) {
const task = new Task({
taskId: counter.experiment.task_id,
bits: 8,
vdaf: "histogram",
length: counter.experiment.task_veclen,
defaultMeasurement: 0,
});
tasks[counter.experiment.task_id] = task;
}
this.dapReportContoller = new DAPReportController({
tasks,
options: {
windowDays: 7,
submissionIntervalMins: 240,
},
});
this.dapReportContoller.startTimedSubmission();
}
});
}
initialize_counters() {
let experiments = lazy.NimbusFeatures.dapTelemetry.getVariable(
"visitCountingExperimentList"
);
this.counters = [];
// This allows two different formats for distributing the URLs for the
// experiment. The experiments get quite large and over 4096 bytes they
// result in a warning (when mirrored in a pref as in this case).
if (Array.isArray(experiments)) {
for (const experiment of experiments) {
let counter = { experiment, count: 0, patterns: [] };
this.counters.push(counter);
for (const url of experiment.urls) {
let mpattern = new MatchPattern(url);
counter.patterns.push(mpattern);
}
}
} else {
for (const [task, urls] of Object.entries(experiments)) {
for (const [idx, url] of urls.entries()) {
const fullUrl = `*://${url}/*`;
this.counters.push({
experiment: {
task_id: task,
task_veclen: 20,
bucket: idx,
},
count: 0,
patterns: [new MatchPattern(fullUrl)],
});
}
}
}
}
show() {
for (const counter of this.counters) {
lazy.logConsole.info(`Experiment: ${counter.experiment.url}`);
}
return this.counters;
}
})();