Bug 1775138 - Part 1: Snapshot Firefox Messaging System targeting configuration periodically. r=barret

This commit arranges to write `targeting.snapshot.json` to the local
profile directory every 30 minutes, and just before shutdown.  For
simplicity, it uses the existing `JSONFile.jsm` implementation.

Differential Revision: https://phabricator.services.mozilla.com/D151057
This commit is contained in:
Nick Alexander 2022-07-08 20:36:08 +00:00
Родитель 86c60e4e77
Коммит 485c3c31e4
7 изменённых файлов: 122 добавлений и 1 удалений

Просмотреть файл

@ -180,6 +180,9 @@ pref("app.update.langpack.enabled", true);
pref("app.update.background.timeoutSec", 600);
// By default, check for updates when the browser is not running every 7 hours.
pref("app.update.background.interval", 25200);
// By default, snapshot Firefox Messaging System targeting for use by the
// background update task every 30 minutes.
pref("app.update.background.messaging.targeting.snapshot.intervalSec", 1800);
#endif
#ifdef XP_MACOSX

Просмотреть файл

@ -2796,6 +2796,14 @@ BrowserGlue.prototype = {
lazy.RemoteAgent.running) &&
Services.prefs.getBoolPref("app.update.disabledForTesting", false);
if (!disabledForTesting) {
try {
lazy.BackgroundUpdate.scheduleFirefoxMessagingSystemTargetingSnapshotting();
} catch (e) {
Cu.reportError(
"There was an error scheduling Firefox Messaging System targeting snapshotting: " +
e
);
}
lazy.BackgroundUpdate.maybeScheduleBackgroundUpdateTask();
}
},

Просмотреть файл

@ -692,6 +692,40 @@ const TargetingGetters = {
const ASRouterTargeting = {
Environment: TargetingGetters,
/**
* Snapshot the current targeting environment.
*
* Asynchronous getters are handled. Getters that throw or reject
* are ignored.
*
* @param {object} target - the environment to snapshot.
* @return {object} snapshot of target with `environment` object and `version`
* integer.
*/
async getEnvironmentSnapshot(target = ASRouterTargeting.Environment) {
// One promise for each named property. Label promises with property name.
let promises = Object.keys(target).map(async name => [
name,
await target[name],
]);
// Ignore properties that are rejected.
let results = await Promise.allSettled(promises);
let environment = {};
for (let result of results) {
if (result.status === "fulfilled") {
let [name, value] = result.value;
environment[name] = value;
}
}
// Should we need to migrate in the future.
const snapshot = { environment, version: 1 };
return snapshot;
},
isTriggerMatch(trigger = {}, candidateMessageTrigger = {}) {
if (trigger.id !== candidateMessageTrigger.id) {
return false;

Просмотреть файл

@ -0,0 +1,24 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
"use strict";
const { ASRouterTargeting } = ChromeUtils.import(
"resource://activity-stream/lib/ASRouterTargeting.jsm"
);
add_task(async function should_ignore_rejections() {
let target = {
get foo() {
return new Promise(resolve => resolve(1));
},
get bar() {
return new Promise((resolve, reject) => reject(new Error("unspecified")));
},
};
let snapshot = await ASRouterTargeting.getEnvironmentSnapshot(target);
deepEqual(snapshot, { environment: { foo: 1 }, version: 1 });
});

Просмотреть файл

@ -18,6 +18,7 @@ skip-if =
[test_AboutWelcomeAttribution.js]
[test_ASRouterTargeting_attribution.js]
skip-if = toolkit != "cocoa" # osx specific tests
[test_ASRouterTargeting_snapshot.js]
[test_AboutWelcomeTelemetry.js]
[test_OnboardingMessageProvider.js]
[test_PanelTestProvider.js]

Просмотреть файл

@ -22,8 +22,10 @@ const lazy = {};
XPCOMUtils.defineLazyModuleGetters(lazy, {
AddonManager: "resource://gre/modules/AddonManager.jsm",
ASRouterTargeting: "resource://activity-stream/lib/ASRouterTargeting.jsm",
BackgroundTasksUtils: "resource://gre/modules/BackgroundTasksUtils.jsm",
FileUtils: "resource://gre/modules/FileUtils.jsm",
JSONFile: "resource://gre/modules/JSONFile.jsm",
TaskScheduler: "resource://gre/modules/TaskScheduler.jsm",
UpdateUtils: "resource://gre/modules/UpdateUtils.jsm",
});
@ -614,6 +616,55 @@ var BackgroundUpdate = {
);
Glean.update.canUsuallyUseBits.set(lazy.UpdateService.canUsuallyUseBits);
},
/**
* Schedule periodic snapshotting of the Firefox Messaging System
* targeting configuration.
*
* The background update task will target messages based on the
* latest snapshot of the default profile's targeting configuration.
*/
async scheduleFirefoxMessagingSystemTargetingSnapshotting() {
let SLUG = "scheduleFirefoxMessagingSystemTargetingSnapshotting";
let path = PathUtils.join(PathUtils.profileDir, "targeting.snapshot.json");
let snapshot = new lazy.JSONFile({
beforeSave: async () => {
lazy.log.debug(
`${SLUG}: preparing to write Firefox Messaging System targeting information to ${path}`
);
snapshot.data = await lazy.ASRouterTargeting.getEnvironmentSnapshot();
},
path,
});
// We don't `load`, since we don't care about reading existing (now stale)
// data.
snapshot.data = lazy.ASRouterTargeting.getEnvironmentSnapshot();
// Persist.
snapshot.saveSoon();
// Continue persisting periodically. `JSONFile.jsm` will also persist one
// last time before shutdown.
this._targetingSnapshottingTimer = Cc[
"@mozilla.org/timer;1"
].createInstance(Ci.nsITimer);
// Hold a reference to prevent GC.
this._targetingSnapshottingTimer.initWithCallback(
() => {
snapshot.saveSoon();
},
// By default, snapshot Firefox Messaging System targeting for use by the
// background update task every 30 minutes.
Services.prefs.getIntPref(
"app.update.background.messaging.targeting.snapshot.intervalSec",
1800
) * 1000,
Ci.nsITimer.TYPE_REPEATING_SLACK_LOW_PRIORITY
);
},
};
BackgroundUpdate.REASON = {

Просмотреть файл

@ -131,7 +131,7 @@ Scheduling background tasks
We use OS-level scheduling mechanisms to schedule the command ``firefox
--backgroundtask backgroundupdate`` to run on a particular cadence. This cadence
is controlled by the ``app.background.update.interval`` preference, which
is controlled by the ``app.update.background.interval`` preference, which
defaults to 7 hours.
On Windows, we use the `Task Scheduler