Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  GMPProvider.sys.mjs   Sprache: unbekannt

 
/* 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/. */

import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";

import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";

const lazy = {};

ChromeUtils.defineESModuleGetters(lazy, {
  AddonManager: "resource://gre/modules/AddonManager.sys.mjs",
  AddonManagerPrivate: "resource://gre/modules/AddonManager.sys.mjs",
  GMPInstallManager: "resource://gre/modules/GMPInstallManager.sys.mjs",
  Log: "resource://gre/modules/Log.sys.mjs",
  setTimeout: "resource://gre/modules/Timer.sys.mjs",
});

import {
  GMPPrefs,
  GMPUtils,
  OPEN_H264_ID,
  WIDEVINE_L1_ID,
  WIDEVINE_L3_ID,
} from "resource://gre/modules/GMPUtils.sys.mjs";

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 XHTML = "http://www.w3.org/1999/xhtml";

const NS_GRE_DIR = "GreD";
const CLEARKEY_PLUGIN_ID = "gmp-clearkey";
const CLEARKEY_VERSION = "0.1";

const FIRST_CONTENT_PROCESS_TOPIC = "ipc:first-content-process-created";

const GMP_LICENSE_INFO = "plugins-gmp-license-info";
const GMP_PRIVACY_INFO = "plugins-gmp-privacy-info";
const GMP_LEARN_MORE = "learn_more_label";

const GMP_PLUGINS = [
  {
    id: OPEN_H264_ID,
    name: "plugins-openh264-name",
    description: "plugins-openh264-description",
    level: "",
    libName: "gmpopenh264",
    // 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: "https://www.openh264.org/",
  },
  {
    id: WIDEVINE_L1_ID,
    name: "plugins-widevine-name",
    description: "plugins-widevine-description",
    level: "L1",
    libName: "Google.Widevine.CDM",
    licenseURL: "https://www.google.com/policies/privacy/",
    homepageURL: "https://www.widevine.com/",
    isEME: true,
  },
  {
    id: WIDEVINE_L3_ID,
    name: "plugins-widevine-name",
    description: "plugins-widevine-description",
    level: "L3",
    libName: "widevinecdm",
    licenseURL: "https://www.google.com/policies/privacy/",
    homepageURL: "https://www.widevine.com/",
    isEME: true,
  },
];

ChromeUtils.defineLazyGetter(
  lazy,
  "addonsBundle",
  () => new Localization(["toolkit/about/aboutAddons.ftl"], true)
);
ChromeUtils.defineLazyGetter(lazy, "gmpService", () =>
  Cc["@mozilla.org/gecko-media-plugin-service;1"].getService(
    Ci.mozIGeckoMediaPluginChromeService
  )
);

XPCOMUtils.defineLazyPreferenceGetter(
  lazy,
  "gmpProviderEnabled",
  GMPPrefs.KEY_PROVIDER_ENABLED
);

var gLogger;
var gLogAppenderDump = null;

