diff options
Diffstat (limited to 'components/addons/src/GMPProvider.jsm')
-rw-r--r-- | components/addons/src/GMPProvider.jsm | 605 |
1 files changed, 0 insertions, 605 deletions
diff --git a/components/addons/src/GMPProvider.jsm b/components/addons/src/GMPProvider.jsm deleted file mode 100644 index c89427101..000000000 --- a/components/addons/src/GMPProvider.jsm +++ /dev/null @@ -1,605 +0,0 @@ -/* 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"; - -var Cc = Components.classes; -var Ci = Components.interfaces; -var Cu = Components.utils; - -this.EXPORTED_SYMBOLS = []; - -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.import("resource://gre/modules/AddonManager.jsm"); -Cu.import("resource://gre/modules/Services.jsm"); -Cu.import("resource://gre/modules/Preferences.jsm"); -Cu.import("resource://gre/modules/osfile.jsm"); -Cu.import("resource://gre/modules/Log.jsm"); -Cu.import("resource://gre/modules/Task.jsm"); -Cu.import("resource://gre/modules/GMPUtils.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_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: WIDEVINE_ID, - name: "widevine_name", - // Describe the purpose of both CDMs in the same way. - description: "widevine_description2", - 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; }, - 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 (time !== NaN && 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* GMPProvider_updateTask() { - this._log.trace("findUpdates() - updateTask"); - try { - let installManager = new GMPInstallManager(); - let gmpAddons = yield installManager.checkForAddons(); - let update = gmpAddons.find(function(aAddon) { - return aAddon.id === this._plugin.id; - }, this); - 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() { - 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() { - AddonManagerPrivate.callAddonListeners("onPropertyChanged", this, - ["appDisabled"]); - if (this.appDisabled) { - this.uninstallPlugin(); - } else { - 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" || status == "cdm-insufficient-version") { - 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); - 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; - }, -}; - -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) { - this._log.info("startup - adding gmp directory " + gmpPath); - try { - gmpService.addPluginDirectory(gmpPath); - } catch (e if e.name == 'NS_ERROR_NOT_AVAILABLE') { - this._log.warn("startup - adding gmp directory failed with " + - e.name + " - sandboxing not available?", e); - } - } - } - - if (Preferences.get(GMPPrefs.KEY_EME_ENABLED, false)) { - 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* GMPProvider_shutdownTask() { - 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; - } - - // Tycho: - // let results = [p.wrapper for ([id, p] of this._plugins) - // if (!GMPUtils.isPluginHidden(p))]; - let results = []; - for (let [id, p] of this._plugins) { - if (!GMPUtils.isPluginHidden(p)) { - results.push(p.wrapper); - } - } - - aCallback(results); - }, - - get isEnabled() { - return GMPPrefs.get(GMPPrefs.KEY_PROVIDER_ENABLED, false); - }, - - generateFullDescription: function(aLicenseURL, aLicenseInfo) { - return "<xhtml:a href=\"" + aLicenseURL + "\" target=\"_blank\">" + - aLicenseInfo + "</xhtml:a>." - }, - - buildPluginList: function() { - let licenseInfo = pluginsBundle.GetStringFromName(GMP_LICENSE_INFO); - - 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, - }; - if (aPlugin.licenseURL) { - plugin.fullDescription = - this.generateFullDescription(aPlugin.licenseURL, licenseInfo); - } - 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) -]); |