Bug 1920197 - Add prefs to allow updating Widevine directly from the Chromium update service. r=media-playback-reviewers,alwu

This patch allows us to download Widevine updates directly from the
Chromium update service, bypassing balrog and fallback configuration
options. This will be useful in the early stages of testing Widevine
updates, allowing us to use whatever Google has pushed to its own users,
including beta updates, before we engage release engineering.

Relevant Widevine L3 prefs have been added:
- media.gmp-widevinecdm.force-chromium-update
- media.gmp-widevinecdm.force-chromium-beta

which force the use of the Chromium update service, and requesting beta
versions (if available) respectively.

Similarly, Widevine L1 prefs have been added as well:
- media.gmp-widevinecdm-l1.force-chromium-update
- media.gmp-widevinecdm-l1.force-chromium-beta

Differential Revision: https://phabricator.services.mozilla.com/D223017
This commit is contained in:
Andrew Osmond
2024-10-22 02:15:14 +00:00
parent cbbe362eed
commit c6cdd190db
3 changed files with 150 additions and 11 deletions

View File

@@ -2104,10 +2104,17 @@ pref("identity.fxaccounts.telemetry.clientAssociationPing.enabled", true);
// unsupported. // unsupported.
#ifdef MOZ_WIDEVINE_EME #ifdef MOZ_WIDEVINE_EME
pref("media.gmp-manager.chromium-update-url", "https://update.googleapis.com/service/update2/crx?response=redirect&x=id%3D%GUID%%26uc&acceptformat=crx3&updaterversion=999");
pref("media.gmp-widevinecdm.visible", true); pref("media.gmp-widevinecdm.visible", true);
pref("media.gmp-widevinecdm.enabled", true); pref("media.gmp-widevinecdm.enabled", true);
pref("media.gmp-widevinecdm.chromium-guid", "oimompecagnajdejgnnjijobebaeigek");
pref("media.gmp-widevinecdm.force-chromium-update", false);
pref("media.gmp-widevinecdm.force-chromium-beta", false);
#if defined(MOZ_WMF_CDM) && defined(_M_AMD64) #if defined(MOZ_WMF_CDM) && defined(_M_AMD64)
pref("media.gmp-widevinecdm-l1.forceInstall", false); pref("media.gmp-widevinecdm-l1.forceInstall", false);
pref("media.gmp-widevinecdm-l1.chromium-guid", "neifaoindggfcjicffkgpmnlppeffabd");
pref("media.gmp-widevinecdm-l1.force-chromium-update", false);
pref("media.gmp-widevinecdm-l1.force-chromium-beta", false);
#ifdef NIGHTLY_BUILD #ifdef NIGHTLY_BUILD
pref("media.gmp-widevinecdm-l1.visible", true); pref("media.gmp-widevinecdm-l1.visible", true);
pref("media.gmp-widevinecdm-l1.enabled", true); pref("media.gmp-widevinecdm-l1.enabled", true);

View File

@@ -59,6 +59,27 @@ function getLocalSources() {
return []; return [];
} }
function redirectChromiumUpdateService(uri) {
let log = getScopedLogger("GMPInstallManager.checkForAddons");
log.info("fetching redirect from: " + uri);
return new Promise((resolve, reject) => {
let xmlHttp = new lazy.ServiceRequest({ mozAnon: true });
xmlHttp.onload = function () {
resolve(this.responseURL);
};
xmlHttp.onerror = function (e) {
reject("Fetching " + uri + " results in error code: " + e.target.status);
};
xmlHttp.open("GET", uri);
xmlHttp.overrideMimeType("*/*");
xmlHttp.setRequestHeader("Range", "bytes=0-0");
xmlHttp.send();
});
}
function downloadJSON(uri) { function downloadJSON(uri) {
let log = getScopedLogger("GMPInstallManager.checkForAddons"); let log = getScopedLogger("GMPInstallManager.checkForAddons");
log.info("fetching config from: " + uri); log.info("fetching config from: " + uri);
@@ -447,6 +468,72 @@ GMPInstallManager.prototype = {
log.info("Failed to force addons: " + err); log.info("Failed to force addons: " + err);
} }
// Now let's check the addons that we are configured to override to go
// directly to the Chromium component update service.
try {
for (let gmpAddon of addons) {
if (
!GMPPrefs.getBool(
GMPPrefs.KEY_PLUGIN_FORCE_CHROMIUM_UPDATE,
false,
gmpAddon.id
)
) {
continue;
}
const guid = GMPPrefs.getString(
GMPPrefs.KEY_PLUGIN_CHROMIUM_GUID,
"",
gmpAddon.id
);
if (guid === "") {
log.warn("Skipping chromium update, missing GUID for ", gmpAddon.id);
continue;
}
const params = GMPUtils._getChromiumUpdateParameters(gmpAddon);
const serviceUrl = GMPPrefs.getString(
GMPPrefs.KEY_CHROMIUM_UPDATE_URL,
""
);
const redirectUrl = await redirectChromiumUpdateService(
serviceUrl.replace("%GUID%", guid) + params
);
const versionMatch = redirectUrl.match(/_(\d+\.\d+\.\d+\.\d+)\//);
if (!versionMatch || versionMatch.length !== 2) {
log.warn(
"Skipping chromium update, no version from URL: ",
redirectUrl
);
continue;
}
const version = versionMatch[1];
log.info(
"Forcing " +
gmpAddon.id +
" to version " +
version +
" from chromium update " +
redirectUrl
);
// Update the addon with the final URL and the extracted version.
gmpAddon.URL = redirectUrl;
gmpAddon.version = version;
gmpAddon.usedChromiumUpdate = true;
// Delete these properties to avoid verifying the addon against our
// balrog configuration, which may or may not match.
delete gmpAddon.size;
delete gmpAddon.hash;
delete gmpAddon.hashFunction;
}
} catch (err) {
log.info("Failed to switch addons to Chromium update service: " + err);
}
this._deferred.resolve({ addons }); this._deferred.resolve({ addons });
delete this._deferred; delete this._deferred;
return deferredPromise; return deferredPromise;
@@ -669,6 +756,7 @@ GMPInstallManager.prototype = {
export function GMPAddon(addon) { export function GMPAddon(addon) {
let log = getScopedLogger("GMPAddon.constructor"); let log = getScopedLogger("GMPAddon.constructor");
this.usedFallback = false; this.usedFallback = false;
this.usedChromiumUpdate = false;
for (let name of Object.keys(addon)) { for (let name of Object.keys(addon)) {
this[name] = addon[name]; this[name] = addon[name];
} }
@@ -704,18 +792,18 @@ GMPAddon.prototype = {
this.id && this.id &&
this.URL && this.URL &&
this.version && this.version &&
this.hashFunction && (this.usedChromiumUpdate || (this.hashFunction && !!this.hashValue))
!!this.hashValue
); );
}, },
get isInstalled() { get isInstalled() {
return ( return (
this.version && this.version &&
!!this.hashValue &&
GMPPrefs.getString(GMPPrefs.KEY_PLUGIN_VERSION, "", this.id) === GMPPrefs.getString(GMPPrefs.KEY_PLUGIN_VERSION, "", this.id) ===
this.version && this.version &&
(this.usedChromiumUpdate ||
(!!this.hashValue &&
GMPPrefs.getString(GMPPrefs.KEY_PLUGIN_HASHVALUE, "", this.id) === GMPPrefs.getString(GMPPrefs.KEY_PLUGIN_HASHVALUE, "", this.id) ===
this.hashValue this.hashValue))
); );
}, },
get isEME() { get isEME() {
@@ -849,12 +937,16 @@ GMPDownloader.prototype = {
log.info("Setting ABI to '" + abi + "' for " + gmpAddon.id); log.info("Setting ABI to '" + abi + "' for " + gmpAddon.id);
GMPPrefs.setString(GMPPrefs.KEY_PLUGIN_ABI, abi, gmpAddon.id); GMPPrefs.setString(GMPPrefs.KEY_PLUGIN_ABI, abi, gmpAddon.id);
// We use the combination of the hash and version to ensure we are // We use the combination of the hash and version to ensure we are
// up to date. // up to date. Ignored if we used the Chromium update service directly.
if (!gmpAddon.usedChromiumUpdate) {
GMPPrefs.setString( GMPPrefs.setString(
GMPPrefs.KEY_PLUGIN_HASHVALUE, GMPPrefs.KEY_PLUGIN_HASHVALUE,
gmpAddon.hashValue, gmpAddon.hashValue,
gmpAddon.id gmpAddon.id
); );
} else {
GMPPrefs.reset(GMPPrefs.KEY_PLUGIN_HASHVALUE, gmpAddon.id);
}
// Setting the version pref signals installation completion to consumers, // Setting the version pref signals installation completion to consumers,
// if you need to set other prefs etc. do it before this. // if you need to set other prefs etc. do it before this.
GMPPrefs.setString( GMPPrefs.setString(

View File

@@ -101,6 +101,42 @@ export var GMPUtils = {
); );
}, },
_getChromiumUpdateParameters(aPlugin) {
let params = "";
if (AppConstants.platform === "win") {
params += "&os=win";
} else if (AppConstants.platform === "macosx") {
params += "&os=mac";
} else if (AppConstants.platform === "linux") {
params += "&os=Linux";
} else {
throw new Error("Unknown platform " + AppConstants.platform);
}
const abi = Services.appinfo.XPCOMABI;
if (abi.match(/aarch64/)) {
params += "&arch=arm64&os_arch=arm64";
} else if (abi.match(/x86_64/)) {
params += "&arch=x64&os_arch=x64";
} else if (abi.match(/x86/)) {
params += "&arch=x86&os_arch=x86";
} else {
throw new Error("Unknown ABI " + abi);
}
if (
GMPPrefs.getBool(
GMPPrefs.KEY_PLUGIN_FORCE_CHROMIUM_BETA,
false,
aPlugin.id
)
) {
params += "&testrequest=1";
}
return params;
},
_expectedABI(aPlugin) { _expectedABI(aPlugin) {
let defaultABI = lazy.UpdateUtils.ABI; let defaultABI = lazy.UpdateUtils.ABI;
let expectedABIs = [defaultABI]; let expectedABIs = [defaultABI];
@@ -134,9 +170,13 @@ export var GMPPrefs = {
KEY_PLUGIN_FORCE_SUPPORTED: "media.{0}.forceSupported", KEY_PLUGIN_FORCE_SUPPORTED: "media.{0}.forceSupported",
KEY_PLUGIN_FORCE_INSTALL: "media.{0}.forceInstall", KEY_PLUGIN_FORCE_INSTALL: "media.{0}.forceInstall",
KEY_PLUGIN_ALLOW_X64_ON_ARM64: "media.{0}.allow-x64-plugin-on-arm64", KEY_PLUGIN_ALLOW_X64_ON_ARM64: "media.{0}.allow-x64-plugin-on-arm64",
KEY_PLUGIN_CHROMIUM_GUID: "media.{0}.chromium-guid",
KEY_PLUGIN_FORCE_CHROMIUM_UPDATE: "media.{0}.force-chromium-update",
KEY_PLUGIN_FORCE_CHROMIUM_BETA: "media.{0}.force-chromium-beta",
KEY_ALLOW_LOCAL_SOURCES: "media.gmp-manager.allowLocalSources", KEY_ALLOW_LOCAL_SOURCES: "media.gmp-manager.allowLocalSources",
KEY_URL: "media.gmp-manager.url", KEY_URL: "media.gmp-manager.url",
KEY_URL_OVERRIDE: "media.gmp-manager.url.override", KEY_URL_OVERRIDE: "media.gmp-manager.url.override",
KEY_CHROMIUM_UPDATE_URL: "media.gmp-manager.chromium-update-url",
KEY_CERT_CHECKATTRS: "media.gmp-manager.cert.checkAttributes", KEY_CERT_CHECKATTRS: "media.gmp-manager.cert.checkAttributes",
KEY_CERT_REQUIREBUILTIN: "media.gmp-manager.cert.requireBuiltIn", KEY_CERT_REQUIREBUILTIN: "media.gmp-manager.cert.requireBuiltIn",
KEY_CHECK_CONTENT_SIGNATURE: "media.gmp-manager.checkContentSignature", KEY_CHECK_CONTENT_SIGNATURE: "media.gmp-manager.checkContentSignature",