function configureLogging() {
  if (!gLogger) {
    gLogger = lazy.Log.repository.getLogger("Toolkit.GMP");
    gLogger.addAppender(
      new lazy.Log.ConsoleAppender(new lazy.Log.BasicFormatter())
    );
  }
  gLogger.level = GMPPrefs.getInt(
    GMPPrefs.KEY_LOGGING_LEVEL,
    lazy.Log.Level.Warn
  );

  let logDumping = GMPPrefs.getBool(GMPPrefs.KEY_LOGGING_DUMP, false);
  if (logDumping != !!gLogAppenderDump) {
    if (logDumping) {
      gLogAppenderDump = new lazy.Log.DumpAppender(
        new lazy.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, aRawPluginInfo) {
  this._plugin = aPluginInfo;
  this._rawPlugin = aRawPluginInfo;
  this._log = lazy.Log.repository.getLoggerWithMessagePrefix(
    "Toolkit.GMP",
    "GMPWrapper(" + this._plugin.id + ") "
  );
  Services.prefs.addObserver(
    GMPPrefs.getPrefKey(GMPPrefs.KEY_PLUGIN_ENABLED, this._plugin.id),
    this,
    true
  );
  Services.prefs.addObserver(
    GMPPrefs.getPrefKey(GMPPrefs.KEY_PLUGIN_VERSION, this._plugin.id),
    this,
    true
  );
  if (this._plugin.isEME) {
    Services.prefs.addObserver(GMPPrefs.KEY_EME_ENABLED, this, true);
    Services.obs.addObserver(this, "EMEVideo:CDMMissing");
  }
}

GMPWrapper.prototype = {
  QueryInterface: ChromeUtils.generateQI([
    "nsIObserver",
    "nsISupportsWeakReference",
  ]),

  // An active task that checks for plugin updates and installs them.
  _updateTask: null,
  _gmpPath: null,
  _isUpdateCheckPending: false,

  set gmpPath(aPath) {
    this._gmpPath = aPath;
  },
  get gmpPath() {
    if (!this._gmpPath && this.isInstalled) {
      this._gmpPath = PathUtils.join(
        Services.dirsvc.get("ProfD", Ci.nsIFile).path,
        this._plugin.id,
        GMPPrefs.getString(GMPPrefs.KEY_PLUGIN_VERSION, null, this._plugin.id)
      );
    }
    return this._gmpPath;
  },

  get id() {
    return this._plugin.id;
  },
  get libName() {
    return this._plugin.libName;
  },
  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 null;
  },

  getFullDescription(doc) {
    let plugin = this._rawPlugin;

    let frag = doc.createDocumentFragment();
    for (let [urlProp, labelId] of [
      ["learnMoreURL", GMP_LEARN_MORE],
      [
        "licenseURL",
        this.id == WIDEVINE_L1_ID || this.id == WIDEVINE_L3_ID
          ? GMP_PRIVACY_INFO
          : GMP_LICENSE_INFO,
      ],
    ]) {
      if (plugin[urlProp]) {
        let a = doc.createElementNS(XHTML, "a");
        a.href = plugin[urlProp];
        a.target = "_blank";
        a.textContent = lazy.addonsBundle.formatValueSync(labelId);

        if (frag.childElementCount) {
          frag.append(
            doc.createElementNS(XHTML, "br"),
            doc.createElementNS(XHTML, "br")
          );
        }
        frag.append(a);
      }
    }

    return frag;
  },

  get version() {
    return GMPPrefs.getString(
      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.getBool(GMPPrefs.KEY_EME_ENABLED, true)
    ) {
      // If "media.eme.enabled" is false, all EME plugins are disabled.
      return true;
    }
    return false;
  },

  get userDisabled() {
    return !GMPPrefs.getBool(
      GMPPrefs.KEY_PLUGIN_ENABLED,
      true,
      this._plugin.id
    );
  },
  set userDisabled(aVal) {
    GMPPrefs.setBool(
      GMPPrefs.KEY_PLUGIN_ENABLED,
      aVal === false,
      this._plugin.id
    );
  },

  async enable() {
    this.userDisabled = false;
  },
  async disable() {
    this.userDisabled = true;
  },

  get blocklistState() {
    return Ci.nsIBlocklistService.STATE_NOT_BLOCKED;
  },
  get size() {
    return 0;
  },
  get scope() {
    return lazy.AddonManager.SCOPE_APPLICATION;
  },
  get pendingOperations() {
    return lazy.AddonManager.PENDING_NONE;
  },

  get operationsRequiringRestart() {
    return lazy.AddonManager.OP_NEEDS_RESTART_NONE;
  },

  get permissions() {
    let permissions = 0;
    if (!this.appDisabled) {
      permissions |= lazy.AddonManager.PERM_CAN_UPGRADE;
      permissions |= this.userDisabled
        ? lazy.AddonManager.PERM_CAN_ENABLE
        : lazy.AddonManager.PERM_CAN_DISABLE;
    }
    return permissions;
  },

  get updateDate() {
    let time = Number(
      GMPPrefs.getInt(GMPPrefs.KEY_PLUGIN_LAST_UPDATE, 0, this._plugin.id)
    );
    if (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;
  },

  get installTelemetryInfo() {
    return { source: "gmp-plugin" };
  },

  isCompatibleWith() {
    return true;
  },

  get applyBackgroundUpdates() {
    if (!GMPPrefs.isSet(GMPPrefs.KEY_PLUGIN_AUTOUPDATE, this._plugin.id)) {
      return lazy.AddonManager.AUTOUPDATE_DEFAULT;
    }

    return GMPPrefs.getBool(
      GMPPrefs.KEY_PLUGIN_AUTOUPDATE,
      true,
      this._plugin.id
    )
      ? lazy.AddonManager.AUTOUPDATE_ENABLE
      : lazy.AddonManager.AUTOUPDATE_DISABLE;
  },

  set applyBackgroundUpdates(aVal) {
    if (aVal == lazy.AddonManager.AUTOUPDATE_DEFAULT) {
      GMPPrefs.reset(GMPPrefs.KEY_PLUGIN_AUTOUPDATE, this._plugin.id);
    } else if (aVal == lazy.AddonManager.AUTOUPDATE_ENABLE) {
      GMPPrefs.setBool(GMPPrefs.KEY_PLUGIN_AUTOUPDATE, true, this._plugin.id);
    } else if (aVal == lazy.AddonManager.AUTOUPDATE_DISABLE) {
      GMPPrefs.setBool(GMPPrefs.KEY_PLUGIN_AUTOUPDATE, false, this._plugin.id);
    }
  },

  /**
   * Called by the addon manager to update GMP addons. For example this will be
   * used if a user manually checks for GMP plugin updates by using the
   * menu in about:addons.
   *
   * This function is not used if MediaKeySystemAccess is requested and
   * Widevine is not yet installed, or if the user toggles prefs to enable EME.
   * For the function used in those cases see `checkForUpdates`.
   */
  findUpdates(aListener, aReason) {
    this._log.trace(
      "findUpdates() - " + this._plugin.id + " - reason=" + aReason
    );

    // In the case of GMP addons we do not wish to implement AddonInstall, as
    // we don't want to display information as in a normal addon install such
    // as a download progress bar. As such, we short circuit our
    // listeners by indicating that no updates exist (though some may).
    lazy.AddonManagerPrivate.callNoUpdateListeners(this, aListener);

    if (aReason === lazy.AddonManager.UPDATE_WHEN_PERIODIC_UPDATE) {
      if (!lazy.AddonManager.shouldAutoUpdate(this)) {
        this._log.trace(
          "findUpdates() - " + this._plugin.id + " - no autoupdate"
        );
        return Promise.resolve(false);
      }

      let secSinceLastCheck =
        Date.now() / 1000 -
        Services.prefs.getIntPref(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 !== lazy.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 = (async () => {
      this._log.trace("findUpdates() - updateTask");
      try {
        let installManager = new lazy.GMPInstallManager();
        let res = await installManager.checkForAddons();
        let update = res.addons.find(addon => addon.id === this._plugin.id);
        if (update && update.isValid && !update.isInstalled) {
          this._log.trace(
            "findUpdates() - found update for " +
              this._plugin.id +
              ", installing"
          );
          await 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;
    })();

    return this._updateTask;
  },

  get pluginLibraries() {
    if (this.isInstalled) {
      let path = this.version;
      return [path];
    }
    return [];
  },
  get pluginFullpath() {
    if (this.isInstalled) {
      let path = PathUtils.join(
        Services.dirsvc.get("ProfD", Ci.nsIFile).path,
        this._plugin.id,
        this.version
      );
      return [path];
    }
    return [];
  },

  get isInstalled() {
    return this.version && !!this.version.length;
  },

  _handleEnabledChanged() {
    this._log.info(
      "_handleEnabledChanged() id=" +
        this._plugin.id +
        " isActive=" +
        this.isActive
    );

    lazy.AddonManagerPrivate.callAddonListeners(
      this.isActive ? "onEnabling" : "onDisabling",
      this,
      false
    );
    if (this._gmpPath) {
      if (this.isActive) {
        this._log.info(
          "onPrefEnabledChanged() - adding gmp directory " + this._gmpPath
        );
        lazy.gmpService.addPluginDirectory(this._gmpPath);
      } else {
        this._log.info(
          "onPrefEnabledChanged() - removing gmp directory " + this._gmpPath
        );
        lazy.gmpService.removePluginDirectory(this._gmpPath);
      }
    }
    lazy.AddonManagerPrivate.callAddonListeners(
      this.isActive ? "onEnabled" : "onDisabled",
      this
    );
  },

  onPrefEMEGlobalEnabledChanged() {
    this._log.info(
      "onPrefEMEGlobalEnabledChanged() id=" +
        this._plugin.id +
        " appDisabled=" +
        this.appDisabled +
        " isActive=" +
        this.isActive +
        " hidden=" +
        GMPUtils.isPluginHidden(this._plugin)
    );

    lazy.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)) {
      lazy.AddonManagerPrivate.callInstallListeners(
        "onExternalInstall",
        null,
        this,
        null,
        false
      );
      lazy.AddonManagerPrivate.callAddonListeners("onInstalling", this, false);
      lazy.AddonManagerPrivate.callAddonListeners("onInstalled", this);
      this.checkForUpdates(GMP_CHECK_DELAY);
    }
    if (!this.userDisabled) {
      this._handleEnabledChanged();
    }
  },

  /**
   * This is called if prefs are changed to enable EME, or if Widevine
   * MediaKeySystemAccess is requested but the Widevine CDM is not installed.
   *
   * For the function used by the addon manager see `findUpdates`.
   */
  checkForUpdates(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.
    lazy.setTimeout(() => {
      if (!this.appDisabled) {
        let gmpInstallManager = new lazy.GMPInstallManager();
        // We don't really care about the results, if someone is interested
        // they can check the log.
        gmpInstallManager.simpleCheckAndInstall().catch(() => {});
      }
      this._isUpdateCheckPending = false;
    }, delay);
  },

  onPrefEnabledChanged() {
    if (!this._plugin.isEME || !this.appDisabled) {
      this._handleEnabledChanged();
    }
  },

  onPrefVersionChanged() {
    lazy.AddonManagerPrivate.callAddonListeners("onUninstalling", this, false);
    if (this._gmpPath) {
      this._log.info(
        "onPrefVersionChanged() - unregistering gmp directory " + this._gmpPath
      );
      lazy.gmpService.removeAndDeletePluginDirectory(
        this._gmpPath,
        true /* can defer */
      );
    }
    lazy.AddonManagerPrivate.callAddonListeners("onUninstalled", this);

    lazy.AddonManagerPrivate.callInstallListeners(
      "onExternalInstall",
      null,
      this,
      null,
      false
    );
    lazy.AddonManagerPrivate.callAddonListeners("onInstalling", this, false);
    this._gmpPath = null;
    if (this.isInstalled) {
      this._gmpPath = PathUtils.join(
        Services.dirsvc.get("ProfD", Ci.nsIFile).path,
        this._plugin.id,
        GMPPrefs.getString(GMPPrefs.KEY_PLUGIN_VERSION, null, this._plugin.id)
      );
    }
    if (this._gmpPath && this.isActive) {
      this._log.info(
        "onPrefVersionChanged() - registering gmp directory " + this._gmpPath
      );
      lazy.gmpService.addPluginDirectory(this._gmpPath);
    }
    lazy.AddonManagerPrivate.callAddonListeners("onInstalled", this);
  },

  observe(subject, topic, data) {
    if (topic == "nsPref:changed") {
      let pref = data;
      if (
        pref ==
        GMPPrefs.getPrefKey(GMPPrefs.KEY_PLUGIN_ENABLED, this._plugin.id)
      ) {
        this.onPrefEnabledChanged();
      } else if (
        pref ==
        GMPPrefs.getPrefKey(GMPPrefs.KEY_PLUGIN_VERSION, this._plugin.id)
      ) {
        this.onPrefVersionChanged();
      } else if (pref == GMPPrefs.KEY_EME_ENABLED) {
        this.onPrefEMEGlobalEnabledChanged();
      }
    } else if (topic == "EMEVideo:CDMMissing") {
      this.checkForUpdates(0);
    }
  },

  uninstallPlugin() {
    lazy.AddonManagerPrivate.callAddonListeners("onUninstalling", this, false);
    if (this.gmpPath) {
      this._log.info(
        "uninstallPlugin() - unregistering gmp directory " + this.gmpPath
      );
      lazy.gmpService.removeAndDeletePluginDirectory(this.gmpPath);
    }
    GMPPrefs.reset(GMPPrefs.KEY_PLUGIN_VERSION, this.id);
    GMPPrefs.reset(GMPPrefs.KEY_PLUGIN_HASHVALUE, this.id);
    GMPPrefs.reset(GMPPrefs.KEY_PLUGIN_ABI, this.id);
    GMPPrefs.reset(GMPPrefs.KEY_PLUGIN_LAST_UPDATE, this.id);
    lazy.AddonManagerPrivate.callAddonListeners("onUninstalled", this);
  },

  shutdown() {
    Services.prefs.removeObserver(
      GMPPrefs.getPrefKey(GMPPrefs.KEY_PLUGIN_ENABLED, this._plugin.id),
      this
    );
    Services.prefs.removeObserver(
      GMPPrefs.getPrefKey(GMPPrefs.KEY_PLUGIN_VERSION, this._plugin.id),
      this
    );
    if (this._plugin.isEME) {
      Services.prefs.removeObserver(GMPPrefs.KEY_EME_ENABLED, this);
      Services.obs.removeObserver(this, "EMEVideo:CDMMissing");
    }
    return this._updateTask;
  },

  _arePluginFilesOnDisk() {
    let fileExists = function (aGmpPath, aFileName) {
      let f = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
      let path = PathUtils.join(aGmpPath, aFileName);
      f.initWithPath(path);
      return f.exists();
    };

    let libName =
      AppConstants.DLL_PREFIX + this._plugin.libName + AppConstants.DLL_SUFFIX;
    let infoName;
    if (
      this._plugin.id == WIDEVINE_L1_ID ||
      this._plugin.id == WIDEVINE_L3_ID
    ) {
      infoName = "manifest.json";
    } else {
      infoName = this._plugin.id.substring(4) + ".info";
    }

    return (
      fileExists(this.gmpPath, libName) && fileExists(this.gmpPath, infoName)
    );
  },

  validate() {
    if (!this.isInstalled) {
      // Not installed -> Valid.
      return {
        installed: false,
        valid: true,
      };
    }

    let expectedABI = GMPUtils._expectedABI(this._plugin);
    let abi = GMPPrefs.getString(
      GMPPrefs.KEY_PLUGIN_ABI,
      expectedABI,
      this._plugin.id
    );
    if (abi != expectedABI) {
      // 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() {
    configureLogging();
    this._log = lazy.Log.repository.getLoggerWithMessagePrefix(
      "Toolkit.GMP",
      "GMPProvider."
    );
    this.buildPluginList();
    this.ensureProperCDMInstallState();

    Services.prefs.addObserver(GMPPrefs.KEY_LOG_BASE, configureLogging);

    for (let plugin of this._plugins.values()) {
      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 {
          lazy.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.nsIFile);
      let path = greDir.path;
      if (
        GMPUtils._isWindowsOnARM64() &&
        GMPPrefs.getBool(
          GMPPrefs.KEY_PLUGIN_ALLOW_X64_ON_ARM64,
          true,
          CLEARKEY_PLUGIN_ID
        )
      ) {
        path = PathUtils.join(path, "i686");
      }
      let clearkeyPath = PathUtils.join(
        path,
        CLEARKEY_PLUGIN_ID,
        CLEARKEY_VERSION
      );
      this._log.info("startup - adding clearkey CDM directory " + clearkeyPath);
      lazy.gmpService.addPluginDirectory(clearkeyPath);
    } catch (e) {
      this._log.warn("startup - adding clearkey CDM failed", e);
    }
  },

  shutdown() {
    this._log.trace("shutdown");
    Services.prefs.removeObserver(GMPPrefs.KEY_LOG_BASE, configureLogging);

    let shutdownTask = (async () => {
      this._log.trace("shutdown - shutdownTask");
      let shutdownSucceeded = true;

      for (let plugin of this._plugins.values()) {
        try {
          await plugin.wrapper.shutdown();
        } catch (e) {
          shutdownSucceeded = false;
        }
      }

      this._plugins = null;

      if (!shutdownSucceeded) {
        throw new Error("Shutdown failed");
      }
    })();

    return shutdownTask;
  },

  async getAddonByID(aId) {
    if (!this.isEnabled) {
      return null;
    }

    let plugin = this._plugins.get(aId);
    if (plugin && !GMPUtils.isPluginHidden(plugin)) {
      return plugin.wrapper;
    }
    return null;
  },

  async getAddonsByTypes(aTypes) {
    if (!this.isEnabled || (aTypes && !aTypes.includes("plugin"))) {
      return [];
    }

    let results = Array.from(this._plugins.values())
      .filter(p => !GMPUtils.isPluginHidden(p))
      .map(p => p.wrapper);

    return results;
  },

  get isEnabled() {
    return lazy.gmpProviderEnabled;
  },

  buildPluginList() {
    this._plugins = new Map();
    for (let aPlugin of GMP_PLUGINS) {
      let plugin = {
        id: aPlugin.id,
        name: lazy.addonsBundle.formatValueSync(aPlugin.name),
        description: lazy.addonsBundle.formatValueSync(aPlugin.description),
        libName: aPlugin.libName,
        homepageURL: aPlugin.homepageURL,
        optionsURL: aPlugin.optionsURL,
        wrapper: null,
        isEME: aPlugin.isEME,
      };
      plugin.wrapper = new GMPWrapper(plugin, aPlugin);
      this._plugins.set(plugin.id, plugin);
    }
  },

  ensureProperCDMInstallState() {
    if (!GMPPrefs.getBool(GMPPrefs.KEY_EME_ENABLED, true)) {
      for (let plugin of this._plugins.values()) {
        if (plugin.isEME && plugin.wrapper.isInstalled) {
          lazy.gmpService.addPluginDirectory(plugin.wrapper.gmpPath);
          plugin.wrapper.uninstallPlugin();
        }
      }
    }
  },

  observe(subject, topic) {
    if (topic == FIRST_CONTENT_PROCESS_TOPIC) {
      lazy.AddonManagerPrivate.registerProvider(GMPProvider, ["plugin"]);
      Services.obs.notifyObservers(null, "gmp-provider-registered");

      Services.obs.removeObserver(this, FIRST_CONTENT_PROCESS_TOPIC);
    }
  },

  addObserver() {
    Services.obs.addObserver(this, FIRST_CONTENT_PROCESS_TOPIC);
  },
};

GMPProvider.addObserver();

// For test use only.
export const GMPTestUtils = {
  /**
   * Used to override the GMP service with a mock.
   *
   * @param {object} mockService
   *        The mocked gmpService object.
   * @param {function} callback
   *        Method called with the overridden gmpService. The override
   *        is undone after the callback returns.
   */
  async overrideGmpService(mockService, callback) {
    let originalGmpService = lazy.gmpService;
    lazy.gmpService = mockService;
    try {
      return await callback();
    } finally {
      lazy.gmpService = originalGmpService;
    }
  },
};

[ Dauer der Verarbeitung: 0.36 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge