mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-19 23:07:33 +09:00
Move WebExtensions enabled Add-ons Manager
This commit is contained in:
parent
d7d16e7fbb
commit
358cd0404a
1100 changed files with 133 additions and 106 deletions
699
toolkit/mozapps/webextensions/internal/GMPProvider.jsm
Normal file
699
toolkit/mozapps/webextensions/internal/GMPProvider.jsm
Normal file
|
|
@ -0,0 +1,699 @@
|
|||
/* 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 Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
this.EXPORTED_SYMBOLS = [];
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/AddonManager.jsm");
|
||||
/* globals AddonManagerPrivate*/
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Preferences.jsm");
|
||||
Cu.import("resource://gre/modules/osfile.jsm");
|
||||
/* globals OS*/
|
||||
Cu.import("resource://gre/modules/Log.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
Cu.import("resource://gre/modules/GMPUtils.jsm");
|
||||
/* globals EME_ADOBE_ID, GMP_PLUGIN_IDS, GMPPrefs, GMPUtils, OPEN_H264_ID, WIDEVINE_ID */
|
||||
Cu.import("resource://gre/modules/AppConstants.jsm");
|
||||
Cu.import("resource://gre/modules/UpdateUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(
|
||||
this, "GMPInstallManager", "resource://gre/modules/GMPInstallManager.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(
|
||||
this, "setTimeout", "resource://gre/modules/Timer.jsm");
|
||||
|
||||
const URI_EXTENSION_STRINGS = "chrome://mozapps/locale/extensions/extensions.properties";
|
||||
const STRING_TYPE_NAME = "type.%ID%.name";
|
||||
|
||||
const SEC_IN_A_DAY = 24 * 60 * 60;
|
||||
// How long to wait after a user enabled EME before attempting to download CDMs.
|
||||
const GMP_CHECK_DELAY = 10 * 1000; // milliseconds
|
||||
|
||||
const NS_GRE_DIR = "GreD";
|
||||
const CLEARKEY_PLUGIN_ID = "gmp-clearkey";
|
||||
const CLEARKEY_VERSION = "0.1";
|
||||
|
||||
const GMP_LICENSE_INFO = "gmp_license_info";
|
||||
const GMP_PRIVACY_INFO = "gmp_privacy_info";
|
||||
const GMP_LEARN_MORE = "learn_more_label";
|
||||
|
||||
const GMP_PLUGINS = [
|
||||
{
|
||||
id: OPEN_H264_ID,
|
||||
name: "openH264_name",
|
||||
description: "openH264_description2",
|
||||
// The following licenseURL is part of an awful hack to include the OpenH264
|
||||
// license without having bug 624602 fixed yet, and intentionally ignores
|
||||
// localisation.
|
||||
licenseURL: "chrome://mozapps/content/extensions/OpenH264-license.txt",
|
||||
homepageURL: "http://www.openh264.org/",
|
||||
optionsURL: "chrome://mozapps/content/extensions/gmpPrefs.xul",
|
||||
},
|
||||
{
|
||||
id: EME_ADOBE_ID,
|
||||
name: "eme-adobe_name",
|
||||
description: "eme-adobe_description",
|
||||
// The following learnMoreURL is another hack to be able to support a SUMO page for this
|
||||
// feature.
|
||||
get learnMoreURL() {
|
||||
return Services.urlFormatter.formatURLPref("app.support.baseURL") + "drm-content";
|
||||
},
|
||||
licenseURL: "http://help.adobe.com/en_US/primetime/drm/HTML5_CDM_EULA/index.html",
|
||||
homepageURL: "http://help.adobe.com/en_US/primetime/drm/HTML5_CDM",
|
||||
optionsURL: "chrome://mozapps/content/extensions/gmpPrefs.xul",
|
||||
isEME: true,
|
||||
},
|
||||
{
|
||||
id: WIDEVINE_ID,
|
||||
name: "widevine_description",
|
||||
// Describe the purpose of both CDMs in the same way.
|
||||
description: "eme-adobe_description",
|
||||
licenseURL: "https://www.google.com/policies/privacy/",
|
||||
homepageURL: "https://www.widevine.com/",
|
||||
optionsURL: "chrome://mozapps/content/extensions/gmpPrefs.xul",
|
||||
isEME: true
|
||||
}];
|
||||
XPCOMUtils.defineConstant(this, "GMP_PLUGINS", GMP_PLUGINS);
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "pluginsBundle",
|
||||
() => Services.strings.createBundle("chrome://global/locale/plugins.properties"));
|
||||
XPCOMUtils.defineLazyGetter(this, "gmpService",
|
||||
() => Cc["@mozilla.org/gecko-media-plugin-service;1"].getService(Ci.mozIGeckoMediaPluginChromeService));
|
||||
|
||||
var messageManager = Cc["@mozilla.org/globalmessagemanager;1"]
|
||||
.getService(Ci.nsIMessageListenerManager);
|
||||
|
||||
var gLogger;
|
||||
var gLogAppenderDump = null;
|
||||
|
||||
function configureLogging() {
|
||||
if (!gLogger) {
|
||||
gLogger = Log.repository.getLogger("Toolkit.GMP");
|
||||
gLogger.addAppender(new Log.ConsoleAppender(new Log.BasicFormatter()));
|
||||
}
|
||||
gLogger.level = GMPPrefs.get(GMPPrefs.KEY_LOGGING_LEVEL, Log.Level.Warn);
|
||||
|
||||
let logDumping = GMPPrefs.get(GMPPrefs.KEY_LOGGING_DUMP, false);
|
||||
if (logDumping != !!gLogAppenderDump) {
|
||||
if (logDumping) {
|
||||
gLogAppenderDump = new Log.DumpAppender(new Log.BasicFormatter());
|
||||
gLogger.addAppender(gLogAppenderDump);
|
||||
} else {
|
||||
gLogger.removeAppender(gLogAppenderDump);
|
||||
gLogAppenderDump = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The GMPWrapper provides the info for the various GMP plugins to public
|
||||
* callers through the API.
|
||||
*/
|
||||
function GMPWrapper(aPluginInfo) {
|
||||
this._plugin = aPluginInfo;
|
||||
this._log =
|
||||
Log.repository.getLoggerWithMessagePrefix("Toolkit.GMP",
|
||||
"GMPWrapper(" +
|
||||
this._plugin.id + ") ");
|
||||
Preferences.observe(GMPPrefs.getPrefKey(GMPPrefs.KEY_PLUGIN_ENABLED,
|
||||
this._plugin.id),
|
||||
this.onPrefEnabledChanged, this);
|
||||
Preferences.observe(GMPPrefs.getPrefKey(GMPPrefs.KEY_PLUGIN_VERSION,
|
||||
this._plugin.id),
|
||||
this.onPrefVersionChanged, this);
|
||||
if (this._plugin.isEME) {
|
||||
Preferences.observe(GMPPrefs.KEY_EME_ENABLED,
|
||||
this.onPrefEMEGlobalEnabledChanged, this);
|
||||
messageManager.addMessageListener("EMEVideo:ContentMediaKeysRequest", this);
|
||||
}
|
||||
}
|
||||
|
||||
GMPWrapper.prototype = {
|
||||
// An active task that checks for plugin updates and installs them.
|
||||
_updateTask: null,
|
||||
_gmpPath: null,
|
||||
_isUpdateCheckPending: false,
|
||||
|
||||
optionsType: AddonManager.OPTIONS_TYPE_INLINE,
|
||||
get optionsURL() { return this._plugin.optionsURL; },
|
||||
|
||||
set gmpPath(aPath) { this._gmpPath = aPath; },
|
||||
get gmpPath() {
|
||||
if (!this._gmpPath && this.isInstalled) {
|
||||
this._gmpPath = OS.Path.join(OS.Constants.Path.profileDir,
|
||||
this._plugin.id,
|
||||
GMPPrefs.get(GMPPrefs.KEY_PLUGIN_VERSION,
|
||||
null, this._plugin.id));
|
||||
}
|
||||
return this._gmpPath;
|
||||
},
|
||||
|
||||
get id() { return this._plugin.id; },
|
||||
get type() { return "plugin"; },
|
||||
get isGMPlugin() { return true; },
|
||||
get name() { return this._plugin.name; },
|
||||
get creator() { return null; },
|
||||
get homepageURL() { return this._plugin.homepageURL; },
|
||||
|
||||
get description() { return this._plugin.description; },
|
||||
get fullDescription() { return this._plugin.fullDescription; },
|
||||
|
||||
get version() { return GMPPrefs.get(GMPPrefs.KEY_PLUGIN_VERSION, null,
|
||||
this._plugin.id); },
|
||||
|
||||
get isActive() {
|
||||
return !this.appDisabled &&
|
||||
!this.userDisabled &&
|
||||
!GMPUtils.isPluginHidden(this._plugin);
|
||||
},
|
||||
get appDisabled() {
|
||||
if (this._plugin.isEME && !GMPPrefs.get(GMPPrefs.KEY_EME_ENABLED, true)) {
|
||||
// If "media.eme.enabled" is false, all EME plugins are disabled.
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
get userDisabled() {
|
||||
return !GMPPrefs.get(GMPPrefs.KEY_PLUGIN_ENABLED, true, this._plugin.id);
|
||||
},
|
||||
set userDisabled(aVal) { GMPPrefs.set(GMPPrefs.KEY_PLUGIN_ENABLED,
|
||||
aVal === false,
|
||||
this._plugin.id); },
|
||||
|
||||
get blocklistState() { return Ci.nsIBlocklistService.STATE_NOT_BLOCKED; },
|
||||
get size() { return 0; },
|
||||
get scope() { return AddonManager.SCOPE_APPLICATION; },
|
||||
get pendingOperations() { return AddonManager.PENDING_NONE; },
|
||||
|
||||
get operationsRequiringRestart() { return AddonManager.OP_NEEDS_RESTART_NONE },
|
||||
|
||||
get permissions() {
|
||||
let permissions = 0;
|
||||
if (!this.appDisabled) {
|
||||
permissions |= AddonManager.PERM_CAN_UPGRADE;
|
||||
permissions |= this.userDisabled ? AddonManager.PERM_CAN_ENABLE :
|
||||
AddonManager.PERM_CAN_DISABLE;
|
||||
}
|
||||
return permissions;
|
||||
},
|
||||
|
||||
get updateDate() {
|
||||
let time = Number(GMPPrefs.get(GMPPrefs.KEY_PLUGIN_LAST_UPDATE, null,
|
||||
this._plugin.id));
|
||||
if (!isNaN(time) && this.isInstalled) {
|
||||
return new Date(time * 1000)
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
get isCompatible() {
|
||||
return true;
|
||||
},
|
||||
|
||||
get isPlatformCompatible() {
|
||||
return true;
|
||||
},
|
||||
|
||||
get providesUpdatesSecurely() {
|
||||
return true;
|
||||
},
|
||||
|
||||
get foreignInstall() {
|
||||
return false;
|
||||
},
|
||||
|
||||
isCompatibleWith: function(aAppVersion, aPlatformVersion) {
|
||||
return true;
|
||||
},
|
||||
|
||||
get applyBackgroundUpdates() {
|
||||
if (!GMPPrefs.isSet(GMPPrefs.KEY_PLUGIN_AUTOUPDATE, this._plugin.id)) {
|
||||
return AddonManager.AUTOUPDATE_DEFAULT;
|
||||
}
|
||||
|
||||
return GMPPrefs.get(GMPPrefs.KEY_PLUGIN_AUTOUPDATE, true, this._plugin.id) ?
|
||||
AddonManager.AUTOUPDATE_ENABLE : AddonManager.AUTOUPDATE_DISABLE;
|
||||
},
|
||||
|
||||
set applyBackgroundUpdates(aVal) {
|
||||
if (aVal == AddonManager.AUTOUPDATE_DEFAULT) {
|
||||
GMPPrefs.reset(GMPPrefs.KEY_PLUGIN_AUTOUPDATE, this._plugin.id);
|
||||
} else if (aVal == AddonManager.AUTOUPDATE_ENABLE) {
|
||||
GMPPrefs.set(GMPPrefs.KEY_PLUGIN_AUTOUPDATE, true, this._plugin.id);
|
||||
} else if (aVal == AddonManager.AUTOUPDATE_DISABLE) {
|
||||
GMPPrefs.set(GMPPrefs.KEY_PLUGIN_AUTOUPDATE, false, this._plugin.id);
|
||||
}
|
||||
},
|
||||
|
||||
findUpdates: function(aListener, aReason, aAppVersion, aPlatformVersion) {
|
||||
this._log.trace("findUpdates() - " + this._plugin.id + " - reason=" +
|
||||
aReason);
|
||||
|
||||
AddonManagerPrivate.callNoUpdateListeners(this, aListener);
|
||||
|
||||
if (aReason === AddonManager.UPDATE_WHEN_PERIODIC_UPDATE) {
|
||||
if (!AddonManager.shouldAutoUpdate(this)) {
|
||||
this._log.trace("findUpdates() - " + this._plugin.id +
|
||||
" - no autoupdate");
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
let secSinceLastCheck =
|
||||
Date.now() / 1000 - Preferences.get(GMPPrefs.KEY_UPDATE_LAST_CHECK, 0);
|
||||
if (secSinceLastCheck <= SEC_IN_A_DAY) {
|
||||
this._log.trace("findUpdates() - " + this._plugin.id +
|
||||
" - last check was less then a day ago");
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
} else if (aReason !== AddonManager.UPDATE_WHEN_USER_REQUESTED) {
|
||||
this._log.trace("findUpdates() - " + this._plugin.id +
|
||||
" - the given reason to update is not supported");
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
if (this._updateTask !== null) {
|
||||
this._log.trace("findUpdates() - " + this._plugin.id +
|
||||
" - update task already running");
|
||||
return this._updateTask;
|
||||
}
|
||||
|
||||
this._updateTask = Task.spawn(function*() {
|
||||
this._log.trace("findUpdates() - updateTask");
|
||||
try {
|
||||
let installManager = new GMPInstallManager();
|
||||
let res = yield installManager.checkForAddons();
|
||||
let update = res.gmpAddons.find(addon => addon.id === this._plugin.id);
|
||||
if (update && update.isValid && !update.isInstalled) {
|
||||
this._log.trace("findUpdates() - found update for " +
|
||||
this._plugin.id + ", installing");
|
||||
yield installManager.installAddon(update);
|
||||
} else {
|
||||
this._log.trace("findUpdates() - no updates for " + this._plugin.id);
|
||||
}
|
||||
this._log.info("findUpdates() - updateTask succeeded for " +
|
||||
this._plugin.id);
|
||||
} catch (e) {
|
||||
this._log.error("findUpdates() - updateTask for " + this._plugin.id +
|
||||
" threw", e);
|
||||
throw e;
|
||||
} finally {
|
||||
this._updateTask = null;
|
||||
return true;
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
return this._updateTask;
|
||||
},
|
||||
|
||||
get pluginMimeTypes() { return []; },
|
||||
get pluginLibraries() {
|
||||
if (this.isInstalled) {
|
||||
let path = this.version;
|
||||
return [path];
|
||||
}
|
||||
return [];
|
||||
},
|
||||
get pluginFullpath() {
|
||||
if (this.isInstalled) {
|
||||
let path = OS.Path.join(OS.Constants.Path.profileDir,
|
||||
this._plugin.id,
|
||||
this.version);
|
||||
return [path];
|
||||
}
|
||||
return [];
|
||||
},
|
||||
|
||||
get isInstalled() {
|
||||
return this.version && this.version.length > 0;
|
||||
},
|
||||
|
||||
_handleEnabledChanged: function() {
|
||||
this._log.info("_handleEnabledChanged() id=" +
|
||||
this._plugin.id + " isActive=" + this.isActive);
|
||||
|
||||
AddonManagerPrivate.callAddonListeners(this.isActive ?
|
||||
"onEnabling" : "onDisabling",
|
||||
this, false);
|
||||
if (this._gmpPath) {
|
||||
if (this.isActive) {
|
||||
this._log.info("onPrefEnabledChanged() - adding gmp directory " +
|
||||
this._gmpPath);
|
||||
gmpService.addPluginDirectory(this._gmpPath);
|
||||
} else {
|
||||
this._log.info("onPrefEnabledChanged() - removing gmp directory " +
|
||||
this._gmpPath);
|
||||
gmpService.removePluginDirectory(this._gmpPath);
|
||||
}
|
||||
}
|
||||
AddonManagerPrivate.callAddonListeners(this.isActive ?
|
||||
"onEnabled" : "onDisabled",
|
||||
this);
|
||||
},
|
||||
|
||||
onPrefEMEGlobalEnabledChanged: function() {
|
||||
this._log.info("onPrefEMEGlobalEnabledChanged() id=" + this._plugin.id +
|
||||
" appDisabled=" + this.appDisabled + " isActive=" + this.isActive +
|
||||
" hidden=" + GMPUtils.isPluginHidden(this._plugin));
|
||||
|
||||
AddonManagerPrivate.callAddonListeners("onPropertyChanged", this,
|
||||
["appDisabled"]);
|
||||
// If EME or the GMP itself are disabled, uninstall the GMP.
|
||||
// Otherwise, check for updates, so we download and install the GMP.
|
||||
if (this.appDisabled) {
|
||||
this.uninstallPlugin();
|
||||
} else if (!GMPUtils.isPluginHidden(this._plugin)) {
|
||||
AddonManagerPrivate.callInstallListeners("onExternalInstall", null, this,
|
||||
null, false);
|
||||
AddonManagerPrivate.callAddonListeners("onInstalling", this, false);
|
||||
AddonManagerPrivate.callAddonListeners("onInstalled", this);
|
||||
this.checkForUpdates(GMP_CHECK_DELAY);
|
||||
}
|
||||
if (!this.userDisabled) {
|
||||
this._handleEnabledChanged();
|
||||
}
|
||||
},
|
||||
|
||||
checkForUpdates: function(delay) {
|
||||
if (this._isUpdateCheckPending) {
|
||||
return;
|
||||
}
|
||||
this._isUpdateCheckPending = true;
|
||||
GMPPrefs.reset(GMPPrefs.KEY_UPDATE_LAST_CHECK, null);
|
||||
// Delay this in case the user changes his mind and doesn't want to
|
||||
// enable EME after all.
|
||||
setTimeout(() => {
|
||||
if (!this.appDisabled) {
|
||||
let gmpInstallManager = new GMPInstallManager();
|
||||
// We don't really care about the results, if someone is interested
|
||||
// they can check the log.
|
||||
gmpInstallManager.simpleCheckAndInstall().then(null, () => {});
|
||||
}
|
||||
this._isUpdateCheckPending = false;
|
||||
}, delay);
|
||||
},
|
||||
|
||||
receiveMessage: function({target: browser, data: data}) {
|
||||
this._log.trace("receiveMessage() data=" + data);
|
||||
let parsedData;
|
||||
try {
|
||||
parsedData = JSON.parse(data);
|
||||
} catch (ex) {
|
||||
this._log.error("Malformed EME video message with data: " + data);
|
||||
return;
|
||||
}
|
||||
let {status: status, keySystem: keySystem} = parsedData;
|
||||
if (status == "cdm-not-installed") {
|
||||
this.checkForUpdates(0);
|
||||
}
|
||||
},
|
||||
|
||||
onPrefEnabledChanged: function() {
|
||||
if (!this._plugin.isEME || !this.appDisabled) {
|
||||
this._handleEnabledChanged();
|
||||
}
|
||||
},
|
||||
|
||||
onPrefVersionChanged: function() {
|
||||
AddonManagerPrivate.callAddonListeners("onUninstalling", this, false);
|
||||
if (this._gmpPath) {
|
||||
this._log.info("onPrefVersionChanged() - unregistering gmp directory " +
|
||||
this._gmpPath);
|
||||
gmpService.removeAndDeletePluginDirectory(this._gmpPath, true /* can defer */);
|
||||
}
|
||||
AddonManagerPrivate.callAddonListeners("onUninstalled", this);
|
||||
|
||||
AddonManagerPrivate.callInstallListeners("onExternalInstall", null, this,
|
||||
null, false);
|
||||
AddonManagerPrivate.callAddonListeners("onInstalling", this, false);
|
||||
this._gmpPath = null;
|
||||
if (this.isInstalled) {
|
||||
this._gmpPath = OS.Path.join(OS.Constants.Path.profileDir,
|
||||
this._plugin.id,
|
||||
GMPPrefs.get(GMPPrefs.KEY_PLUGIN_VERSION,
|
||||
null, this._plugin.id));
|
||||
}
|
||||
if (this._gmpPath && this.isActive) {
|
||||
this._log.info("onPrefVersionChanged() - registering gmp directory " +
|
||||
this._gmpPath);
|
||||
gmpService.addPluginDirectory(this._gmpPath);
|
||||
}
|
||||
AddonManagerPrivate.callAddonListeners("onInstalled", this);
|
||||
},
|
||||
|
||||
uninstallPlugin: function() {
|
||||
AddonManagerPrivate.callAddonListeners("onUninstalling", this, false);
|
||||
if (this.gmpPath) {
|
||||
this._log.info("uninstallPlugin() - unregistering gmp directory " +
|
||||
this.gmpPath);
|
||||
gmpService.removeAndDeletePluginDirectory(this.gmpPath);
|
||||
}
|
||||
GMPPrefs.reset(GMPPrefs.KEY_PLUGIN_VERSION, this.id);
|
||||
GMPPrefs.reset(GMPPrefs.KEY_PLUGIN_ABI, this.id);
|
||||
GMPPrefs.reset(GMPPrefs.KEY_PLUGIN_LAST_UPDATE, this.id);
|
||||
AddonManagerPrivate.callAddonListeners("onUninstalled", this);
|
||||
},
|
||||
|
||||
shutdown: function() {
|
||||
Preferences.ignore(GMPPrefs.getPrefKey(GMPPrefs.KEY_PLUGIN_ENABLED,
|
||||
this._plugin.id),
|
||||
this.onPrefEnabledChanged, this);
|
||||
Preferences.ignore(GMPPrefs.getPrefKey(GMPPrefs.KEY_PLUGIN_VERSION,
|
||||
this._plugin.id),
|
||||
this.onPrefVersionChanged, this);
|
||||
if (this._plugin.isEME) {
|
||||
Preferences.ignore(GMPPrefs.KEY_EME_ENABLED,
|
||||
this.onPrefEMEGlobalEnabledChanged, this);
|
||||
messageManager.removeMessageListener("EMEVideo:ContentMediaKeysRequest", this);
|
||||
}
|
||||
return this._updateTask;
|
||||
},
|
||||
|
||||
_arePluginFilesOnDisk: function() {
|
||||
let fileExists = function(aGmpPath, aFileName) {
|
||||
let f = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
|
||||
let path = OS.Path.join(aGmpPath, aFileName);
|
||||
f.initWithPath(path);
|
||||
return f.exists();
|
||||
};
|
||||
|
||||
let id = this._plugin.id.substring(4);
|
||||
let libName = AppConstants.DLL_PREFIX + id + AppConstants.DLL_SUFFIX;
|
||||
let infoName;
|
||||
if (this._plugin.id == WIDEVINE_ID) {
|
||||
infoName = "manifest.json";
|
||||
} else {
|
||||
infoName = id + ".info";
|
||||
}
|
||||
|
||||
return fileExists(this.gmpPath, libName) &&
|
||||
fileExists(this.gmpPath, infoName) &&
|
||||
(this._plugin.id != EME_ADOBE_ID || fileExists(this.gmpPath, id + ".voucher"));
|
||||
},
|
||||
|
||||
validate: function() {
|
||||
if (!this.isInstalled) {
|
||||
// Not installed -> Valid.
|
||||
return {
|
||||
installed: false,
|
||||
valid: true
|
||||
};
|
||||
}
|
||||
|
||||
let abi = GMPPrefs.get(GMPPrefs.KEY_PLUGIN_ABI, UpdateUtils.ABI, this._plugin.id);
|
||||
if (abi != UpdateUtils.ABI) {
|
||||
// ABI doesn't match. Possibly this is a profile migrated across platforms
|
||||
// or from 32 -> 64 bit.
|
||||
return {
|
||||
installed: true,
|
||||
mismatchedABI: true,
|
||||
valid: false
|
||||
};
|
||||
}
|
||||
|
||||
// Installed -> Check if files are missing.
|
||||
let filesOnDisk = this._arePluginFilesOnDisk();
|
||||
return {
|
||||
installed: true,
|
||||
valid: filesOnDisk
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
var GMPProvider = {
|
||||
get name() { return "GMPProvider"; },
|
||||
|
||||
_plugins: null,
|
||||
|
||||
startup: function() {
|
||||
configureLogging();
|
||||
this._log = Log.repository.getLoggerWithMessagePrefix("Toolkit.GMP",
|
||||
"GMPProvider.");
|
||||
this.buildPluginList();
|
||||
this.ensureProperCDMInstallState();
|
||||
|
||||
Preferences.observe(GMPPrefs.KEY_LOG_BASE, configureLogging);
|
||||
|
||||
for (let [id, plugin] of this._plugins) {
|
||||
let wrapper = plugin.wrapper;
|
||||
let gmpPath = wrapper.gmpPath;
|
||||
let isEnabled = wrapper.isActive;
|
||||
this._log.trace("startup - enabled=" + isEnabled + ", gmpPath=" +
|
||||
gmpPath);
|
||||
|
||||
if (gmpPath && isEnabled) {
|
||||
let validation = wrapper.validate();
|
||||
if (validation.mismatchedABI) {
|
||||
this._log.info("startup - gmp " + plugin.id +
|
||||
" mismatched ABI, uninstalling");
|
||||
wrapper.uninstallPlugin();
|
||||
continue;
|
||||
}
|
||||
if (!validation.valid) {
|
||||
this._log.info("startup - gmp " + plugin.id +
|
||||
" invalid, uninstalling");
|
||||
wrapper.uninstallPlugin();
|
||||
continue;
|
||||
}
|
||||
this._log.info("startup - adding gmp directory " + gmpPath);
|
||||
try {
|
||||
gmpService.addPluginDirectory(gmpPath);
|
||||
} catch (e) {
|
||||
if (e.name != 'NS_ERROR_NOT_AVAILABLE')
|
||||
throw e;
|
||||
this._log.warn("startup - adding gmp directory failed with " +
|
||||
e.name + " - sandboxing not available?", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
let greDir = Services.dirsvc.get(NS_GRE_DIR,
|
||||
Ci.nsILocalFile);
|
||||
let clearkeyPath = OS.Path.join(greDir.path,
|
||||
CLEARKEY_PLUGIN_ID,
|
||||
CLEARKEY_VERSION);
|
||||
this._log.info("startup - adding clearkey CDM directory " +
|
||||
clearkeyPath);
|
||||
gmpService.addPluginDirectory(clearkeyPath);
|
||||
} catch (e) {
|
||||
this._log.warn("startup - adding clearkey CDM failed", e);
|
||||
}
|
||||
},
|
||||
|
||||
shutdown: function() {
|
||||
this._log.trace("shutdown");
|
||||
Preferences.ignore(GMPPrefs.KEY_LOG_BASE, configureLogging);
|
||||
|
||||
let shutdownTask = Task.spawn(function*() {
|
||||
this._log.trace("shutdown - shutdownTask");
|
||||
let shutdownSucceeded = true;
|
||||
|
||||
for (let plugin of this._plugins.values()) {
|
||||
try {
|
||||
yield plugin.wrapper.shutdown();
|
||||
} catch (e) {
|
||||
shutdownSucceeded = false;
|
||||
}
|
||||
}
|
||||
|
||||
this._plugins = null;
|
||||
|
||||
if (!shutdownSucceeded) {
|
||||
throw new Error("Shutdown failed");
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
return shutdownTask;
|
||||
},
|
||||
|
||||
getAddonByID: function(aId, aCallback) {
|
||||
if (!this.isEnabled) {
|
||||
aCallback(null);
|
||||
return;
|
||||
}
|
||||
|
||||
let plugin = this._plugins.get(aId);
|
||||
if (plugin && !GMPUtils.isPluginHidden(plugin)) {
|
||||
aCallback(plugin.wrapper);
|
||||
} else {
|
||||
aCallback(null);
|
||||
}
|
||||
},
|
||||
|
||||
getAddonsByTypes: function(aTypes, aCallback) {
|
||||
if (!this.isEnabled ||
|
||||
(aTypes && aTypes.indexOf("plugin") < 0)) {
|
||||
aCallback([]);
|
||||
return;
|
||||
}
|
||||
|
||||
let results = Array.from(this._plugins.values())
|
||||
.filter(p => !GMPUtils.isPluginHidden(p))
|
||||
.map(p => p.wrapper);
|
||||
|
||||
aCallback(results);
|
||||
},
|
||||
|
||||
get isEnabled() {
|
||||
return GMPPrefs.get(GMPPrefs.KEY_PROVIDER_ENABLED, false);
|
||||
},
|
||||
|
||||
generateFullDescription: function(aPlugin) {
|
||||
let rv = [];
|
||||
for (let [urlProp, labelId] of [["learnMoreURL", GMP_LEARN_MORE],
|
||||
["licenseURL", aPlugin.id == WIDEVINE_ID ?
|
||||
GMP_PRIVACY_INFO : GMP_LICENSE_INFO]]) {
|
||||
if (aPlugin[urlProp]) {
|
||||
let label = pluginsBundle.GetStringFromName(labelId);
|
||||
rv.push(`<xhtml:a href="${aPlugin[urlProp]}" target="_blank">${label}</xhtml:a>.`);
|
||||
}
|
||||
}
|
||||
return rv.length ? rv.join("<xhtml:br /><xhtml:br />") : undefined;
|
||||
},
|
||||
|
||||
buildPluginList: function() {
|
||||
this._plugins = new Map();
|
||||
for (let aPlugin of GMP_PLUGINS) {
|
||||
let plugin = {
|
||||
id: aPlugin.id,
|
||||
name: pluginsBundle.GetStringFromName(aPlugin.name),
|
||||
description: pluginsBundle.GetStringFromName(aPlugin.description),
|
||||
homepageURL: aPlugin.homepageURL,
|
||||
optionsURL: aPlugin.optionsURL,
|
||||
wrapper: null,
|
||||
isEME: aPlugin.isEME,
|
||||
};
|
||||
plugin.fullDescription = this.generateFullDescription(aPlugin);
|
||||
plugin.wrapper = new GMPWrapper(plugin);
|
||||
this._plugins.set(plugin.id, plugin);
|
||||
}
|
||||
},
|
||||
|
||||
ensureProperCDMInstallState: function() {
|
||||
if (!GMPPrefs.get(GMPPrefs.KEY_EME_ENABLED, true)) {
|
||||
for (let [id, plugin] of this._plugins) {
|
||||
if (plugin.isEME && plugin.wrapper.isInstalled) {
|
||||
gmpService.addPluginDirectory(plugin.wrapper.gmpPath);
|
||||
plugin.wrapper.uninstallPlugin();
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
AddonManagerPrivate.registerProvider(GMPProvider, [
|
||||
new AddonManagerPrivate.AddonType("plugin", URI_EXTENSION_STRINGS,
|
||||
STRING_TYPE_NAME,
|
||||
AddonManager.VIEW_TYPE_LIST, 6000,
|
||||
AddonManager.TYPE_SUPPORTS_ASK_TO_ACTIVATE)
|
||||
]);
|
||||
Loading…
Add table
Add a link
Reference in a new issue