Bug 1887980 - Report !UpdateService.disabled for the telemetry environment's update.enabled value r=nalexander,application-update-reviewers

In order to do this without initializing the update system this early, we move the functionality to the stub, add an XPCOM interface for it, and convert it to new-style class using the `class` keyword.

Differential Revision: https://phabricator.services.mozilla.com/D209128
This commit is contained in:
Robin Steuber 2024-05-16 20:01:54 +00:00
parent 2ef30b1bbb
commit 69f5302a38
6 changed files with 119 additions and 33 deletions

View file

@ -9,6 +9,7 @@ import { TelemetryUtils } from "resource://gre/modules/TelemetryUtils.sys.mjs";
import { ObjectUtils } from "resource://gre/modules/ObjectUtils.sys.mjs";
import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
import { UpdateUtils } from "resource://gre/modules/UpdateUtils.sys.mjs";
import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
const Utils = TelemetryUtils;
@ -33,6 +34,15 @@ ChromeUtils.defineLazyGetter(lazy, "fxAccounts", () => {
).getFxAccountsSingleton();
});
if (AppConstants.MOZ_UPDATER) {
XPCOMUtils.defineLazyServiceGetter(
lazy,
"UpdateServiceStub",
"@mozilla.org/updates/update-service-stub;1",
"nsIApplicationUpdateServiceStub"
);
}
// The maximum length of a string (e.g. description) in the addons section.
const MAX_ADDON_STRING_LENGTH = 100;
// The maximum length of a string value in the settings.attribution object.
@ -1620,7 +1630,8 @@ EnvironmentCache.prototype = {
intl: Policy._intlLoaded ? getIntlSettings() : {},
update: {
channel: updateChannel,
enabled: !Services.policies || Services.policies.isAllowed("appUpdate"),
enabled:
AppConstants.MOZ_UPDATER && !lazy.UpdateServiceStub.updateDisabled,
},
userPrefs: this._getPrefData(),
sandbox: this._getSandboxData(),

View file

@ -54,25 +54,6 @@ XPCOMUtils.defineLazyServiceGetter(
"nsIApplicationUpdateServiceStub"
);
if (AppConstants.ENABLE_WEBDRIVER) {
XPCOMUtils.defineLazyServiceGetter(
lazy,
"Marionette",
"@mozilla.org/remote/marionette;1",
"nsIMarionette"
);
XPCOMUtils.defineLazyServiceGetter(
lazy,
"RemoteAgent",
"@mozilla.org/remote/agent;1",
"nsIRemoteAgent"
);
} else {
lazy.Marionette = { running: false };
lazy.RemoteAgent = { running: false };
}
const UPDATESERVICE_CID = Components.ID(
"{B3C290A6-3943-4B89-8BBE-C01EB7B3B311}"
);
@ -90,7 +71,6 @@ const PREF_APP_UPDATE_CHECK_ONLY_INSTANCE_INTERVAL =
"app.update.checkOnlyInstance.interval";
const PREF_APP_UPDATE_CHECK_ONLY_INSTANCE_TIMEOUT =
"app.update.checkOnlyInstance.timeout";
const PREF_APP_UPDATE_DISABLEDFORTESTING = "app.update.disabledForTesting";
const PREF_APP_UPDATE_DOWNLOAD_ATTEMPTS = "app.update.download.attempts";
const PREF_APP_UPDATE_DOWNLOAD_MAXATTEMPTS = "app.update.download.maxAttempts";
const PREF_APP_UPDATE_ELEVATE_NEVER = "app.update.elevate.never";
@ -3891,23 +3871,14 @@ export class UpdateService {
}
get disabledForTesting() {
return (
(Cu.isInAutomation ||
lazy.Marionette.running ||
lazy.RemoteAgent.running) &&
Services.prefs.getBoolPref(PREF_APP_UPDATE_DISABLEDFORTESTING, false)
);
return lazy.UpdateServiceStub.updateDisabledForTesting;
}
/**
* See nsIUpdateService.idl
*/
get disabled() {
return (
(Services.policies && !Services.policies.isAllowed("appUpdate")) ||
this.disabledForTesting ||
Services.sysinfo.getProperty("isPackagedApp")
);
return lazy.UpdateServiceStub.updateDisabled;
}
/**

View file

@ -3,8 +3,9 @@
* 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 { FileUtils } from "resource://gre/modules/FileUtils.sys.mjs";
import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
import { FileUtils } from "resource://gre/modules/FileUtils.sys.mjs";
import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
const lazy = {};
@ -12,6 +13,25 @@ ChromeUtils.defineESModuleGetters(lazy, {
UpdateLog: "resource://gre/modules/UpdateLog.sys.mjs",
});
if (AppConstants.ENABLE_WEBDRIVER) {
XPCOMUtils.defineLazyServiceGetter(
lazy,
"Marionette",
"@mozilla.org/remote/marionette;1",
"nsIMarionette"
);
XPCOMUtils.defineLazyServiceGetter(
lazy,
"RemoteAgent",
"@mozilla.org/remote/agent;1",
"nsIRemoteAgent"
);
} else {
lazy.Marionette = { running: false };
lazy.RemoteAgent = { running: false };
}
const DIR_UPDATES = "updates";
const FILE_UPDATE_STATUS = "update.status";
@ -23,6 +43,7 @@ const KEY_OLD_UPDROOT = "OldUpdRootD";
// happens for every install rather than once per profile)
const PREF_PREFIX_UPDATE_DIR_MIGRATED = "app.update.migrated.updateDir3.";
const PREF_APP_UPDATE_ALTUPDATEDIRPATH = "app.update.altUpdateDirPath";
const PREF_APP_UPDATE_DISABLEDFORTESTING = "app.update.disabledForTesting";
function getUpdateBaseDirNoCreate() {
if (Cu.isInAutomation) {
@ -108,6 +129,10 @@ export class UpdateServiceStub {
}
async #init(force_update_init) {
if (this.updateDisabled) {
return;
}
// We call into this from many places to ensure that initialization is done,
// so we want to optimize for the case where initialization is already
// finished.
@ -166,6 +191,29 @@ export class UpdateServiceStub {
}
}
/**
* See nsIUpdateService.idl
*/
get updateDisabledForTesting() {
return (
(Cu.isInAutomation ||
lazy.Marionette.running ||
lazy.RemoteAgent.running) &&
Services.prefs.getBoolPref(PREF_APP_UPDATE_DISABLEDFORTESTING, false)
);
}
/**
* See nsIUpdateService.idl
*/
get updateDisabled() {
return (
(Services.policies && !Services.policies.isAllowed("appUpdate")) ||
this.updateDisabledForTesting ||
Services.sysinfo.getProperty("isPackagedApp")
);
}
async observe(_subject, topic, _data) {
switch (topic) {
// This is sort of the "default" way of being initialized. The

View file

@ -986,4 +986,15 @@ interface nsIApplicationUpdateServiceStub : nsISupports
* @returns Promise<undefined>
*/
Promise initUpdate();
/**
* This is identical to `nsIApplicationUpdateService.disabled`.
*/
readonly attribute boolean updateDisabled;
/**
* This will be `true` if update is disabled specifically because we are
* running a test that didn't opt-in to updating.
*/
readonly attribute boolean updateDisabledForTesting;
};

View file

@ -0,0 +1,43 @@
/* 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/.
*/
"use strict";
const { TelemetryEnvironment } = ChromeUtils.importESModule(
"resource://gre/modules/TelemetryEnvironment.sys.mjs"
);
/**
* This test ensures that packaged installations don't send an `update.enabled`
* value of `true` in the telemetry environment.
*/
add_task(async function telemetryEnvironmentUpdateEnabled() {
const origSysinfo = Services.sysinfo;
registerCleanupFunction(() => {
Services.sysinfo = origSysinfo;
});
const mockSysinfo = Object.create(origSysinfo, {
getProperty: {
configurable: true,
enumerable: true,
writable: false,
value: prop => {
if (prop == "isPackagedApp") {
return true;
}
return origSysinfo.getProperty(prop);
},
},
});
Services.sysinfo = mockSysinfo;
const environmentData = await TelemetryEnvironment.onInitialized();
Assert.equal(
environmentData.settings.update.enabled,
false,
"Update should not be reported as enabled in a packaged app"
);
});

View file

@ -77,6 +77,8 @@ reason = "Update pref migration is currently Windows only"
run-if = ["os == 'win'"]
reason = "Update directory migration is currently Windows only"
["updateEnabledTelemetry.js"]
["updateManagerXML.js"]
["updateSyncManager.js"]