diff options
author | Matt A. Tobin <email@mattatobin.com> | 2022-04-21 19:47:49 -0500 |
---|---|---|
committer | Matt A. Tobin <email@mattatobin.com> | 2022-04-21 19:47:49 -0500 |
commit | 465f4eb3a68ef3fdd894dafc4a6b9ce7fd7ccf8c (patch) | |
tree | f897ef4b086d31539c914a1d9b35d7cfe82a8cd2 | |
parent | 13d6ff7e3399952875e7ff7673b2506e7e5f4026 (diff) | |
download | aura-central-465f4eb3a68ef3fdd894dafc4a6b9ce7fd7ccf8c.tar.gz |
Issue #25 - Part 18: Remove GMP (or nearly all of it)
I had planned to ifdef GMP but the infection is so deep that I couldn't do discrete parts and have it stay building.
163 files changed, 29 insertions, 23022 deletions
diff --git a/components/addons/content/extensions.js b/components/addons/content/extensions.js index fe84bc460..f65fb4573 100644 --- a/components/addons/content/extensions.js +++ b/components/addons/content/extensions.js @@ -1013,9 +1013,7 @@ var gViewController = { cmd_showItemPreferences: { isEnabled: function cmd_showItemPreferences_isEnabled(aAddon) { - if (!aAddon || - (!aAddon.isActive && !aAddon.isGMPlugin) || - !aAddon.optionsURL) { + if (!aAddon || (!aAddon.isActive) || !aAddon.optionsURL) { return false; } if (gViewController.currentViewObj == gDetailView && @@ -2753,15 +2751,7 @@ var gDetailView = { var fullDesc = document.getElementById("detail-fulldesc"); if (aAddon.fullDescription) { - // The following is part of an awful hack to include the licenses for GMP - // plugins without having bug 624602 fixed yet, and intentionally ignores - // localisation. - if (aAddon.isGMPlugin) { - fullDesc.innerHTML = aAddon.fullDescription; - } else { - fullDesc.textContent = aAddon.fullDescription; - } - + fullDesc.textContent = aAddon.fullDescription; fullDesc.hidden = false; } else { fullDesc.hidden = true; @@ -3036,13 +3026,6 @@ var gDetailView = { errorLink.value = gStrings.ext.GetStringFromName("details.notification.vulnerableNoUpdate.link"); errorLink.href = this._addon.blocklistURL; errorLink.hidden = false; - } else if (this._addon.isGMPlugin && !this._addon.isInstalled && - this._addon.isActive) { - this.node.setAttribute("notification", "warning"); - let warning = document.getElementById("detail-warning"); - warning.textContent = - gStrings.ext.formatStringFromName("details.notification.gmpPending", - [this._addon.name], 1); } else { this.node.removeAttribute("notification"); } diff --git a/components/addons/content/extensions.xml b/components/addons/content/extensions.xml index f862b0f7e..9ea6a50df 100644 --- a/components/addons/content/extensions.xml +++ b/components/addons/content/extensions.xml @@ -1328,12 +1328,6 @@ this._errorLink.value = gStrings.ext.GetStringFromName("notification.vulnerableNoUpdate.link"); this._errorLink.href = this.mAddon.blocklistURL; this._errorLink.hidden = false; - } else if (this.mAddon.isGMPlugin && !this.mAddon.isInstalled && - this.mAddon.isActive) { - this.setAttribute("notification", "warning"); - this._warning.textContent = - gStrings.ext.formatStringFromName("notification.gmpPending", - [this.mAddon.name], 1); } else { this.removeAttribute("notification"); } diff --git a/components/addons/content/gmpPrefs.xul b/components/addons/content/gmpPrefs.xul deleted file mode 100644 index ea7ee92fa..000000000 --- a/components/addons/content/gmpPrefs.xul +++ /dev/null @@ -1,8 +0,0 @@ -<?xml version="1.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/. --> - -<!-- This is intentionally empty and a dummy to let the GMPProvider - have a preferences button in the list view. --> diff --git a/components/addons/extensions.manifest b/components/addons/extensions.manifest index b56152e10..35d605575 100644 --- a/components/addons/extensions.manifest +++ b/components/addons/extensions.manifest @@ -13,4 +13,3 @@ contract @mozilla.org/addons/installtrigger;1 {9df8ef2b-94da-45c9-ab9f-132eb55fd category JavaScript-global-property InstallTrigger @mozilla.org/addons/installtrigger;1 category addon-provider-module PluginProvider resource://gre/modules/addons/PluginProvider.jsm -category addon-provider-module GMPProvider resource://gre/modules/addons/GMPProvider.jsm diff --git a/components/addons/jar.mn b/components/addons/jar.mn index 878be4df1..c674f8f83 100644 --- a/components/addons/jar.mn +++ b/components/addons/jar.mn @@ -29,7 +29,6 @@ toolkit.jar: content/mozapps/extensions/newaddon.js (content/newaddon.js) content/mozapps/extensions/setting.xml (content/setting.xml) content/mozapps/extensions/pluginPrefs.xul (content/pluginPrefs.xul) - content/mozapps/extensions/gmpPrefs.xul (content/gmpPrefs.xul) content/mozapps/extensions/OpenH264-license.txt (content/OpenH264-license.txt) content/mozapps/xpinstall/xpinstallConfirm.xul (content/xpinstallConfirm.xul) content/mozapps/xpinstall/xpinstallConfirm.js (content/xpinstallConfirm.js) diff --git a/components/addons/locale/extensions.properties b/components/addons/locale/extensions.properties index c5de4f0c0..43ab02a47 100644 --- a/components/addons/locale/extensions.properties +++ b/components/addons/locale/extensions.properties @@ -57,8 +57,6 @@ notification.downloadError.retry.tooltip=Try downloading this add-on again notification.installError=There was an error installing %1$S. notification.installError.retry=Try again notification.installError.retry.tooltip=Try downloading and installing this add-on again -#LOCALIZATION NOTE (notification.gmpPending) %1$S is the add-on name. -notification.gmpPending=%1$S will be installed shortly. #LOCALIZATION NOTE (contributionAmount2) %S is the currency amount recommended for contributions contributionAmount2=Suggested Contribution: %S @@ -100,8 +98,6 @@ details.notification.install=%1$S will be installed after you restart %2$S. details.notification.uninstall=%1$S will be uninstalled after you restart %2$S. #LOCALIZATION NOTE (details.notification.upgrade) %1$S is the add-on name, %2$S is brand name details.notification.upgrade=%1$S will be updated after you restart %2$S. -#LOCALIZATION NOTE (details.notification.gmpPending) %1$S is the add-on name -details.notification.gmpPending=%1$S will be installed shortly. installFromFile.dialogTitle=Select add-on to install installFromFile.filterName=Add-ons diff --git a/components/addons/moz.build b/components/addons/moz.build index 6b1e2fe93..f3e953c46 100644 --- a/components/addons/moz.build +++ b/components/addons/moz.build @@ -37,21 +37,15 @@ EXTRA_JS_MODULES += [ 'src/LightweightThemeManager.jsm', ] -EXTRA_PP_JS_MODULES += [ - 'src/AddonManager.jsm', - 'src/GMPInstallManager.jsm', - 'src/GMPUtils.jsm', -] +EXTRA_PP_JS_MODULES += ['src/AddonManager.jsm'] EXTRA_JS_MODULES.addons += [ 'src/AddonLogging.jsm', 'src/AddonRepository.jsm', 'src/AddonRepository_SQLiteMigrator.jsm', 'src/Content.js', - 'src/GMPProvider.jsm', 'src/LightweightThemeImageOptimizer.jsm', 'src/PluginProvider.jsm', - 'src/ProductAddonChecker.jsm', 'src/SpellCheckDictionaryBootstrap.js', ] diff --git a/components/addons/src/GMPInstallManager.jsm b/components/addons/src/GMPInstallManager.jsm deleted file mode 100644 index fe4e2de10..000000000 --- a/components/addons/src/GMPInstallManager.jsm +++ /dev/null @@ -1,917 +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"; - -this.EXPORTED_SYMBOLS = []; - -const {classes: Cc, interfaces: Ci, results: Cr, utils: Cu, manager: Cm} = - Components; -// Chunk size for the incremental downloader -const DOWNLOAD_CHUNK_BYTES_SIZE = 300000; -// Incremental downloader interval -const DOWNLOAD_INTERVAL = 0; -// 1 day default -const DEFAULT_SECONDS_BETWEEN_CHECKS = 60 * 60 * 24; - -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.import("resource://gre/modules/Services.jsm"); -Cu.import("resource://gre/modules/FileUtils.jsm"); -Cu.import("resource://gre/modules/Promise.jsm"); -Cu.import("resource://gre/modules/Preferences.jsm"); -Cu.import("resource://gre/modules/Log.jsm"); -Cu.import("resource://gre/modules/osfile.jsm"); -Cu.import("resource://gre/modules/Task.jsm"); -Cu.import("resource://gre/modules/ctypes.jsm"); -Cu.import("resource://gre/modules/GMPUtils.jsm"); - -this.EXPORTED_SYMBOLS = ["GMPInstallManager", "GMPExtractor", "GMPDownloader", - "GMPAddon"]; - -var gLocale = null; - -// Shared code for suppressing bad cert dialogs -XPCOMUtils.defineLazyGetter(this, "gCertUtils", function() { - let temp = { }; - Cu.import("resource://gre/modules/CertUtils.jsm", temp); - return temp; -}); - -XPCOMUtils.defineLazyModuleGetter(this, "UpdateUtils", - "resource://gre/modules/UpdateUtils.jsm"); - -/** - * Number of milliseconds after which we need to cancel `checkForAddons`. - * - * Bug 1087674 suggests that the XHR we use in `checkForAddons` may - * never terminate in presence of network nuisances (e.g. strange - * antivirus behavior). This timeout is a defensive measure to ensure - * that we fail cleanly in such case. - */ -const CHECK_FOR_ADDONS_TIMEOUT_DELAY_MS = 20000; - -function getScopedLogger(prefix) { - // `PARENT_LOGGER_ID.` being passed here effectively links this logger - // to the parentLogger. - return Log.repository.getLoggerWithMessagePrefix("Toolkit.GMP", prefix + " "); -} - -// This is copied directly from nsUpdateService.js -// It is used for calculating the URL string w/ var replacement. -// TODO: refactor this out somewhere else -XPCOMUtils.defineLazyGetter(this, "gOSVersion", function aus_gOSVersion() { - let osVersion; - let sysInfo = Cc["@mozilla.org/system-info;1"]. - getService(Ci.nsIPropertyBag2); - try { - osVersion = sysInfo.getProperty("name") + " " + sysInfo.getProperty("version"); - } - catch (e) { - LOG("gOSVersion - OS Version unknown: updates are not possible."); - } - - if (osVersion) { -#ifdef XP_WIN - const BYTE = ctypes.uint8_t; - const WORD = ctypes.uint16_t; - const DWORD = ctypes.uint32_t; - const WCHAR = ctypes.char16_t; - const BOOL = ctypes.int; - - // This structure is described at: - // http://msdn.microsoft.com/en-us/library/ms724833%28v=vs.85%29.aspx - const SZCSDVERSIONLENGTH = 128; - const OSVERSIONINFOEXW = new ctypes.StructType('OSVERSIONINFOEXW', - [ - {dwOSVersionInfoSize: DWORD}, - {dwMajorVersion: DWORD}, - {dwMinorVersion: DWORD}, - {dwBuildNumber: DWORD}, - {dwPlatformId: DWORD}, - {szCSDVersion: ctypes.ArrayType(WCHAR, SZCSDVERSIONLENGTH)}, - {wServicePackMajor: WORD}, - {wServicePackMinor: WORD}, - {wSuiteMask: WORD}, - {wProductType: BYTE}, - {wReserved: BYTE} - ]); - - // This structure is described at: - // http://msdn.microsoft.com/en-us/library/ms724958%28v=vs.85%29.aspx - const SYSTEM_INFO = new ctypes.StructType('SYSTEM_INFO', - [ - {wProcessorArchitecture: WORD}, - {wReserved: WORD}, - {dwPageSize: DWORD}, - {lpMinimumApplicationAddress: ctypes.voidptr_t}, - {lpMaximumApplicationAddress: ctypes.voidptr_t}, - {dwActiveProcessorMask: DWORD.ptr}, - {dwNumberOfProcessors: DWORD}, - {dwProcessorType: DWORD}, - {dwAllocationGranularity: DWORD}, - {wProcessorLevel: WORD}, - {wProcessorRevision: WORD} - ]); - - let kernel32 = false; - try { - kernel32 = ctypes.open("Kernel32"); - } catch (e) { - LOG("gOSVersion - Unable to open kernel32! " + e); - osVersion += ".unknown (unknown)"; - } - - if(kernel32) { - try { - // Get Service pack info - try { - let GetVersionEx = kernel32.declare("GetVersionExW", - ctypes.default_abi, - BOOL, - OSVERSIONINFOEXW.ptr); - let winVer = OSVERSIONINFOEXW(); - winVer.dwOSVersionInfoSize = OSVERSIONINFOEXW.size; - - if(0 !== GetVersionEx(winVer.address())) { - osVersion += "." + winVer.wServicePackMajor - + "." + winVer.wServicePackMinor; - } else { - LOG("gOSVersion - Unknown failure in GetVersionEX (returned 0)"); - osVersion += ".unknown"; - } - } catch (e) { - LOG("gOSVersion - error getting service pack information. Exception: " + e); - osVersion += ".unknown"; - } - - // Get processor architecture - let arch = "unknown"; - try { - let GetNativeSystemInfo = kernel32.declare("GetNativeSystemInfo", - ctypes.default_abi, - ctypes.void_t, - SYSTEM_INFO.ptr); - let sysInfo = SYSTEM_INFO(); - // Default to unknown - sysInfo.wProcessorArchitecture = 0xffff; - - GetNativeSystemInfo(sysInfo.address()); - switch(sysInfo.wProcessorArchitecture) { - case 9: - arch = "x64"; - break; - case 6: - arch = "IA64"; - break; - case 0: - arch = "x86"; - break; - } - } catch (e) { - LOG("gOSVersion - error getting processor architecture. Exception: " + e); - } finally { - osVersion += " (" + arch + ")"; - } - } finally { - kernel32.close(); - } - } -#endif - - try { - osVersion += " (" + sysInfo.getProperty("secondaryLibrary") + ")"; - } - catch (e) { - // Not all platforms have a secondary widget library, so an error is nothing to worry about. - } - osVersion = encodeURIComponent(osVersion); - } - return osVersion; -}); - -/** - * Provides an easy API for downloading and installing GMP Addons - */ -function GMPInstallManager() { -} -/** - * Temp file name used for downloading - */ -GMPInstallManager.prototype = { - /** - * Obtains a URL with replacement of vars - */ - _getURL: function() { - let log = getScopedLogger("GMPInstallManager._getURL"); - // Use the override URL if it is specified. The override URL is just like - // the normal URL but it does not check the cert. - let url = GMPPrefs.get(GMPPrefs.KEY_URL_OVERRIDE); - if (url) { - log.info("Using override url: " + url); - } else { - url = GMPPrefs.get(GMPPrefs.KEY_URL); - log.info("Using url: " + url); - } - - url = UpdateUtils.formatUpdateURL(url); - log.info("Using url (with replacement): " + url); - return url; - }, - /** - * Performs an addon check. - * @return a promise which will be resolved or rejected. - * The promise is resolved with an array of GMPAddons - * The promise is rejected with an object with properties: - * target: The XHR request object - * status: The HTTP status code - * type: Sometimes specifies type of rejection - */ - checkForAddons: function() { - let log = getScopedLogger("GMPInstallManager.checkForAddons"); - if (this._deferred) { - log.error("checkForAddons already called"); - return Promise.reject({type: "alreadycalled"}); - } - this._deferred = Promise.defer(); - let url = this._getURL(); - - this._request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]. - createInstance(Ci.nsISupports); - // This is here to let unit test code override XHR - if (this._request.wrappedJSObject) { - this._request = this._request.wrappedJSObject; - } - this._request.open("GET", url, true); - let allowNonBuiltIn = !GMPPrefs.get(GMPPrefs.KEY_CERT_CHECKATTRS, true); - this._request.channel.notificationCallbacks = - new gCertUtils.BadCertHandler(allowNonBuiltIn); - // Prevent the request from reading from the cache. - this._request.channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE; - // Prevent the request from writing to the cache. - this._request.channel.loadFlags |= Ci.nsIRequest.INHIBIT_CACHING; - - this._request.overrideMimeType("text/xml"); - // The Cache-Control header is only interpreted by proxies and the - // final destination. It does not help if a resource is already - // cached locally. - this._request.setRequestHeader("Cache-Control", "no-cache"); - // HTTP/1.0 servers might not implement Cache-Control and - // might only implement Pragma: no-cache - this._request.setRequestHeader("Pragma", "no-cache"); - - this._request.timeout = CHECK_FOR_ADDONS_TIMEOUT_DELAY_MS; - this._request.addEventListener("error", event => this.onFailXML("onErrorXML", event), false); - this._request.addEventListener("abort", event => this.onFailXML("onAbortXML", event), false); - this._request.addEventListener("timeout", event => this.onFailXML("onTimeoutXML", event), false); - this._request.addEventListener("load", event => this.onLoadXML(event), false); - - log.info("sending request to: " + url); - this._request.send(null); - - return this._deferred.promise; - }, - /** - * Installs the specified addon and calls a callback when done. - * @param gmpAddon The GMPAddon object to install - * @return a promise which will be resolved or rejected - * The promise will resolve with an array of paths that were extracted - * The promise will reject with an error object: - * target: The XHR request object - * status: The HTTP status code - * type: A string to represent the type of error - * downloaderr, verifyerr or previouserrorencountered - */ - installAddon: function(gmpAddon) { - if (this._deferred) { - log.error("previous error encountered"); - return Promise.reject({type: "previouserrorencountered"}); - } - this.gmpDownloader = new GMPDownloader(gmpAddon); - return this.gmpDownloader.start(); - }, - _getTimeSinceLastCheck: function() { - let now = Math.round(Date.now() / 1000); - // Default to 0 here because `now - 0` will be returned later if that case - // is hit. We want a large value so a check will occur. - let lastCheck = GMPPrefs.get(GMPPrefs.KEY_UPDATE_LAST_CHECK, 0); - // Handle clock jumps, return now since we want it to represent - // a lot of time has passed since the last check. - if (now < lastCheck) { - return now; - } - return now - lastCheck; - }, - get _isEMEEnabled() { - return GMPPrefs.get(GMPPrefs.KEY_EME_ENABLED, true); - }, - _isAddonUpdateEnabled: function(aAddon) { - return GMPPrefs.get(GMPPrefs.KEY_PLUGIN_ENABLED, true, aAddon) && - GMPPrefs.get(GMPPrefs.KEY_PLUGIN_AUTOUPDATE, true, aAddon); - }, - _updateLastCheck: function() { - let now = Math.round(Date.now() / 1000); - GMPPrefs.set(GMPPrefs.KEY_UPDATE_LAST_CHECK, now); - }, - _versionchangeOccurred: function() { - let savedBuildID = GMPPrefs.get(GMPPrefs.KEY_BUILDID, null); - let buildID = Services.appinfo.platformBuildID; - if (savedBuildID == buildID) { - return false; - } - GMPPrefs.set(GMPPrefs.KEY_BUILDID, buildID); - return true; - }, - /** - * Wrapper for checkForAddons and installAddon. - * Will only install if not already installed and will log the results. - * This will only install/update the OpenH264 and EME plugins - * @return a promise which will be resolved if all addons could be installed - * successfully, rejected otherwise. - */ - simpleCheckAndInstall: Task.async(function*() { - let log = getScopedLogger("GMPInstallManager.simpleCheckAndInstall"); - - if (this._versionchangeOccurred()) { - log.info("A version change occurred. Ignoring " + - "media.gmp-manager.lastCheck to check immediately for " + - "new or updated GMPs."); - } else { - let secondsBetweenChecks = - GMPPrefs.get(GMPPrefs.KEY_SECONDS_BETWEEN_CHECKS, - DEFAULT_SECONDS_BETWEEN_CHECKS) - let secondsSinceLast = this._getTimeSinceLastCheck(); - log.info("Last check was: " + secondsSinceLast + - " seconds ago, minimum seconds: " + secondsBetweenChecks); - if (secondsBetweenChecks > secondsSinceLast) { - log.info("Will not check for updates."); - return {status: "too-frequent-no-check"}; - } - } - - try { - let gmpAddons = yield this.checkForAddons(); - this._updateLastCheck(); - log.info("Found " + gmpAddons.length + " addons advertised."); - let addonsToInstall = gmpAddons.filter(function(gmpAddon) { - log.info("Found addon: " + gmpAddon.toString()); - - if (!gmpAddon.isValid || GMPUtils.isPluginHidden(gmpAddon) || - gmpAddon.isInstalled) { - log.info("Addon invalid, hidden or already installed."); - return false; - } - - let addonUpdateEnabled = false; - if (GMP_PLUGIN_IDS.indexOf(gmpAddon.id) >= 0) { - addonUpdateEnabled = this._isAddonUpdateEnabled(gmpAddon.id); - if (!addonUpdateEnabled) { - log.info("Auto-update is off for " + gmpAddon.id + - ", skipping check."); - } - } else { - // Currently, we only support installs of OpenH264 and EME plugins. - log.info("Auto-update is off for unknown plugin '" + gmpAddon.id + - "', skipping check."); - } - - return addonUpdateEnabled; - }, this); - - if (!addonsToInstall.length) { - log.info("No new addons to install, returning"); - return {status: "nothing-new-to-install"}; - } - - let installResults = []; - let failureEncountered = false; - for (let addon of addonsToInstall) { - try { - yield this.installAddon(addon); - installResults.push({ - id: addon.id, - result: "succeeded", - }); - } catch (e) { - failureEncountered = true; - installResults.push({ - id: addon.id, - result: "failed", - }); - } - } - if (failureEncountered) { - throw {status: "failed", - results: installResults}; - } - return {status: "succeeded", - results: installResults}; - } catch(e) { - log.error("Could not check for addons", e); - throw e; - } - }), - - /** - * Makes sure everything is cleaned up - */ - uninit: function() { - let log = getScopedLogger("GMPInstallManager.uninit"); - if (this._request) { - log.info("Aborting request"); - this._request.abort(); - } - if (this._deferred) { - log.info("Rejecting deferred"); - this._deferred.reject({type: "uninitialized"}); - } - log.info("Done cleanup"); - }, - - /** - * If set to true, specifies to leave the temporary downloaded zip file. - * This is useful for tests. - */ - overrideLeaveDownloadedZip: false, - - /** - * The XMLHttpRequest succeeded and the document was loaded. - * @param event The nsIDOMEvent for the load - */ - onLoadXML: function(event) { - let log = getScopedLogger("GMPInstallManager.onLoadXML"); - try { - log.info("request completed downloading document"); - let certs = null; - if (!Services.prefs.prefHasUserValue(GMPPrefs.KEY_URL_OVERRIDE) && - GMPPrefs.get(GMPPrefs.KEY_CERT_CHECKATTRS, true)) { - certs = gCertUtils.readCertPrefs(GMPPrefs.KEY_CERTS_BRANCH); - } - - let allowNonBuiltIn = !GMPPrefs.get(GMPPrefs.KEY_CERT_REQUIREBUILTIN, - true); - log.info("allowNonBuiltIn: " + allowNonBuiltIn); - - gCertUtils.checkCert(this._request.channel, allowNonBuiltIn, certs); - - this.parseResponseXML(); - } catch (ex) { - log.error("could not load xml: " + ex); - this._deferred.reject({ - target: event.target, - status: this._getChannelStatus(event.target), - message: "" + ex, - }); - delete this._deferred; - } - }, - - /** - * Returns the status code for the XMLHttpRequest - */ - _getChannelStatus: function(request) { - let log = getScopedLogger("GMPInstallManager._getChannelStatus"); - let status = null; - try { - status = request.status; - log.info("request.status is: " + request.status); - } - catch (e) { - } - - if (status == null) { - status = request.channel.QueryInterface(Ci.nsIRequest).status; - } - return status; - }, - - /** - * There was an error of some kind during the XMLHttpRequest. This - * error may have been caused by external factors (e.g. network - * issues) or internally (by a timeout). - * - * @param event The nsIDOMEvent for the error - */ - onFailXML: function(failure, event) { - let log = getScopedLogger("GMPInstallManager.onFailXML " + failure); - let request = event.target; - let status = this._getChannelStatus(request); - let message = "request.status: " + status + " (" + event.type + ")"; - log.warn(message); - this._deferred.reject({ - target: request, - status: status, - message: message - }); - delete this._deferred; - }, - - /** - * Returns an array of GMPAddon objects discovered by the update check. - * Or returns an empty array if there were any problems with parsing. - * If there's an error, it will be logged if logging is enabled. - */ - parseResponseXML: function() { - try { - let log = getScopedLogger("GMPInstallManager.parseResponseXML"); - let updatesElement = this._request.responseXML.documentElement; - if (!updatesElement) { - let message = "empty updates document"; - log.warn(message); - this._deferred.reject({ - target: this._request, - message: message - }); - delete this._deferred; - return; - } - - if (updatesElement.nodeName != "updates") { - let message = "got node name: " + updatesElement.nodeName + - ", expected: updates"; - log.warn(message); - this._deferred.reject({ - target: this._request, - message: message - }); - delete this._deferred; - return; - } - - const ELEMENT_NODE = Ci.nsIDOMNode.ELEMENT_NODE; - let gmpResults = []; - for (let i = 0; i < updatesElement.childNodes.length; ++i) { - let updatesChildElement = updatesElement.childNodes.item(i); - if (updatesChildElement.nodeType != ELEMENT_NODE) { - continue; - } - if (updatesChildElement.localName == "addons") { - gmpResults = GMPAddon.parseGMPAddonsNode(updatesChildElement); - } - } - this._deferred.resolve(gmpResults); - delete this._deferred; - } catch (e) { - this._deferred.reject({ - target: this._request, - message: e - }); - delete this._deferred; - } - }, -}; - -/** - * Used to construct a single GMP addon - * GMPAddon objects are returns from GMPInstallManager.checkForAddons - * GMPAddon objects can also be used in calls to GMPInstallManager.installAddon - * - * @param gmpAddon The AUS response XML's DOM element `addon` - */ -function GMPAddon(gmpAddon) { - let log = getScopedLogger("GMPAddon.constructor"); - gmpAddon.QueryInterface(Ci.nsIDOMElement); - ["id", "URL", "hashFunction", - "hashValue", "version", "size"].forEach(name => { - if (gmpAddon.hasAttribute(name)) { - this[name] = gmpAddon.getAttribute(name); - } - }); - this.size = Number(this.size) || undefined; - log.info ("Created new addon: " + this.toString()); -} -/** - * Parses an XML GMP addons node from AUS into an array - * @param addonsElement An nsIDOMElement compatible node with XML from AUS - * @return An array of GMPAddon results - */ -GMPAddon.parseGMPAddonsNode = function(addonsElement) { - let log = getScopedLogger("GMPAddon.parseGMPAddonsNode"); - let gmpResults = []; - if (addonsElement.localName !== "addons") { - return; - } - - addonsElement.QueryInterface(Ci.nsIDOMElement); - let addonCount = addonsElement.childNodes.length; - for (let i = 0; i < addonCount; ++i) { - let addonElement = addonsElement.childNodes.item(i); - if (addonElement.localName !== "addon") { - continue; - } - addonElement.QueryInterface(Ci.nsIDOMElement); - try { - gmpResults.push(new GMPAddon(addonElement)); - } catch (e) { - log.warn("invalid addon: " + e); - continue; - } - } - return gmpResults; -}; -GMPAddon.prototype = { - /** - * Returns a string representation of the addon - */ - toString: function() { - return this.id + " (" + - "isValid: " + this.isValid + - ", isInstalled: " + this.isInstalled + - ", hashFunction: " + this.hashFunction+ - ", hashValue: " + this.hashValue + - (this.size !== undefined ? ", size: " + this.size : "" ) + - ")"; - }, - /** - * If all the fields aren't specified don't consider this addon valid - * @return true if the addon is parsed and valid - */ - get isValid() { - return this.id && this.URL && this.version && - this.hashFunction && !!this.hashValue; - }, - get isInstalled() { - return this.version && - GMPPrefs.get(GMPPrefs.KEY_PLUGIN_VERSION, "", this.id) === this.version; - }, - get isEME() { - return this.id == "gmp-widevinecdm" || this.id.indexOf("gmp-eme-") == 0; - }, -}; -/** - * Constructs a GMPExtractor object which is used to extract a GMP zip - * into the specified location. (Which typically leties per platform) - * @param zipPath The path on disk of the zip file to extract - */ -function GMPExtractor(zipPath, installToDirPath) { - this.zipPath = zipPath; - this.installToDirPath = installToDirPath; -} -GMPExtractor.prototype = { - /** - * Obtains a list of all the entries in a zipfile in the format of *.*. - * This also includes files inside directories. - * - * @param zipReader the nsIZipReader to check - * @return An array of string name entries which can be used - * in nsIZipReader.extract - */ - _getZipEntries: function(zipReader) { - let entries = []; - let enumerator = zipReader.findEntries("*.*"); - while (enumerator.hasMore()) { - entries.push(enumerator.getNext()); - } - return entries; - }, - /** - * Installs the this.zipPath contents into the directory used to store GMP - * addons for the current platform. - * - * @return a promise which will be resolved or rejected - * See GMPInstallManager.installAddon for resolve/rejected info - */ - install: function() { - try { - let log = getScopedLogger("GMPExtractor.install"); - this._deferred = Promise.defer(); - log.info("Installing " + this.zipPath + "..."); - // Get the input zip file - let zipFile = Cc["@mozilla.org/file/local;1"]. - createInstance(Ci.nsIFile); - zipFile.initWithPath(this.zipPath); - - // Initialize a zipReader and obtain the entries - var zipReader = Cc["@mozilla.org/libjar/zip-reader;1"]. - createInstance(Ci.nsIZipReader); - zipReader.open(zipFile) - let entries = this._getZipEntries(zipReader); - let extractedPaths = []; - - // Extract each of the entries - entries.forEach(entry => { - // We don't need these types of files - if (entry.includes("__MACOSX")) { - return; - } - let outFile = Cc["@mozilla.org/file/local;1"]. - createInstance(Ci.nsILocalFile); - outFile.initWithPath(this.installToDirPath); - outFile.appendRelativePath(entry); - - // Make sure the directory hierarchy exists - if(!outFile.parent.exists()) { - outFile.parent.create(Ci.nsIFile.DIRECTORY_TYPE, parseInt("0755", 8)); - } - zipReader.extract(entry, outFile); - extractedPaths.push(outFile.path); - log.info(entry + " was successfully extracted to: " + - outFile.path); - }); - zipReader.close(); - if (!GMPInstallManager.overrideLeaveDownloadedZip) { - zipFile.remove(false); - } - - log.info(this.zipPath + " was installed successfully"); - this._deferred.resolve(extractedPaths); - } catch (e) { - if (zipReader) { - zipReader.close(); - } - this._deferred.reject({ - target: this, - status: e, - type: "exception" - }); - } - return this._deferred.promise; - } -}; - - -/** - * Constructs an object which downloads and initiates an install of - * the specified GMPAddon object. - * @param gmpAddon The addon to install. - */ -function GMPDownloader(gmpAddon) -{ - this._gmpAddon = gmpAddon; -} -/** - * Computes the file hash of fileToHash with the specified hash function - * @param hashFunctionName A hash function name such as sha512 - * @param fileToHash An nsIFile to hash - * @return a promise which resolve to a digest in binary hex format - */ -GMPDownloader.computeHash = function(hashFunctionName, fileToHash) { - let log = getScopedLogger("GMPDownloader.computeHash"); - let digest; - let fileStream = Cc["@mozilla.org/network/file-input-stream;1"]. - createInstance(Ci.nsIFileInputStream); - fileStream.init(fileToHash, FileUtils.MODE_RDONLY, - FileUtils.PERMS_FILE, 0); - try { - let hash = Cc["@mozilla.org/security/hash;1"]. - createInstance(Ci.nsICryptoHash); - let hashFunction = - Ci.nsICryptoHash[hashFunctionName.toUpperCase()]; - if (!hashFunction) { - log.error("could not get hash function"); - return Promise.reject(); - } - hash.init(hashFunction); - hash.updateFromStream(fileStream, -1); - digest = binaryToHex(hash.finish(false)); - } catch (e) { - log.warn("failed to compute hash: " + e); - digest = ""; - } - fileStream.close(); - return Promise.resolve(digest); -}, -GMPDownloader.prototype = { - /** - * Starts the download process for an addon. - * @return a promise which will be resolved or rejected - * See GMPInstallManager.installAddon for resolve/rejected info - */ - start: function() { - let log = getScopedLogger("GMPDownloader.start"); - this._deferred = Promise.defer(); - if (!this._gmpAddon.isValid) { - log.info("gmpAddon is not valid, will not continue"); - return Promise.reject({ - target: this, - status: status, - type: "downloaderr" - }); - } - - let uri = Services.io.newURI(this._gmpAddon.URL, null, null); - this._request = Cc["@mozilla.org/network/incremental-download;1"]. - createInstance(Ci.nsIIncrementalDownload); - let gmpFile = FileUtils.getFile("TmpD", [this._gmpAddon.id + ".zip"]); - if (gmpFile.exists()) { - gmpFile.remove(false); - } - - log.info("downloading from " + uri.spec + " to " + gmpFile.path); - this._request.init(uri, gmpFile, DOWNLOAD_CHUNK_BYTES_SIZE, - DOWNLOAD_INTERVAL); - this._request.start(this, null); - return this._deferred.promise; - }, - // For nsIRequestObserver - onStartRequest: function(request, context) { - }, - // For nsIRequestObserver - // Called when the GMP addon zip file is downloaded - onStopRequest: function(request, context, status) { - let log = getScopedLogger("GMPDownloader.onStopRequest"); - log.info("onStopRequest called"); - if (!Components.isSuccessCode(status)) { - log.info("status failed: " + status); - this._deferred.reject({ - target: this, - status: status, - type: "downloaderr" - }); - return; - } - - let promise = this._verifyDownload(); - promise.then(() => { - log.info("GMP file is ready to unzip"); - let destination = this._request.destination; - - let zipPath = destination.path; - let gmpAddon = this._gmpAddon; - let installToDirPath = Cc["@mozilla.org/file/local;1"]. - createInstance(Ci.nsIFile); - let path = OS.Path.join(OS.Constants.Path.profileDir, - gmpAddon.id, - gmpAddon.version); - installToDirPath.initWithPath(path); - log.info("install to directory path: " + installToDirPath.path); - let gmpInstaller = new GMPExtractor(zipPath, installToDirPath.path); - let installPromise = gmpInstaller.install(); - installPromise.then(extractedPaths => { - // Success, set the prefs - let now = Math.round(Date.now() / 1000); - GMPPrefs.set(GMPPrefs.KEY_PLUGIN_LAST_UPDATE, now, gmpAddon.id); - // Setting the version pref signals installation completion to consumers, - // if you need to set other prefs etc. do it before this. - GMPPrefs.set(GMPPrefs.KEY_PLUGIN_VERSION, gmpAddon.version, - gmpAddon.id); - this._deferred.resolve(extractedPaths); - }, err => { - this._deferred.reject(err); - }); - }, err => { - log.warn("verifyDownload check failed"); - this._deferred.reject({ - target: this, - status: 200, - type: "verifyerr" - }); - }); - }, - /** - * Verifies that the downloaded zip file's hash matches the GMPAddon hash. - * @return a promise which resolves if the download verifies - */ - _verifyDownload: function() { - let verifyDownloadDeferred = Promise.defer(); - let log = getScopedLogger("GMPDownloader._verifyDownload"); - log.info("_verifyDownload called"); - if (!this._request) { - return Promise.reject(); - } - - let destination = this._request.destination; - log.info("for path: " + destination.path); - - // Ensure that the file size matches the expected file size. - if (this._gmpAddon.size !== undefined && - destination.fileSize != this._gmpAddon.size) { - log.warn("Downloader:_verifyDownload downloaded size " + - destination.fileSize + " != expected size " + - this._gmpAddon.size + "."); - return Promise.reject(); - } - - let promise = GMPDownloader.computeHash(this._gmpAddon.hashFunction, destination); - promise.then(digest => { - let expectedDigest = this._gmpAddon.hashValue.toLowerCase(); - if (digest !== expectedDigest) { - log.warn("hashes do not match! Got: `" + - digest + "`, expected: `" + expectedDigest + "`"); - this._deferred.reject(); - return; - } - - log.info("hashes match!"); - verifyDownloadDeferred.resolve(); - }, err => { - verifyDownloadDeferred.reject(); - }); - return verifyDownloadDeferred.promise; - }, - QueryInterface: XPCOMUtils.generateQI([Ci.nsIRequestObserver]) -}; - -/** - * Convert a string containing binary values to hex. - */ -function binaryToHex(input) { - let result = ""; - for (let i = 0; i < input.length; ++i) { - let hex = input.charCodeAt(i).toString(16); - if (hex.length == 1) - hex = "0" + hex; - result += hex; - } - return result; -} 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) -]); diff --git a/components/addons/src/GMPUtils.jsm b/components/addons/src/GMPUtils.jsm deleted file mode 100644 index 593fc3c8d..000000000 --- a/components/addons/src/GMPUtils.jsm +++ /dev/null @@ -1,187 +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"; - -const {classes: Cc, interfaces: Ci, results: Cr, utils: Cu, manager: Cm} = - Components; - -this.EXPORTED_SYMBOLS = [ "GMP_PLUGIN_IDS", - "GMPPrefs", - "GMPUtils", - "OPEN_H264_ID", - "WIDEVINE_ID" ]; - -Cu.import("resource://gre/modules/Preferences.jsm"); -Cu.import("resource://gre/modules/Services.jsm"); - -// GMP IDs -const OPEN_H264_ID = "gmp-gmpopenh264"; -const WIDEVINE_ID = "gmp-widevinecdm"; -const GMP_PLUGIN_IDS = [ OPEN_H264_ID, WIDEVINE_ID ]; - -var GMPPluginUnsupportedReason = { - NOT_WINDOWS: 1, - WINDOWS_VERSION: 2, -}; - -var GMPPluginHiddenReason = { - UNSUPPORTED: 1, - EME_DISABLED: 2, -}; - -this.GMPUtils = { - /** - * Checks whether or not a given plugin is hidden. Hidden plugins are neither - * downloaded nor displayed in the addons manager. - * @param aPlugin - * The plugin to check. - */ - isPluginHidden: function(aPlugin) { - if (!aPlugin.isEME) { - return false; - } - - if (!this._isPluginSupported(aPlugin) || - !this._isPluginVisible(aPlugin)) { - return true; - } - - if (!GMPPrefs.get(GMPPrefs.KEY_EME_ENABLED, true)) { - return true; - } - - return false; - }, - - /** - * Checks whether or not a given plugin is supported by the current OS. - * @param aPlugin - * The plugin to check. - */ - _isPluginSupported: function(aPlugin) { - if (this._isPluginForceSupported(aPlugin)) { - return true; - } - if (aPlugin.id == WIDEVINE_ID) { - -#if defined(XP_WIN) || defined(XP_LINUX) - // The Widevine plugin is available for Windows versions Vista and later, - // Mac OSX, and Linux. - return true; -#else - return false; -#endif - } - - return true; - }, - - /** - * Checks whether or not a given plugin is visible in the addons manager - * UI and the "enable DRM" notification box. This can be used to test - * plugins that aren't yet turned on in the mozconfig. - * @param aPlugin - * The plugin to check. - */ - _isPluginVisible: function(aPlugin) { - return GMPPrefs.get(GMPPrefs.KEY_PLUGIN_VISIBLE, false, aPlugin.id); - }, - - /** - * Checks whether or not a given plugin is forced-supported. This is used - * in automated tests to override the checks that prevent GMPs running on an - * unsupported platform. - * @param aPlugin - * The plugin to check. - */ - _isPluginForceSupported: function(aPlugin) { - return GMPPrefs.get(GMPPrefs.KEY_PLUGIN_FORCE_SUPPORTED, false, aPlugin.id); - }, -}; - -/** - * Manages preferences for GMP addons - */ -this.GMPPrefs = { - KEY_EME_ENABLED: "media.eme.enabled", - KEY_PLUGIN_ENABLED: "media.{0}.enabled", - KEY_PLUGIN_LAST_UPDATE: "media.{0}.lastUpdate", - KEY_PLUGIN_VERSION: "media.{0}.version", - KEY_PLUGIN_AUTOUPDATE: "media.{0}.autoupdate", - KEY_PLUGIN_VISIBLE: "media.{0}.visible", - KEY_PLUGIN_ABI: "media.{0}.abi", - KEY_PLUGIN_FORCE_SUPPORTED: "media.{0}.forceSupported", - KEY_URL: "media.gmp-manager.url", - KEY_URL_OVERRIDE: "media.gmp-manager.url.override", - KEY_CERT_CHECKATTRS: "media.gmp-manager.cert.checkAttributes", - KEY_CERT_REQUIREBUILTIN: "media.gmp-manager.cert.requireBuiltIn", - KEY_UPDATE_LAST_CHECK: "media.gmp-manager.lastCheck", - KEY_SECONDS_BETWEEN_CHECKS: "media.gmp-manager.secondsBetweenChecks", - KEY_UPDATE_ENABLED: "media.gmp-manager.updateEnabled", - KEY_APP_DISTRIBUTION: "distribution.id", - KEY_APP_DISTRIBUTION_VERSION: "distribution.version", - KEY_BUILDID: "media.gmp-manager.buildID", - KEY_CERTS_BRANCH: "media.gmp-manager.certs.", - KEY_PROVIDER_ENABLED: "media.gmp-provider.enabled", - KEY_LOG_BASE: "media.gmp.log.", - KEY_LOGGING_LEVEL: "media.gmp.log.level", - KEY_LOGGING_DUMP: "media.gmp.log.dump", - - /** - * Obtains the specified preference in relation to the specified plugin. - * @param aKey The preference key value to use. - * @param aDefaultValue The default value if no preference exists. - * @param aPlugin The plugin to scope the preference to. - * @return The obtained preference value, or the defaultValue if none exists. - */ - get: function(aKey, aDefaultValue, aPlugin) { - if (aKey === this.KEY_APP_DISTRIBUTION || - aKey === this.KEY_APP_DISTRIBUTION_VERSION) { - return Services.prefs.getDefaultBranch(null).getCharPref(aKey, "default"); - } - return Preferences.get(this.getPrefKey(aKey, aPlugin), aDefaultValue); - }, - - /** - * Sets the specified preference in relation to the specified plugin. - * @param aKey The preference key value to use. - * @param aVal The value to set. - * @param aPlugin The plugin to scope the preference to. - */ - set: function(aKey, aVal, aPlugin) { - Preferences.set(this.getPrefKey(aKey, aPlugin), aVal); - }, - - /** - * Checks whether or not the specified preference is set in relation to the - * specified plugin. - * @param aKey The preference key value to use. - * @param aPlugin The plugin to scope the preference to. - * @return true if the preference is set, false otherwise. - */ - isSet: function(aKey, aPlugin) { - return Preferences.isSet(this.getPrefKey(aKey, aPlugin)); - }, - - /** - * Resets the specified preference in relation to the specified plugin to its - * default. - * @param aKey The preference key value to use. - * @param aPlugin The plugin to scope the preference to. - */ - reset: function(aKey, aPlugin) { - Preferences.reset(this.getPrefKey(aKey, aPlugin)); - }, - - /** - * Scopes the specified preference key to the specified plugin. - * @param aKey The preference key value to use. - * @param aPlugin The plugin to scope the preference to. - * @return A preference key scoped to the specified plugin. - */ - getPrefKey: function(aKey, aPlugin) { - return aKey.replace("{0}", aPlugin || ""); - }, -}; diff --git a/components/addons/src/ProductAddonChecker.jsm b/components/addons/src/ProductAddonChecker.jsm deleted file mode 100644 index c6324da0a..000000000 --- a/components/addons/src/ProductAddonChecker.jsm +++ /dev/null @@ -1,464 +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"; - -const { classes: Cc, interfaces: Ci, utils: Cu } = Components; - -const LOCAL_EME_SOURCES = [{ - "id": "gmp-gmpopenh264", - "src": "chrome://global/content/gmp-sources/openh264.json" -}, { - "id": "gmp-widevinecdm", - "src": "chrome://global/content/gmp-sources/widevinecdm.json" -}]; - -this.EXPORTED_SYMBOLS = [ "ProductAddonChecker" ]; - -Cu.importGlobalProperties(["XMLHttpRequest"]); - -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.import("resource://gre/modules/Services.jsm"); -Cu.import("resource://gre/modules/Task.jsm"); -Cu.import("resource://gre/modules/Log.jsm"); -Cu.import("resource://gre/modules/CertUtils.jsm"); -/* globals checkCert, BadCertHandler*/ -Cu.import("resource://gre/modules/FileUtils.jsm"); -Cu.import("resource://gre/modules/NetUtil.jsm"); -Cu.import("resource://gre/modules/osfile.jsm"); - -/* globals GMPPrefs */ -XPCOMUtils.defineLazyModuleGetter(this, "GMPPrefs", - "resource://gre/modules/GMPUtils.jsm"); - -/* globals OS */ - -XPCOMUtils.defineLazyModuleGetter(this, "UpdateUtils", - "resource://gre/modules/UpdateUtils.jsm"); - -XPCOMUtils.defineLazyModuleGetter(this, "ServiceRequest", - "resource://gre/modules/ServiceRequest.jsm"); - -// This exists so that tests can override the XHR behaviour for downloading -// the addon update XML file. -var CreateXHR = function() { - return Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]. - createInstance(Ci.nsISupports); -} - -var logger = Log.repository.getLogger("addons.productaddons"); - -/** - * Number of milliseconds after which we need to cancel `downloadXML`. - * - * Bug 1087674 suggests that the XHR we use in `downloadXML` may - * never terminate in presence of network nuisances (e.g. strange - * antivirus behavior). This timeout is a defensive measure to ensure - * that we fail cleanly in such case. - */ -const TIMEOUT_DELAY_MS = 20000; -// Chunk size for the incremental downloader -const DOWNLOAD_CHUNK_BYTES_SIZE = 300000; -// Incremental downloader interval -const DOWNLOAD_INTERVAL = 0; -// How much of a file to read into memory at a time for hashing -const HASH_CHUNK_SIZE = 8192; - -/** - * Gets the status of an XMLHttpRequest either directly or from its underlying - * channel. - * - * @param request - * The XMLHttpRequest. - * @return an integer status value. - */ -function getRequestStatus(request) { - let status = null; - try { - status = request.status; - } - catch (e) { - } - - if (status != null) { - return status; - } - - return request.channel.QueryInterface(Ci.nsIRequest).status; -} - -/** - * Downloads an XML document from a URL optionally testing the SSL certificate - * for certain attributes. - * - * @param url - * The url to download from. - * @param allowNonBuiltIn - * Whether to trust SSL certificates without a built-in CA issuer. - * @param allowedCerts - * The list of certificate attributes to match the SSL certificate - * against or null to skip checks. - * @return a promise that resolves to the DOM document downloaded or rejects - * with a JS exception in case of error. - */ -function downloadXML(url, allowNonBuiltIn = false, allowedCerts = null) { - return new Promise((resolve, reject) => { - let request = CreateXHR(); - // This is here to let unit test code override XHR - if (request.wrappedJSObject) { - request = request.wrappedJSObject; - } - request.open("GET", url, true); - request.channel.notificationCallbacks = new BadCertHandler(allowNonBuiltIn); - // Prevent the request from reading from the cache. - request.channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE; - // Prevent the request from writing to the cache. - request.channel.loadFlags |= Ci.nsIRequest.INHIBIT_CACHING; - // Use conservative TLS settings. See bug 1325501. - // TODO move to ServiceRequest. - if (request.channel instanceof Ci.nsIHttpChannelInternal) { - request.channel.QueryInterface(Ci.nsIHttpChannelInternal).beConservative = true; - } - request.timeout = TIMEOUT_DELAY_MS; - - request.overrideMimeType("text/xml"); - // The Cache-Control header is only interpreted by proxies and the - // final destination. It does not help if a resource is already - // cached locally. - request.setRequestHeader("Cache-Control", "no-cache"); - // HTTP/1.0 servers might not implement Cache-Control and - // might only implement Pragma: no-cache - request.setRequestHeader("Pragma", "no-cache"); - - let fail = (event) => { - let request = event.target; - let status = getRequestStatus(request); - let message = "Failed downloading XML, status: " + status + ", reason: " + event.type; - logger.warn(message); - let ex = new Error(message); - ex.status = status; - reject(ex); - }; - - let success = (event) => { - logger.info("Completed downloading document"); - let request = event.target; - - try { - checkCert(request.channel, allowNonBuiltIn, allowedCerts); - } catch (ex) { - logger.error("Request failed certificate checks: " + ex); - ex.status = getRequestStatus(request); - reject(ex); - return; - } - - resolve(request.responseXML); - }; - - request.addEventListener("error", fail, false); - request.addEventListener("abort", fail, false); - request.addEventListener("timeout", fail, false); - request.addEventListener("load", success, false); - - logger.info("sending request to: " + url); - request.send(null); - }); -} - -function downloadJSON(uri) { - logger.info("fetching config from: " + uri); - return new Promise((resolve, reject) => { - let xmlHttp = new ServiceRequest({mozAnon: true}); - - xmlHttp.onload = function(aResponse) { - resolve(JSON.parse(this.responseText)); - }; - - xmlHttp.onerror = function(e) { - reject("Fetching " + uri + " results in error code: " + e.target.status); - }; - - xmlHttp.open("GET", uri); - xmlHttp.overrideMimeType("application/json"); - xmlHttp.send(); - }); -} - - -/** - * Parses a list of add-ons from a DOM document. - * - * @param document - * The DOM document to parse. - * @return null if there is no <addons> element otherwise an object containing - * an array of the addons listed and a field notifying whether the - * fallback was used. - */ -function parseXML(document) { - // Check that the root element is correct - if (document.documentElement.localName != "updates") { - throw new Error("got node name: " + document.documentElement.localName + - ", expected: updates"); - } - - // Check if there are any addons elements in the updates element - let addons = document.querySelector("updates:root > addons"); - if (!addons) { - return null; - } - - let results = []; - let addonList = document.querySelectorAll("updates:root > addons > addon"); - for (let addonElement of addonList) { - let addon = {}; - - for (let name of ["id", "URL", "hashFunction", "hashValue", "version", "size"]) { - if (addonElement.hasAttribute(name)) { - addon[name] = addonElement.getAttribute(name); - } - } - addon.size = Number(addon.size) || undefined; - - results.push(addon); - } - - return { - usedFallback: false, - gmpAddons: results - }; -} - -/** - * If downloading from the network fails (AUS server is down), - * load the sources from local build configuration. - */ -function downloadLocalConfig() { - - if (!GMPPrefs.get(GMPPrefs.KEY_UPDATE_ENABLED, true)) { - logger.info("Updates are disabled via media.gmp-manager.updateEnabled"); - return Promise.resolve({usedFallback: true, gmpAddons: []}); - } - - return Promise.all(LOCAL_EME_SOURCES.map(conf => { - return downloadJSON(conf.src).then(addons => { - - let platforms = addons.vendors[conf.id].platforms; - let target = Services.appinfo.OS + "_" + UpdateUtils.ABI; - let details = null; - - while (!details) { - if (!(target in platforms)) { - // There was no matching platform so return false, this addon - // will be filtered from the results below - logger.info("no details found for: " + target); - return false; - } - // Field either has the details of the binary or is an alias - // to another build target key that does - if (platforms[target].alias) { - target = platforms[target].alias; - } else { - details = platforms[target]; - } - } - - logger.info("found plugin: " + conf.id); - return { - "id": conf.id, - "URL": details.fileUrl, - "hashFunction": addons.hashFunction, - "hashValue": details.hashValue, - "version": addons.vendors[conf.id].version, - "size": details.filesize - }; - }); - })).then(addons => { - - // Some filters may not match this platform so - // filter those out - addons = addons.filter(x => x !== false); - - return { - usedFallback: true, - gmpAddons: addons - }; - }); -} - -/** - * Downloads file from a URL using XHR. - * - * @param url - * The url to download from. - * @return a promise that resolves to the path of a temporary file or rejects - * with a JS exception in case of error. - */ -function downloadFile(url) { - return new Promise((resolve, reject) => { - let xhr = new XMLHttpRequest(); - xhr.onload = function(response) { - logger.info("downloadXHR File download. status=" + xhr.status); - if (xhr.status != 200 && xhr.status != 206) { - reject(Components.Exception("File download failed", xhr.status)); - return; - } - Task.spawn(function* () { - let f = yield OS.File.openUnique(OS.Path.join(OS.Constants.Path.tmpDir, "tmpaddon")); - let path = f.path; - logger.info(`Downloaded file will be saved to ${path}`); - yield f.file.close(); - yield OS.File.writeAtomic(path, new Uint8Array(xhr.response)); - return path; - }).then(resolve, reject); - }; - - let fail = (event) => { - let request = event.target; - let status = getRequestStatus(request); - let message = "Failed downloading via XHR, status: " + status + ", reason: " + event.type; - logger.warn(message); - let ex = new Error(message); - ex.status = status; - reject(ex); - }; - xhr.addEventListener("error", fail); - xhr.addEventListener("abort", fail); - - xhr.responseType = "arraybuffer"; - try { - xhr.open("GET", url); - // Use conservative TLS settings. See bug 1325501. - // TODO move to ServiceRequest. - if (xhr.channel instanceof Ci.nsIHttpChannelInternal) { - xhr.channel.QueryInterface(Ci.nsIHttpChannelInternal).beConservative = true; - } - xhr.send(null); - } catch (ex) { - reject(ex); - } - }); -} - -/** - * Convert a string containing binary values to hex. - */ -function binaryToHex(input) { - let result = ""; - for (let i = 0; i < input.length; ++i) { - let hex = input.charCodeAt(i).toString(16); - if (hex.length == 1) { - hex = "0" + hex; - } - result += hex; - } - return result; -} - -/** - * Calculates the hash of a file. - * - * @param hashFunction - * The type of hash function to use, must be supported by nsICryptoHash. - * @param path - * The path of the file to hash. - * @return a promise that resolves to hash of the file or rejects with a JS - * exception in case of error. - */ -var computeHash = Task.async(function*(hashFunction, path) { - let file = yield OS.File.open(path, { existing: true, read: true }); - try { - let hasher = Cc["@mozilla.org/security/hash;1"]. - createInstance(Ci.nsICryptoHash); - hasher.initWithString(hashFunction); - - let bytes; - do { - bytes = yield file.read(HASH_CHUNK_SIZE); - hasher.update(bytes, bytes.length); - } while (bytes.length == HASH_CHUNK_SIZE); - - return binaryToHex(hasher.finish(false)); - } - finally { - yield file.close(); - } -}); - -/** - * Verifies that a downloaded file matches what was expected. - * - * @param properties - * The properties to check, `size` and `hashFunction` with `hashValue` - * are supported. Any properties missing won't be checked. - * @param path - * The path of the file to check. - * @return a promise that resolves if the file matched or rejects with a JS - * exception in case of error. - */ -var verifyFile = Task.async(function*(properties, path) { - if (properties.size !== undefined) { - let stat = yield OS.File.stat(path); - if (stat.size != properties.size) { - throw new Error("Downloaded file was " + stat.size + " bytes but expected " + properties.size + " bytes."); - } - } - - if (properties.hashFunction !== undefined) { - let expectedDigest = properties.hashValue.toLowerCase(); - let digest = yield computeHash(properties.hashFunction, path); - if (digest != expectedDigest) { - throw new Error("Hash was `" + digest + "` but expected `" + expectedDigest + "`."); - } - } -}); - -const ProductAddonChecker = { - /** - * Downloads a list of add-ons from a URL optionally testing the SSL - * certificate for certain attributes. - * - * @param url - * The url to download from. - * @param allowNonBuiltIn - * Whether to trust SSL certificates without a built-in CA issuer. - * @param allowedCerts - * The list of certificate attributes to match the SSL certificate - * against or null to skip checks. - * @return a promise that resolves to an object containing the list of add-ons - * and whether the local fallback was used, or rejects with a JS - * exception in case of error. - */ - getProductAddonList: function(url, allowNonBuiltIn = false, allowedCerts = null) { - if (!GMPPrefs.get(GMPPrefs.KEY_UPDATE_ENABLED, true)) { - logger.info("Updates are disabled via media.gmp-manager.updateEnabled"); - return Promise.resolve({usedFallback: true, gmpAddons: []}); - } - - return downloadXML(url, allowNonBuiltIn, allowedCerts) - .then(parseXML) - .catch(downloadLocalConfig); - }, - - /** - * Downloads an add-on to a local file and checks that it matches the expected - * file. The caller is responsible for deleting the temporary file returned. - * - * @param addon - * The addon to download. - * @return a promise that resolves to the temporary file downloaded or rejects - * with a JS exception in case of error. - */ - downloadAddon: Task.async(function*(addon) { - let path = yield downloadFile(addon.URL); - try { - yield verifyFile(addon, path); - return path; - } - catch (e) { - yield OS.File.remove(path); - throw e; - } - }) -} diff --git a/components/global/content/process-content.js b/components/global/content/process-content.js index 2ff8f908a..9d7e37100 100644 --- a/components/global/content/process-content.js +++ b/components/global/content/process-content.js @@ -14,13 +14,6 @@ Cu.import("resource://gre/modules/Services.jsm"); const gInContentProcess = Services.appinfo.processType == Ci.nsIXULRuntime.PROCESS_TYPE_CONTENT; -Services.cpmm.addMessageListener("gmp-plugin-crash", msg => { - let gmpservice = Cc["@mozilla.org/gecko-media-plugin-service;1"] - .getService(Ci.mozIGeckoMediaPluginService); - - gmpservice.RunPluginCrashCallbacks(msg.data.pluginID, msg.data.pluginName); -}); - if (gInContentProcess) { let ProcessObserver = { TOPICS: [ diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index 8780fbf36..f1e6c9bc1 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -59,7 +59,6 @@ #include "mozilla/BasePrincipal.h" #include "mozilla/WebBrowserPersistDocumentChild.h" #include "imgLoader.h" -#include "GMPServiceChild.h" #include "mozilla/Unused.h" @@ -155,7 +154,6 @@ #include "mozilla/net/NeckoMessageUtils.h" #include "mozilla/widget/PuppetBidiKeyboard.h" #include "mozilla/RemoteSpellCheckEngineChild.h" -#include "GMPServiceChild.h" #include "gfxPlatform.h" #include "nscore.h" // for NS_FREE_PERMANENT_DATA @@ -165,7 +163,6 @@ using namespace mozilla::dom::ipc; using namespace mozilla::dom::workers; using namespace mozilla::media; using namespace mozilla::embedding; -using namespace mozilla::gmp; using namespace mozilla::hal_sandbox; using namespace mozilla::ipc; using namespace mozilla::layers; @@ -1117,20 +1114,6 @@ ContentChild::AllocPContentBridgeParent(mozilla::ipc::Transport* aTransport, return mLastBridge; } -PGMPServiceChild* -ContentChild::AllocPGMPServiceChild(mozilla::ipc::Transport* aTransport, - base::ProcessId aOtherProcess) -{ - return GMPServiceChild::Create(aTransport, aOtherProcess); -} - -bool -ContentChild::RecvGMPsChanged(nsTArray<GMPCapabilityData>&& capabilities) -{ - GeckoMediaPluginServiceChild::UpdateGMPCapabilities(Move(capabilities)); - return true; -} - bool ContentChild::RecvInitRendering(Endpoint<PCompositorBridgeChild>&& aCompositor, Endpoint<PImageBridgeChild>&& aImageBridge, diff --git a/dom/ipc/ContentChild.h b/dom/ipc/ContentChild.h index 7b2298feb..5ca7a053b 100644 --- a/dom/ipc/ContentChild.h +++ b/dom/ipc/ContentChild.h @@ -140,13 +140,6 @@ public: AllocPContentBridgeChild(mozilla::ipc::Transport* transport, base::ProcessId otherProcess) override; - PGMPServiceChild* - AllocPGMPServiceChild(mozilla::ipc::Transport* transport, - base::ProcessId otherProcess) override; - - bool - RecvGMPsChanged(nsTArray<GMPCapabilityData>&& capabilities) override; - bool RecvInitRendering( Endpoint<PCompositorBridgeChild>&& aCompositor, diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index f20312807..76ffc5ba6 100644 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -21,7 +21,6 @@ #include "AppProcessChecker.h" #include "AudioChannelService.h" #include "BlobParent.h" -#include "GMPServiceParent.h" #include "HandlerServiceParent.h" #include "IHistory.h" #include "imgIContainer.h" @@ -220,7 +219,6 @@ using namespace mozilla::dom::power; using namespace mozilla::media; using namespace mozilla::embedding; using namespace mozilla::gfx; -using namespace mozilla::gmp; using namespace mozilla::hal; using namespace mozilla::ipc; using namespace mozilla::layers; @@ -857,12 +855,6 @@ static nsIDocShell* GetOpenerDocShellHelper(Element* aFrameElement) } bool -ContentParent::RecvCreateGMPService() -{ - return PGMPService::Open(this); -} - -bool ContentParent::RecvLoadPlugin(const uint32_t& aPluginId, nsresult* aRv, uint32_t* aRunID) { *aRv = NS_OK; @@ -1257,9 +1249,6 @@ ContentParent::Init() #endif } #endif - - RefPtr<GeckoMediaPluginServiceParent> gmps(GeckoMediaPluginServiceParent::GetSingleton()); - gmps->UpdateContentProcessGMPCapabilities(); } void @@ -2526,13 +2515,6 @@ ContentParent::Observe(nsISupports* aSubject, return NS_OK; } -PGMPServiceParent* -ContentParent::AllocPGMPServiceParent(mozilla::ipc::Transport* aTransport, - base::ProcessId aOtherProcess) -{ - return GMPServiceParent::Create(aTransport, aOtherProcess); -} - PBackgroundParent* ContentParent::AllocPBackgroundParent(Transport* aTransport, ProcessId aOtherProcess) diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h index 7a4d3d55a..ab3258e4f 100644 --- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -237,8 +237,6 @@ public: virtual bool RecvBridgeToChildProcess(const ContentParentId& aCpId) override; - virtual bool RecvCreateGMPService() override; - virtual bool RecvLoadPlugin(const uint32_t& aPluginId, nsresult* aRv, uint32_t* aRunID) override; @@ -670,10 +668,6 @@ private: TabParent* aTopLevel, const TabId& aTabId, uint64_t* aId); - PGMPServiceParent* - AllocPGMPServiceParent(mozilla::ipc::Transport* aTransport, - base::ProcessId aOtherProcess) override; - PBackgroundParent* AllocPBackgroundParent(Transport* aTransport, ProcessId aOtherProcess) override; diff --git a/dom/ipc/PContent.ipdl b/dom/ipc/PContent.ipdl index 70ef084cd..41e8f7b0f 100644 --- a/dom/ipc/PContent.ipdl +++ b/dom/ipc/PContent.ipdl @@ -21,15 +21,7 @@ include protocol PImageBridge; include protocol PMedia; include protocol PMemoryReportRequest; include protocol PNecko; -// FIXME This is pretty ridiculous, but we have to keep the order of the -// following 4 includes, or the parser is confused about PGMPContent -// bridging PContent and PGMP. As soon as it registers the bridge between -// PContent and PPluginModule it seems to think that PContent's parent and -// child live in the same process! -include protocol PGMPContent; -include protocol PGMPService; include protocol PPluginModule; -include protocol PGMP; include protocol PPrinting; include protocol PSendStream; include protocol POfflineCacheUpdate; @@ -210,25 +202,11 @@ struct BlobURLRegistrationData Principal principal; }; -struct GMPAPITags -{ - nsCString api; - nsCString[] tags; -}; - -struct GMPCapabilityData -{ - nsCString name; - nsCString version; - GMPAPITags[] capabilities; -}; - nested(upto inside_cpow) sync protocol PContent { parent spawns PPluginModule; parent opens PProcessHangMonitor; - parent opens PGMPService; child opens PBackground; manages PBlob; @@ -514,9 +492,6 @@ child: async BlobURLUnregistration(nsCString aURI); - - async GMPsChanged(GMPCapabilityData[] capabilities); - parent: /** * Tell the content process some attributes of itself. This is @@ -548,8 +523,6 @@ parent: returns (ContentParentId cpId, bool isForApp, bool isForBrowser, TabId tabId); sync BridgeToChildProcess(ContentParentId cpId); - async CreateGMPService(); - /** * This call connects the content process to a plugin process. While this * call runs, a new PluginModuleParent will be created in the ContentChild @@ -1006,4 +979,4 @@ both: }; } -} +}
\ No newline at end of file diff --git a/dom/media/AbstractMediaDecoder.h b/dom/media/AbstractMediaDecoder.h index 3b7ad0ca0..170437c65 100644 --- a/dom/media/AbstractMediaDecoder.h +++ b/dom/media/AbstractMediaDecoder.h @@ -17,8 +17,6 @@ #include "nsDataHashtable.h" #include "nsThreadUtils.h" -class GMPCrashHelper; - namespace mozilla { @@ -98,8 +96,6 @@ public: // Set by Reader if the current audio track can be offloaded virtual void SetPlatformCanOffloadAudio(bool aCanOffloadAudio) {} - virtual already_AddRefed<GMPCrashHelper> GetCrashHelper() { return nullptr; } - // Stack based class to assist in notifying the frame statistics of // parsed and decoded frames. Use inside video demux & decode functions // to ensure all parsed and decoded frames are reported on all return paths. diff --git a/dom/media/MediaDecoder.cpp b/dom/media/MediaDecoder.cpp index ebc694b47..3988d37b1 100644 --- a/dom/media/MediaDecoder.cpp +++ b/dom/media/MediaDecoder.cpp @@ -29,7 +29,6 @@ #include "mozilla/dom/VideoTrack.h" #include "mozilla/dom/VideoTrackList.h" #include "nsPrintfCString.h" -#include "GMPService.h" #include "Layers.h" #include "mozilla/layers/ShadowLayers.h" @@ -926,34 +925,6 @@ MediaDecoder::OwnerHasError() const return mOwner->HasError(); } -class MediaElementGMPCrashHelper : public GMPCrashHelper -{ -public: - explicit MediaElementGMPCrashHelper(HTMLMediaElement* aElement) - : mElement(aElement) - { - MOZ_ASSERT(NS_IsMainThread()); // WeakPtr isn't thread safe. - } - already_AddRefed<nsPIDOMWindowInner> GetPluginCrashedEventTarget() override - { - MOZ_ASSERT(NS_IsMainThread()); // WeakPtr isn't thread safe. - if (!mElement) { - return nullptr; - } - return do_AddRef(mElement->OwnerDoc()->GetInnerWindow()); - } -private: - WeakPtr<HTMLMediaElement> mElement; -}; - -already_AddRefed<GMPCrashHelper> -MediaDecoder::GetCrashHelper() -{ - MOZ_ASSERT(NS_IsMainThread()); - return mOwner->GetMediaElement() ? - MakeAndAddRef<MediaElementGMPCrashHelper>(mOwner->GetMediaElement()) : nullptr; -} - bool MediaDecoder::IsEnded() const { diff --git a/dom/media/MediaDecoder.h b/dom/media/MediaDecoder.h index 3c409b118..1606819ba 100644 --- a/dom/media/MediaDecoder.h +++ b/dom/media/MediaDecoder.h @@ -243,8 +243,6 @@ public: // Must be called before Shutdown(). bool OwnerHasError() const; - already_AddRefed<GMPCrashHelper> GetCrashHelper() override; - protected: // Updates the media duration. This is called while the media is being // played, calls before the media has reached loaded metadata are ignored. diff --git a/dom/media/MediaFormatReader.cpp b/dom/media/MediaFormatReader.cpp index 411b84e09..6ef614403 100644 --- a/dom/media/MediaFormatReader.cpp +++ b/dom/media/MediaFormatReader.cpp @@ -359,7 +359,6 @@ MediaFormatReader::DecoderFactory::DoCreateDecoder(TrackType aTrack) : *ownerData.mOriginalInfo->GetAsAudioInfo(), ownerData.mTaskQueue, ownerData.mCallback.get(), - mOwner->mCrashHelper, ownerData.mIsBlankDecode, &result }); @@ -377,7 +376,6 @@ MediaFormatReader::DecoderFactory::DoCreateDecoder(TrackType aTrack) ownerData.mCallback.get(), mOwner->mKnowsCompositor, mOwner->GetImageContainer(), - mOwner->mCrashHelper, ownerData.mIsBlankDecode, &result }); @@ -570,10 +568,6 @@ MediaFormatReader::InitInternal() mVideo.mTaskQueue = new TaskQueue(GetMediaThreadPool(MediaThreadType::PLATFORM_DECODER)); - // Note: GMPCrashHelper must be created on main thread, as it may use - // weak references, which aren't threadsafe. - mCrashHelper = mDecoder->GetCrashHelper(); - return NS_OK; } diff --git a/dom/media/MediaFormatReader.h b/dom/media/MediaFormatReader.h index 7648a42a5..1cf3dbe33 100644 --- a/dom/media/MediaFormatReader.h +++ b/dom/media/MediaFormatReader.h @@ -570,8 +570,6 @@ private: RefPtr<VideoFrameContainer> mVideoFrameContainer; layers::ImageContainer* GetImageContainer(); - RefPtr<GMPCrashHelper> mCrashHelper; - void SetBlankDecode(TrackType aTrack, bool aIsBlankDecode); class DecoderFactory; diff --git a/dom/media/gmp/GMPAudioDecoderChild.cpp b/dom/media/gmp/GMPAudioDecoderChild.cpp deleted file mode 100644 index 53550d4a1..000000000 --- a/dom/media/gmp/GMPAudioDecoderChild.cpp +++ /dev/null @@ -1,172 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#include "GMPAudioDecoderChild.h" -#include "GMPContentChild.h" -#include "GMPAudioHost.h" -#include "mozilla/Unused.h" -#include <stdio.h> - -namespace mozilla { -namespace gmp { - -GMPAudioDecoderChild::GMPAudioDecoderChild(GMPContentChild* aPlugin) - : mPlugin(aPlugin) - , mAudioDecoder(nullptr) -{ - MOZ_ASSERT(mPlugin); -} - -GMPAudioDecoderChild::~GMPAudioDecoderChild() -{ -} - -void -GMPAudioDecoderChild::Init(GMPAudioDecoder* aDecoder) -{ - MOZ_ASSERT(aDecoder, "Cannot initialize Audio decoder child without a Audio decoder!"); - mAudioDecoder = aDecoder; -} - -GMPAudioHostImpl& -GMPAudioDecoderChild::Host() -{ - return mAudioHost; -} - -void -GMPAudioDecoderChild::Decoded(GMPAudioSamples* aDecodedSamples) -{ - MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current()); - - if (!aDecodedSamples) { - MOZ_CRASH("Not given decoded audio samples!"); - } - - GMPAudioDecodedSampleData samples; - samples.mData().AppendElements((int16_t*)aDecodedSamples->Buffer(), - aDecodedSamples->Size() / sizeof(int16_t)); - samples.mTimeStamp() = aDecodedSamples->TimeStamp(); - samples.mChannelCount() = aDecodedSamples->Channels(); - samples.mSamplesPerSecond() = aDecodedSamples->Rate(); - - Unused << SendDecoded(samples); - - aDecodedSamples->Destroy(); -} - -void -GMPAudioDecoderChild::InputDataExhausted() -{ - MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current()); - - Unused << SendInputDataExhausted(); -} - -void -GMPAudioDecoderChild::DrainComplete() -{ - MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current()); - - Unused << SendDrainComplete(); -} - -void -GMPAudioDecoderChild::ResetComplete() -{ - MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current()); - - Unused << SendResetComplete(); -} - -void -GMPAudioDecoderChild::Error(GMPErr aError) -{ - MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current()); - - Unused << SendError(aError); -} - -bool -GMPAudioDecoderChild::RecvInitDecode(const GMPAudioCodecData& a) -{ - MOZ_ASSERT(mAudioDecoder); - if (!mAudioDecoder) { - return false; - } - - GMPAudioCodec codec; - codec.mCodecType = a.mCodecType(); - codec.mChannelCount = a.mChannelCount(); - codec.mBitsPerChannel = a.mBitsPerChannel(); - codec.mSamplesPerSecond = a.mSamplesPerSecond(); - codec.mExtraData = a.mExtraData().Elements(); - codec.mExtraDataLen = a.mExtraData().Length(); - - // Ignore any return code. It is OK for this to fail without killing the process. - mAudioDecoder->InitDecode(codec, this); - - return true; -} - -bool -GMPAudioDecoderChild::RecvDecode(const GMPAudioEncodedSampleData& aEncodedSamples) -{ - if (!mAudioDecoder) { - return false; - } - - GMPAudioSamples* samples = new GMPAudioSamplesImpl(aEncodedSamples); - - // Ignore any return code. It is OK for this to fail without killing the process. - mAudioDecoder->Decode(samples); - - return true; -} - -bool -GMPAudioDecoderChild::RecvReset() -{ - if (!mAudioDecoder) { - return false; - } - - // Ignore any return code. It is OK for this to fail without killing the process. - mAudioDecoder->Reset(); - - return true; -} - -bool -GMPAudioDecoderChild::RecvDrain() -{ - if (!mAudioDecoder) { - return false; - } - - // Ignore any return code. It is OK for this to fail without killing the process. - mAudioDecoder->Drain(); - - return true; -} - -bool -GMPAudioDecoderChild::RecvDecodingComplete() -{ - if (mAudioDecoder) { - // Ignore any return code. It is OK for this to fail without killing the process. - mAudioDecoder->DecodingComplete(); - mAudioDecoder = nullptr; - } - - mPlugin = nullptr; - - Unused << Send__delete__(this); - - return true; -} - -} // namespace gmp -} // namespace mozilla diff --git a/dom/media/gmp/GMPAudioDecoderChild.h b/dom/media/gmp/GMPAudioDecoderChild.h deleted file mode 100644 index 0393fa573..000000000 --- a/dom/media/gmp/GMPAudioDecoderChild.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#ifndef GMPAudioDecoderChild_h_ -#define GMPAudioDecoderChild_h_ - -#include "mozilla/gmp/PGMPAudioDecoderChild.h" -#include "gmp-audio-decode.h" -#include "GMPAudioHost.h" - -namespace mozilla { -namespace gmp { - -class GMPContentChild; - -class GMPAudioDecoderChild : public PGMPAudioDecoderChild, - public GMPAudioDecoderCallback -{ -public: - explicit GMPAudioDecoderChild(GMPContentChild* aPlugin); - virtual ~GMPAudioDecoderChild(); - - void Init(GMPAudioDecoder* aDecoder); - GMPAudioHostImpl& Host(); - - // GMPAudioDecoderCallback - void Decoded(GMPAudioSamples* aEncodedSamples) override; - void InputDataExhausted() override; - void DrainComplete() override; - void ResetComplete() override; - void Error(GMPErr aError) override; - -private: - // PGMPAudioDecoderChild - bool RecvInitDecode(const GMPAudioCodecData& codecSettings) override; - bool RecvDecode(const GMPAudioEncodedSampleData& input) override; - bool RecvReset() override; - bool RecvDrain() override; - bool RecvDecodingComplete() override; - - GMPContentChild* mPlugin; - GMPAudioDecoder* mAudioDecoder; - GMPAudioHostImpl mAudioHost; -}; - -} // namespace gmp -} // namespace mozilla - -#endif // GMPAudioDecoderChild_h_ diff --git a/dom/media/gmp/GMPAudioDecoderParent.cpp b/dom/media/gmp/GMPAudioDecoderParent.cpp deleted file mode 100644 index 592c7719b..000000000 --- a/dom/media/gmp/GMPAudioDecoderParent.cpp +++ /dev/null @@ -1,369 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#include "GMPAudioDecoderParent.h" -#include "GMPContentParent.h" -#include <stdio.h> -#include "mozilla/Unused.h" -#include "GMPMessageUtils.h" -#include "nsThreadUtils.h" -#include "mozilla/Logging.h" - -namespace mozilla { - -#ifdef LOG -#undef LOG -#endif - -extern LogModule* GetGMPLog(); - -#define LOGV(msg) MOZ_LOG(GetGMPLog(), mozilla::LogLevel::Verbose, msg) -#define LOGD(msg) MOZ_LOG(GetGMPLog(), mozilla::LogLevel::Debug, msg) -#define LOG(level, msg) MOZ_LOG(GetGMPLog(), (level), msg) - -namespace gmp { - -GMPAudioDecoderParent::GMPAudioDecoderParent(GMPContentParent* aPlugin) - : mIsOpen(false) - , mShuttingDown(false) - , mActorDestroyed(false) - , mIsAwaitingResetComplete(false) - , mIsAwaitingDrainComplete(false) - , mPlugin(aPlugin) - , mCallback(nullptr) -{ - MOZ_ASSERT(mPlugin); -} - -GMPAudioDecoderParent::~GMPAudioDecoderParent() -{ -} - -nsresult -GMPAudioDecoderParent::InitDecode(GMPAudioCodecType aCodecType, - uint32_t aChannelCount, - uint32_t aBitsPerChannel, - uint32_t aSamplesPerSecond, - nsTArray<uint8_t>& aExtraData, - GMPAudioDecoderCallbackProxy* aCallback) -{ - LOGD(("GMPAudioDecoderParent[%p]::InitDecode()", this)); - - if (mIsOpen) { - NS_WARNING("Trying to re-init an in-use GMP audio decoder!"); - return NS_ERROR_FAILURE; - } - - MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread()); - - if (!aCallback) { - return NS_ERROR_FAILURE; - } - mCallback = aCallback; - - GMPAudioCodecData data; - data.mCodecType() = aCodecType; - data.mChannelCount() = aChannelCount; - data.mBitsPerChannel() = aBitsPerChannel; - data.mSamplesPerSecond() = aSamplesPerSecond; - data.mExtraData() = aExtraData; - if (!SendInitDecode(data)) { - return NS_ERROR_FAILURE; - } - mIsOpen = true; - - // Async IPC, we don't have access to a return value. - return NS_OK; -} - -nsresult -GMPAudioDecoderParent::Decode(GMPAudioSamplesImpl& aEncodedSamples) -{ - LOGV(("GMPAudioDecoderParent[%p]::Decode() timestamp=%lld", - this, aEncodedSamples.TimeStamp())); - - if (!mIsOpen) { - NS_WARNING("Trying to use a dead GMP Audio decoder!"); - return NS_ERROR_FAILURE; - } - - MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread()); - - GMPAudioEncodedSampleData samples; - aEncodedSamples.RelinquishData(samples); - - if (!SendDecode(samples)) { - return NS_ERROR_FAILURE; - } - - // Async IPC, we don't have access to a return value. - return NS_OK; -} - -nsresult -GMPAudioDecoderParent::Reset() -{ - LOGD(("GMPAudioDecoderParent[%p]::Reset()", this)); - - if (!mIsOpen) { - NS_WARNING("Trying to use a dead GMP Audio decoder!"); - return NS_ERROR_FAILURE; - } - - MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread()); - - if (!SendReset()) { - return NS_ERROR_FAILURE; - } - - mIsAwaitingResetComplete = true; - - // Async IPC, we don't have access to a return value. - return NS_OK; -} - -nsresult -GMPAudioDecoderParent::Drain() -{ - LOGD(("GMPAudioDecoderParent[%p]::Drain()", this)); - - if (!mIsOpen) { - NS_WARNING("Trying to use a dead GMP Audio decoder!"); - return NS_ERROR_FAILURE; - } - - MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread()); - - if (!SendDrain()) { - return NS_ERROR_FAILURE; - } - - mIsAwaitingDrainComplete = true; - - // Async IPC, we don't have access to a return value. - return NS_OK; -} - -// Note: Consider keeping ActorDestroy sync'd up when making changes here. -nsresult -GMPAudioDecoderParent::Close() -{ - LOGD(("GMPAudioDecoderParent[%p]::Close()", this)); - MOZ_ASSERT(!mPlugin || mPlugin->GMPThread() == NS_GetCurrentThread()); - - // Ensure if we've received a Close while waiting for a ResetComplete - // or DrainComplete notification, we'll unblock the caller before processing - // the close. This seems unlikely to happen, but better to be careful. - UnblockResetAndDrain(); - - // Consumer is done with us; we can shut down. No more callbacks should - // be made to mCallback. Note: do this before Shutdown()! - mCallback = nullptr; - // Let Shutdown mark us as dead so it knows if we had been alive - - // In case this is the last reference - RefPtr<GMPAudioDecoderParent> kungfudeathgrip(this); - Release(); - Shutdown(); - - return NS_OK; -} - -// Note: Consider keeping ActorDestroy sync'd up when making changes here. -nsresult -GMPAudioDecoderParent::Shutdown() -{ - LOGD(("GMPAudioDecoderParent[%p]::Shutdown()", this)); - MOZ_ASSERT(!mPlugin || mPlugin->GMPThread() == NS_GetCurrentThread()); - - if (mShuttingDown) { - return NS_OK; - } - mShuttingDown = true; - - // Ensure if we've received a shutdown while waiting for a ResetComplete - // or DrainComplete notification, we'll unblock the caller before processing - // the shutdown. - UnblockResetAndDrain(); - - // Notify client we're gone! Won't occur after Close() - if (mCallback) { - mCallback->Terminated(); - mCallback = nullptr; - } - - mIsOpen = false; - if (!mActorDestroyed) { - Unused << SendDecodingComplete(); - } - - return NS_OK; -} - -// Note: Keep this sync'd up with DecodingComplete -void -GMPAudioDecoderParent::ActorDestroy(ActorDestroyReason aWhy) -{ - LOGD(("GMPAudioDecoderParent[%p]::ActorDestroy(reason=%d)", this, aWhy)); - - mIsOpen = false; - mActorDestroyed = true; - - // Ensure if we've received a destroy while waiting for a ResetComplete - // or DrainComplete notification, we'll unblock the caller before processing - // the error. - UnblockResetAndDrain(); - - if (mCallback) { - // May call Close() (and Shutdown()) immediately or with a delay - mCallback->Terminated(); - mCallback = nullptr; - } - if (mPlugin) { - // Ignore any return code. It is OK for this to fail without killing the process. - mPlugin->AudioDecoderDestroyed(this); - mPlugin = nullptr; - } - MaybeDisconnect(aWhy == AbnormalShutdown); -} - -bool -GMPAudioDecoderParent::RecvDecoded(const GMPAudioDecodedSampleData& aDecoded) -{ - LOGV(("GMPAudioDecoderParent[%p]::RecvDecoded() timestamp=%lld", - this, aDecoded.mTimeStamp())); - - if (!mCallback) { - return false; - } - - mCallback->Decoded(aDecoded.mData(), - aDecoded.mTimeStamp(), - aDecoded.mChannelCount(), - aDecoded.mSamplesPerSecond()); - - return true; -} - -bool -GMPAudioDecoderParent::RecvInputDataExhausted() -{ - LOGV(("GMPAudioDecoderParent[%p]::RecvInputDataExhausted()", this)); - - if (!mCallback) { - return false; - } - - // Ignore any return code. It is OK for this to fail without killing the process. - mCallback->InputDataExhausted(); - - return true; -} - -bool -GMPAudioDecoderParent::RecvDrainComplete() -{ - LOGD(("GMPAudioDecoderParent[%p]::RecvDrainComplete()", this)); - - if (!mCallback) { - return false; - } - - if (!mIsAwaitingDrainComplete) { - return true; - } - mIsAwaitingDrainComplete = false; - - // Ignore any return code. It is OK for this to fail without killing the process. - mCallback->DrainComplete(); - - return true; -} - -bool -GMPAudioDecoderParent::RecvResetComplete() -{ - LOGD(("GMPAudioDecoderParent[%p]::RecvResetComplete()", this)); - - if (!mCallback) { - return false; - } - - if (!mIsAwaitingResetComplete) { - return true; - } - mIsAwaitingResetComplete = false; - - // Ignore any return code. It is OK for this to fail without killing the process. - mCallback->ResetComplete(); - - return true; -} - -bool -GMPAudioDecoderParent::RecvError(const GMPErr& aError) -{ - LOGD(("GMPAudioDecoderParent[%p]::RecvError(error=%d)", this, aError)); - - if (!mCallback) { - return false; - } - - // Ensure if we've received an error while waiting for a ResetComplete - // or DrainComplete notification, we'll unblock the caller before processing - // the error. - UnblockResetAndDrain(); - - // Ignore any return code. It is OK for this to fail without killing the process. - mCallback->Error(aError); - - return true; -} - -bool -GMPAudioDecoderParent::RecvShutdown() -{ - LOGD(("GMPAudioDecoderParent[%p]::RecvShutdown()", this)); - - Shutdown(); - return true; -} - -bool -GMPAudioDecoderParent::Recv__delete__() -{ - LOGD(("GMPAudioDecoderParent[%p]::Recv__delete__()", this)); - - if (mPlugin) { - // Ignore any return code. It is OK for this to fail without killing the process. - mPlugin->AudioDecoderDestroyed(this); - mPlugin = nullptr; - } - - return true; -} - -void -GMPAudioDecoderParent::UnblockResetAndDrain() -{ - LOGD(("GMPAudioDecoderParent[%p]::UnblockResetAndDrain()", this)); - - if (!mCallback) { - MOZ_ASSERT(!mIsAwaitingResetComplete); - MOZ_ASSERT(!mIsAwaitingDrainComplete); - return; - } - if (mIsAwaitingResetComplete) { - mIsAwaitingResetComplete = false; - mCallback->ResetComplete(); - } - if (mIsAwaitingDrainComplete) { - mIsAwaitingDrainComplete = false; - mCallback->DrainComplete(); - } -} - -} // namespace gmp -} // namespace mozilla diff --git a/dom/media/gmp/GMPAudioDecoderParent.h b/dom/media/gmp/GMPAudioDecoderParent.h deleted file mode 100644 index 5ced5ca61..000000000 --- a/dom/media/gmp/GMPAudioDecoderParent.h +++ /dev/null @@ -1,72 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#ifndef GMPAudioDecoderParent_h_ -#define GMPAudioDecoderParent_h_ - -#include "mozilla/RefPtr.h" -#include "gmp-audio-decode.h" -#include "gmp-audio-codec.h" -#include "mozilla/gmp/PGMPAudioDecoderParent.h" -#include "GMPMessageUtils.h" -#include "GMPAudioDecoderProxy.h" -#include "GMPCrashHelperHolder.h" - -namespace mozilla { -namespace gmp { - -class GMPContentParent; - -class GMPAudioDecoderParent final : public GMPAudioDecoderProxy - , public PGMPAudioDecoderParent - , public GMPCrashHelperHolder -{ -public: - NS_INLINE_DECL_REFCOUNTING(GMPAudioDecoderParent) - - explicit GMPAudioDecoderParent(GMPContentParent *aPlugin); - - nsresult Shutdown(); - - // GMPAudioDecoderProxy - nsresult InitDecode(GMPAudioCodecType aCodecType, - uint32_t aChannelCount, - uint32_t aBitsPerChannel, - uint32_t aSamplesPerSecond, - nsTArray<uint8_t>& aExtraData, - GMPAudioDecoderCallbackProxy* aCallback) override; - nsresult Decode(GMPAudioSamplesImpl& aInput) override; - nsresult Reset() override; - nsresult Drain() override; - nsresult Close() override; - -private: - ~GMPAudioDecoderParent(); - - // PGMPAudioDecoderParent - void ActorDestroy(ActorDestroyReason aWhy) override; - bool RecvDecoded(const GMPAudioDecodedSampleData& aDecoded) override; - bool RecvInputDataExhausted() override; - bool RecvDrainComplete() override; - bool RecvResetComplete() override; - bool RecvError(const GMPErr& aError) override; - bool RecvShutdown() override; - bool Recv__delete__() override; - - void UnblockResetAndDrain(); - - bool mIsOpen; - bool mShuttingDown; - bool mActorDestroyed; - bool mIsAwaitingResetComplete; - bool mIsAwaitingDrainComplete; - RefPtr<GMPContentParent> mPlugin; - GMPAudioDecoderCallbackProxy* mCallback; -}; - -} // namespace gmp -} // namespace mozilla - -#endif // GMPAudioDecoderParent_h_ diff --git a/dom/media/gmp/GMPAudioDecoderProxy.h b/dom/media/gmp/GMPAudioDecoderProxy.h deleted file mode 100644 index 6d71ba089..000000000 --- a/dom/media/gmp/GMPAudioDecoderProxy.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#ifndef GMPAudioDecoderProxy_h_ -#define GMPAudioDecoderProxy_h_ - -#include "GMPCallbackBase.h" -#include "gmp-audio-codec.h" -#include "GMPAudioHost.h" -#include "nsTArray.h" -#include "mozilla/gmp/GMPTypes.h" - -class GMPAudioDecoderCallbackProxy : public GMPCallbackBase { -public: - virtual ~GMPAudioDecoderCallbackProxy() {} - // Note: aChannelCount and aSamplesPerSecond may not be consistent from - // one invocation to the next. - virtual void Decoded(const nsTArray<int16_t>& aPCM, - uint64_t aTimeStamp, - uint32_t aChannelCount, - uint32_t aSamplesPerSecond) = 0; - virtual void InputDataExhausted() = 0; - virtual void DrainComplete() = 0; - virtual void ResetComplete() = 0; - virtual void Error(GMPErr aError) = 0; -}; - -class GMPAudioDecoderProxy { -public: - virtual ~GMPAudioDecoderProxy() {} - - virtual nsresult InitDecode(GMPAudioCodecType aCodecType, - uint32_t aChannelCount, - uint32_t aBitsPerChannel, - uint32_t aSamplesPerSecond, - nsTArray<uint8_t>& aExtraData, - GMPAudioDecoderCallbackProxy* aCallback) = 0; - virtual nsresult Decode(mozilla::gmp::GMPAudioSamplesImpl& aSamples) = 0; - virtual nsresult Reset() = 0; - virtual nsresult Drain() = 0; - // Call to tell GMP/plugin the consumer will no longer use this - // interface/codec. - virtual nsresult Close() = 0; -}; - -#endif // GMPAudioDecoderProxy_h_ diff --git a/dom/media/gmp/GMPAudioHost.cpp b/dom/media/gmp/GMPAudioHost.cpp deleted file mode 100644 index 4e14fed0b..000000000 --- a/dom/media/gmp/GMPAudioHost.cpp +++ /dev/null @@ -1,162 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#include "GMPAudioHost.h" -#include "gmp-audio-samples.h" -#include "gmp-errors.h" -#include "GMPEncryptedBufferDataImpl.h" -#include "MediaData.h" - -namespace mozilla { -namespace gmp { - -GMPAudioSamplesImpl::GMPAudioSamplesImpl(GMPAudioFormat aFormat) - : mFormat(aFormat) - , mTimeStamp(0) - , mChannels(0) - , mRate(0) -{ -} - -GMPAudioSamplesImpl::GMPAudioSamplesImpl(const GMPAudioEncodedSampleData& aData) - : mFormat(kGMPAudioEncodedSamples) - , mBuffer(aData.mData()) - , mTimeStamp(aData.mTimeStamp()) - , mChannels(aData.mChannelCount()) - , mRate(aData.mSamplesPerSecond()) -{ - if (aData.mDecryptionData().mKeyId().Length() > 0) { - mCrypto = new GMPEncryptedBufferDataImpl(aData.mDecryptionData()); - } -} - -GMPAudioSamplesImpl::GMPAudioSamplesImpl(MediaRawData* aSample, - uint32_t aChannels, - uint32_t aRate) - : mFormat(kGMPAudioEncodedSamples) - , mTimeStamp(aSample->mTime) - , mChannels(aChannels) - , mRate(aRate) -{ - mBuffer.AppendElements(aSample->Data(), aSample->Size()); - if (aSample->mCrypto.mValid) { - mCrypto = new GMPEncryptedBufferDataImpl(aSample->mCrypto); - } -} - -GMPAudioSamplesImpl::~GMPAudioSamplesImpl() -{ -} - -GMPAudioFormat -GMPAudioSamplesImpl::GetFormat() -{ - return mFormat; -} - -void -GMPAudioSamplesImpl::Destroy() -{ - delete this; -} - -GMPErr -GMPAudioSamplesImpl::SetBufferSize(uint32_t aSize) -{ - mBuffer.SetLength(aSize); - return GMPNoErr; -} - -uint32_t -GMPAudioSamplesImpl::Size() -{ - return mBuffer.Length(); -} - -void -GMPAudioSamplesImpl::SetTimeStamp(uint64_t aTimeStamp) -{ - mTimeStamp = aTimeStamp; -} - -uint64_t -GMPAudioSamplesImpl::TimeStamp() -{ - return mTimeStamp; -} - -const uint8_t* -GMPAudioSamplesImpl::Buffer() const -{ - return mBuffer.Elements(); -} - -uint8_t* -GMPAudioSamplesImpl::Buffer() -{ - return mBuffer.Elements(); -} - -const GMPEncryptedBufferMetadata* -GMPAudioSamplesImpl::GetDecryptionData() const -{ - return mCrypto; -} - -void -GMPAudioSamplesImpl::InitCrypto(const CryptoSample& aCrypto) -{ - if (!aCrypto.mValid) { - return; - } - mCrypto = new GMPEncryptedBufferDataImpl(aCrypto); -} - -void -GMPAudioSamplesImpl::RelinquishData(GMPAudioEncodedSampleData& aData) -{ - aData.mData() = Move(mBuffer); - aData.mTimeStamp() = TimeStamp(); - if (mCrypto) { - mCrypto->RelinquishData(aData.mDecryptionData()); - } -} - -uint32_t -GMPAudioSamplesImpl::Channels() const -{ - return mChannels; -} - -void -GMPAudioSamplesImpl::SetChannels(uint32_t aChannels) -{ - mChannels = aChannels; -} - -uint32_t -GMPAudioSamplesImpl::Rate() const -{ - return mRate; -} - -void -GMPAudioSamplesImpl::SetRate(uint32_t aRate) -{ - mRate = aRate; -} - - -GMPErr -GMPAudioHostImpl::CreateSamples(GMPAudioFormat aFormat, - GMPAudioSamples** aSamples) -{ - - *aSamples = new GMPAudioSamplesImpl(aFormat); - return GMPNoErr; -} - -} // namespace gmp -} // namespace mozilla diff --git a/dom/media/gmp/GMPAudioHost.h b/dom/media/gmp/GMPAudioHost.h deleted file mode 100644 index ed829b9c5..000000000 --- a/dom/media/gmp/GMPAudioHost.h +++ /dev/null @@ -1,71 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#ifndef GMPAudioHost_h_ -#define GMPAudioHost_h_ - -#include "gmp-audio-host.h" -#include "gmp-audio-samples.h" -#include "nsTArray.h" -#include "gmp-decryption.h" -#include "nsAutoPtr.h" -#include "GMPEncryptedBufferDataImpl.h" -#include "mozilla/gmp/GMPTypes.h" - -namespace mozilla { -class CryptoSample; -class MediaRawData; - -namespace gmp { - -class GMPAudioSamplesImpl : public GMPAudioSamples { -public: - explicit GMPAudioSamplesImpl(GMPAudioFormat aFormat); - explicit GMPAudioSamplesImpl(const GMPAudioEncodedSampleData& aData); - GMPAudioSamplesImpl(MediaRawData* aSample, - uint32_t aChannels, - uint32_t aRate); - virtual ~GMPAudioSamplesImpl(); - - GMPAudioFormat GetFormat() override; - void Destroy() override; - GMPErr SetBufferSize(uint32_t aSize) override; - uint32_t Size() override; - void SetTimeStamp(uint64_t aTimeStamp) override; - uint64_t TimeStamp() override; - const uint8_t* Buffer() const override; - uint8_t* Buffer() override; - const GMPEncryptedBufferMetadata* GetDecryptionData() const override; - - void InitCrypto(const CryptoSample& aCrypto); - - void RelinquishData(GMPAudioEncodedSampleData& aData); - - uint32_t Channels() const override; - void SetChannels(uint32_t aChannels) override; - uint32_t Rate() const override; - void SetRate(uint32_t aRate) override; - -private: - GMPAudioFormat mFormat; - nsTArray<uint8_t> mBuffer; - int64_t mTimeStamp; - nsAutoPtr<GMPEncryptedBufferDataImpl> mCrypto; - uint32_t mChannels; - uint32_t mRate; -}; - -class GMPAudioHostImpl : public GMPAudioHost -{ -public: - GMPErr CreateSamples(GMPAudioFormat aFormat, - GMPAudioSamples** aSamples) override; -private: -}; - -} // namespace gmp -} // namespace mozilla - -#endif // GMPAudioHost_h_ diff --git a/dom/media/gmp/GMPCallbackBase.h b/dom/media/gmp/GMPCallbackBase.h deleted file mode 100644 index 3d96629ef..000000000 --- a/dom/media/gmp/GMPCallbackBase.h +++ /dev/null @@ -1,21 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#ifndef GMPCallbackBase_h_ -#define GMPCallbackBase_h_ - -class GMPCallbackBase -{ -public: - virtual ~GMPCallbackBase() {} - - // The GMP code will call this if the codec crashes or shuts down. It's - // expected that the consumer (destination of this callback) will respond - // by dropping their reference to the proxy, allowing the proxy/parent to - // be destroyed. - virtual void Terminated() = 0; -}; - -#endif diff --git a/dom/media/gmp/GMPChild.cpp b/dom/media/gmp/GMPChild.cpp deleted file mode 100644 index f8c5f0aef..000000000 --- a/dom/media/gmp/GMPChild.cpp +++ /dev/null @@ -1,492 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#include "GMPChild.h" -#include "GMPContentChild.h" -#include "GMPProcessChild.h" -#include "GMPLoader.h" -#include "GMPVideoDecoderChild.h" -#include "GMPVideoEncoderChild.h" -#include "GMPAudioDecoderChild.h" -#include "GMPDecryptorChild.h" -#include "GMPVideoHost.h" -#include "nsDebugImpl.h" -#include "nsIFile.h" -#include "nsXULAppAPI.h" -#include "gmp-video-decode.h" -#include "gmp-video-encode.h" -#include "GMPPlatform.h" -#include "mozilla/ipc/ProcessChild.h" -#include "GMPUtils.h" -#include "prio.h" -#include "base/task.h" - -using namespace mozilla::ipc; - -static const int MAX_VOUCHER_LENGTH = 500000; - -#ifdef XP_WIN -#include <stdlib.h> // for _exit() -#else -#include <unistd.h> // for _exit() -#endif - -namespace mozilla { - -#undef LOG -#undef LOGD - -extern LogModule* GetGMPLog(); -#define LOG(level, x, ...) MOZ_LOG(GetGMPLog(), (level), (x, ##__VA_ARGS__)) -#define LOGD(x, ...) LOG(mozilla::LogLevel::Debug, "GMPChild[pid=%d] " x, (int)base::GetCurrentProcId(), ##__VA_ARGS__) - -namespace gmp { - -GMPChild::GMPChild() - : mAsyncShutdown(nullptr) - , mGMPMessageLoop(MessageLoop::current()) - , mGMPLoader(nullptr) -{ - LOGD("GMPChild ctor"); - nsDebugImpl::SetMultiprocessMode("GMP"); -} - -GMPChild::~GMPChild() -{ - LOGD("GMPChild dtor"); -} - -static bool -GetFileBase(const nsAString& aPluginPath, - nsCOMPtr<nsIFile>& aLibDirectory, - nsCOMPtr<nsIFile>& aFileBase, - nsAutoString& aBaseName) -{ - nsresult rv = NS_NewLocalFile(aPluginPath, - true, getter_AddRefs(aFileBase)); - if (NS_FAILED(rv)) { - return false; - } - - if (NS_FAILED(aFileBase->Clone(getter_AddRefs(aLibDirectory)))) { - return false; - } - - nsCOMPtr<nsIFile> parent; - rv = aFileBase->GetParent(getter_AddRefs(parent)); - if (NS_FAILED(rv)) { - return false; - } - - nsAutoString parentLeafName; - rv = parent->GetLeafName(parentLeafName); - if (NS_FAILED(rv)) { - return false; - } - - aBaseName = Substring(parentLeafName, - 4, - parentLeafName.Length() - 1); - return true; -} - -static bool -GetFileBase(const nsAString& aPluginPath, - nsCOMPtr<nsIFile>& aFileBase, - nsAutoString& aBaseName) -{ - nsCOMPtr<nsIFile> unusedLibDir; - return GetFileBase(aPluginPath, unusedLibDir, aFileBase, aBaseName); -} - -static bool -GetPluginFile(const nsAString& aPluginPath, - nsCOMPtr<nsIFile>& aLibDirectory, - nsCOMPtr<nsIFile>& aLibFile) -{ - nsAutoString baseName; - GetFileBase(aPluginPath, aLibDirectory, aLibFile, baseName); - -#if defined(OS_POSIX) - nsAutoString binaryName = NS_LITERAL_STRING("lib") + baseName + NS_LITERAL_STRING(".so"); -#elif defined(XP_WIN) - nsAutoString binaryName = baseName + NS_LITERAL_STRING(".dll"); -#else -#error Unsupported O.S. -#endif - aLibFile->AppendRelativePath(binaryName); - return true; -} - -static bool -GetPluginFile(const nsAString& aPluginPath, - nsCOMPtr<nsIFile>& aLibFile) -{ - nsCOMPtr<nsIFile> unusedlibDir; - return GetPluginFile(aPluginPath, unusedlibDir, aLibFile); -} - -bool -GMPChild::Init(const nsAString& aPluginPath, - const nsAString& aVoucherPath, - base::ProcessId aParentPid, - MessageLoop* aIOLoop, - IPC::Channel* aChannel) -{ - LOGD("%s pluginPath=%s", __FUNCTION__, NS_ConvertUTF16toUTF8(aPluginPath).get()); - - if (NS_WARN_IF(!Open(aChannel, aParentPid, aIOLoop))) { - return false; - } - - mPluginPath = aPluginPath; - mSandboxVoucherPath = aVoucherPath; - - return true; -} - -bool -GMPChild::RecvSetNodeId(const nsCString& aNodeId) -{ - LOGD("%s nodeId=%s", __FUNCTION__, aNodeId.Data()); - - // Store the per origin salt for the node id. Note: we do this in a - // separate message than RecvStartPlugin() so that the string is not - // sitting in a string on the IPC code's call stack. - mNodeId = aNodeId; - return true; -} - -GMPErr -GMPChild::GetAPI(const char* aAPIName, - void* aHostAPI, - void** aPluginAPI, - uint32_t aDecryptorId) -{ - if (!mGMPLoader) { - return GMPGenericErr; - } - return mGMPLoader->GetAPI(aAPIName, aHostAPI, aPluginAPI, aDecryptorId); -} - -bool -GMPChild::RecvPreloadLibs(const nsCString& aLibs) -{ -#ifdef XP_WIN - // Pre-load DLLs that need to be used by the EME plugin but that can't be - // loaded after the sandbox has started - // Items in this must be lowercase! - static const char* whitelist[] = { - "d3d9.dll", // Create an `IDirect3D9` to get adapter information - "dxva2.dll", // Get monitor information - "evr.dll", // MFGetStrideForBitmapInfoHeader - "mfh264dec.dll", // H.264 decoder (on Windows Vista) - "mfheaacdec.dll", // AAC decoder (on Windows Vista) - "mfplat.dll", // MFCreateSample, MFCreateAlignedMemoryBuffer, MFCreateMediaType - "msauddecmft.dll", // AAC decoder (on Windows 8) - "msmpeg2adec.dll", // AAC decoder (on Windows 7) - "msmpeg2vdec.dll", // H.264 decoder - }; - - nsTArray<nsCString> libs; - SplitAt(", ", aLibs, libs); - for (nsCString lib : libs) { - ToLowerCase(lib); - for (const char* whiteListedLib : whitelist) { - if (lib.EqualsASCII(whiteListedLib)) { - LoadLibraryA(lib.get()); - break; - } - } - } -#endif - return true; -} - -bool -GMPChild::GetUTF8LibPath(nsACString& aOutLibPath) -{ - nsCOMPtr<nsIFile> libFile; - if (!GetPluginFile(mPluginPath, libFile)) { - return false; - } - - if (!FileExists(libFile)) { - NS_WARNING("Can't find GMP library file!"); - return false; - } - - nsAutoString path; - libFile->GetPath(path); - aOutLibPath = NS_ConvertUTF16toUTF8(path); - - return true; -} - -bool -GMPChild::AnswerStartPlugin(const nsString& aAdapter) -{ - LOGD("%s", __FUNCTION__); - - if (!PreLoadPluginVoucher()) { - NS_WARNING("Plugin voucher failed to load!"); - return false; - } - PreLoadSandboxVoucher(); - - nsCString libPath; - if (!GetUTF8LibPath(libPath)) { - return false; - } - - auto platformAPI = new GMPPlatformAPI(); - InitPlatformAPI(*platformAPI, this); - - mGMPLoader = GMPProcessChild::GetGMPLoader(); - if (!mGMPLoader) { - NS_WARNING("Failed to get GMPLoader"); - delete platformAPI; - return false; - } - - GMPAdapter* adapter = nullptr; - - if (!mGMPLoader->Load(libPath.get(), - libPath.Length(), - mNodeId.BeginWriting(), - mNodeId.Length(), - platformAPI, - adapter)) { - NS_WARNING("Failed to load GMP"); - delete platformAPI; - return false; - } - - void* sh = nullptr; - GMPAsyncShutdownHost* host = static_cast<GMPAsyncShutdownHost*>(this); - GMPErr err = GetAPI(GMP_API_ASYNC_SHUTDOWN, host, &sh); - if (err == GMPNoErr && sh) { - mAsyncShutdown = reinterpret_cast<GMPAsyncShutdown*>(sh); - SendAsyncShutdownRequired(); - } - - return true; -} - -MessageLoop* -GMPChild::GMPMessageLoop() -{ - return mGMPMessageLoop; -} - -void -GMPChild::ActorDestroy(ActorDestroyReason aWhy) -{ - LOGD("%s reason=%d", __FUNCTION__, aWhy); - - for (uint32_t i = mGMPContentChildren.Length(); i > 0; i--) { - MOZ_ASSERT_IF(aWhy == NormalShutdown, !mGMPContentChildren[i - 1]->IsUsed()); - mGMPContentChildren[i - 1]->Close(); - } - - if (mGMPLoader) { - mGMPLoader->Shutdown(); - } - if (AbnormalShutdown == aWhy) { - NS_WARNING("Abnormal shutdown of GMP process!"); - ProcessChild::QuickExit(); - } - - XRE_ShutdownChildProcess(); -} - -void -GMPChild::ProcessingError(Result aCode, const char* aReason) -{ - switch (aCode) { - case MsgDropped: - _exit(0); // Don't trigger a crash report. - case MsgNotKnown: - MOZ_CRASH("aborting because of MsgNotKnown"); - case MsgNotAllowed: - MOZ_CRASH("aborting because of MsgNotAllowed"); - case MsgPayloadError: - MOZ_CRASH("aborting because of MsgPayloadError"); - case MsgProcessingError: - MOZ_CRASH("aborting because of MsgProcessingError"); - case MsgRouteError: - MOZ_CRASH("aborting because of MsgRouteError"); - case MsgValueError: - MOZ_CRASH("aborting because of MsgValueError"); - default: - MOZ_CRASH("not reached"); - } -} - -PGMPTimerChild* -GMPChild::AllocPGMPTimerChild() -{ - return new GMPTimerChild(this); -} - -bool -GMPChild::DeallocPGMPTimerChild(PGMPTimerChild* aActor) -{ - MOZ_ASSERT(mTimerChild == static_cast<GMPTimerChild*>(aActor)); - mTimerChild = nullptr; - return true; -} - -GMPTimerChild* -GMPChild::GetGMPTimers() -{ - if (!mTimerChild) { - PGMPTimerChild* sc = SendPGMPTimerConstructor(); - if (!sc) { - return nullptr; - } - mTimerChild = static_cast<GMPTimerChild*>(sc); - } - return mTimerChild; -} - -PGMPStorageChild* -GMPChild::AllocPGMPStorageChild() -{ - return new GMPStorageChild(this); -} - -bool -GMPChild::DeallocPGMPStorageChild(PGMPStorageChild* aActor) -{ - mStorage = nullptr; - return true; -} - -GMPStorageChild* -GMPChild::GetGMPStorage() -{ - if (!mStorage) { - PGMPStorageChild* sc = SendPGMPStorageConstructor(); - if (!sc) { - return nullptr; - } - mStorage = static_cast<GMPStorageChild*>(sc); - } - return mStorage; -} - -bool -GMPChild::RecvCrashPluginNow() -{ - MOZ_CRASH(); - return true; -} - -bool -GMPChild::RecvBeginAsyncShutdown() -{ - LOGD("%s AsyncShutdown=%d", __FUNCTION__, mAsyncShutdown!=nullptr); - - MOZ_ASSERT(mGMPMessageLoop == MessageLoop::current()); - if (mAsyncShutdown) { - mAsyncShutdown->BeginShutdown(); - } else { - ShutdownComplete(); - } - return true; -} - -bool -GMPChild::RecvCloseActive() -{ - for (uint32_t i = mGMPContentChildren.Length(); i > 0; i--) { - mGMPContentChildren[i - 1]->CloseActive(); - } - return true; -} - -void -GMPChild::ShutdownComplete() -{ - LOGD("%s", __FUNCTION__); - MOZ_ASSERT(mGMPMessageLoop == MessageLoop::current()); - mAsyncShutdown = nullptr; - SendAsyncShutdownComplete(); -} - -static void -GetPluginVoucherFile(const nsAString& aPluginPath, - nsCOMPtr<nsIFile>& aOutVoucherFile) -{ - nsAutoString baseName; - GetFileBase(aPluginPath, aOutVoucherFile, baseName); - nsAutoString infoFileName = baseName + NS_LITERAL_STRING(".voucher"); - aOutVoucherFile->AppendRelativePath(infoFileName); -} - -bool -GMPChild::PreLoadPluginVoucher() -{ - nsCOMPtr<nsIFile> voucherFile; - GetPluginVoucherFile(mPluginPath, voucherFile); - if (!FileExists(voucherFile)) { - // Assume missing file is not fatal; that would break OpenH264. - return true; - } - return ReadIntoArray(voucherFile, mPluginVoucher, MAX_VOUCHER_LENGTH); -} - -void -GMPChild::PreLoadSandboxVoucher() -{ - nsCOMPtr<nsIFile> f; - nsresult rv = NS_NewLocalFile(mSandboxVoucherPath, true, getter_AddRefs(f)); - if (NS_FAILED(rv)) { - NS_WARNING("Can't create nsIFile for sandbox voucher"); - return; - } - if (!FileExists(f)) { - // Assume missing file is not fatal; that would break OpenH264. - return; - } - - if (!ReadIntoArray(f, mSandboxVoucher, MAX_VOUCHER_LENGTH)) { - NS_WARNING("Failed to read sandbox voucher"); - } -} - -PGMPContentChild* -GMPChild::AllocPGMPContentChild(Transport* aTransport, - ProcessId aOtherPid) -{ - GMPContentChild* child = - mGMPContentChildren.AppendElement(new GMPContentChild(this))->get(); - child->Open(aTransport, aOtherPid, XRE_GetIOMessageLoop(), ipc::ChildSide); - - return child; -} - -void -GMPChild::GMPContentChildActorDestroy(GMPContentChild* aGMPContentChild) -{ - for (uint32_t i = mGMPContentChildren.Length(); i > 0; i--) { - UniquePtr<GMPContentChild>& toDestroy = mGMPContentChildren[i - 1]; - if (toDestroy.get() == aGMPContentChild) { - SendPGMPContentChildDestroyed(); - RefPtr<DeleteTask<GMPContentChild>> task = - new DeleteTask<GMPContentChild>(toDestroy.release()); - MessageLoop::current()->PostTask(task.forget()); - mGMPContentChildren.RemoveElementAt(i - 1); - break; - } - } -} - -} // namespace gmp -} // namespace mozilla - -#undef LOG -#undef LOGD diff --git a/dom/media/gmp/GMPChild.h b/dom/media/gmp/GMPChild.h deleted file mode 100644 index 722e4c7a9..000000000 --- a/dom/media/gmp/GMPChild.h +++ /dev/null @@ -1,92 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#ifndef GMPChild_h_ -#define GMPChild_h_ - -#include "mozilla/gmp/PGMPChild.h" -#include "GMPTimerChild.h" -#include "GMPStorageChild.h" -#include "GMPLoader.h" -#include "gmp-async-shutdown.h" -#include "gmp-entrypoints.h" -#include "prlink.h" - -namespace mozilla { -namespace gmp { - -class GMPContentChild; - -class GMPChild : public PGMPChild - , public GMPAsyncShutdownHost -{ -public: - GMPChild(); - virtual ~GMPChild(); - - bool Init(const nsAString& aPluginPath, - const nsAString& aVoucherPath, - base::ProcessId aParentPid, - MessageLoop* aIOLoop, - IPC::Channel* aChannel); - MessageLoop* GMPMessageLoop(); - - // Main thread only. - GMPTimerChild* GetGMPTimers(); - GMPStorageChild* GetGMPStorage(); - - // GMPAsyncShutdownHost - void ShutdownComplete() override; - -private: - friend class GMPContentChild; - - bool PreLoadPluginVoucher(); - void PreLoadSandboxVoucher(); - - bool GetUTF8LibPath(nsACString& aOutLibPath); - - bool RecvSetNodeId(const nsCString& aNodeId) override; - bool AnswerStartPlugin(const nsString& aAdapter) override; - bool RecvPreloadLibs(const nsCString& aLibs) override; - - PGMPTimerChild* AllocPGMPTimerChild() override; - bool DeallocPGMPTimerChild(PGMPTimerChild* aActor) override; - - PGMPStorageChild* AllocPGMPStorageChild() override; - bool DeallocPGMPStorageChild(PGMPStorageChild* aActor) override; - - PGMPContentChild* AllocPGMPContentChild(Transport* aTransport, - ProcessId aOtherPid) override; - void GMPContentChildActorDestroy(GMPContentChild* aGMPContentChild); - - bool RecvCrashPluginNow() override; - bool RecvBeginAsyncShutdown() override; - bool RecvCloseActive() override; - - void ActorDestroy(ActorDestroyReason aWhy) override; - void ProcessingError(Result aCode, const char* aReason) override; - - GMPErr GetAPI(const char* aAPIName, void* aHostAPI, void** aPluginAPI, uint32_t aDecryptorId = 0); - - nsTArray<UniquePtr<GMPContentChild>> mGMPContentChildren; - - GMPAsyncShutdown* mAsyncShutdown; - RefPtr<GMPTimerChild> mTimerChild; - RefPtr<GMPStorageChild> mStorage; - - MessageLoop* mGMPMessageLoop; - nsString mPluginPath; - nsString mSandboxVoucherPath; - nsCString mNodeId; - GMPLoader* mGMPLoader; - nsTArray<uint8_t> mPluginVoucher; - nsTArray<uint8_t> mSandboxVoucher; -}; - -} // namespace gmp -} // namespace mozilla - -#endif // GMPChild_h_ diff --git a/dom/media/gmp/GMPContentChild.cpp b/dom/media/gmp/GMPContentChild.cpp deleted file mode 100644 index 415736e11..000000000 --- a/dom/media/gmp/GMPContentChild.cpp +++ /dev/null @@ -1,320 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#include "GMPContentChild.h" -#include "GMPChild.h" -#include "GMPAudioDecoderChild.h" -#include "GMPDecryptorChild.h" -#include "GMPVideoDecoderChild.h" -#include "GMPVideoEncoderChild.h" -#include "base/task.h" - -namespace mozilla { -namespace gmp { - -GMPContentChild::GMPContentChild(GMPChild* aChild) - : mGMPChild(aChild) -{ - MOZ_COUNT_CTOR(GMPContentChild); -} - -GMPContentChild::~GMPContentChild() -{ - MOZ_COUNT_DTOR(GMPContentChild); -} - -MessageLoop* -GMPContentChild::GMPMessageLoop() -{ - return mGMPChild->GMPMessageLoop(); -} - -void -GMPContentChild::CheckThread() -{ - MOZ_ASSERT(mGMPChild->mGMPMessageLoop == MessageLoop::current()); -} - -void -GMPContentChild::ActorDestroy(ActorDestroyReason aWhy) -{ - mGMPChild->GMPContentChildActorDestroy(this); -} - -void -GMPContentChild::ProcessingError(Result aCode, const char* aReason) -{ - mGMPChild->ProcessingError(aCode, aReason); -} - -PGMPAudioDecoderChild* -GMPContentChild::AllocPGMPAudioDecoderChild() -{ - return new GMPAudioDecoderChild(this); -} - -bool -GMPContentChild::DeallocPGMPAudioDecoderChild(PGMPAudioDecoderChild* aActor) -{ - delete aActor; - return true; -} - -PGMPDecryptorChild* -GMPContentChild::AllocPGMPDecryptorChild() -{ - GMPDecryptorChild* actor = new GMPDecryptorChild(this, - mGMPChild->mPluginVoucher, - mGMPChild->mSandboxVoucher); - actor->AddRef(); - return actor; -} - -bool -GMPContentChild::DeallocPGMPDecryptorChild(PGMPDecryptorChild* aActor) -{ - static_cast<GMPDecryptorChild*>(aActor)->Release(); - return true; -} - -PGMPVideoDecoderChild* -GMPContentChild::AllocPGMPVideoDecoderChild(const uint32_t& aDecryptorId) -{ - GMPVideoDecoderChild* actor = new GMPVideoDecoderChild(this); - actor->AddRef(); - return actor; -} - -bool -GMPContentChild::DeallocPGMPVideoDecoderChild(PGMPVideoDecoderChild* aActor) -{ - static_cast<GMPVideoDecoderChild*>(aActor)->Release(); - return true; -} - -PGMPVideoEncoderChild* -GMPContentChild::AllocPGMPVideoEncoderChild() -{ - GMPVideoEncoderChild* actor = new GMPVideoEncoderChild(this); - actor->AddRef(); - return actor; -} - -bool -GMPContentChild::DeallocPGMPVideoEncoderChild(PGMPVideoEncoderChild* aActor) -{ - static_cast<GMPVideoEncoderChild*>(aActor)->Release(); - return true; -} - -// Adapts GMPDecryptor7 to the current GMPDecryptor version. -class GMPDecryptor7BackwardsCompat : public GMPDecryptor { -public: - explicit GMPDecryptor7BackwardsCompat(GMPDecryptor7* aDecryptorV7) - : mDecryptorV7(aDecryptorV7) - { - } - - void Init(GMPDecryptorCallback* aCallback, - bool aDistinctiveIdentifierRequired, - bool aPersistentStateRequired) override - { - // Distinctive identifier and persistent state arguments not present - // in v7 interface. - mDecryptorV7->Init(aCallback); - } - - void CreateSession(uint32_t aCreateSessionToken, - uint32_t aPromiseId, - const char* aInitDataType, - uint32_t aInitDataTypeSize, - const uint8_t* aInitData, - uint32_t aInitDataSize, - GMPSessionType aSessionType) override - { - mDecryptorV7->CreateSession(aCreateSessionToken, - aPromiseId, - aInitDataType, - aInitDataTypeSize, - aInitData, - aInitDataSize, - aSessionType); - } - - void LoadSession(uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength) override - { - mDecryptorV7->LoadSession(aPromiseId, aSessionId, aSessionIdLength); - } - - void UpdateSession(uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength, - const uint8_t* aResponse, - uint32_t aResponseSize) override - { - mDecryptorV7->UpdateSession(aPromiseId, - aSessionId, - aSessionIdLength, - aResponse, - aResponseSize); - } - - void CloseSession(uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength) override - { - mDecryptorV7->CloseSession(aPromiseId, aSessionId, aSessionIdLength); - } - - void RemoveSession(uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength) override - { - mDecryptorV7->RemoveSession(aPromiseId, aSessionId, aSessionIdLength); - } - - void SetServerCertificate(uint32_t aPromiseId, - const uint8_t* aServerCert, - uint32_t aServerCertSize) override - { - mDecryptorV7->SetServerCertificate(aPromiseId, aServerCert, aServerCertSize); - } - - void Decrypt(GMPBuffer* aBuffer, - GMPEncryptedBufferMetadata* aMetadata) override - { - mDecryptorV7->Decrypt(aBuffer, aMetadata); - } - - void DecryptingComplete() override - { - mDecryptorV7->DecryptingComplete(); - delete this; - } -private: - GMPDecryptor7* mDecryptorV7; -}; - -bool -GMPContentChild::RecvPGMPDecryptorConstructor(PGMPDecryptorChild* aActor) -{ - GMPDecryptorChild* child = static_cast<GMPDecryptorChild*>(aActor); - GMPDecryptorHost* host = static_cast<GMPDecryptorHost*>(child); - - void* ptr = nullptr; - GMPErr err = mGMPChild->GetAPI(GMP_API_DECRYPTOR, host, &ptr, aActor->Id()); - GMPDecryptor* decryptor = nullptr; - if (GMP_SUCCEEDED(err) && ptr) { - decryptor = static_cast<GMPDecryptor*>(ptr); - } else if (err != GMPNoErr) { - // We Adapt the previous GMPDecryptor version to the current, so that - // Gecko thinks it's only talking to the current version. v7 differs - // from v9 in its Init() function arguments, and v9 has extra enumeration - // members at the end of the key status enumerations. - err = mGMPChild->GetAPI(GMP_API_DECRYPTOR_BACKWARDS_COMPAT, host, &ptr); - if (err != GMPNoErr || !ptr) { - return false; - } - decryptor = new GMPDecryptor7BackwardsCompat(static_cast<GMPDecryptor7*>(ptr)); - } - - child->Init(decryptor); - - return true; -} - -bool -GMPContentChild::RecvPGMPAudioDecoderConstructor(PGMPAudioDecoderChild* aActor) -{ - auto vdc = static_cast<GMPAudioDecoderChild*>(aActor); - - void* vd = nullptr; - GMPErr err = mGMPChild->GetAPI(GMP_API_AUDIO_DECODER, &vdc->Host(), &vd); - if (err != GMPNoErr || !vd) { - return false; - } - - vdc->Init(static_cast<GMPAudioDecoder*>(vd)); - - return true; -} - -bool -GMPContentChild::RecvPGMPVideoDecoderConstructor(PGMPVideoDecoderChild* aActor, - const uint32_t& aDecryptorId) -{ - auto vdc = static_cast<GMPVideoDecoderChild*>(aActor); - - void* vd = nullptr; - GMPErr err = mGMPChild->GetAPI(GMP_API_VIDEO_DECODER, &vdc->Host(), &vd, aDecryptorId); - if (err != GMPNoErr || !vd) { - NS_WARNING("GMPGetAPI call failed trying to construct decoder."); - return false; - } - - vdc->Init(static_cast<GMPVideoDecoder*>(vd)); - - return true; -} - -bool -GMPContentChild::RecvPGMPVideoEncoderConstructor(PGMPVideoEncoderChild* aActor) -{ - auto vec = static_cast<GMPVideoEncoderChild*>(aActor); - - void* ve = nullptr; - GMPErr err = mGMPChild->GetAPI(GMP_API_VIDEO_ENCODER, &vec->Host(), &ve); - if (err != GMPNoErr || !ve) { - NS_WARNING("GMPGetAPI call failed trying to construct encoder."); - return false; - } - - vec->Init(static_cast<GMPVideoEncoder*>(ve)); - - return true; -} - -void -GMPContentChild::CloseActive() -{ - // Invalidate and remove any remaining API objects. - const ManagedContainer<PGMPAudioDecoderChild>& audioDecoders = - ManagedPGMPAudioDecoderChild(); - for (auto iter = audioDecoders.ConstIter(); !iter.Done(); iter.Next()) { - iter.Get()->GetKey()->SendShutdown(); - } - - const ManagedContainer<PGMPDecryptorChild>& decryptors = - ManagedPGMPDecryptorChild(); - for (auto iter = decryptors.ConstIter(); !iter.Done(); iter.Next()) { - iter.Get()->GetKey()->SendShutdown(); - } - - const ManagedContainer<PGMPVideoDecoderChild>& videoDecoders = - ManagedPGMPVideoDecoderChild(); - for (auto iter = videoDecoders.ConstIter(); !iter.Done(); iter.Next()) { - iter.Get()->GetKey()->SendShutdown(); - } - - const ManagedContainer<PGMPVideoEncoderChild>& videoEncoders = - ManagedPGMPVideoEncoderChild(); - for (auto iter = videoEncoders.ConstIter(); !iter.Done(); iter.Next()) { - iter.Get()->GetKey()->SendShutdown(); - } -} - -bool -GMPContentChild::IsUsed() -{ - return !ManagedPGMPAudioDecoderChild().IsEmpty() || - !ManagedPGMPDecryptorChild().IsEmpty() || - !ManagedPGMPVideoDecoderChild().IsEmpty() || - !ManagedPGMPVideoEncoderChild().IsEmpty(); -} - -} // namespace gmp -} // namespace mozilla diff --git a/dom/media/gmp/GMPContentChild.h b/dom/media/gmp/GMPContentChild.h deleted file mode 100644 index 714207608..000000000 --- a/dom/media/gmp/GMPContentChild.h +++ /dev/null @@ -1,58 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#ifndef GMPContentChild_h_ -#define GMPContentChild_h_ - -#include "mozilla/gmp/PGMPContentChild.h" -#include "GMPSharedMemManager.h" - -namespace mozilla { -namespace gmp { - -class GMPChild; - -class GMPContentChild : public PGMPContentChild - , public GMPSharedMem -{ -public: - explicit GMPContentChild(GMPChild* aChild); - virtual ~GMPContentChild(); - - MessageLoop* GMPMessageLoop(); - - bool RecvPGMPAudioDecoderConstructor(PGMPAudioDecoderChild* aActor) override; - bool RecvPGMPDecryptorConstructor(PGMPDecryptorChild* aActor) override; - bool RecvPGMPVideoDecoderConstructor(PGMPVideoDecoderChild* aActor, const uint32_t& aDecryptorId) override; - bool RecvPGMPVideoEncoderConstructor(PGMPVideoEncoderChild* aActor) override; - - PGMPAudioDecoderChild* AllocPGMPAudioDecoderChild() override; - bool DeallocPGMPAudioDecoderChild(PGMPAudioDecoderChild* aActor) override; - - PGMPDecryptorChild* AllocPGMPDecryptorChild() override; - bool DeallocPGMPDecryptorChild(PGMPDecryptorChild* aActor) override; - - PGMPVideoDecoderChild* AllocPGMPVideoDecoderChild(const uint32_t& aDecryptorId) override; - bool DeallocPGMPVideoDecoderChild(PGMPVideoDecoderChild* aActor) override; - - PGMPVideoEncoderChild* AllocPGMPVideoEncoderChild() override; - bool DeallocPGMPVideoEncoderChild(PGMPVideoEncoderChild* aActor) override; - - void ActorDestroy(ActorDestroyReason aWhy) override; - void ProcessingError(Result aCode, const char* aReason) override; - - // GMPSharedMem - void CheckThread() override; - - void CloseActive(); - bool IsUsed(); - - GMPChild* mGMPChild; -}; - -} // namespace gmp -} // namespace mozilla - -#endif // GMPContentChild_h_ diff --git a/dom/media/gmp/GMPContentParent.cpp b/dom/media/gmp/GMPContentParent.cpp deleted file mode 100644 index 12f6f4c48..000000000 --- a/dom/media/gmp/GMPContentParent.cpp +++ /dev/null @@ -1,298 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#include "GMPContentParent.h" -#include "GMPAudioDecoderParent.h" -#include "GMPDecryptorParent.h" -#include "GMPParent.h" -#include "GMPServiceChild.h" -#include "GMPVideoDecoderParent.h" -#include "GMPVideoEncoderParent.h" -#include "mozIGeckoMediaPluginService.h" -#include "mozilla/Logging.h" -#include "mozilla/Unused.h" -#include "base/task.h" - -namespace mozilla { - -#ifdef LOG -#undef LOG -#endif - -extern LogModule* GetGMPLog(); - -#define LOGD(msg) MOZ_LOG(GetGMPLog(), mozilla::LogLevel::Debug, msg) -#define LOG(level, msg) MOZ_LOG(GetGMPLog(), (level), msg) - -#ifdef __CLASS__ -#undef __CLASS__ -#endif -#define __CLASS__ "GMPContentParent" - -namespace gmp { - -GMPContentParent::GMPContentParent(GMPParent* aParent) - : mParent(aParent) -{ - if (mParent) { - SetDisplayName(mParent->GetDisplayName()); - SetPluginId(mParent->GetPluginId()); - } -} - -GMPContentParent::~GMPContentParent() -{ -} - -class ReleaseGMPContentParent : public Runnable -{ -public: - explicit ReleaseGMPContentParent(GMPContentParent* aToRelease) - : mToRelease(aToRelease) - { - } - - NS_IMETHOD Run() override - { - return NS_OK; - } - -private: - RefPtr<GMPContentParent> mToRelease; -}; - -void -GMPContentParent::ActorDestroy(ActorDestroyReason aWhy) -{ - MOZ_ASSERT(mAudioDecoders.IsEmpty() && - mDecryptors.IsEmpty() && - mVideoDecoders.IsEmpty() && - mVideoEncoders.IsEmpty()); - NS_DispatchToCurrentThread(new ReleaseGMPContentParent(this)); -} - -void -GMPContentParent::CheckThread() -{ - MOZ_ASSERT(mGMPThread == NS_GetCurrentThread()); -} - -void -GMPContentParent::AudioDecoderDestroyed(GMPAudioDecoderParent* aDecoder) -{ - MOZ_ASSERT(GMPThread() == NS_GetCurrentThread()); - - MOZ_ALWAYS_TRUE(mAudioDecoders.RemoveElement(aDecoder)); - CloseIfUnused(); -} - -void -GMPContentParent::VideoDecoderDestroyed(GMPVideoDecoderParent* aDecoder) -{ - MOZ_ASSERT(GMPThread() == NS_GetCurrentThread()); - - // If the constructor fails, we'll get called before it's added - Unused << NS_WARN_IF(!mVideoDecoders.RemoveElement(aDecoder)); - CloseIfUnused(); -} - -void -GMPContentParent::VideoEncoderDestroyed(GMPVideoEncoderParent* aEncoder) -{ - MOZ_ASSERT(GMPThread() == NS_GetCurrentThread()); - - // If the constructor fails, we'll get called before it's added - Unused << NS_WARN_IF(!mVideoEncoders.RemoveElement(aEncoder)); - CloseIfUnused(); -} - -void -GMPContentParent::DecryptorDestroyed(GMPDecryptorParent* aSession) -{ - MOZ_ASSERT(GMPThread() == NS_GetCurrentThread()); - - MOZ_ALWAYS_TRUE(mDecryptors.RemoveElement(aSession)); - CloseIfUnused(); -} - -void -GMPContentParent::CloseIfUnused() -{ - if (mAudioDecoders.IsEmpty() && - mDecryptors.IsEmpty() && - mVideoDecoders.IsEmpty() && - mVideoEncoders.IsEmpty()) { - RefPtr<GMPContentParent> toClose; - if (mParent) { - toClose = mParent->ForgetGMPContentParent(); - } else { - toClose = this; - RefPtr<GeckoMediaPluginServiceChild> gmp( - GeckoMediaPluginServiceChild::GetSingleton()); - gmp->RemoveGMPContentParent(toClose); - } - NS_DispatchToCurrentThread(NewRunnableMethod(toClose, - &GMPContentParent::Close)); - } -} - -nsresult -GMPContentParent::GetGMPDecryptor(GMPDecryptorParent** aGMPDP) -{ - PGMPDecryptorParent* pdp = SendPGMPDecryptorConstructor(); - if (!pdp) { - return NS_ERROR_FAILURE; - } - GMPDecryptorParent* dp = static_cast<GMPDecryptorParent*>(pdp); - // This addref corresponds to the Proxy pointer the consumer is returned. - // It's dropped by calling Close() on the interface. - NS_ADDREF(dp); - mDecryptors.AppendElement(dp); - *aGMPDP = dp; - - return NS_OK; -} - -nsIThread* -GMPContentParent::GMPThread() -{ - if (!mGMPThread) { - nsCOMPtr<mozIGeckoMediaPluginService> mps = do_GetService("@mozilla.org/gecko-media-plugin-service;1"); - MOZ_ASSERT(mps); - if (!mps) { - return nullptr; - } - // Not really safe if we just grab to the mGMPThread, as we don't know - // what thread we're running on and other threads may be trying to - // access this without locks! However, debug only, and primary failure - // mode outside of compiler-helped TSAN is a leak. But better would be - // to use swap() under a lock. - mps->GetThread(getter_AddRefs(mGMPThread)); - MOZ_ASSERT(mGMPThread); - } - - return mGMPThread; -} - -nsresult -GMPContentParent::GetGMPAudioDecoder(GMPAudioDecoderParent** aGMPAD) -{ - PGMPAudioDecoderParent* pvap = SendPGMPAudioDecoderConstructor(); - if (!pvap) { - return NS_ERROR_FAILURE; - } - GMPAudioDecoderParent* vap = static_cast<GMPAudioDecoderParent*>(pvap); - // This addref corresponds to the Proxy pointer the consumer is returned. - // It's dropped by calling Close() on the interface. - NS_ADDREF(vap); - *aGMPAD = vap; - mAudioDecoders.AppendElement(vap); - - return NS_OK; -} - -nsresult -GMPContentParent::GetGMPVideoDecoder(GMPVideoDecoderParent** aGMPVD, - uint32_t aDecryptorId) -{ - // returned with one anonymous AddRef that locks it until Destroy - PGMPVideoDecoderParent* pvdp = SendPGMPVideoDecoderConstructor(aDecryptorId); - if (!pvdp) { - return NS_ERROR_FAILURE; - } - GMPVideoDecoderParent *vdp = static_cast<GMPVideoDecoderParent*>(pvdp); - // This addref corresponds to the Proxy pointer the consumer is returned. - // It's dropped by calling Close() on the interface. - NS_ADDREF(vdp); - *aGMPVD = vdp; - mVideoDecoders.AppendElement(vdp); - - return NS_OK; -} - -nsresult -GMPContentParent::GetGMPVideoEncoder(GMPVideoEncoderParent** aGMPVE) -{ - // returned with one anonymous AddRef that locks it until Destroy - PGMPVideoEncoderParent* pvep = SendPGMPVideoEncoderConstructor(); - if (!pvep) { - return NS_ERROR_FAILURE; - } - GMPVideoEncoderParent *vep = static_cast<GMPVideoEncoderParent*>(pvep); - // This addref corresponds to the Proxy pointer the consumer is returned. - // It's dropped by calling Close() on the interface. - NS_ADDREF(vep); - *aGMPVE = vep; - mVideoEncoders.AppendElement(vep); - - return NS_OK; -} - -PGMPVideoDecoderParent* -GMPContentParent::AllocPGMPVideoDecoderParent(const uint32_t& aDecryptorId) -{ - GMPVideoDecoderParent* vdp = new GMPVideoDecoderParent(this); - NS_ADDREF(vdp); - return vdp; -} - -bool -GMPContentParent::DeallocPGMPVideoDecoderParent(PGMPVideoDecoderParent* aActor) -{ - GMPVideoDecoderParent* vdp = static_cast<GMPVideoDecoderParent*>(aActor); - NS_RELEASE(vdp); - return true; -} - -PGMPVideoEncoderParent* -GMPContentParent::AllocPGMPVideoEncoderParent() -{ - GMPVideoEncoderParent* vep = new GMPVideoEncoderParent(this); - NS_ADDREF(vep); - return vep; -} - -bool -GMPContentParent::DeallocPGMPVideoEncoderParent(PGMPVideoEncoderParent* aActor) -{ - GMPVideoEncoderParent* vep = static_cast<GMPVideoEncoderParent*>(aActor); - NS_RELEASE(vep); - return true; -} - -PGMPDecryptorParent* -GMPContentParent::AllocPGMPDecryptorParent() -{ - GMPDecryptorParent* ksp = new GMPDecryptorParent(this); - NS_ADDREF(ksp); - return ksp; -} - -bool -GMPContentParent::DeallocPGMPDecryptorParent(PGMPDecryptorParent* aActor) -{ - GMPDecryptorParent* ksp = static_cast<GMPDecryptorParent*>(aActor); - NS_RELEASE(ksp); - return true; -} - -PGMPAudioDecoderParent* -GMPContentParent::AllocPGMPAudioDecoderParent() -{ - GMPAudioDecoderParent* vdp = new GMPAudioDecoderParent(this); - NS_ADDREF(vdp); - return vdp; -} - -bool -GMPContentParent::DeallocPGMPAudioDecoderParent(PGMPAudioDecoderParent* aActor) -{ - GMPAudioDecoderParent* vdp = static_cast<GMPAudioDecoderParent*>(aActor); - NS_RELEASE(vdp); - return true; -} - -} // namespace gmp -} // namespace mozilla diff --git a/dom/media/gmp/GMPContentParent.h b/dom/media/gmp/GMPContentParent.h deleted file mode 100644 index 81f79bc73..000000000 --- a/dom/media/gmp/GMPContentParent.h +++ /dev/null @@ -1,103 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#ifndef GMPContentParent_h_ -#define GMPContentParent_h_ - -#include "mozilla/gmp/PGMPContentParent.h" -#include "GMPSharedMemManager.h" -#include "nsISupportsImpl.h" - -namespace mozilla { -namespace gmp { - -class GMPAudioDecoderParent; -class GMPDecryptorParent; -class GMPParent; -class GMPVideoDecoderParent; -class GMPVideoEncoderParent; - -class GMPContentParent final : public PGMPContentParent, - public GMPSharedMem -{ -public: - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GMPContentParent) - - explicit GMPContentParent(GMPParent* aParent = nullptr); - - nsresult GetGMPVideoDecoder(GMPVideoDecoderParent** aGMPVD, - uint32_t aDecryptorId); - void VideoDecoderDestroyed(GMPVideoDecoderParent* aDecoder); - - nsresult GetGMPVideoEncoder(GMPVideoEncoderParent** aGMPVE); - void VideoEncoderDestroyed(GMPVideoEncoderParent* aEncoder); - - nsresult GetGMPDecryptor(GMPDecryptorParent** aGMPKS); - void DecryptorDestroyed(GMPDecryptorParent* aSession); - - nsresult GetGMPAudioDecoder(GMPAudioDecoderParent** aGMPAD); - void AudioDecoderDestroyed(GMPAudioDecoderParent* aDecoder); - - nsIThread* GMPThread(); - - // GMPSharedMem - void CheckThread() override; - - void SetDisplayName(const nsCString& aDisplayName) - { - mDisplayName = aDisplayName; - } - const nsCString& GetDisplayName() - { - return mDisplayName; - } - void SetPluginId(const uint32_t aPluginId) - { - mPluginId = aPluginId; - } - uint32_t GetPluginId() const - { - return mPluginId; - } - -private: - ~GMPContentParent(); - - void ActorDestroy(ActorDestroyReason aWhy) override; - - PGMPVideoDecoderParent* AllocPGMPVideoDecoderParent(const uint32_t& aDecryptorId) override; - bool DeallocPGMPVideoDecoderParent(PGMPVideoDecoderParent* aActor) override; - - PGMPVideoEncoderParent* AllocPGMPVideoEncoderParent() override; - bool DeallocPGMPVideoEncoderParent(PGMPVideoEncoderParent* aActor) override; - - PGMPDecryptorParent* AllocPGMPDecryptorParent() override; - bool DeallocPGMPDecryptorParent(PGMPDecryptorParent* aActor) override; - - PGMPAudioDecoderParent* AllocPGMPAudioDecoderParent() override; - bool DeallocPGMPAudioDecoderParent(PGMPAudioDecoderParent* aActor) override; - - void CloseIfUnused(); - // Needed because NewRunnableMethod tried to use the class that the method - // lives on to store the receiver, but PGMPContentParent isn't refcounted. - void Close() - { - PGMPContentParent::Close(); - } - - nsTArray<RefPtr<GMPVideoDecoderParent>> mVideoDecoders; - nsTArray<RefPtr<GMPVideoEncoderParent>> mVideoEncoders; - nsTArray<RefPtr<GMPDecryptorParent>> mDecryptors; - nsTArray<RefPtr<GMPAudioDecoderParent>> mAudioDecoders; - nsCOMPtr<nsIThread> mGMPThread; - RefPtr<GMPParent> mParent; - nsCString mDisplayName; - uint32_t mPluginId; -}; - -} // namespace gmp -} // namespace mozilla - -#endif // GMPParent_h_ diff --git a/dom/media/gmp/GMPCrashHelperHolder.h b/dom/media/gmp/GMPCrashHelperHolder.h deleted file mode 100644 index ea6f36c83..000000000 --- a/dom/media/gmp/GMPCrashHelperHolder.h +++ /dev/null @@ -1,81 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#ifndef GMPCrashHelperHolder_h_ -#define GMPCrashHelperHolder_h_ - -#include "GMPService.h" -#include "mozilla/RefPtr.h" -#include "nsPIDOMWindow.h" -#include "mozilla/ipc/ProtocolUtils.h" - -class GMPCrashHelper; - -namespace mozilla { - -// Disconnecting the GMPCrashHelpers at the right time is hard. We need to -// ensure that in the crashing case that we stay connected until the -// "gmp-plugin-crashed" message is processed in the content process. -// -// We have two channels connecting to the GMP; PGMP which connects from -// chrome to GMP process, and PGMPContent, which bridges between the content -// and GMP process. If the GMP crashes both PGMP and PGMPContent receive -// ActorDestroy messages and begin to shutdown at the same time. -// -// However the crash report mini dump must be generated in the chrome -// process' ActorDestroy, before the "gmp-plugin-crashed" message can be sent -// to the content process. We fire the "PluginCrashed" event when we handle -// the "gmp-plugin-crashed" message in the content process, and we need the -// crash helpers to do that. -// -// The PGMPContent's managed actors' ActorDestroy messages are the only shutdown -// notification we get in the content process, but we can't disconnect the -// crash handlers there in the crashing case, as ActorDestroy happens before -// we've received the "gmp-plugin-crashed" message and had a chance for the -// crash helpers to generate the window to dispatch PluginCrashed to initiate -// the crash report submission notification box. -// -// So we need to ensure that in the content process, the GMPCrashHelpers stay -// connected to the GMPService until after ActorDestroy messages are received -// if there's an abnormal shutdown. In the case where the GMP doesn't crash, -// we do actually want to disconnect GMPCrashHandlers in ActorDestroy, since -// we don't have any other signal that a GMP actor is shutting down. If we don't -// disconnect the crash helper there in the normal shutdown case, the helper -// will stick around forever and leak. -// -// In the crashing case, the GMPCrashHelpers are deallocated when the crash -// report is processed in GeckoMediaPluginService::RunPluginCrashCallbacks(). -// -// It's a bit yuck that we have to have two paths for disconnecting the crash -// helpers, but there aren't really any better options. -class GMPCrashHelperHolder -{ -public: - - void SetCrashHelper(GMPCrashHelper* aHelper) - { - mCrashHelper = aHelper; - } - - GMPCrashHelper* GetCrashHelper() - { - return mCrashHelper; - } - - void MaybeDisconnect(bool aAbnormalShutdown) - { - if (!aAbnormalShutdown) { - RefPtr<gmp::GeckoMediaPluginService> service(gmp::GeckoMediaPluginService::GetGeckoMediaPluginService()); - service->DisconnectCrashHelper(GetCrashHelper()); - } - } - -private: - RefPtr<GMPCrashHelper> mCrashHelper; -}; - -} - -#endif // GMPCrashHelperHolder_h_ diff --git a/dom/media/gmp/GMPDecryptorChild.cpp b/dom/media/gmp/GMPDecryptorChild.cpp deleted file mode 100644 index 6da3c6c43..000000000 --- a/dom/media/gmp/GMPDecryptorChild.cpp +++ /dev/null @@ -1,403 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#include "GMPDecryptorChild.h" -#include "GMPContentChild.h" -#include "GMPChild.h" -#include "base/task.h" -#include "mozilla/TimeStamp.h" -#include "mozilla/Unused.h" -#include "runnable_utils.h" -#include <ctime> - -#define ON_GMP_THREAD() (mPlugin->GMPMessageLoop() == MessageLoop::current()) - -#define CALL_ON_GMP_THREAD(_func, ...) \ - CallOnGMPThread(&GMPDecryptorChild::_func, __VA_ARGS__) - -namespace mozilla { -namespace gmp { - -GMPDecryptorChild::GMPDecryptorChild(GMPContentChild* aPlugin, - const nsTArray<uint8_t>& aPluginVoucher, - const nsTArray<uint8_t>& aSandboxVoucher) - : mSession(nullptr) - , mPlugin(aPlugin) - , mPluginVoucher(aPluginVoucher) - , mSandboxVoucher(aSandboxVoucher) -{ - MOZ_ASSERT(mPlugin); -} - -GMPDecryptorChild::~GMPDecryptorChild() -{ -} - -template <typename MethodType, typename... ParamType> -void -GMPDecryptorChild::CallMethod(MethodType aMethod, ParamType&&... aParams) -{ - MOZ_ASSERT(ON_GMP_THREAD()); - // Don't send IPC messages after tear-down. - if (mSession) { - (this->*aMethod)(Forward<ParamType>(aParams)...); - } -} - -template<typename T> -struct AddConstReference { - typedef const typename RemoveReference<T>::Type& Type; -}; - -template<typename MethodType, typename... ParamType> -void -GMPDecryptorChild::CallOnGMPThread(MethodType aMethod, ParamType&&... aParams) -{ - if (ON_GMP_THREAD()) { - // Use forwarding reference when we can. - CallMethod(aMethod, Forward<ParamType>(aParams)...); - } else { - // Use const reference when we have to. - auto m = &GMPDecryptorChild::CallMethod< - decltype(aMethod), typename AddConstReference<ParamType>::Type...>; - RefPtr<mozilla::Runnable> t = - dont_add_new_uses_of_this::NewRunnableMethod(this, m, aMethod, Forward<ParamType>(aParams)...); - mPlugin->GMPMessageLoop()->PostTask(t.forget()); - } -} - -void -GMPDecryptorChild::Init(GMPDecryptor* aSession) -{ - MOZ_ASSERT(aSession); - mSession = aSession; - // The ID of this decryptor is the IPDL actor ID. Note it's unique inside - // the child process, but not necessarily across all gecko processes. However, - // since GMPDecryptors are segregated by node ID/origin, we shouldn't end up - // with clashes in the content process. - SendSetDecryptorId(Id()); -} - -void -GMPDecryptorChild::SetSessionId(uint32_t aCreateSessionToken, - const char* aSessionId, - uint32_t aSessionIdLength) -{ - CALL_ON_GMP_THREAD(SendSetSessionId, - aCreateSessionToken, nsCString(aSessionId, aSessionIdLength)); -} - -void -GMPDecryptorChild::ResolveLoadSessionPromise(uint32_t aPromiseId, - bool aSuccess) -{ - CALL_ON_GMP_THREAD(SendResolveLoadSessionPromise, aPromiseId, aSuccess); -} - -void -GMPDecryptorChild::ResolvePromise(uint32_t aPromiseId) -{ - CALL_ON_GMP_THREAD(SendResolvePromise, aPromiseId); -} - -void -GMPDecryptorChild::RejectPromise(uint32_t aPromiseId, - GMPDOMException aException, - const char* aMessage, - uint32_t aMessageLength) -{ - CALL_ON_GMP_THREAD(SendRejectPromise, - aPromiseId, aException, nsCString(aMessage, aMessageLength)); -} - -void -GMPDecryptorChild::SessionMessage(const char* aSessionId, - uint32_t aSessionIdLength, - GMPSessionMessageType aMessageType, - const uint8_t* aMessage, - uint32_t aMessageLength) -{ - nsTArray<uint8_t> msg; - msg.AppendElements(aMessage, aMessageLength); - CALL_ON_GMP_THREAD(SendSessionMessage, - nsCString(aSessionId, aSessionIdLength), - aMessageType, Move(msg)); -} - -void -GMPDecryptorChild::ExpirationChange(const char* aSessionId, - uint32_t aSessionIdLength, - GMPTimestamp aExpiryTime) -{ - CALL_ON_GMP_THREAD(SendExpirationChange, - nsCString(aSessionId, aSessionIdLength), aExpiryTime); -} - -void -GMPDecryptorChild::SessionClosed(const char* aSessionId, - uint32_t aSessionIdLength) -{ - CALL_ON_GMP_THREAD(SendSessionClosed, - nsCString(aSessionId, aSessionIdLength)); -} - -void -GMPDecryptorChild::SessionError(const char* aSessionId, - uint32_t aSessionIdLength, - GMPDOMException aException, - uint32_t aSystemCode, - const char* aMessage, - uint32_t aMessageLength) -{ - CALL_ON_GMP_THREAD(SendSessionError, - nsCString(aSessionId, aSessionIdLength), - aException, aSystemCode, - nsCString(aMessage, aMessageLength)); -} - -void -GMPDecryptorChild::KeyStatusChanged(const char* aSessionId, - uint32_t aSessionIdLength, - const uint8_t* aKeyId, - uint32_t aKeyIdLength, - GMPMediaKeyStatus aStatus) -{ - AutoTArray<uint8_t, 16> kid; - kid.AppendElements(aKeyId, aKeyIdLength); - - nsTArray<GMPKeyInformation> keyInfos; - keyInfos.AppendElement(GMPKeyInformation(kid, aStatus)); - CALL_ON_GMP_THREAD(SendBatchedKeyStatusChanged, - nsCString(aSessionId, aSessionIdLength), - keyInfos); -} - -void -GMPDecryptorChild::BatchedKeyStatusChanged(const char* aSessionId, - uint32_t aSessionIdLength, - const GMPMediaKeyInfo* aKeyInfos, - uint32_t aKeyInfosLength) -{ - nsTArray<GMPKeyInformation> keyInfos; - for (uint32_t i = 0; i < aKeyInfosLength; i++) { - nsTArray<uint8_t> keyId; - keyId.AppendElements(aKeyInfos[i].keyid, aKeyInfos[i].keyid_size); - keyInfos.AppendElement(GMPKeyInformation(keyId, aKeyInfos[i].status)); - } - CALL_ON_GMP_THREAD(SendBatchedKeyStatusChanged, - nsCString(aSessionId, aSessionIdLength), - keyInfos); -} - -void -GMPDecryptorChild::Decrypted(GMPBuffer* aBuffer, GMPErr aResult) -{ - if (!ON_GMP_THREAD()) { - // We should run this whole method on the GMP thread since the buffer needs - // to be deleted after the SendDecrypted call. - mPlugin->GMPMessageLoop()->PostTask(NewRunnableMethod - <GMPBuffer*, GMPErr>(this, - &GMPDecryptorChild::Decrypted, - aBuffer, aResult)); - return; - } - - if (!aBuffer) { - NS_WARNING("GMPDecryptorCallback passed bull GMPBuffer"); - return; - } - - auto buffer = static_cast<GMPBufferImpl*>(aBuffer); - if (mSession) { - SendDecrypted(buffer->mId, aResult, buffer->mData); - } - delete buffer; -} - -void -GMPDecryptorChild::SetCapabilities(uint64_t aCaps) -{ - // Deprecated. -} - -void -GMPDecryptorChild::GetSandboxVoucher(const uint8_t** aVoucher, - uint32_t* aVoucherLength) -{ - if (!aVoucher || !aVoucherLength) { - return; - } - *aVoucher = mSandboxVoucher.Elements(); - *aVoucherLength = mSandboxVoucher.Length(); -} - -void -GMPDecryptorChild::GetPluginVoucher(const uint8_t** aVoucher, - uint32_t* aVoucherLength) -{ - if (!aVoucher || !aVoucherLength) { - return; - } - *aVoucher = mPluginVoucher.Elements(); - *aVoucherLength = mPluginVoucher.Length(); -} - -bool -GMPDecryptorChild::RecvInit(const bool& aDistinctiveIdentifierRequired, - const bool& aPersistentStateRequired) -{ - if (!mSession) { - return false; - } - mSession->Init(this, aDistinctiveIdentifierRequired, aPersistentStateRequired); - return true; -} - -bool -GMPDecryptorChild::RecvCreateSession(const uint32_t& aCreateSessionToken, - const uint32_t& aPromiseId, - const nsCString& aInitDataType, - InfallibleTArray<uint8_t>&& aInitData, - const GMPSessionType& aSessionType) -{ - if (!mSession) { - return false; - } - - mSession->CreateSession(aCreateSessionToken, - aPromiseId, - aInitDataType.get(), - aInitDataType.Length(), - aInitData.Elements(), - aInitData.Length(), - aSessionType); - - return true; -} - -bool -GMPDecryptorChild::RecvLoadSession(const uint32_t& aPromiseId, - const nsCString& aSessionId) -{ - if (!mSession) { - return false; - } - - mSession->LoadSession(aPromiseId, - aSessionId.get(), - aSessionId.Length()); - - return true; -} - -bool -GMPDecryptorChild::RecvUpdateSession(const uint32_t& aPromiseId, - const nsCString& aSessionId, - InfallibleTArray<uint8_t>&& aResponse) -{ - if (!mSession) { - return false; - } - - mSession->UpdateSession(aPromiseId, - aSessionId.get(), - aSessionId.Length(), - aResponse.Elements(), - aResponse.Length()); - - return true; -} - -bool -GMPDecryptorChild::RecvCloseSession(const uint32_t& aPromiseId, - const nsCString& aSessionId) -{ - if (!mSession) { - return false; - } - - mSession->CloseSession(aPromiseId, - aSessionId.get(), - aSessionId.Length()); - - return true; -} - -bool -GMPDecryptorChild::RecvRemoveSession(const uint32_t& aPromiseId, - const nsCString& aSessionId) -{ - if (!mSession) { - return false; - } - - mSession->RemoveSession(aPromiseId, - aSessionId.get(), - aSessionId.Length()); - - return true; -} - -bool -GMPDecryptorChild::RecvSetServerCertificate(const uint32_t& aPromiseId, - InfallibleTArray<uint8_t>&& aServerCert) -{ - if (!mSession) { - return false; - } - - mSession->SetServerCertificate(aPromiseId, - aServerCert.Elements(), - aServerCert.Length()); - - return true; -} - -bool -GMPDecryptorChild::RecvDecrypt(const uint32_t& aId, - InfallibleTArray<uint8_t>&& aBuffer, - const GMPDecryptionData& aMetadata) -{ - if (!mSession) { - return false; - } - - // Note: the GMPBufferImpl created here is deleted when the GMP passes - // it back in the Decrypted() callback above. - GMPBufferImpl* buffer = new GMPBufferImpl(aId, aBuffer); - - // |metadata| lifetime is managed by |buffer|. - GMPEncryptedBufferDataImpl* metadata = new GMPEncryptedBufferDataImpl(aMetadata); - buffer->SetMetadata(metadata); - - mSession->Decrypt(buffer, metadata); - return true; -} - -bool -GMPDecryptorChild::RecvDecryptingComplete() -{ - // Reset |mSession| before calling DecryptingComplete(). We should not send - // any IPC messages during tear-down. - auto session = mSession; - mSession = nullptr; - - if (!session) { - return false; - } - - session->DecryptingComplete(); - - Unused << Send__delete__(this); - - return true; -} - -} // namespace gmp -} // namespace mozilla - -// avoid redefined macro in unified build -#undef ON_GMP_THREAD -#undef CALL_ON_GMP_THREAD diff --git a/dom/media/gmp/GMPDecryptorChild.h b/dom/media/gmp/GMPDecryptorChild.h deleted file mode 100644 index 434da774f..000000000 --- a/dom/media/gmp/GMPDecryptorChild.h +++ /dev/null @@ -1,142 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#ifndef GMPDecryptorChild_h_ -#define GMPDecryptorChild_h_ - -#include "mozilla/gmp/PGMPDecryptorChild.h" -#include "gmp-decryption.h" -#include "mozilla/gmp/GMPTypes.h" -#include "GMPEncryptedBufferDataImpl.h" -#include <string> - -namespace mozilla { -namespace gmp { - -class GMPContentChild; - -class GMPDecryptorChild : public GMPDecryptorCallback - , public GMPDecryptorHost - , public PGMPDecryptorChild -{ -public: - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GMPDecryptorChild); - - explicit GMPDecryptorChild(GMPContentChild* aPlugin, - const nsTArray<uint8_t>& aPluginVoucher, - const nsTArray<uint8_t>& aSandboxVoucher); - - void Init(GMPDecryptor* aSession); - - // GMPDecryptorCallback - void SetSessionId(uint32_t aCreateSessionToken, - const char* aSessionId, - uint32_t aSessionIdLength) override; - void ResolveLoadSessionPromise(uint32_t aPromiseId, - bool aSuccess) override; - void ResolvePromise(uint32_t aPromiseId) override; - - void RejectPromise(uint32_t aPromiseId, - GMPDOMException aException, - const char* aMessage, - uint32_t aMessageLength) override; - - void SessionMessage(const char* aSessionId, - uint32_t aSessionIdLength, - GMPSessionMessageType aMessageType, - const uint8_t* aMessage, - uint32_t aMessageLength) override; - - void ExpirationChange(const char* aSessionId, - uint32_t aSessionIdLength, - GMPTimestamp aExpiryTime) override; - - void SessionClosed(const char* aSessionId, - uint32_t aSessionIdLength) override; - - void SessionError(const char* aSessionId, - uint32_t aSessionIdLength, - GMPDOMException aException, - uint32_t aSystemCode, - const char* aMessage, - uint32_t aMessageLength) override; - - void KeyStatusChanged(const char* aSessionId, - uint32_t aSessionIdLength, - const uint8_t* aKeyId, - uint32_t aKeyIdLength, - GMPMediaKeyStatus aStatus) override; - - void SetCapabilities(uint64_t aCaps) override; - - void Decrypted(GMPBuffer* aBuffer, GMPErr aResult) override; - - void BatchedKeyStatusChanged(const char* aSessionId, - uint32_t aSessionIdLength, - const GMPMediaKeyInfo* aKeyInfos, - uint32_t aKeyInfosLength) override; - - // GMPDecryptorHost - void GetSandboxVoucher(const uint8_t** aVoucher, - uint32_t* aVoucherLength) override; - - void GetPluginVoucher(const uint8_t** aVoucher, - uint32_t* aVoucherLength) override; -private: - ~GMPDecryptorChild(); - - // GMPDecryptorChild - bool RecvInit(const bool& aDistinctiveIdentifierRequired, - const bool& aPersistentStateRequired) override; - - bool RecvCreateSession(const uint32_t& aCreateSessionToken, - const uint32_t& aPromiseId, - const nsCString& aInitDataType, - InfallibleTArray<uint8_t>&& aInitData, - const GMPSessionType& aSessionType) override; - - bool RecvLoadSession(const uint32_t& aPromiseId, - const nsCString& aSessionId) override; - - bool RecvUpdateSession(const uint32_t& aPromiseId, - const nsCString& aSessionId, - InfallibleTArray<uint8_t>&& aResponse) override; - - bool RecvCloseSession(const uint32_t& aPromiseId, - const nsCString& aSessionId) override; - - bool RecvRemoveSession(const uint32_t& aPromiseId, - const nsCString& aSessionId) override; - - bool RecvDecrypt(const uint32_t& aId, - InfallibleTArray<uint8_t>&& aBuffer, - const GMPDecryptionData& aMetadata) override; - - // Resolve/reject promise on completion. - bool RecvSetServerCertificate(const uint32_t& aPromiseId, - InfallibleTArray<uint8_t>&& aServerCert) override; - - bool RecvDecryptingComplete() override; - - template <typename MethodType, typename... ParamType> - void CallMethod(MethodType, ParamType&&...); - - template<typename MethodType, typename... ParamType> - void CallOnGMPThread(MethodType, ParamType&&...); - - // GMP's GMPDecryptor implementation. - // Only call into this on the (GMP process) main thread. - GMPDecryptor* mSession; - GMPContentChild* mPlugin; - - // Reference to the vouchers owned by the GMPChild. - const nsTArray<uint8_t>& mPluginVoucher; - const nsTArray<uint8_t>& mSandboxVoucher; -}; - -} // namespace gmp -} // namespace mozilla - -#endif // GMPDecryptorChild_h_ diff --git a/dom/media/gmp/GMPDecryptorParent.cpp b/dom/media/gmp/GMPDecryptorParent.cpp deleted file mode 100644 index 30bb72c39..000000000 --- a/dom/media/gmp/GMPDecryptorParent.cpp +++ /dev/null @@ -1,373 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#include "GMPDecryptorParent.h" - -#include "GMPContentParent.h" -#include "GMPUtils.h" -#include "MediaData.h" -#include "mozilla/Unused.h" - -namespace mozilla { - -#ifdef LOG -#undef LOG -#endif - -extern LogModule* GetGMPLog(); - -#define LOGV(msg) MOZ_LOG(GetGMPLog(), mozilla::LogLevel::Verbose, msg) -#define LOGD(msg) MOZ_LOG(GetGMPLog(), mozilla::LogLevel::Debug, msg) -#define LOG(level, msg) MOZ_LOG(GetGMPLog(), (level), msg) - -namespace gmp { - -GMPDecryptorParent::GMPDecryptorParent(GMPContentParent* aPlugin) - : mIsOpen(false) - , mShuttingDown(false) - , mActorDestroyed(false) - , mPlugin(aPlugin) - , mPluginId(aPlugin->GetPluginId()) - , mCallback(nullptr) -#ifdef DEBUG - , mGMPThread(aPlugin->GMPThread()) -#endif -{ - MOZ_ASSERT(mPlugin && mGMPThread); -} - -GMPDecryptorParent::~GMPDecryptorParent() -{ -} - -bool -GMPDecryptorParent::RecvSetDecryptorId(const uint32_t& aId) -{ - return true; -} - -nsresult -GMPDecryptorParent::Init(GMPDecryptorProxyCallback* aCallback, - bool aDistinctiveIdentifierRequired, - bool aPersistentStateRequired) -{ - LOGD(("GMPDecryptorParent[%p]::Init()", this)); - - if (mIsOpen) { - NS_WARNING("Trying to re-use an in-use GMP decrypter!"); - return NS_ERROR_FAILURE; - } - mCallback = aCallback; - if (!SendInit(aDistinctiveIdentifierRequired, aPersistentStateRequired)) { - return NS_ERROR_FAILURE; - } - mIsOpen = true; - return NS_OK; -} - -void -GMPDecryptorParent::CreateSession(uint32_t aCreateSessionToken, - uint32_t aPromiseId, - const nsCString& aInitDataType, - const nsTArray<uint8_t>& aInitData, - GMPSessionType aSessionType) -{ - LOGD(("GMPDecryptorParent[%p]::CreateSession(token=%u, promiseId=%u, aInitData='%s')", - this, aCreateSessionToken, aPromiseId, ToBase64(aInitData).get())); - - if (!mIsOpen) { - NS_WARNING("Trying to use a dead GMP decrypter!"); - return; - } - // Caller should ensure parameters passed in from JS are valid. - MOZ_ASSERT(!aInitDataType.IsEmpty() && !aInitData.IsEmpty()); - Unused << SendCreateSession(aCreateSessionToken, aPromiseId, aInitDataType, aInitData, aSessionType); -} - -void -GMPDecryptorParent::LoadSession(uint32_t aPromiseId, - const nsCString& aSessionId) -{ - LOGD(("GMPDecryptorParent[%p]::LoadSession(sessionId='%s', promiseId=%u)", - this, aSessionId.get(), aPromiseId)); - if (!mIsOpen) { - NS_WARNING("Trying to use a dead GMP decrypter!"); - return; - } - // Caller should ensure parameters passed in from JS are valid. - MOZ_ASSERT(!aSessionId.IsEmpty()); - Unused << SendLoadSession(aPromiseId, aSessionId); -} - -void -GMPDecryptorParent::UpdateSession(uint32_t aPromiseId, - const nsCString& aSessionId, - const nsTArray<uint8_t>& aResponse) -{ - LOGD(("GMPDecryptorParent[%p]::UpdateSession(sessionId='%s', promiseId=%u response='%s')", - this, aSessionId.get(), aPromiseId, ToBase64(aResponse).get())); - - if (!mIsOpen) { - NS_WARNING("Trying to use a dead GMP decrypter!"); - return; - } - // Caller should ensure parameters passed in from JS are valid. - MOZ_ASSERT(!aSessionId.IsEmpty() && !aResponse.IsEmpty()); - Unused << SendUpdateSession(aPromiseId, aSessionId, aResponse); -} - -void -GMPDecryptorParent::CloseSession(uint32_t aPromiseId, - const nsCString& aSessionId) -{ - LOGD(("GMPDecryptorParent[%p]::CloseSession(sessionId='%s', promiseId=%u)", - this, aSessionId.get(), aPromiseId)); - - if (!mIsOpen) { - NS_WARNING("Trying to use a dead GMP decrypter!"); - return; - } - // Caller should ensure parameters passed in from JS are valid. - MOZ_ASSERT(!aSessionId.IsEmpty()); - Unused << SendCloseSession(aPromiseId, aSessionId); -} - -void -GMPDecryptorParent::RemoveSession(uint32_t aPromiseId, - const nsCString& aSessionId) -{ - LOGD(("GMPDecryptorParent[%p]::RemoveSession(sessionId='%s', promiseId=%u)", - this, aSessionId.get(), aPromiseId)); - - if (!mIsOpen) { - NS_WARNING("Trying to use a dead GMP decrypter!"); - return; - } - // Caller should ensure parameters passed in from JS are valid. - MOZ_ASSERT(!aSessionId.IsEmpty()); - Unused << SendRemoveSession(aPromiseId, aSessionId); -} - -void -GMPDecryptorParent::SetServerCertificate(uint32_t aPromiseId, - const nsTArray<uint8_t>& aServerCert) -{ - LOGD(("GMPDecryptorParent[%p]::SetServerCertificate(promiseId=%u)", - this, aPromiseId)); - - if (!mIsOpen) { - NS_WARNING("Trying to use a dead GMP decrypter!"); - return; - } - // Caller should ensure parameters passed in from JS are valid. - MOZ_ASSERT(!aServerCert.IsEmpty()); - Unused << SendSetServerCertificate(aPromiseId, aServerCert); -} - -void -GMPDecryptorParent::Decrypt(uint32_t aId, - const CryptoSample& aCrypto, - const nsTArray<uint8_t>& aBuffer) -{ - LOGV(("GMPDecryptorParent[%p]::Decrypt(id=%d)", this, aId)); - - if (!mIsOpen) { - NS_WARNING("Trying to use a dead GMP decrypter!"); - return; - } - - // Caller should ensure parameters passed in are valid. - MOZ_ASSERT(!aBuffer.IsEmpty()); - - if (aCrypto.mValid) { - GMPDecryptionData data(aCrypto.mKeyId, - aCrypto.mIV, - aCrypto.mPlainSizes, - aCrypto.mEncryptedSizes, - aCrypto.mSessionIds); - - Unused << SendDecrypt(aId, aBuffer, data); - } else { - GMPDecryptionData data; - Unused << SendDecrypt(aId, aBuffer, data); - } -} - -bool -GMPDecryptorParent::RecvSetSessionId(const uint32_t& aCreateSessionId, - const nsCString& aSessionId) -{ - return true; -} - -bool -GMPDecryptorParent::RecvResolveLoadSessionPromise(const uint32_t& aPromiseId, - const bool& aSuccess) -{ - return true; -} - -bool -GMPDecryptorParent::RecvResolvePromise(const uint32_t& aPromiseId) -{ - return true; -} - -nsresult -GMPExToNsresult(GMPDOMException aDomException) { - switch (aDomException) { - case kGMPNoModificationAllowedError: return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR; - case kGMPNotFoundError: return NS_ERROR_DOM_NOT_FOUND_ERR; - case kGMPNotSupportedError: return NS_ERROR_DOM_NOT_SUPPORTED_ERR; - case kGMPInvalidStateError: return NS_ERROR_DOM_INVALID_STATE_ERR; - case kGMPSyntaxError: return NS_ERROR_DOM_SYNTAX_ERR; - case kGMPInvalidModificationError: return NS_ERROR_DOM_INVALID_MODIFICATION_ERR; - case kGMPInvalidAccessError: return NS_ERROR_DOM_INVALID_ACCESS_ERR; - case kGMPSecurityError: return NS_ERROR_DOM_SECURITY_ERR; - case kGMPAbortError: return NS_ERROR_DOM_ABORT_ERR; - case kGMPQuotaExceededError: return NS_ERROR_DOM_QUOTA_EXCEEDED_ERR; - case kGMPTimeoutError: return NS_ERROR_DOM_TIMEOUT_ERR; - case kGMPTypeError: return NS_ERROR_DOM_TYPE_ERR; - default: return NS_ERROR_DOM_UNKNOWN_ERR; - } -} - -bool -GMPDecryptorParent::RecvRejectPromise(const uint32_t& aPromiseId, - const GMPDOMException& aException, - const nsCString& aMessage) -{ - return true; -} - -bool -GMPDecryptorParent::RecvSessionMessage(const nsCString& aSessionId, - const GMPSessionMessageType& aMessageType, - nsTArray<uint8_t>&& aMessage) -{ - return true; -} - -bool -GMPDecryptorParent::RecvExpirationChange(const nsCString& aSessionId, - const double& aExpiryTime) -{ - return true; -} - -bool -GMPDecryptorParent::RecvSessionClosed(const nsCString& aSessionId) -{ - return true; -} - -bool -GMPDecryptorParent::RecvSessionError(const nsCString& aSessionId, - const GMPDOMException& aException, - const uint32_t& aSystemCode, - const nsCString& aMessage) -{ - return true; -} - -bool -GMPDecryptorParent::RecvBatchedKeyStatusChanged(const nsCString& aSessionId, - InfallibleTArray<GMPKeyInformation>&& aKeyInfos) -{ - return true; -} - -bool -GMPDecryptorParent::RecvDecrypted(const uint32_t& aId, - const GMPErr& aErr, - InfallibleTArray<uint8_t>&& aBuffer) -{ - return true; -} - -bool -GMPDecryptorParent::RecvShutdown() -{ - LOGD(("GMPDecryptorParent[%p]::RecvShutdown()", this)); - - Shutdown(); - return true; -} - -// Note: may be called via Terminated() -void -GMPDecryptorParent::Close() -{ - LOGD(("GMPDecryptorParent[%p]::Close()", this)); - MOZ_ASSERT(mGMPThread == NS_GetCurrentThread()); - - // Consumer is done with us; we can shut down. No more callbacks should - // be made to mCallback. Note: do this before Shutdown()! - mCallback = nullptr; - // Let Shutdown mark us as dead so it knows if we had been alive - - // In case this is the last reference - RefPtr<GMPDecryptorParent> kungfudeathgrip(this); - this->Release(); - Shutdown(); -} - -void -GMPDecryptorParent::Shutdown() -{ - LOGD(("GMPDecryptorParent[%p]::Shutdown()", this)); - MOZ_ASSERT(mGMPThread == NS_GetCurrentThread()); - - if (mShuttingDown) { - return; - } - mShuttingDown = true; - - // Notify client we're gone! Won't occur after Close() - if (mCallback) { - mCallback->Terminated(); - mCallback = nullptr; - } - - mIsOpen = false; - if (!mActorDestroyed) { - Unused << SendDecryptingComplete(); - } -} - -// Note: Keep this sync'd up with Shutdown -void -GMPDecryptorParent::ActorDestroy(ActorDestroyReason aWhy) -{ - LOGD(("GMPDecryptorParent[%p]::ActorDestroy(reason=%d)", this, aWhy)); - - mIsOpen = false; - mActorDestroyed = true; - if (mCallback) { - // May call Close() (and Shutdown()) immediately or with a delay - mCallback->Terminated(); - mCallback = nullptr; - } - if (mPlugin) { - mPlugin->DecryptorDestroyed(this); - mPlugin = nullptr; - } - MaybeDisconnect(aWhy == AbnormalShutdown); -} - -bool -GMPDecryptorParent::Recv__delete__() -{ - LOGD(("GMPDecryptorParent[%p]::Recv__delete__()", this)); - - if (mPlugin) { - mPlugin->DecryptorDestroyed(this); - mPlugin = nullptr; - } - return true; -} - -} // namespace gmp -} // namespace mozilla diff --git a/dom/media/gmp/GMPDecryptorParent.h b/dom/media/gmp/GMPDecryptorParent.h deleted file mode 100644 index 30ff24690..000000000 --- a/dom/media/gmp/GMPDecryptorParent.h +++ /dev/null @@ -1,129 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#ifndef GMPDecryptorParent_h_ -#define GMPDecryptorParent_h_ - -#include "mozilla/gmp/PGMPDecryptorParent.h" -#include "mozilla/RefPtr.h" -#include "gmp-decryption.h" -#include "GMPDecryptorProxy.h" -#include "GMPCrashHelperHolder.h" - -namespace mozilla { - -class CryptoSample; - -namespace gmp { - -class GMPContentParent; - -class GMPDecryptorParent final : public GMPDecryptorProxy - , public PGMPDecryptorParent - , public GMPCrashHelperHolder -{ -public: - NS_INLINE_DECL_REFCOUNTING(GMPDecryptorParent) - - explicit GMPDecryptorParent(GMPContentParent *aPlugin); - - // GMPDecryptorProxy - - uint32_t GetPluginId() const override { return mPluginId; } - - nsresult Init(GMPDecryptorProxyCallback* aCallback, - bool aDistinctiveIdentifierRequired, - bool aPersistentStateRequired) override; - - void CreateSession(uint32_t aCreateSessionToken, - uint32_t aPromiseId, - const nsCString& aInitDataType, - const nsTArray<uint8_t>& aInitData, - GMPSessionType aSessionType) override; - - void LoadSession(uint32_t aPromiseId, - const nsCString& aSessionId) override; - - void UpdateSession(uint32_t aPromiseId, - const nsCString& aSessionId, - const nsTArray<uint8_t>& aResponse) override; - - void CloseSession(uint32_t aPromiseId, - const nsCString& aSessionId) override; - - void RemoveSession(uint32_t aPromiseId, - const nsCString& aSessionId) override; - - void SetServerCertificate(uint32_t aPromiseId, - const nsTArray<uint8_t>& aServerCert) override; - - void Decrypt(uint32_t aId, - const CryptoSample& aCrypto, - const nsTArray<uint8_t>& aBuffer) override; - - void Close() override; - - void Shutdown(); - -private: - ~GMPDecryptorParent(); - - // PGMPDecryptorParent - - bool RecvSetDecryptorId(const uint32_t& aId) override; - - bool RecvSetSessionId(const uint32_t& aCreateSessionToken, - const nsCString& aSessionId) override; - - bool RecvResolveLoadSessionPromise(const uint32_t& aPromiseId, - const bool& aSuccess) override; - - bool RecvResolvePromise(const uint32_t& aPromiseId) override; - - bool RecvRejectPromise(const uint32_t& aPromiseId, - const GMPDOMException& aException, - const nsCString& aMessage) override; - - bool RecvSessionMessage(const nsCString& aSessionId, - const GMPSessionMessageType& aMessageType, - nsTArray<uint8_t>&& aMessage) override; - - bool RecvExpirationChange(const nsCString& aSessionId, - const double& aExpiryTime) override; - - bool RecvSessionClosed(const nsCString& aSessionId) override; - - bool RecvSessionError(const nsCString& aSessionId, - const GMPDOMException& aException, - const uint32_t& aSystemCode, - const nsCString& aMessage) override; - - bool RecvDecrypted(const uint32_t& aId, - const GMPErr& aErr, - InfallibleTArray<uint8_t>&& aBuffer) override; - - bool RecvBatchedKeyStatusChanged(const nsCString& aSessionId, - InfallibleTArray<GMPKeyInformation>&& aKeyInfos) override; - - bool RecvShutdown() override; - - void ActorDestroy(ActorDestroyReason aWhy) override; - bool Recv__delete__() override; - - bool mIsOpen; - bool mShuttingDown; - bool mActorDestroyed; - RefPtr<GMPContentParent> mPlugin; - uint32_t mPluginId; - GMPDecryptorProxyCallback* mCallback; -#ifdef DEBUG - nsIThread* const mGMPThread; -#endif -}; - -} // namespace gmp -} // namespace mozilla - -#endif // GMPDecryptorChild_h_ diff --git a/dom/media/gmp/GMPDecryptorProxy.h b/dom/media/gmp/GMPDecryptorProxy.h deleted file mode 100644 index 71565c4da..000000000 --- a/dom/media/gmp/GMPDecryptorProxy.h +++ /dev/null @@ -1,61 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#ifndef GMPDecryptorProxy_h_ -#define GMPDecryptorProxy_h_ - -#include "GMPCallbackBase.h" -#include "gmp-decryption.h" -#include "nsString.h" - -namespace mozilla { -class CryptoSample; -} // namespace mozilla - -class GMPDecryptorProxyCallback : public GMPCallbackBase { -public: - virtual ~GMPDecryptorProxyCallback() {} -}; - -class GMPDecryptorProxy { -public: - ~GMPDecryptorProxy() {} - - virtual uint32_t GetPluginId() const = 0; - - virtual nsresult Init(GMPDecryptorProxyCallback* aCallback, - bool aDistinctiveIdentifierRequired, - bool aPersistentStateRequired) = 0; - - virtual void CreateSession(uint32_t aCreateSessionToken, - uint32_t aPromiseId, - const nsCString& aInitDataType, - const nsTArray<uint8_t>& aInitData, - GMPSessionType aSessionType) = 0; - - virtual void LoadSession(uint32_t aPromiseId, - const nsCString& aSessionId) = 0; - - virtual void UpdateSession(uint32_t aPromiseId, - const nsCString& aSessionId, - const nsTArray<uint8_t>& aResponse) = 0; - - virtual void CloseSession(uint32_t aPromiseId, - const nsCString& aSessionId) = 0; - - virtual void RemoveSession(uint32_t aPromiseId, - const nsCString& aSessionId) = 0; - - virtual void SetServerCertificate(uint32_t aPromiseId, - const nsTArray<uint8_t>& aServerCert) = 0; - - virtual void Decrypt(uint32_t aId, - const mozilla::CryptoSample& aCrypto, - const nsTArray<uint8_t>& aBuffer) = 0; - - virtual void Close() = 0; -}; - -#endif // GMPDecryptorProxy_h_ diff --git a/dom/media/gmp/GMPDiskStorage.cpp b/dom/media/gmp/GMPDiskStorage.cpp deleted file mode 100644 index 11f49c8fe..000000000 --- a/dom/media/gmp/GMPDiskStorage.cpp +++ /dev/null @@ -1,499 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#include "plhash.h" -#include "nsDirectoryServiceUtils.h" -#include "nsDirectoryServiceDefs.h" -#include "nsAppDirectoryServiceDefs.h" -#include "GMPParent.h" -#include "gmp-storage.h" -#include "mozilla/Unused.h" -#include "mozilla/EndianUtils.h" -#include "nsClassHashtable.h" -#include "prio.h" -#include "mozIGeckoMediaPluginService.h" -#include "nsContentCID.h" -#include "nsServiceManagerUtils.h" -#include "nsISimpleEnumerator.h" - -namespace mozilla { - -#ifdef LOG -#undef LOG -#endif - -extern LogModule* GetGMPLog(); - -#define LOGD(msg) MOZ_LOG(GetGMPLog(), mozilla::LogLevel::Debug, msg) -#define LOG(level, msg) MOZ_LOG(GetGMPLog(), (level), msg) - -namespace gmp { - -// We store the records for a given GMP as files in the profile dir. -// $profileDir/gmp/$platform/$gmpName/storage/$nodeId/ -static nsresult -GetGMPStorageDir(nsIFile** aTempDir, - const nsString& aGMPName, - const nsCString& aNodeId) -{ - if (NS_WARN_IF(!aTempDir)) { - return NS_ERROR_INVALID_ARG; - } - - nsCOMPtr<mozIGeckoMediaPluginChromeService> mps = - do_GetService("@mozilla.org/gecko-media-plugin-service;1"); - if (NS_WARN_IF(!mps)) { - return NS_ERROR_FAILURE; - } - - nsCOMPtr<nsIFile> tmpFile; - nsresult rv = mps->GetStorageDir(getter_AddRefs(tmpFile)); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - rv = tmpFile->Append(aGMPName); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - rv = tmpFile->Create(nsIFile::DIRECTORY_TYPE, 0700); - if (rv != NS_ERROR_FILE_ALREADY_EXISTS && NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - rv = tmpFile->AppendNative(NS_LITERAL_CSTRING("storage")); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - rv = tmpFile->Create(nsIFile::DIRECTORY_TYPE, 0700); - if (rv != NS_ERROR_FILE_ALREADY_EXISTS && NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - rv = tmpFile->AppendNative(aNodeId); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - rv = tmpFile->Create(nsIFile::DIRECTORY_TYPE, 0700); - if (rv != NS_ERROR_FILE_ALREADY_EXISTS && NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - tmpFile.forget(aTempDir); - - return NS_OK; -} - -// Disk-backed GMP storage. Records are stored in files on disk in -// the profile directory. The record name is a hash of the filename, -// and we resolve hash collisions by just adding 1 to the hash code. -// The format of records on disk is: -// 4 byte, uint32_t $recordNameLength, in little-endian byte order, -// record name (i.e. $recordNameLength bytes, no null terminator) -// record bytes (entire remainder of file) -class GMPDiskStorage : public GMPStorage { -public: - explicit GMPDiskStorage(const nsCString& aNodeId, - const nsString& aGMPName) - : mNodeId(aNodeId) - , mGMPName(aGMPName) - { - } - - ~GMPDiskStorage() { - // Close all open file handles. - for (auto iter = mRecords.ConstIter(); !iter.Done(); iter.Next()) { - Record* record = iter.UserData(); - if (record->mFileDesc) { - PR_Close(record->mFileDesc); - record->mFileDesc = nullptr; - } - } - } - - nsresult Init() { - // Build our index of records on disk. - nsCOMPtr<nsIFile> storageDir; - nsresult rv = GetGMPStorageDir(getter_AddRefs(storageDir), mGMPName, mNodeId); - if (NS_WARN_IF(NS_FAILED(rv))) { - return NS_ERROR_FAILURE; - } - - DirectoryEnumerator iter(storageDir, DirectoryEnumerator::FilesAndDirs); - for (nsCOMPtr<nsIFile> dirEntry; (dirEntry = iter.Next()) != nullptr;) { - PRFileDesc* fd = nullptr; - if (NS_FAILED(dirEntry->OpenNSPRFileDesc(PR_RDONLY, 0, &fd))) { - continue; - } - int32_t recordLength = 0; - nsCString recordName; - nsresult err = ReadRecordMetadata(fd, recordLength, recordName); - PR_Close(fd); - if (NS_FAILED(err)) { - // File is not a valid storage file. Don't index it. Delete the file, - // to make our indexing faster in future. - dirEntry->Remove(false); - continue; - } - - nsAutoString filename; - rv = dirEntry->GetLeafName(filename); - if (NS_FAILED(rv)) { - continue; - } - - mRecords.Put(recordName, new Record(filename, recordName)); - } - - return NS_OK; - } - - GMPErr Open(const nsCString& aRecordName) override - { - MOZ_ASSERT(!IsOpen(aRecordName)); - nsresult rv; - Record* record = nullptr; - if (!mRecords.Get(aRecordName, &record)) { - // New file. - nsAutoString filename; - rv = GetUnusedFilename(aRecordName, filename); - if (NS_WARN_IF(NS_FAILED(rv))) { - return GMPGenericErr; - } - record = new Record(filename, aRecordName); - mRecords.Put(aRecordName, record); - } - - MOZ_ASSERT(record); - if (record->mFileDesc) { - NS_WARNING("Tried to open already open record"); - return GMPRecordInUse; - } - - rv = OpenStorageFile(record->mFilename, ReadWrite, &record->mFileDesc); - if (NS_WARN_IF(NS_FAILED(rv))) { - return GMPGenericErr; - } - - MOZ_ASSERT(IsOpen(aRecordName)); - - return GMPNoErr; - } - - bool IsOpen(const nsCString& aRecordName) const override { - // We are open if we have a record indexed, and it has a valid - // file descriptor. - const Record* record = mRecords.Get(aRecordName); - return record && !!record->mFileDesc; - } - - GMPErr Read(const nsCString& aRecordName, - nsTArray<uint8_t>& aOutBytes) override - { - if (!IsOpen(aRecordName)) { - return GMPClosedErr; - } - - Record* record = nullptr; - mRecords.Get(aRecordName, &record); - MOZ_ASSERT(record && !!record->mFileDesc); // IsOpen() guarantees this. - - // Our error strategy is to report records with invalid contents as - // containing 0 bytes. Zero length records are considered "deleted" by - // the GMPStorage API. - aOutBytes.SetLength(0); - - int32_t recordLength = 0; - nsCString recordName; - nsresult err = ReadRecordMetadata(record->mFileDesc, - recordLength, - recordName); - if (NS_FAILED(err) || recordLength == 0) { - // We failed to read the record metadata. Or the record is 0 length. - // Treat damaged records as empty. - // ReadRecordMetadata() could fail if the GMP opened a new record and - // tried to read it before anything was written to it.. - return GMPNoErr; - } - - if (!aRecordName.Equals(recordName)) { - NS_WARNING("Record file contains some other record's contents!"); - return GMPRecordCorrupted; - } - - // After calling ReadRecordMetadata, we should be ready to read the - // record data. - if (PR_Available(record->mFileDesc) != recordLength) { - NS_WARNING("Record file length mismatch!"); - return GMPRecordCorrupted; - } - - aOutBytes.SetLength(recordLength); - int32_t bytesRead = PR_Read(record->mFileDesc, aOutBytes.Elements(), recordLength); - return (bytesRead == recordLength) ? GMPNoErr : GMPRecordCorrupted; - } - - GMPErr Write(const nsCString& aRecordName, - const nsTArray<uint8_t>& aBytes) override - { - if (!IsOpen(aRecordName)) { - return GMPClosedErr; - } - - Record* record = nullptr; - mRecords.Get(aRecordName, &record); - MOZ_ASSERT(record && !!record->mFileDesc); // IsOpen() guarantees this. - - // Write operations overwrite the entire record. So close it now. - PR_Close(record->mFileDesc); - record->mFileDesc = nullptr; - - // Writing 0 bytes means removing (deleting) the file. - if (aBytes.Length() == 0) { - nsresult rv = RemoveStorageFile(record->mFilename); - if (NS_WARN_IF(NS_FAILED(rv))) { - // Could not delete file -> Continue with trying to erase the contents. - } else { - return GMPNoErr; - } - } - - // Write operations overwrite the entire record. So re-open the file - // in truncate mode, to clear its contents. - if (NS_FAILED(OpenStorageFile(record->mFilename, - Truncate, - &record->mFileDesc))) { - return GMPGenericErr; - } - - // Store the length of the record name followed by the record name - // at the start of the file. - int32_t bytesWritten = 0; - char buf[sizeof(uint32_t)] = {0}; - LittleEndian::writeUint32(buf, aRecordName.Length()); - bytesWritten = PR_Write(record->mFileDesc, buf, MOZ_ARRAY_LENGTH(buf)); - if (bytesWritten != MOZ_ARRAY_LENGTH(buf)) { - NS_WARNING("Failed to write GMPStorage record name length."); - return GMPRecordCorrupted; - } - bytesWritten = PR_Write(record->mFileDesc, - aRecordName.get(), - aRecordName.Length()); - if (bytesWritten != (int32_t)aRecordName.Length()) { - NS_WARNING("Failed to write GMPStorage record name."); - return GMPRecordCorrupted; - } - - bytesWritten = PR_Write(record->mFileDesc, aBytes.Elements(), aBytes.Length()); - if (bytesWritten != (int32_t)aBytes.Length()) { - NS_WARNING("Failed to write GMPStorage record data."); - return GMPRecordCorrupted; - } - - // Try to sync the file to disk, so that in the event of a crash, - // the record is less likely to be corrupted. - PR_Sync(record->mFileDesc); - - return GMPNoErr; - } - - GMPErr GetRecordNames(nsTArray<nsCString>& aOutRecordNames) const override - { - for (auto iter = mRecords.ConstIter(); !iter.Done(); iter.Next()) { - aOutRecordNames.AppendElement(iter.UserData()->mRecordName); - } - return GMPNoErr; - } - - void Close(const nsCString& aRecordName) override - { - Record* record = nullptr; - mRecords.Get(aRecordName, &record); - if (record && !!record->mFileDesc) { - PR_Close(record->mFileDesc); - record->mFileDesc = nullptr; - } - MOZ_ASSERT(!IsOpen(aRecordName)); - } - -private: - - // We store records in a file which is a hash of the record name. - // If there is a hash collision, we just keep adding 1 to the hash - // code, until we find a free slot. - nsresult GetUnusedFilename(const nsACString& aRecordName, - nsString& aOutFilename) - { - nsCOMPtr<nsIFile> storageDir; - nsresult rv = GetGMPStorageDir(getter_AddRefs(storageDir), mGMPName, mNodeId); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - uint64_t recordNameHash = HashString(PromiseFlatCString(aRecordName).get()); - for (int i = 0; i < 1000000; i++) { - nsCOMPtr<nsIFile> f; - rv = storageDir->Clone(getter_AddRefs(f)); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - nsAutoString hashStr; - hashStr.AppendInt(recordNameHash); - rv = f->Append(hashStr); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - bool exists = false; - f->Exists(&exists); - if (!exists) { - // Filename not in use, we can write into this file. - aOutFilename = hashStr; - return NS_OK; - } else { - // Hash collision; just increment the hash name and try that again. - ++recordNameHash; - continue; - } - } - // Somehow, we've managed to completely fail to find a vacant file name. - // Give up. - NS_WARNING("GetUnusedFilename had extreme hash collision!"); - return NS_ERROR_FAILURE; - } - - enum OpenFileMode { ReadWrite, Truncate }; - - nsresult OpenStorageFile(const nsAString& aFileLeafName, - const OpenFileMode aMode, - PRFileDesc** aOutFD) - { - MOZ_ASSERT(aOutFD); - - nsCOMPtr<nsIFile> f; - nsresult rv = GetGMPStorageDir(getter_AddRefs(f), mGMPName, mNodeId); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - f->Append(aFileLeafName); - - auto mode = PR_RDWR | PR_CREATE_FILE; - if (aMode == Truncate) { - mode |= PR_TRUNCATE; - } - - return f->OpenNSPRFileDesc(mode, PR_IRWXU, aOutFD); - } - - nsresult ReadRecordMetadata(PRFileDesc* aFd, - int32_t& aOutRecordLength, - nsACString& aOutRecordName) - { - int32_t offset = PR_Seek(aFd, 0, PR_SEEK_END); - PR_Seek(aFd, 0, PR_SEEK_SET); - - if (offset < 0 || offset > GMP_MAX_RECORD_SIZE) { - // Refuse to read big records, or records where we can't get a length. - return NS_ERROR_FAILURE; - } - const uint32_t fileLength = static_cast<uint32_t>(offset); - - // At the start of the file the length of the record name is stored in a - // uint32_t (little endian byte order) followed by the record name at the - // start of the file. The record name is not null terminated. The remainder - // of the file is the record's data. - - if (fileLength < sizeof(uint32_t)) { - // Record file doesn't have enough contents to store the record name - // length. Fail. - return NS_ERROR_FAILURE; - } - - // Read length, and convert to host byte order. - uint32_t recordNameLength = 0; - char buf[sizeof(recordNameLength)] = { 0 }; - int32_t bytesRead = PR_Read(aFd, &buf, sizeof(recordNameLength)); - recordNameLength = LittleEndian::readUint32(buf); - if (sizeof(recordNameLength) != bytesRead || - recordNameLength == 0 || - recordNameLength + sizeof(recordNameLength) > fileLength || - recordNameLength > GMP_MAX_RECORD_NAME_SIZE) { - // Record file has invalid contents. Fail. - return NS_ERROR_FAILURE; - } - - nsCString recordName; - recordName.SetLength(recordNameLength); - bytesRead = PR_Read(aFd, recordName.BeginWriting(), recordNameLength); - if ((uint32_t)bytesRead != recordNameLength) { - // Read failed. - return NS_ERROR_FAILURE; - } - - MOZ_ASSERT(fileLength >= sizeof(recordNameLength) + recordNameLength); - int32_t recordLength = fileLength - (sizeof(recordNameLength) + recordNameLength); - - aOutRecordLength = recordLength; - aOutRecordName = recordName; - - // Read cursor should be positioned after the record name, before the record contents. - if (PR_Seek(aFd, 0, PR_SEEK_CUR) != (int32_t)(sizeof(recordNameLength) + recordNameLength)) { - NS_WARNING("Read cursor mismatch after ReadRecordMetadata()"); - return NS_ERROR_FAILURE; - } - - return NS_OK; - } - - nsresult RemoveStorageFile(const nsString& aFilename) - { - nsCOMPtr<nsIFile> f; - nsresult rv = GetGMPStorageDir(getter_AddRefs(f), mGMPName, mNodeId); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - rv = f->Append(aFilename); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - return f->Remove(/* bool recursive= */ false); - } - - struct Record { - Record(const nsAString& aFilename, - const nsACString& aRecordName) - : mFilename(aFilename) - , mRecordName(aRecordName) - , mFileDesc(0) - {} - ~Record() { - MOZ_ASSERT(!mFileDesc); - } - nsString mFilename; - nsCString mRecordName; - PRFileDesc* mFileDesc; - }; - - // Hash record name to record data. - nsClassHashtable<nsCStringHashKey, Record> mRecords; - const nsCString mNodeId; - const nsString mGMPName; -}; - -already_AddRefed<GMPStorage> CreateGMPDiskStorage(const nsCString& aNodeId, - const nsString& aGMPName) -{ - RefPtr<GMPDiskStorage> storage(new GMPDiskStorage(aNodeId, aGMPName)); - if (NS_FAILED(storage->Init())) { - NS_WARNING("Failed to initialize on disk GMP storage"); - return nullptr; - } - return storage.forget(); -} - -} // namespace gmp -} // namespace mozilla diff --git a/dom/media/gmp/GMPEncryptedBufferDataImpl.cpp b/dom/media/gmp/GMPEncryptedBufferDataImpl.cpp deleted file mode 100644 index 206d7b42a..000000000 --- a/dom/media/gmp/GMPEncryptedBufferDataImpl.cpp +++ /dev/null @@ -1,132 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#include "GMPEncryptedBufferDataImpl.h" -#include "mozilla/gmp/GMPTypes.h" -#include "MediaData.h" - -namespace mozilla { -namespace gmp { - -GMPEncryptedBufferDataImpl::GMPEncryptedBufferDataImpl(const CryptoSample& aCrypto) - : mKeyId(aCrypto.mKeyId) - , mIV(aCrypto.mIV) - , mClearBytes(aCrypto.mPlainSizes) - , mCipherBytes(aCrypto.mEncryptedSizes) - , mSessionIdList(aCrypto.mSessionIds) -{ -} - -GMPEncryptedBufferDataImpl::GMPEncryptedBufferDataImpl(const GMPDecryptionData& aData) - : mKeyId(aData.mKeyId()) - , mIV(aData.mIV()) - , mClearBytes(aData.mClearBytes()) - , mCipherBytes(aData.mCipherBytes()) - , mSessionIdList(aData.mSessionIds()) -{ - MOZ_ASSERT(mClearBytes.Length() == mCipherBytes.Length()); -} - -GMPEncryptedBufferDataImpl::~GMPEncryptedBufferDataImpl() -{ -} - -void -GMPEncryptedBufferDataImpl::RelinquishData(GMPDecryptionData& aData) -{ - aData.mKeyId() = Move(mKeyId); - aData.mIV() = Move(mIV); - aData.mClearBytes() = Move(mClearBytes); - aData.mCipherBytes() = Move(mCipherBytes); - mSessionIdList.RelinquishData(aData.mSessionIds()); -} - -const uint8_t* -GMPEncryptedBufferDataImpl::KeyId() const -{ - return mKeyId.Elements(); -} - -uint32_t -GMPEncryptedBufferDataImpl::KeyIdSize() const -{ - return mKeyId.Length(); -} - -const uint8_t* -GMPEncryptedBufferDataImpl::IV() const -{ - return mIV.Elements(); -} - -uint32_t -GMPEncryptedBufferDataImpl::IVSize() const -{ - return mIV.Length(); -} - -const uint16_t* -GMPEncryptedBufferDataImpl::ClearBytes() const -{ - return mClearBytes.Elements(); -} - -const uint32_t* -GMPEncryptedBufferDataImpl::CipherBytes() const -{ - return mCipherBytes.Elements(); -} - -const GMPStringList* -GMPEncryptedBufferDataImpl::SessionIds() const -{ - return &mSessionIdList; -} - -uint32_t -GMPEncryptedBufferDataImpl::NumSubsamples() const -{ - MOZ_ASSERT(mClearBytes.Length() == mCipherBytes.Length()); - // Return the min of the two, to ensure there's not chance of array index - // out-of-bounds shenanigans. - return std::min<uint32_t>(mClearBytes.Length(), mCipherBytes.Length()); -} - -GMPStringListImpl::GMPStringListImpl(const nsTArray<nsCString>& aStrings) - : mStrings(aStrings) -{ -} - -uint32_t -GMPStringListImpl::Size() const -{ - return mStrings.Length(); -} - -void -GMPStringListImpl::StringAt(uint32_t aIndex, - const char** aOutString, - uint32_t *aOutLength) const -{ - if (NS_WARN_IF(aIndex >= Size())) { - return; - } - - *aOutString = mStrings[aIndex].BeginReading(); - *aOutLength = mStrings[aIndex].Length(); -} - -void -GMPStringListImpl::RelinquishData(nsTArray<nsCString>& aStrings) -{ - aStrings = Move(mStrings); -} - -GMPStringListImpl::~GMPStringListImpl() -{ -} - -} // namespace gmp -} // namespace mozilla diff --git a/dom/media/gmp/GMPEncryptedBufferDataImpl.h b/dom/media/gmp/GMPEncryptedBufferDataImpl.h deleted file mode 100644 index f0d5728df..000000000 --- a/dom/media/gmp/GMPEncryptedBufferDataImpl.h +++ /dev/null @@ -1,92 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#ifndef GMPEncryptedBufferDataImpl_h_ -#define GMPEncryptedBufferDataImpl_h_ - -#include "gmp-decryption.h" -#include "nsAutoPtr.h" -#include "nsTArray.h" -#include "mozilla/gmp/GMPTypes.h" - -namespace mozilla { -class CryptoSample; - -namespace gmp { - -class GMPStringListImpl : public GMPStringList -{ -public: - explicit GMPStringListImpl(const nsTArray<nsCString>& aStrings); - uint32_t Size() const override; - void StringAt(uint32_t aIndex, - const char** aOutString, uint32_t *aOutLength) const override; - virtual ~GMPStringListImpl() override; - void RelinquishData(nsTArray<nsCString>& aStrings); - -private: - nsTArray<nsCString> mStrings; -}; - -class GMPEncryptedBufferDataImpl : public GMPEncryptedBufferMetadata { -public: - explicit GMPEncryptedBufferDataImpl(const CryptoSample& aCrypto); - explicit GMPEncryptedBufferDataImpl(const GMPDecryptionData& aData); - virtual ~GMPEncryptedBufferDataImpl(); - - void RelinquishData(GMPDecryptionData& aData); - - const uint8_t* KeyId() const override; - uint32_t KeyIdSize() const override; - const uint8_t* IV() const override; - uint32_t IVSize() const override; - uint32_t NumSubsamples() const override; - const uint16_t* ClearBytes() const override; - const uint32_t* CipherBytes() const override; - const GMPStringList* SessionIds() const override; - -private: - nsTArray<uint8_t> mKeyId; - nsTArray<uint8_t> mIV; - nsTArray<uint16_t> mClearBytes; - nsTArray<uint32_t> mCipherBytes; - - GMPStringListImpl mSessionIdList; -}; - -class GMPBufferImpl : public GMPBuffer { -public: - GMPBufferImpl(uint32_t aId, const nsTArray<uint8_t>& aData) - : mId(aId) - , mData(aData) - { - } - uint32_t Id() const override { - return mId; - } - uint8_t* Data() override { - return mData.Elements(); - } - uint32_t Size() const override { - return mData.Length(); - } - void Resize(uint32_t aSize) override { - mData.SetLength(aSize); - } - - // Set metadata object to be freed when this buffer is destroyed. - void SetMetadata(GMPEncryptedBufferDataImpl* aMetadata) { - mMetadata = aMetadata; - } - - uint32_t mId; - nsTArray<uint8_t> mData; - nsAutoPtr<GMPEncryptedBufferDataImpl> mMetadata; -}; - -} // namespace gmp -} // namespace mozilla - -#endif // GMPEncryptedBufferDataImpl_h_ diff --git a/dom/media/gmp/GMPLoader.cpp b/dom/media/gmp/GMPLoader.cpp deleted file mode 100644 index 0bccdd0b1..000000000 --- a/dom/media/gmp/GMPLoader.cpp +++ /dev/null @@ -1,209 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: sw=4 ts=4 et : - * 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/. */ - -#include "GMPLoader.h" -#include <stdio.h> -#include "mozilla/Attributes.h" -#include "gmp-entrypoints.h" -#include "prlink.h" -#include "prenv.h" - -#include <string> - -#ifdef XP_WIN -#include "windows.h" -#endif - -#include "GMPDeviceBinding.h" - -namespace mozilla { -namespace gmp { - -class GMPLoaderImpl : public GMPLoader { -public: - explicit GMPLoaderImpl(SandboxStarter* aStarter) - : mSandboxStarter(aStarter) - , mAdapter(nullptr) - {} - virtual ~GMPLoaderImpl() {} - - bool Load(const char* aUTF8LibPath, - uint32_t aUTF8LibPathLen, - char* aOriginSalt, - uint32_t aOriginSaltLen, - const GMPPlatformAPI* aPlatformAPI, - GMPAdapter* aAdapter) override; - - GMPErr GetAPI(const char* aAPIName, - void* aHostAPI, - void** aPluginAPI, - uint32_t aDecryptorId) override; - - void Shutdown() override; - -private: - SandboxStarter* mSandboxStarter; - UniquePtr<GMPAdapter> mAdapter; -}; - -UniquePtr<GMPLoader> CreateGMPLoader(SandboxStarter* aStarter) { - return MakeUnique<GMPLoaderImpl>(aStarter); -} - -class PassThroughGMPAdapter : public GMPAdapter { -public: - ~PassThroughGMPAdapter() { - // Ensure we're always shutdown, even if caller forgets to call GMPShutdown(). - GMPShutdown(); - } - - void SetAdaptee(PRLibrary* aLib) override - { - mLib = aLib; - } - - GMPErr GMPInit(const GMPPlatformAPI* aPlatformAPI) override - { - if (!mLib) { - return GMPGenericErr; - } - GMPInitFunc initFunc = reinterpret_cast<GMPInitFunc>(PR_FindFunctionSymbol(mLib, "GMPInit")); - if (!initFunc) { - return GMPNotImplementedErr; - } - return initFunc(aPlatformAPI); - } - - GMPErr GMPGetAPI(const char* aAPIName, - void* aHostAPI, - void** aPluginAPI, - uint32_t aDecryptorId) override - { - if (!mLib) { - return GMPGenericErr; - } - GMPGetAPIFunc getapiFunc = reinterpret_cast<GMPGetAPIFunc>(PR_FindFunctionSymbol(mLib, "GMPGetAPI")); - if (!getapiFunc) { - return GMPNotImplementedErr; - } - return getapiFunc(aAPIName, aHostAPI, aPluginAPI); - } - - void GMPShutdown() override - { - if (mLib) { - GMPShutdownFunc shutdownFunc = reinterpret_cast<GMPShutdownFunc>(PR_FindFunctionSymbol(mLib, "GMPShutdown")); - if (shutdownFunc) { - shutdownFunc(); - } - PR_UnloadLibrary(mLib); - mLib = nullptr; - } - } - - void GMPSetNodeId(const char* aNodeId, uint32_t aLength) override - { - if (!mLib) { - return; - } - GMPSetNodeIdFunc setNodeIdFunc = reinterpret_cast<GMPSetNodeIdFunc>(PR_FindFunctionSymbol(mLib, "GMPSetNodeId")); - if (setNodeIdFunc) { - setNodeIdFunc(aNodeId, aLength); - } - } - -private: - PRLibrary* mLib = nullptr; -}; - -bool -GMPLoaderImpl::Load(const char* aUTF8LibPath, - uint32_t aUTF8LibPathLen, - char* aOriginSalt, - uint32_t aOriginSaltLen, - const GMPPlatformAPI* aPlatformAPI, - GMPAdapter* aAdapter) -{ - std::string nodeId; - if (!CalculateGMPDeviceId(aOriginSalt, aOriginSaltLen, nodeId)) { - return false; - } - - // Start the sandbox now that we've generated the device bound node id. - // This must happen after the node id is bound to the device id, as - // generating the device id requires privileges. - if (mSandboxStarter && !mSandboxStarter->Start(aUTF8LibPath)) { - return false; - } - - // Load the GMP. - PRLibSpec libSpec; -#ifdef XP_WIN - int pathLen = MultiByteToWideChar(CP_UTF8, 0, aUTF8LibPath, -1, nullptr, 0); - if (pathLen == 0) { - return false; - } - - auto widePath = MakeUnique<wchar_t[]>(pathLen); - if (MultiByteToWideChar(CP_UTF8, 0, aUTF8LibPath, -1, widePath.get(), pathLen) == 0) { - return false; - } - - libSpec.value.pathname_u = widePath.get(); - libSpec.type = PR_LibSpec_PathnameU; -#else - libSpec.value.pathname = aUTF8LibPath; - libSpec.type = PR_LibSpec_Pathname; -#endif - PRLibrary* lib = PR_LoadLibraryWithFlags(libSpec, 0); - if (!lib) { - return false; - } - - GMPInitFunc initFunc = reinterpret_cast<GMPInitFunc>(PR_FindFunctionSymbol(lib, "GMPInit")); - if ((initFunc && aAdapter) || - (!initFunc && !aAdapter)) { - // Ensure that if we're dealing with a GMP we do *not* use an adapter - // provided from the outside world. This is important as it means we - // don't call code not covered by Adobe's plugin-container voucher - // before we pass the node Id to Adobe's GMP. - return false; - } - - // Note: PassThroughGMPAdapter's code must remain in this file so that it's - // covered by Adobe's plugin-container voucher. - mAdapter.reset((!aAdapter) ? new PassThroughGMPAdapter() : aAdapter); - mAdapter->SetAdaptee(lib); - - if (mAdapter->GMPInit(aPlatformAPI) != GMPNoErr) { - return false; - } - - mAdapter->GMPSetNodeId(nodeId.c_str(), nodeId.size()); - - return true; -} - -GMPErr -GMPLoaderImpl::GetAPI(const char* aAPIName, - void* aHostAPI, - void** aPluginAPI, - uint32_t aDecryptorId) -{ - return mAdapter->GMPGetAPI(aAPIName, aHostAPI, aPluginAPI, aDecryptorId); -} - -void -GMPLoaderImpl::Shutdown() -{ - if (mAdapter) { - mAdapter->GMPShutdown(); - } -} - -} // namespace gmp -} // namespace mozilla - diff --git a/dom/media/gmp/GMPLoader.h b/dom/media/gmp/GMPLoader.h deleted file mode 100644 index 8e6b3cfac..000000000 --- a/dom/media/gmp/GMPLoader.h +++ /dev/null @@ -1,96 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: sw=4 ts=4 et : - * 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/. */ - -#ifndef GMP_LOADER_H__ -#define GMP_LOADER_H__ - -#include <stdint.h> -#include "prlink.h" -#include "gmp-entrypoints.h" -#include "mozilla/UniquePtr.h" - -namespace mozilla { -namespace gmp { - -class SandboxStarter { -public: - virtual ~SandboxStarter() {} - virtual bool Start(const char* aLibPath) = 0; -}; - -// Interface that adapts a plugin to the GMP API. -class GMPAdapter { -public: - virtual ~GMPAdapter() {} - // Sets the adapted to plugin library module. - // Note: the GMPAdapter is responsible for calling PR_UnloadLibrary on aLib - // when it's finished with it. - virtual void SetAdaptee(PRLibrary* aLib) = 0; - - // These are called in place of the corresponding GMP API functions. - virtual GMPErr GMPInit(const GMPPlatformAPI* aPlatformAPI) = 0; - virtual GMPErr GMPGetAPI(const char* aAPIName, - void* aHostAPI, - void** aPluginAPI, - uint32_t aDecryptorId) = 0; - virtual void GMPShutdown() = 0; - virtual void GMPSetNodeId(const char* aNodeId, uint32_t aLength) = 0; -}; - -// Encapsulates generating the device-bound node id, activating the sandbox, -// loading the GMP, and passing the node id to the GMP (in that order). -// -// In Desktop Gecko, the implementation of this lives in plugin-container, -// and is passed into XUL code from on startup. The GMP IPC child protocol actor -// uses this interface to load and retrieve interfaces from the GMPs. -// -// In Desktop Gecko the implementation lives in the plugin-container so that -// it can be covered by DRM vendor's voucher. -// -// On Android the GMPLoader implementation lives in libxul (because for the time -// being GMPLoader relies upon NSPR, which we can't use in plugin-container -// on Android). -// -// There is exactly one GMPLoader per GMP child process, and only one GMP -// per child process (so the GMPLoader only loads one GMP). -// -// Load() takes an optional GMPAdapter which can be used to adapt non-GMPs -// to adhere to the GMP API. -class GMPLoader { -public: - virtual ~GMPLoader() {} - - // Calculates the device-bound node id, then activates the sandbox, - // then loads the GMP library and (if applicable) passes the bound node id - // to the GMP. If aAdapter is non-null, the lib path is assumed to be - // a non-GMP, and the adapter is initialized with the lib and the adapter - // is used to interact with the plugin. - virtual bool Load(const char* aUTF8LibPath, - uint32_t aLibPathLen, - char* aOriginSalt, - uint32_t aOriginSaltLen, - const GMPPlatformAPI* aPlatformAPI, - GMPAdapter* aAdapter = nullptr) = 0; - - // Retrieves an interface pointer from the GMP. - virtual GMPErr GetAPI(const char* aAPIName, - void* aHostAPI, - void** aPluginAPI, - uint32_t aDecryptorId) = 0; - - // Calls the GMPShutdown function exported by the GMP lib, and unloads the - // plugin library. - virtual void Shutdown() = 0; -}; - -// On Desktop, this function resides in plugin-container. -// On Mobile, this function resides in XUL. -UniquePtr<GMPLoader> CreateGMPLoader(SandboxStarter* aStarter); - -} // namespace gmp -} // namespace mozilla - -#endif // GMP_LOADER_H__ diff --git a/dom/media/gmp/GMPMemoryStorage.cpp b/dom/media/gmp/GMPMemoryStorage.cpp deleted file mode 100644 index dc799caa1..000000000 --- a/dom/media/gmp/GMPMemoryStorage.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#include "GMPStorage.h" -#include "nsClassHashtable.h" - -namespace mozilla { -namespace gmp { - -class GMPMemoryStorage : public GMPStorage { -public: - GMPErr Open(const nsCString& aRecordName) override - { - MOZ_ASSERT(!IsOpen(aRecordName)); - - Record* record = nullptr; - if (!mRecords.Get(aRecordName, &record)) { - record = new Record(); - mRecords.Put(aRecordName, record); - } - record->mIsOpen = true; - return GMPNoErr; - } - - bool IsOpen(const nsCString& aRecordName) const override { - const Record* record = mRecords.Get(aRecordName); - if (!record) { - return false; - } - return record->mIsOpen; - } - - GMPErr Read(const nsCString& aRecordName, - nsTArray<uint8_t>& aOutBytes) override - { - const Record* record = mRecords.Get(aRecordName); - if (!record) { - return GMPGenericErr; - } - aOutBytes = record->mData; - return GMPNoErr; - } - - GMPErr Write(const nsCString& aRecordName, - const nsTArray<uint8_t>& aBytes) override - { - Record* record = nullptr; - if (!mRecords.Get(aRecordName, &record)) { - return GMPClosedErr; - } - record->mData = aBytes; - return GMPNoErr; - } - - GMPErr GetRecordNames(nsTArray<nsCString>& aOutRecordNames) const override - { - for (auto iter = mRecords.ConstIter(); !iter.Done(); iter.Next()) { - aOutRecordNames.AppendElement(iter.Key()); - } - return GMPNoErr; - } - - void Close(const nsCString& aRecordName) override - { - Record* record = nullptr; - if (!mRecords.Get(aRecordName, &record)) { - return; - } - if (!record->mData.Length()) { - // Record is empty, delete. - mRecords.Remove(aRecordName); - } else { - record->mIsOpen = false; - } - } - -private: - - struct Record { - nsTArray<uint8_t> mData; - bool mIsOpen = false; - }; - - nsClassHashtable<nsCStringHashKey, Record> mRecords; -}; - -already_AddRefed<GMPStorage> CreateGMPMemoryStorage() -{ - return RefPtr<GMPStorage>(new GMPMemoryStorage()).forget(); -} - -} // namespace gmp -} // namespace mozilla diff --git a/dom/media/gmp/GMPMessageUtils.h b/dom/media/gmp/GMPMessageUtils.h deleted file mode 100644 index 13f6127f3..000000000 --- a/dom/media/gmp/GMPMessageUtils.h +++ /dev/null @@ -1,253 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#ifndef GMPMessageUtils_h_ -#define GMPMessageUtils_h_ - -#include "gmp-video-codec.h" -#include "gmp-video-frame-encoded.h" -#include "gmp-audio-codec.h" -#include "gmp-decryption.h" - -namespace IPC { - -template <> -struct ParamTraits<GMPErr> -: public ContiguousEnumSerializer<GMPErr, - GMPNoErr, - GMPLastErr> -{}; - -struct GMPDomExceptionValidator { - static bool IsLegalValue(GMPDOMException aValue) { - switch (aValue) { - case kGMPNoModificationAllowedError: - case kGMPNotFoundError: - case kGMPNotSupportedError: - case kGMPInvalidStateError: - case kGMPSyntaxError: - case kGMPInvalidModificationError: - case kGMPInvalidAccessError: - case kGMPSecurityError: - case kGMPAbortError: - case kGMPQuotaExceededError: - case kGMPTimeoutError: - case kGMPTypeError: - return true; - default: - return false; - } - } -}; - -template <> -struct ParamTraits<GMPVideoFrameType> -: public ContiguousEnumSerializer<GMPVideoFrameType, - kGMPKeyFrame, - kGMPVideoFrameInvalid> -{}; - -template<> -struct ParamTraits<GMPDOMException> -: public EnumSerializer<GMPDOMException, GMPDomExceptionValidator> -{}; - -template <> -struct ParamTraits<GMPSessionMessageType> -: public ContiguousEnumSerializer<GMPSessionMessageType, - kGMPLicenseRequest, - kGMPMessageInvalid> -{}; - -template <> -struct ParamTraits<GMPMediaKeyStatus> -: public ContiguousEnumSerializer<GMPMediaKeyStatus, - kGMPUsable, - kGMPMediaKeyStatusInvalid> -{}; - -template <> -struct ParamTraits<GMPSessionType> -: public ContiguousEnumSerializer<GMPSessionType, - kGMPTemporySession, - kGMPSessionInvalid> -{}; - -template <> -struct ParamTraits<GMPAudioCodecType> -: public ContiguousEnumSerializer<GMPAudioCodecType, - kGMPAudioCodecAAC, - kGMPAudioCodecInvalid> -{}; - -template <> -struct ParamTraits<GMPVideoCodecComplexity> -: public ContiguousEnumSerializer<GMPVideoCodecComplexity, - kGMPComplexityNormal, - kGMPComplexityInvalid> -{}; - -template <> -struct ParamTraits<GMPVP8ResilienceMode> -: public ContiguousEnumSerializer<GMPVP8ResilienceMode, - kResilienceOff, - kResilienceInvalid> -{}; - -template <> -struct ParamTraits<GMPVideoCodecType> -: public ContiguousEnumSerializer<GMPVideoCodecType, - kGMPVideoCodecVP8, - kGMPVideoCodecInvalid> -{}; - -template <> -struct ParamTraits<GMPVideoCodecMode> -: public ContiguousEnumSerializer<GMPVideoCodecMode, - kGMPRealtimeVideo, - kGMPCodecModeInvalid> -{}; - -template <> -struct ParamTraits<GMPBufferType> -: public ContiguousEnumSerializer<GMPBufferType, - GMP_BufferSingle, - GMP_BufferInvalid> -{}; - -template <> -struct ParamTraits<GMPSimulcastStream> -{ - typedef GMPSimulcastStream paramType; - - static void Write(Message* aMsg, const paramType& aParam) - { - WriteParam(aMsg, aParam.mWidth); - WriteParam(aMsg, aParam.mHeight); - WriteParam(aMsg, aParam.mNumberOfTemporalLayers); - WriteParam(aMsg, aParam.mMaxBitrate); - WriteParam(aMsg, aParam.mTargetBitrate); - WriteParam(aMsg, aParam.mMinBitrate); - WriteParam(aMsg, aParam.mQPMax); - } - - static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult) - { - if (ReadParam(aMsg, aIter, &(aResult->mWidth)) && - ReadParam(aMsg, aIter, &(aResult->mHeight)) && - ReadParam(aMsg, aIter, &(aResult->mNumberOfTemporalLayers)) && - ReadParam(aMsg, aIter, &(aResult->mMaxBitrate)) && - ReadParam(aMsg, aIter, &(aResult->mTargetBitrate)) && - ReadParam(aMsg, aIter, &(aResult->mMinBitrate)) && - ReadParam(aMsg, aIter, &(aResult->mQPMax))) { - return true; - } - return false; - } - - static void Log(const paramType& aParam, std::wstring* aLog) - { - aLog->append(StringPrintf(L"[%u, %u, %u, %u, %u, %u, %u]", aParam.mWidth, aParam.mHeight, - aParam.mNumberOfTemporalLayers, aParam.mMaxBitrate, - aParam.mTargetBitrate, aParam.mMinBitrate, aParam.mQPMax)); - } -}; - -template <> -struct ParamTraits<GMPVideoCodec> -{ - typedef GMPVideoCodec paramType; - - static void Write(Message* aMsg, const paramType& aParam) - { - WriteParam(aMsg, aParam.mGMPApiVersion); - WriteParam(aMsg, aParam.mCodecType); - WriteParam(aMsg, static_cast<const nsCString&>(nsDependentCString(aParam.mPLName))); - WriteParam(aMsg, aParam.mPLType); - WriteParam(aMsg, aParam.mWidth); - WriteParam(aMsg, aParam.mHeight); - WriteParam(aMsg, aParam.mStartBitrate); - WriteParam(aMsg, aParam.mMaxBitrate); - WriteParam(aMsg, aParam.mMinBitrate); - WriteParam(aMsg, aParam.mMaxFramerate); - WriteParam(aMsg, aParam.mFrameDroppingOn); - WriteParam(aMsg, aParam.mKeyFrameInterval); - WriteParam(aMsg, aParam.mQPMax); - WriteParam(aMsg, aParam.mNumberOfSimulcastStreams); - for (uint32_t i = 0; i < aParam.mNumberOfSimulcastStreams; i++) { - WriteParam(aMsg, aParam.mSimulcastStream[i]); - } - WriteParam(aMsg, aParam.mMode); - } - - static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult) - { - // NOTE: make sure this matches any versions supported - if (!ReadParam(aMsg, aIter, &(aResult->mGMPApiVersion)) || - aResult->mGMPApiVersion != kGMPVersion33) { - return false; - } - if (!ReadParam(aMsg, aIter, &(aResult->mCodecType))) { - return false; - } - - nsAutoCString plName; - if (!ReadParam(aMsg, aIter, &plName) || - plName.Length() > kGMPPayloadNameSize - 1) { - return false; - } - memcpy(aResult->mPLName, plName.get(), plName.Length()); - memset(aResult->mPLName + plName.Length(), 0, kGMPPayloadNameSize - plName.Length()); - - if (!ReadParam(aMsg, aIter, &(aResult->mPLType)) || - !ReadParam(aMsg, aIter, &(aResult->mWidth)) || - !ReadParam(aMsg, aIter, &(aResult->mHeight)) || - !ReadParam(aMsg, aIter, &(aResult->mStartBitrate)) || - !ReadParam(aMsg, aIter, &(aResult->mMaxBitrate)) || - !ReadParam(aMsg, aIter, &(aResult->mMinBitrate)) || - !ReadParam(aMsg, aIter, &(aResult->mMaxFramerate)) || - !ReadParam(aMsg, aIter, &(aResult->mFrameDroppingOn)) || - !ReadParam(aMsg, aIter, &(aResult->mKeyFrameInterval))) { - return false; - } - - if (!ReadParam(aMsg, aIter, &(aResult->mQPMax)) || - !ReadParam(aMsg, aIter, &(aResult->mNumberOfSimulcastStreams))) { - return false; - } - - if (aResult->mNumberOfSimulcastStreams > kGMPMaxSimulcastStreams) { - return false; - } - - for (uint32_t i = 0; i < aResult->mNumberOfSimulcastStreams; i++) { - if (!ReadParam(aMsg, aIter, &(aResult->mSimulcastStream[i]))) { - return false; - } - } - - if (!ReadParam(aMsg, aIter, &(aResult->mMode))) { - return false; - } - - return true; - } - - static void Log(const paramType& aParam, std::wstring* aLog) - { - const char* codecName = nullptr; - if (aParam.mCodecType == kGMPVideoCodecVP8) { - codecName = "VP8"; - } - aLog->append(StringPrintf(L"[%s, %u, %u]", - codecName, - aParam.mWidth, - aParam.mHeight)); - } -}; - -} // namespace IPC - -#endif // GMPMessageUtils_h_ diff --git a/dom/media/gmp/GMPParent.cpp b/dom/media/gmp/GMPParent.cpp deleted file mode 100644 index c4a7a84a0..000000000 --- a/dom/media/gmp/GMPParent.cpp +++ /dev/null @@ -1,926 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#include "GMPParent.h" -#include "mozilla/Logging.h" -#include "nsComponentManagerUtils.h" -#include "nsComponentManagerUtils.h" -#include "nsThreadUtils.h" -#include "nsIRunnable.h" -#include "nsIWritablePropertyBag2.h" -#include "mozIGeckoMediaPluginService.h" -#include "mozilla/ipc/GeckoChildProcessHost.h" -#include "mozilla/SSE.h" -#include "mozilla/SyncRunnable.h" -#include "mozilla/Unused.h" -#include "nsIObserverService.h" -#include "GMPTimerParent.h" -#include "runnable_utils.h" -#include "GMPContentParent.h" -#include "MediaPrefs.h" -#include "VideoUtils.h" - -using mozilla::ipc::GeckoChildProcessHost; - -#ifdef XP_WIN -#include "WMFDecoderModule.h" -#endif - -namespace mozilla { - -#undef LOG -#undef LOGD - -extern LogModule* GetGMPLog(); -#define LOG(level, x, ...) MOZ_LOG(GetGMPLog(), (level), (x, ##__VA_ARGS__)) -#define LOGD(x, ...) LOG(mozilla::LogLevel::Debug, "GMPParent[%p|childPid=%d] " x, this, mChildPid, ##__VA_ARGS__) - -#ifdef __CLASS__ -#undef __CLASS__ -#endif -#define __CLASS__ "GMPParent" - -namespace gmp { - -GMPParent::GMPParent() - : mState(GMPStateNotLoaded) - , mProcess(nullptr) - , mDeleteProcessOnlyOnUnload(false) - , mAbnormalShutdownInProgress(false) - , mIsBlockingDeletion(false) - , mCanDecrypt(false) - , mGMPContentChildCount(0) - , mAsyncShutdownRequired(false) - , mAsyncShutdownInProgress(false) - , mChildPid(0) - , mHoldingSelfRef(false) -{ - mPluginId = GeckoChildProcessHost::GetUniqueID(); - LOGD("GMPParent ctor id=%u", mPluginId); -} - -GMPParent::~GMPParent() -{ - LOGD("GMPParent dtor id=%u", mPluginId); - MOZ_ASSERT(!mProcess); -} - -nsresult -GMPParent::CloneFrom(const GMPParent* aOther) -{ - MOZ_ASSERT(GMPThread() == NS_GetCurrentThread()); - MOZ_ASSERT(aOther->mDirectory && aOther->mService, "null plugin directory"); - - mService = aOther->mService; - mDirectory = aOther->mDirectory; - mName = aOther->mName; - mVersion = aOther->mVersion; - mDescription = aOther->mDescription; - mDisplayName = aOther->mDisplayName; -#ifdef XP_WIN - mLibs = aOther->mLibs; -#endif - for (const GMPCapability& cap : aOther->mCapabilities) { - mCapabilities.AppendElement(cap); - } - mAdapter = aOther->mAdapter; - return NS_OK; -} - -RefPtr<GenericPromise> -GMPParent::Init(GeckoMediaPluginServiceParent* aService, nsIFile* aPluginDir) -{ - MOZ_ASSERT(aPluginDir); - MOZ_ASSERT(aService); - MOZ_ASSERT(GMPThread() == NS_GetCurrentThread()); - - mService = aService; - mDirectory = aPluginDir; - - // aPluginDir is <profile-dir>/<gmp-plugin-id>/<version> - // where <gmp-plugin-id> should be gmp-gmpopenh264 - nsCOMPtr<nsIFile> parent; - nsresult rv = aPluginDir->GetParent(getter_AddRefs(parent)); - if (NS_FAILED(rv)) { - return GenericPromise::CreateAndReject(rv, __func__); - } - nsAutoString parentLeafName; - rv = parent->GetLeafName(parentLeafName); - if (NS_FAILED(rv)) { - return GenericPromise::CreateAndReject(rv, __func__); - } - LOGD("%s: for %s", __FUNCTION__, NS_LossyConvertUTF16toASCII(parentLeafName).get()); - - MOZ_ASSERT(parentLeafName.Length() > 4); - mName = Substring(parentLeafName, 4); - - return ReadGMPMetaData(); -} - -void -GMPParent::Crash() -{ - if (mState != GMPStateNotLoaded) { - Unused << SendCrashPluginNow(); - } -} - -nsresult -GMPParent::LoadProcess() -{ - MOZ_ASSERT(mDirectory, "Plugin directory cannot be NULL!"); - MOZ_ASSERT(GMPThread() == NS_GetCurrentThread()); - MOZ_ASSERT(mState == GMPStateNotLoaded); - - nsAutoString path; - if (NS_FAILED(mDirectory->GetPath(path))) { - return NS_ERROR_FAILURE; - } - LOGD("%s: for %s", __FUNCTION__, NS_ConvertUTF16toUTF8(path).get()); - - if (!mProcess) { - mProcess = new GMPProcessParent(NS_ConvertUTF16toUTF8(path).get()); - if (!mProcess->Launch(30 * 1000)) { - LOGD("%s: Failed to launch new child process", __FUNCTION__); - mProcess->Delete(); - mProcess = nullptr; - return NS_ERROR_FAILURE; - } - - mChildPid = base::GetProcId(mProcess->GetChildProcessHandle()); - LOGD("%s: Launched new child process", __FUNCTION__); - - bool opened = Open(mProcess->GetChannel(), - base::GetProcId(mProcess->GetChildProcessHandle())); - if (!opened) { - LOGD("%s: Failed to open channel to new child process", __FUNCTION__); - mProcess->Delete(); - mProcess = nullptr; - return NS_ERROR_FAILURE; - } - LOGD("%s: Opened channel to new child process", __FUNCTION__); - - bool ok = SendSetNodeId(mNodeId); - if (!ok) { - LOGD("%s: Failed to send node id to child process", __FUNCTION__); - return NS_ERROR_FAILURE; - } - LOGD("%s: Sent node id to child process", __FUNCTION__); - -#ifdef XP_WIN - if (!mLibs.IsEmpty()) { - bool ok = SendPreloadLibs(mLibs); - if (!ok) { - LOGD("%s: Failed to send preload-libs to child process", __FUNCTION__); - return NS_ERROR_FAILURE; - } - LOGD("%s: Sent preload-libs ('%s') to child process", __FUNCTION__, mLibs.get()); - } -#endif - - // Intr call to block initialization on plugin load. - ok = CallStartPlugin(mAdapter); - if (!ok) { - LOGD("%s: Failed to send start to child process", __FUNCTION__); - return NS_ERROR_FAILURE; - } - LOGD("%s: Sent StartPlugin to child process", __FUNCTION__); - } - - mState = GMPStateLoaded; - - // Hold a self ref while the child process is alive. This ensures that - // during shutdown the GMPParent stays alive long enough to - // terminate the child process. - MOZ_ASSERT(!mHoldingSelfRef); - mHoldingSelfRef = true; - AddRef(); - - return NS_OK; -} - -// static -void -GMPParent::AbortWaitingForGMPAsyncShutdown(nsITimer* aTimer, void* aClosure) -{ - NS_WARNING("Timed out waiting for GMP async shutdown!"); - GMPParent* parent = reinterpret_cast<GMPParent*>(aClosure); - MOZ_ASSERT(parent->mService); - parent->mService->AsyncShutdownComplete(parent); -} - -nsresult -GMPParent::EnsureAsyncShutdownTimeoutSet() -{ - MOZ_ASSERT(mAsyncShutdownRequired); - if (mAsyncShutdownTimeout) { - return NS_OK; - } - - nsresult rv; - mAsyncShutdownTimeout = do_CreateInstance(NS_TIMER_CONTRACTID, &rv); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - // Set timer to abort waiting for plugin to shutdown if it takes - // too long. - rv = mAsyncShutdownTimeout->SetTarget(mGMPThread); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - int32_t timeout = MediaPrefs::GMPAsyncShutdownTimeout(); - RefPtr<GeckoMediaPluginServiceParent> service = - GeckoMediaPluginServiceParent::GetSingleton(); - if (service) { - timeout = service->AsyncShutdownTimeoutMs(); - } - rv = mAsyncShutdownTimeout->InitWithFuncCallback( - &AbortWaitingForGMPAsyncShutdown, this, timeout, - nsITimer::TYPE_ONE_SHOT); - Unused << NS_WARN_IF(NS_FAILED(rv)); - return rv; -} - -bool -GMPParent::RecvPGMPContentChildDestroyed() -{ - --mGMPContentChildCount; - if (!IsUsed()) { - CloseIfUnused(); - } - return true; -} - -void -GMPParent::CloseIfUnused() -{ - MOZ_ASSERT(GMPThread() == NS_GetCurrentThread()); - LOGD("%s: mAsyncShutdownRequired=%d", __FUNCTION__, mAsyncShutdownRequired); - - if ((mDeleteProcessOnlyOnUnload || - mState == GMPStateLoaded || - mState == GMPStateUnloading) && - !IsUsed()) { - // Ensure all timers are killed. - for (uint32_t i = mTimers.Length(); i > 0; i--) { - mTimers[i - 1]->Shutdown(); - } - - if (mAsyncShutdownRequired) { - if (!mAsyncShutdownInProgress) { - LOGD("%s: sending async shutdown notification", __FUNCTION__); - mAsyncShutdownInProgress = true; - if (!SendBeginAsyncShutdown()) { - AbortAsyncShutdown(); - } else if (NS_FAILED(EnsureAsyncShutdownTimeoutSet())) { - AbortAsyncShutdown(); - } - } - } else { - // No async-shutdown, kill async-shutdown timer started in CloseActive(). - AbortAsyncShutdown(); - // Any async shutdown must be complete. Shutdown GMPStorage. - for (size_t i = mStorage.Length(); i > 0; i--) { - mStorage[i - 1]->Shutdown(); - } - Shutdown(); - } - } -} - -void -GMPParent::AbortAsyncShutdown() -{ - MOZ_ASSERT(GMPThread() == NS_GetCurrentThread()); - LOGD("%s", __FUNCTION__); - - if (mAsyncShutdownTimeout) { - mAsyncShutdownTimeout->Cancel(); - mAsyncShutdownTimeout = nullptr; - } - - if (!mAsyncShutdownRequired || !mAsyncShutdownInProgress) { - return; - } - - RefPtr<GMPParent> kungFuDeathGrip(this); - mService->AsyncShutdownComplete(this); - mAsyncShutdownRequired = false; - mAsyncShutdownInProgress = false; - CloseIfUnused(); -} - -void -GMPParent::CloseActive(bool aDieWhenUnloaded) -{ - LOGD("%s: state %d", __FUNCTION__, mState); - MOZ_ASSERT(GMPThread() == NS_GetCurrentThread()); - - if (aDieWhenUnloaded) { - mDeleteProcessOnlyOnUnload = true; // don't allow this to go back... - } - if (mState == GMPStateLoaded) { - mState = GMPStateUnloading; - } - if (mState != GMPStateNotLoaded && IsUsed()) { - if (!SendCloseActive()) { - AbortAsyncShutdown(); - } else if (IsUsed()) { - // We're expecting RecvPGMPContentChildDestroyed's -> Start async-shutdown timer now if needed. - if (mAsyncShutdownRequired && NS_FAILED(EnsureAsyncShutdownTimeoutSet())) { - AbortAsyncShutdown(); - } - } else { - // We're not expecting any RecvPGMPContentChildDestroyed - // -> Call CloseIfUnused() now, to run async shutdown if necessary. - // Note that CloseIfUnused() may have already been called from a prior - // RecvPGMPContentChildDestroyed(), however depending on the state at - // that time, it might not have proceeded with shutdown; And calling it - // again after shutdown is fine because after the first one we'll be in - // GMPStateNotLoaded. - CloseIfUnused(); - } - } -} - -void -GMPParent::MarkForDeletion() -{ - mDeleteProcessOnlyOnUnload = true; - mIsBlockingDeletion = true; -} - -bool -GMPParent::IsMarkedForDeletion() -{ - return mIsBlockingDeletion; -} - -void -GMPParent::Shutdown() -{ - LOGD("%s", __FUNCTION__); - MOZ_ASSERT(GMPThread() == NS_GetCurrentThread()); - - MOZ_ASSERT(!mAsyncShutdownTimeout, "Should have canceled shutdown timeout"); - - if (mAbnormalShutdownInProgress) { - return; - } - - MOZ_ASSERT(!IsUsed()); - if (mState == GMPStateNotLoaded || mState == GMPStateClosing) { - return; - } - - RefPtr<GMPParent> self(this); - DeleteProcess(); - - // XXX Get rid of mDeleteProcessOnlyOnUnload and this code when - // Bug 1043671 is fixed - if (!mDeleteProcessOnlyOnUnload) { - // Destroy ourselves and rise from the fire to save memory - mService->ReAddOnGMPThread(self); - } // else we've been asked to die and stay dead - MOZ_ASSERT(mState == GMPStateNotLoaded); -} - -class NotifyGMPShutdownTask : public Runnable { -public: - explicit NotifyGMPShutdownTask(const nsAString& aNodeId) - : mNodeId(aNodeId) - { - } - NS_IMETHOD Run() override { - MOZ_ASSERT(NS_IsMainThread()); - nsCOMPtr<nsIObserverService> obsService = mozilla::services::GetObserverService(); - MOZ_ASSERT(obsService); - if (obsService) { - obsService->NotifyObservers(nullptr, "gmp-shutdown", mNodeId.get()); - } - return NS_OK; - } - nsString mNodeId; -}; - -void -GMPParent::ChildTerminated() -{ - RefPtr<GMPParent> self(this); - nsIThread* gmpThread = GMPThread(); - - if (!gmpThread) { - // Bug 1163239 - this can happen on shutdown. - // PluginTerminated removes the GMP from the GMPService. - // On shutdown we can have this case where it is already been - // removed so there is no harm in not trying to remove it again. - LOGD("%s::%s: GMPThread() returned nullptr.", __CLASS__, __FUNCTION__); - } else { - gmpThread->Dispatch(NewRunnableMethod<RefPtr<GMPParent>>( - mService, - &GeckoMediaPluginServiceParent::PluginTerminated, - self), - NS_DISPATCH_NORMAL); - } -} - -void -GMPParent::DeleteProcess() -{ - LOGD("%s", __FUNCTION__); - - if (mState != GMPStateClosing) { - // Don't Close() twice! - // Probably remove when bug 1043671 is resolved - mState = GMPStateClosing; - Close(); - } - mProcess->Delete(NewRunnableMethod(this, &GMPParent::ChildTerminated)); - LOGD("%s: Shut down process", __FUNCTION__); - mProcess = nullptr; - mState = GMPStateNotLoaded; - - NS_DispatchToMainThread( - new NotifyGMPShutdownTask(NS_ConvertUTF8toUTF16(mNodeId)), - NS_DISPATCH_NORMAL); - - if (mHoldingSelfRef) { - Release(); - mHoldingSelfRef = false; - } -} - -GMPState -GMPParent::State() const -{ - return mState; -} - -// Not changing to use mService since we'll be removing it -nsIThread* -GMPParent::GMPThread() -{ - if (!mGMPThread) { - nsCOMPtr<mozIGeckoMediaPluginService> mps = do_GetService("@mozilla.org/gecko-media-plugin-service;1"); - MOZ_ASSERT(mps); - if (!mps) { - return nullptr; - } - // Not really safe if we just grab to the mGMPThread, as we don't know - // what thread we're running on and other threads may be trying to - // access this without locks! However, debug only, and primary failure - // mode outside of compiler-helped TSAN is a leak. But better would be - // to use swap() under a lock. - mps->GetThread(getter_AddRefs(mGMPThread)); - MOZ_ASSERT(mGMPThread); - } - - return mGMPThread; -} - -/* static */ -bool -GMPCapability::Supports(const nsTArray<GMPCapability>& aCapabilities, - const nsCString& aAPI, - const nsTArray<nsCString>& aTags) -{ - for (const nsCString& tag : aTags) { - if (!GMPCapability::Supports(aCapabilities, aAPI, tag)) { - return false; - } - } - return true; -} - -/* static */ -bool -GMPCapability::Supports(const nsTArray<GMPCapability>& aCapabilities, - const nsCString& aAPI, - const nsCString& aTag) -{ - for (const GMPCapability& capabilities : aCapabilities) { - if (!capabilities.mAPIName.Equals(aAPI)) { - continue; - } - for (const nsCString& tag : capabilities.mAPITags) { - if (tag.Equals(aTag)) { -#ifdef XP_WIN - // Clearkey on Windows advertises that it can decode in its GMP info - // file, but uses Windows Media Foundation to decode. That's not present - // on Windows N and KN variants without certain services packs. - if (tag.Equals(kEMEKeySystemClearkey)) { - if (capabilities.mAPIName.EqualsLiteral(GMP_API_VIDEO_DECODER)) { - if (!WMFDecoderModule::HasH264()) { - continue; - } - } else if (capabilities.mAPIName.EqualsLiteral(GMP_API_AUDIO_DECODER)) { - if (!WMFDecoderModule::HasAAC()) { - continue; - } - } - } -#endif - return true; - } - } - } - return false; -} - -bool -GMPParent::EnsureProcessLoaded() -{ - if (mState == GMPStateLoaded) { - return true; - } - if (mState == GMPStateClosing || - mState == GMPStateUnloading) { - return false; - } - - nsresult rv = LoadProcess(); - - return NS_SUCCEEDED(rv); -} - -void -GMPParent::ActorDestroy(ActorDestroyReason aWhy) -{ - LOGD("%s: (%d)", __FUNCTION__, (int)aWhy); - // warn us off trying to close again - mState = GMPStateClosing; - mAbnormalShutdownInProgress = true; - CloseActive(false); - - // Normal Shutdown() will delete the process on unwind. - if (AbnormalShutdown == aWhy) { - RefPtr<GMPParent> self(this); - if (mAsyncShutdownRequired) { - mService->AsyncShutdownComplete(this); - mAsyncShutdownRequired = false; - } - // Must not call Close() again in DeleteProcess(), as we'll recurse - // infinitely if we do. - MOZ_ASSERT(mState == GMPStateClosing); - DeleteProcess(); - // Note: final destruction will be Dispatched to ourself - mService->ReAddOnGMPThread(self); - } -} - -PGMPStorageParent* -GMPParent::AllocPGMPStorageParent() -{ - GMPStorageParent* p = new GMPStorageParent(mNodeId, this); - mStorage.AppendElement(p); // Addrefs, released in DeallocPGMPStorageParent. - return p; -} - -bool -GMPParent::DeallocPGMPStorageParent(PGMPStorageParent* aActor) -{ - GMPStorageParent* p = static_cast<GMPStorageParent*>(aActor); - p->Shutdown(); - mStorage.RemoveElement(p); - return true; -} - -bool -GMPParent::RecvPGMPStorageConstructor(PGMPStorageParent* aActor) -{ - GMPStorageParent* p = (GMPStorageParent*)aActor; - if (NS_WARN_IF(NS_FAILED(p->Init()))) { - return false; - } - return true; -} - -bool -GMPParent::RecvPGMPTimerConstructor(PGMPTimerParent* actor) -{ - return true; -} - -PGMPTimerParent* -GMPParent::AllocPGMPTimerParent() -{ - GMPTimerParent* p = new GMPTimerParent(GMPThread()); - mTimers.AppendElement(p); // Released in DeallocPGMPTimerParent, or on shutdown. - return p; -} - -bool -GMPParent::DeallocPGMPTimerParent(PGMPTimerParent* aActor) -{ - GMPTimerParent* p = static_cast<GMPTimerParent*>(aActor); - p->Shutdown(); - mTimers.RemoveElement(p); - return true; -} - -bool -ReadInfoField(GMPInfoFileParser& aParser, const nsCString& aKey, nsACString& aOutValue) -{ - if (!aParser.Contains(aKey) || aParser.Get(aKey).IsEmpty()) { - return false; - } - aOutValue = aParser.Get(aKey); - return true; -} - -RefPtr<GenericPromise> -GMPParent::ReadGMPMetaData() -{ - MOZ_ASSERT(mDirectory, "Plugin directory cannot be NULL!"); - MOZ_ASSERT(!mName.IsEmpty(), "Plugin mName cannot be empty!"); - - nsCOMPtr<nsIFile> infoFile; - nsresult rv = mDirectory->Clone(getter_AddRefs(infoFile)); - if (NS_FAILED(rv)) { - return GenericPromise::CreateAndReject(rv, __func__); - } - infoFile->AppendRelativePath(mName + NS_LITERAL_STRING(".info")); - - if (FileExists(infoFile)) { - return ReadGMPInfoFile(infoFile); - } - - return GenericPromise::CreateAndReject(NS_ERROR_FAILURE, __func__); -} - -RefPtr<GenericPromise> -GMPParent::ReadGMPInfoFile(nsIFile* aFile) -{ - GMPInfoFileParser parser; - if (!parser.Init(aFile)) { - return GenericPromise::CreateAndReject(NS_ERROR_FAILURE, __func__); - } - - nsAutoCString apis; - if (!ReadInfoField(parser, NS_LITERAL_CSTRING("name"), mDisplayName) || - !ReadInfoField(parser, NS_LITERAL_CSTRING("description"), mDescription) || - !ReadInfoField(parser, NS_LITERAL_CSTRING("version"), mVersion) || - !ReadInfoField(parser, NS_LITERAL_CSTRING("apis"), apis)) { - return GenericPromise::CreateAndReject(NS_ERROR_FAILURE, __func__); - } - -#ifdef XP_WIN - // "Libraries" field is optional. - ReadInfoField(parser, NS_LITERAL_CSTRING("libraries"), mLibs); -#endif - - nsTArray<nsCString> apiTokens; - SplitAt(", ", apis, apiTokens); - for (nsCString api : apiTokens) { - int32_t tagsStart = api.FindChar('['); - if (tagsStart == 0) { - // Not allowed to be the first character. - // API name must be at least one character. - continue; - } - - GMPCapability cap; - if (tagsStart == -1) { - // No tags. - cap.mAPIName.Assign(api); - } else { - auto tagsEnd = api.FindChar(']'); - if (tagsEnd == -1 || tagsEnd < tagsStart) { - // Invalid syntax, skip whole capability. - continue; - } - - cap.mAPIName.Assign(Substring(api, 0, tagsStart)); - - if ((tagsEnd - tagsStart) > 1) { - const nsDependentCSubstring ts(Substring(api, tagsStart + 1, tagsEnd - tagsStart - 1)); - nsTArray<nsCString> tagTokens; - SplitAt(":", ts, tagTokens); - for (nsCString tag : tagTokens) { - cap.mAPITags.AppendElement(tag); - } - } - } - - // We support the current GMPDecryptor version, and the previous. - // We Adapt the previous to the current in the GMPContentChild. - if (cap.mAPIName.EqualsLiteral(GMP_API_DECRYPTOR_BACKWARDS_COMPAT)) { - cap.mAPIName.AssignLiteral(GMP_API_DECRYPTOR); - } - - if (cap.mAPIName.EqualsLiteral(GMP_API_DECRYPTOR)) { - mCanDecrypt = true; - } - - mCapabilities.AppendElement(Move(cap)); - } - - if (mCapabilities.IsEmpty()) { - return GenericPromise::CreateAndReject(NS_ERROR_FAILURE, __func__); - } - - return GenericPromise::CreateAndResolve(true, __func__); -} - -RefPtr<GenericPromise> -GMPParent::ReadChromiumManifestFile(nsIFile* aFile) -{ - nsAutoCString json; - if (!ReadIntoString(aFile, json, 5 * 1024)) { - return GenericPromise::CreateAndReject(NS_ERROR_FAILURE, __func__); - } - - // DOM JSON parsing needs to run on the main thread. - return InvokeAsync(AbstractThread::MainThread(), this, __func__, - &GMPParent::ParseChromiumManifest, NS_ConvertUTF8toUTF16(json)); -} - -RefPtr<GenericPromise> -GMPParent::ParseChromiumManifest(nsString aJSON) -{ - MOZ_ASSERT_UNREACHABLE("don't call me if EME isn't enabled"); - return GenericPromise::CreateAndReject(NS_ERROR_FAILURE, __func__); -} - -bool -GMPParent::CanBeSharedCrossNodeIds() const -{ - return !mAsyncShutdownInProgress && - mNodeId.IsEmpty() && - // XXX bug 1159300 hack -- maybe remove after openh264 1.4 - // We don't want to use CDM decoders for non-encrypted playback - // just yet; especially not for WebRTC. Don't allow CDMs to be used - // without a node ID. - !mCanDecrypt; -} - -bool -GMPParent::CanBeUsedFrom(const nsACString& aNodeId) const -{ - return !mAsyncShutdownInProgress && mNodeId == aNodeId; -} - -void -GMPParent::SetNodeId(const nsACString& aNodeId) -{ - MOZ_ASSERT(!aNodeId.IsEmpty()); - mNodeId = aNodeId; -} - -const nsCString& -GMPParent::GetDisplayName() const -{ - return mDisplayName; -} - -const nsCString& -GMPParent::GetVersion() const -{ - return mVersion; -} - -uint32_t -GMPParent::GetPluginId() const -{ - return mPluginId; -} - -bool -GMPParent::RecvAsyncShutdownRequired() -{ - LOGD("%s", __FUNCTION__); - if (mAsyncShutdownRequired) { - NS_WARNING("Received AsyncShutdownRequired message more than once!"); - return true; - } - mAsyncShutdownRequired = true; - mService->AsyncShutdownNeeded(this); - return true; -} - -bool -GMPParent::RecvAsyncShutdownComplete() -{ - LOGD("%s", __FUNCTION__); - - MOZ_ASSERT(mAsyncShutdownRequired); - AbortAsyncShutdown(); - return true; -} - -class RunCreateContentParentCallbacks : public Runnable -{ -public: - explicit RunCreateContentParentCallbacks(GMPContentParent* aGMPContentParent) - : mGMPContentParent(aGMPContentParent) - { - } - - void TakeCallbacks(nsTArray<UniquePtr<GetGMPContentParentCallback>>& aCallbacks) - { - mCallbacks.SwapElements(aCallbacks); - } - - NS_IMETHOD - Run() override - { - for (uint32_t i = 0, length = mCallbacks.Length(); i < length; ++i) { - mCallbacks[i]->Done(mGMPContentParent); - } - return NS_OK; - } - -private: - RefPtr<GMPContentParent> mGMPContentParent; - nsTArray<UniquePtr<GetGMPContentParentCallback>> mCallbacks; -}; - -PGMPContentParent* -GMPParent::AllocPGMPContentParent(Transport* aTransport, ProcessId aOtherPid) -{ - MOZ_ASSERT(GMPThread() == NS_GetCurrentThread()); - MOZ_ASSERT(!mGMPContentParent); - - mGMPContentParent = new GMPContentParent(this); - mGMPContentParent->Open(aTransport, aOtherPid, XRE_GetIOMessageLoop(), - ipc::ParentSide); - - RefPtr<RunCreateContentParentCallbacks> runCallbacks = - new RunCreateContentParentCallbacks(mGMPContentParent); - runCallbacks->TakeCallbacks(mCallbacks); - NS_DispatchToCurrentThread(runCallbacks); - MOZ_ASSERT(mCallbacks.IsEmpty()); - - return mGMPContentParent; -} - -bool -GMPParent::GetGMPContentParent(UniquePtr<GetGMPContentParentCallback>&& aCallback) -{ - LOGD("%s %p", __FUNCTION__, this); - MOZ_ASSERT(GMPThread() == NS_GetCurrentThread()); - - if (mGMPContentParent) { - aCallback->Done(mGMPContentParent); - } else { - mCallbacks.AppendElement(Move(aCallback)); - // If we don't have a GMPContentParent and we try to get one for the first - // time (mCallbacks.Length() == 1) then call PGMPContent::Open. If more - // calls to GetGMPContentParent happen before mGMPContentParent has been - // set then we should just store them, so that they get called when we set - // mGMPContentParent as a result of the PGMPContent::Open call. - if (mCallbacks.Length() == 1) { - if (!EnsureProcessLoaded() || !PGMPContent::Open(this)) { - return false; - } - // We want to increment this as soon as possible, to avoid that we'd try - // to shut down the GMP process while we're still trying to get a - // PGMPContentParent actor. - ++mGMPContentChildCount; - } - } - return true; -} - -already_AddRefed<GMPContentParent> -GMPParent::ForgetGMPContentParent() -{ - MOZ_ASSERT(mCallbacks.IsEmpty()); - return Move(mGMPContentParent.forget()); -} - -bool -GMPParent::EnsureProcessLoaded(base::ProcessId* aID) -{ - if (!EnsureProcessLoaded()) { - return false; - } - *aID = OtherPid(); - return true; -} - -bool -GMPParent::Bridge(GMPServiceParent* aGMPServiceParent) -{ - if (NS_FAILED(PGMPContent::Bridge(aGMPServiceParent, this))) { - return false; - } - ++mGMPContentChildCount; - return true; -} - -nsString -GMPParent::GetPluginBaseName() const -{ - return NS_LITERAL_STRING("gmp-") + mName; -} - -} // namespace gmp -} // namespace mozilla - -#undef LOG -#undef LOGD diff --git a/dom/media/gmp/GMPParent.h b/dom/media/gmp/GMPParent.h deleted file mode 100644 index dacd6feeb..000000000 --- a/dom/media/gmp/GMPParent.h +++ /dev/null @@ -1,242 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#ifndef GMPParent_h_ -#define GMPParent_h_ - -#include "GMPProcessParent.h" -#include "GMPServiceParent.h" -#include "GMPAudioDecoderParent.h" -#include "GMPDecryptorParent.h" -#include "GMPVideoDecoderParent.h" -#include "GMPVideoEncoderParent.h" -#include "GMPTimerParent.h" -#include "GMPStorageParent.h" -#include "mozilla/gmp/PGMPParent.h" -#include "nsCOMPtr.h" -#include "nscore.h" -#include "nsISupports.h" -#include "nsString.h" -#include "nsTArray.h" -#include "nsIFile.h" -#include "mozilla/MozPromise.h" - -class nsIThread; - -namespace mozilla { -namespace gmp { - -class GMPCapability -{ -public: - explicit GMPCapability() {} - GMPCapability(GMPCapability&& aOther) - : mAPIName(Move(aOther.mAPIName)) - , mAPITags(Move(aOther.mAPITags)) - { - } - explicit GMPCapability(const nsCString& aAPIName) - : mAPIName(aAPIName) - {} - explicit GMPCapability(const GMPCapability& aOther) = default; - nsCString mAPIName; - nsTArray<nsCString> mAPITags; - - static bool Supports(const nsTArray<GMPCapability>& aCapabilities, - const nsCString& aAPI, - const nsTArray<nsCString>& aTags); - - static bool Supports(const nsTArray<GMPCapability>& aCapabilities, - const nsCString& aAPI, - const nsCString& aTag); -}; - -enum GMPState { - GMPStateNotLoaded, - GMPStateLoaded, - GMPStateUnloading, - GMPStateClosing -}; - -class GMPContentParent; - -class GetGMPContentParentCallback -{ -public: - GetGMPContentParentCallback() - { - MOZ_COUNT_CTOR(GetGMPContentParentCallback); - }; - virtual ~GetGMPContentParentCallback() - { - MOZ_COUNT_DTOR(GetGMPContentParentCallback); - }; - virtual void Done(GMPContentParent* aGMPContentParent) = 0; -}; - -class GMPParent final : public PGMPParent -{ -public: - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GMPParent) - - GMPParent(); - - RefPtr<GenericPromise> Init(GeckoMediaPluginServiceParent* aService, nsIFile* aPluginDir); - nsresult CloneFrom(const GMPParent* aOther); - - void Crash(); - - nsresult LoadProcess(); - - // Called internally to close this if we don't need it - void CloseIfUnused(); - - // Notify all active de/encoders that we are closing, either because of - // normal shutdown or unexpected shutdown/crash. - void CloseActive(bool aDieWhenUnloaded); - - // Tell the plugin to die after shutdown. - void MarkForDeletion(); - bool IsMarkedForDeletion(); - - // Called by the GMPService to forcibly close active de/encoders at shutdown - void Shutdown(); - - // This must not be called while we're in the middle of abnormal ActorDestroy - void DeleteProcess(); - - GMPState State() const; - nsIThread* GMPThread(); - - // A GMP can either be a single instance shared across all NodeIds (like - // in the OpenH264 case), or we can require a new plugin instance for every - // NodeIds running the plugin (as in the EME plugin case). - // - // A NodeId is a hash of the ($urlBarOrigin, $ownerDocOrigin) pair. - // - // Plugins are associated with an NodeIds by calling SetNodeId() before - // loading. - // - // If a plugin has no NodeId specified and it is loaded, it is assumed to - // be shared across NodeIds. - - // Specifies that a GMP can only work with the specified NodeIds. - void SetNodeId(const nsACString& aNodeId); - const nsACString& GetNodeId() const { return mNodeId; } - - const nsCString& GetDisplayName() const; - const nsCString& GetVersion() const; - uint32_t GetPluginId() const; - nsString GetPluginBaseName() const; - - // Returns true if a plugin can be or is being used across multiple NodeIds. - bool CanBeSharedCrossNodeIds() const; - - // A GMP can be used from a NodeId if it's already been set to work with - // that NodeId, or if it's not been set to work with any NodeId and has - // not yet been loaded (i.e. it's not shared across NodeIds). - bool CanBeUsedFrom(const nsACString& aNodeId) const; - - already_AddRefed<nsIFile> GetDirectory() { - return nsCOMPtr<nsIFile>(mDirectory).forget(); - } - - void AbortAsyncShutdown(); - - // Called when the child process has died. - void ChildTerminated(); - - bool GetGMPContentParent(UniquePtr<GetGMPContentParentCallback>&& aCallback); - already_AddRefed<GMPContentParent> ForgetGMPContentParent(); - - bool EnsureProcessLoaded(base::ProcessId* aID); - - bool Bridge(GMPServiceParent* aGMPServiceParent); - - const nsTArray<GMPCapability>& GetCapabilities() const { return mCapabilities; } - -private: - ~GMPParent(); - - RefPtr<GeckoMediaPluginServiceParent> mService; - bool EnsureProcessLoaded(); - RefPtr<GenericPromise> ReadGMPMetaData(); - RefPtr<GenericPromise> ReadGMPInfoFile(nsIFile* aFile); - RefPtr<GenericPromise> ParseChromiumManifest(nsString aJSON); // Main thread. - RefPtr<GenericPromise> ReadChromiumManifestFile(nsIFile* aFile); // GMP thread. - void ActorDestroy(ActorDestroyReason aWhy) override; - - bool RecvPGMPStorageConstructor(PGMPStorageParent* actor) override; - PGMPStorageParent* AllocPGMPStorageParent() override; - bool DeallocPGMPStorageParent(PGMPStorageParent* aActor) override; - - PGMPContentParent* AllocPGMPContentParent(Transport* aTransport, - ProcessId aOtherPid) override; - - bool RecvPGMPTimerConstructor(PGMPTimerParent* actor) override; - PGMPTimerParent* AllocPGMPTimerParent() override; - bool DeallocPGMPTimerParent(PGMPTimerParent* aActor) override; - - bool RecvAsyncShutdownComplete() override; - bool RecvAsyncShutdownRequired() override; - - bool RecvPGMPContentChildDestroyed() override; - bool IsUsed() - { - return mGMPContentChildCount > 0; - } - - - static void AbortWaitingForGMPAsyncShutdown(nsITimer* aTimer, void* aClosure); - nsresult EnsureAsyncShutdownTimeoutSet(); - - GMPState mState; - nsCOMPtr<nsIFile> mDirectory; // plugin directory on disk - nsString mName; // base name of plugin on disk, UTF-16 because used for paths - nsCString mDisplayName; // name of plugin displayed to users - nsCString mDescription; // description of plugin for display to users - nsCString mVersion; -#ifdef XP_WIN - nsCString mLibs; -#endif - nsString mAdapter; - uint32_t mPluginId; - nsTArray<GMPCapability> mCapabilities; - GMPProcessParent* mProcess; - bool mDeleteProcessOnlyOnUnload; - bool mAbnormalShutdownInProgress; - bool mIsBlockingDeletion; - - bool mCanDecrypt; - - nsTArray<RefPtr<GMPTimerParent>> mTimers; - nsTArray<RefPtr<GMPStorageParent>> mStorage; - nsCOMPtr<nsIThread> mGMPThread; - nsCOMPtr<nsITimer> mAsyncShutdownTimeout; // GMP Thread only. - // NodeId the plugin is assigned to, or empty if the the plugin is not - // assigned to a NodeId. - nsCString mNodeId; - // This is used for GMP content in the parent, there may be more of these in - // the content processes. - RefPtr<GMPContentParent> mGMPContentParent; - nsTArray<UniquePtr<GetGMPContentParentCallback>> mCallbacks; - uint32_t mGMPContentChildCount; - - bool mAsyncShutdownRequired; - bool mAsyncShutdownInProgress; - - int mChildPid; - - // We hold a self reference to ourself while the child process is alive. - // This ensures that if the GMPService tries to shut us down and drops - // its reference to us, we stay alive long enough for the child process - // to terminate gracefully. - bool mHoldingSelfRef; -}; - -} // namespace gmp -} // namespace mozilla - -#endif // GMPParent_h_ diff --git a/dom/media/gmp/GMPPlatform.cpp b/dom/media/gmp/GMPPlatform.cpp deleted file mode 100644 index 71fa03468..000000000 --- a/dom/media/gmp/GMPPlatform.cpp +++ /dev/null @@ -1,300 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#include "GMPPlatform.h" -#include "GMPStorageChild.h" -#include "GMPTimerChild.h" -#include "mozilla/Monitor.h" -#include "GMPChild.h" -#include <ctime> - -namespace mozilla { -namespace gmp { - -static MessageLoop* sMainLoop = nullptr; -static GMPChild* sChild = nullptr; - -static bool -IsOnChildMainThread() -{ - return sMainLoop && sMainLoop == MessageLoop::current(); -} - -// We just need a refcounted wrapper for GMPTask objects. -class GMPRunnable final -{ -public: - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GMPRunnable) - - explicit GMPRunnable(GMPTask* aTask) - : mTask(aTask) - { - MOZ_ASSERT(mTask); - } - - void Run() - { - mTask->Run(); - mTask->Destroy(); - mTask = nullptr; - } - -private: - ~GMPRunnable() - { - } - - GMPTask* mTask; -}; - -class GMPSyncRunnable final -{ -public: - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GMPSyncRunnable) - - GMPSyncRunnable(GMPTask* aTask, MessageLoop* aMessageLoop) - : mDone(false) - , mTask(aTask) - , mMessageLoop(aMessageLoop) - , mMonitor("GMPSyncRunnable") - { - MOZ_ASSERT(mTask); - MOZ_ASSERT(mMessageLoop); - } - - void Post() - { - // We assert here for two reasons. - // 1) Nobody should be blocking the main thread. - // 2) This prevents deadlocks when doing sync calls to main which if the - // main thread tries to do a sync call back to the calling thread. - MOZ_ASSERT(!IsOnChildMainThread()); - - mMessageLoop->PostTask(NewRunnableMethod(this, &GMPSyncRunnable::Run)); - MonitorAutoLock lock(mMonitor); - while (!mDone) { - lock.Wait(); - } - } - - void Run() - { - mTask->Run(); - mTask->Destroy(); - mTask = nullptr; - MonitorAutoLock lock(mMonitor); - mDone = true; - lock.Notify(); - } - -private: - ~GMPSyncRunnable() - { - } - - bool mDone; - GMPTask* mTask; - MessageLoop* mMessageLoop; - Monitor mMonitor; -}; - -GMPErr -CreateThread(GMPThread** aThread) -{ - if (!aThread) { - return GMPGenericErr; - } - - *aThread = new GMPThreadImpl(); - - return GMPNoErr; -} - -GMPErr -RunOnMainThread(GMPTask* aTask) -{ - if (!aTask || !sMainLoop) { - return GMPGenericErr; - } - - RefPtr<GMPRunnable> r = new GMPRunnable(aTask); - sMainLoop->PostTask(NewRunnableMethod(r, &GMPRunnable::Run)); - - return GMPNoErr; -} - -GMPErr -SyncRunOnMainThread(GMPTask* aTask) -{ - if (!aTask || !sMainLoop || IsOnChildMainThread()) { - return GMPGenericErr; - } - - RefPtr<GMPSyncRunnable> r = new GMPSyncRunnable(aTask, sMainLoop); - - r->Post(); - - return GMPNoErr; -} - -GMPErr -CreateMutex(GMPMutex** aMutex) -{ - if (!aMutex) { - return GMPGenericErr; - } - - *aMutex = new GMPMutexImpl(); - - return GMPNoErr; -} - -GMPErr -CreateRecord(const char* aRecordName, - uint32_t aRecordNameSize, - GMPRecord** aOutRecord, - GMPRecordClient* aClient) -{ - if (aRecordNameSize > GMP_MAX_RECORD_NAME_SIZE || - aRecordNameSize == 0) { - NS_WARNING("GMP tried to CreateRecord with too long or 0 record name"); - return GMPGenericErr; - } - GMPStorageChild* storage = sChild->GetGMPStorage(); - if (!storage) { - return GMPGenericErr; - } - MOZ_ASSERT(storage); - return storage->CreateRecord(nsDependentCString(aRecordName, aRecordNameSize), - aOutRecord, - aClient); -} - -GMPErr -SetTimerOnMainThread(GMPTask* aTask, int64_t aTimeoutMS) -{ - if (!aTask || !sMainLoop || !IsOnChildMainThread()) { - return GMPGenericErr; - } - GMPTimerChild* timers = sChild->GetGMPTimers(); - NS_ENSURE_TRUE(timers, GMPGenericErr); - return timers->SetTimer(aTask, aTimeoutMS); -} - -GMPErr -GetClock(GMPTimestamp* aOutTime) -{ - *aOutTime = time(0) * 1000; - return GMPNoErr; -} - -GMPErr -CreateRecordIterator(RecvGMPRecordIteratorPtr aRecvIteratorFunc, - void* aUserArg) -{ - if (!aRecvIteratorFunc) { - return GMPInvalidArgErr; - } - GMPStorageChild* storage = sChild->GetGMPStorage(); - if (!storage) { - return GMPGenericErr; - } - MOZ_ASSERT(storage); - return storage->EnumerateRecords(aRecvIteratorFunc, aUserArg); -} - -void -InitPlatformAPI(GMPPlatformAPI& aPlatformAPI, GMPChild* aChild) -{ - if (!sMainLoop) { - sMainLoop = MessageLoop::current(); - } - if (!sChild) { - sChild = aChild; - } - - aPlatformAPI.version = 0; - aPlatformAPI.createthread = &CreateThread; - aPlatformAPI.runonmainthread = &RunOnMainThread; - aPlatformAPI.syncrunonmainthread = &SyncRunOnMainThread; - aPlatformAPI.createmutex = &CreateMutex; - aPlatformAPI.createrecord = &CreateRecord; - aPlatformAPI.settimer = &SetTimerOnMainThread; - aPlatformAPI.getcurrenttime = &GetClock; - aPlatformAPI.getrecordenumerator = &CreateRecordIterator; -} - -GMPThreadImpl::GMPThreadImpl() -: mMutex("GMPThreadImpl"), - mThread("GMPThread") -{ - MOZ_COUNT_CTOR(GMPThread); -} - -GMPThreadImpl::~GMPThreadImpl() -{ - MOZ_COUNT_DTOR(GMPThread); -} - -void -GMPThreadImpl::Post(GMPTask* aTask) -{ - MutexAutoLock lock(mMutex); - - if (!mThread.IsRunning()) { - bool started = mThread.Start(); - if (!started) { - NS_WARNING("Unable to start GMPThread!"); - return; - } - } - - RefPtr<GMPRunnable> r = new GMPRunnable(aTask); - mThread.message_loop()->PostTask(NewRunnableMethod(r.get(), &GMPRunnable::Run)); -} - -void -GMPThreadImpl::Join() -{ - { - MutexAutoLock lock(mMutex); - if (mThread.IsRunning()) { - mThread.Stop(); - } - } - delete this; -} - -GMPMutexImpl::GMPMutexImpl() -: mMonitor("gmp-mutex") -{ - MOZ_COUNT_CTOR(GMPMutexImpl); -} - -GMPMutexImpl::~GMPMutexImpl() -{ - MOZ_COUNT_DTOR(GMPMutexImpl); -} - -void -GMPMutexImpl::Destroy() -{ - delete this; -} - -void -GMPMutexImpl::Acquire() -{ - mMonitor.Enter(); -} - -void -GMPMutexImpl::Release() -{ - mMonitor.Exit(); -} - -} // namespace gmp -} // namespace mozilla diff --git a/dom/media/gmp/GMPPlatform.h b/dom/media/gmp/GMPPlatform.h deleted file mode 100644 index 79079c327..000000000 --- a/dom/media/gmp/GMPPlatform.h +++ /dev/null @@ -1,56 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#ifndef GMPPlatform_h_ -#define GMPPlatform_h_ - -#include "mozilla/Mutex.h" -#include "gmp-platform.h" -#include "base/thread.h" -#include "mozilla/ReentrantMonitor.h" - -namespace mozilla { -namespace gmp { - -class GMPChild; - -void InitPlatformAPI(GMPPlatformAPI& aPlatformAPI, GMPChild* aChild); - -GMPErr RunOnMainThread(GMPTask* aTask); - -class GMPThreadImpl : public GMPThread -{ -public: - GMPThreadImpl(); - virtual ~GMPThreadImpl(); - - // GMPThread - void Post(GMPTask* aTask) override; - void Join() override; - -private: - Mutex mMutex; - base::Thread mThread; -}; - -class GMPMutexImpl : public GMPMutex -{ -public: - GMPMutexImpl(); - virtual ~GMPMutexImpl(); - - // GMPMutex - void Acquire() override; - void Release() override; - void Destroy() override; - -private: - ReentrantMonitor mMonitor; -}; - -} // namespace gmp -} // namespace mozilla - -#endif // GMPPlatform_h_ diff --git a/dom/media/gmp/GMPProcessChild.cpp b/dom/media/gmp/GMPProcessChild.cpp deleted file mode 100644 index 294cabb42..000000000 --- a/dom/media/gmp/GMPProcessChild.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#include "GMPProcessChild.h" - -#include "base/command_line.h" -#include "base/string_util.h" -#include "mozilla/ipc/IOThreadChild.h" -#include "mozilla/BackgroundHangMonitor.h" - -using mozilla::ipc::IOThreadChild; - -namespace mozilla { -namespace gmp { - -GMPProcessChild::GMPProcessChild(ProcessId aParentPid) -: ProcessChild(aParentPid) -{ -} - -GMPProcessChild::~GMPProcessChild() -{ -} - -bool -GMPProcessChild::Init() -{ - nsAutoString pluginFilename; - nsAutoString voucherFilename; - -#if defined(OS_POSIX) - // NB: need to be very careful in ensuring that the first arg - // (after the binary name) here is indeed the plugin module path. - // Keep in sync with dom/plugins/PluginModuleParent. - std::vector<std::string> values = CommandLine::ForCurrentProcess()->argv(); - MOZ_ASSERT(values.size() >= 3, "not enough args"); - pluginFilename = NS_ConvertUTF8toUTF16(nsDependentCString(values[1].c_str())); - voucherFilename = NS_ConvertUTF8toUTF16(nsDependentCString(values[2].c_str())); -#elif defined(OS_WIN) - std::vector<std::wstring> values = CommandLine::ForCurrentProcess()->GetLooseValues(); - MOZ_ASSERT(values.size() >= 2, "not enough loose args"); - pluginFilename = nsDependentString(values[0].c_str()); - voucherFilename = nsDependentString(values[1].c_str()); -#else -#error Not implemented -#endif - - BackgroundHangMonitor::Startup(); - - return mPlugin.Init(pluginFilename, - voucherFilename, - ParentPid(), - IOThreadChild::message_loop(), - IOThreadChild::channel()); -} - -void -GMPProcessChild::CleanUp() -{ - BackgroundHangMonitor::Shutdown(); -} - -GMPLoader* GMPProcessChild::mLoader = nullptr; - -/* static */ -void -GMPProcessChild::SetGMPLoader(GMPLoader* aLoader) -{ - mLoader = aLoader; -} - -/* static */ -GMPLoader* -GMPProcessChild::GetGMPLoader() -{ - return mLoader; -} - -} // namespace gmp -} // namespace mozilla diff --git a/dom/media/gmp/GMPProcessChild.h b/dom/media/gmp/GMPProcessChild.h deleted file mode 100644 index 1a8df7653..000000000 --- a/dom/media/gmp/GMPProcessChild.h +++ /dev/null @@ -1,43 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#ifndef GMPProcessChild_h_ -#define GMPProcessChild_h_ - -#include "mozilla/ipc/ProcessChild.h" -#include "GMPChild.h" - -namespace mozilla { -namespace gmp { - -class GMPLoader; - -class GMPProcessChild final : public mozilla::ipc::ProcessChild { -protected: - typedef mozilla::ipc::ProcessChild ProcessChild; - -public: - explicit GMPProcessChild(ProcessId aParentPid); - ~GMPProcessChild(); - - bool Init() override; - void CleanUp() override; - - // Set/get the GMPLoader singleton for this child process. - // Note: The GMPLoader is not deleted by this object, the caller of - // SetGMPLoader() must manage the GMPLoader's lifecycle. - static void SetGMPLoader(GMPLoader* aHost); - static GMPLoader* GetGMPLoader(); - -private: - GMPChild mPlugin; - static GMPLoader* mLoader; - DISALLOW_COPY_AND_ASSIGN(GMPProcessChild); -}; - -} // namespace gmp -} // namespace mozilla - -#endif // GMPProcessChild_h_ diff --git a/dom/media/gmp/GMPProcessParent.cpp b/dom/media/gmp/GMPProcessParent.cpp deleted file mode 100644 index ef58175e8..000000000 --- a/dom/media/gmp/GMPProcessParent.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * vim: sw=2 ts=2 et : - * 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/. */ - -#include "GMPProcessParent.h" -#include "GMPUtils.h" -#include "nsIFile.h" -#include "nsIRunnable.h" - -#include "base/string_util.h" -#include "base/process_util.h" - -#include <string> - -using std::vector; -using std::string; - -using mozilla::gmp::GMPProcessParent; -using mozilla::ipc::GeckoChildProcessHost; -using base::ProcessArchitecture; - -namespace mozilla { - -extern LogModule* GetGMPLog(); -#define GMP_LOG(msg, ...) MOZ_LOG(GetGMPLog(), mozilla::LogLevel::Debug, (msg, ##__VA_ARGS__)) - -namespace gmp { - -GMPProcessParent::GMPProcessParent(const std::string& aGMPPath) -: GeckoChildProcessHost(GeckoProcessType_GMPlugin), - mGMPPath(aGMPPath) -{ - MOZ_COUNT_CTOR(GMPProcessParent); -} - -GMPProcessParent::~GMPProcessParent() -{ - MOZ_COUNT_DTOR(GMPProcessParent); -} - -bool -GMPProcessParent::Launch(int32_t aTimeoutMs) -{ - nsCOMPtr<nsIFile> path; - if (!GetEMEVoucherPath(getter_AddRefs(path))) { - NS_WARNING("GMPProcessParent can't get EME voucher path!"); - return false; - } - nsAutoCString voucherPath; - path->GetNativePath(voucherPath); - - vector<string> args; - - args.push_back(mGMPPath); - - args.push_back(string(voucherPath.BeginReading(), voucherPath.EndReading())); - - return SyncLaunch(args, aTimeoutMs, base::GetCurrentProcessArchitecture()); -} - -void -GMPProcessParent::Delete(nsCOMPtr<nsIRunnable> aCallback) -{ - mDeletedCallback = aCallback; - XRE_GetIOMessageLoop()->PostTask(NewNonOwningRunnableMethod(this, &GMPProcessParent::DoDelete)); -} - -void -GMPProcessParent::DoDelete() -{ - MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop()); - Join(); - - if (mDeletedCallback) { - mDeletedCallback->Run(); - } - - delete this; -} - -} // namespace gmp -} // namespace mozilla diff --git a/dom/media/gmp/GMPProcessParent.h b/dom/media/gmp/GMPProcessParent.h deleted file mode 100644 index b94f203cf..000000000 --- a/dom/media/gmp/GMPProcessParent.h +++ /dev/null @@ -1,52 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: sw=4 ts=4 et : - * 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/. */ - -#ifndef GMPProcessParent_h -#define GMPProcessParent_h 1 - -#include "mozilla/Attributes.h" -#include "base/basictypes.h" -#include "base/file_path.h" -#include "base/thread.h" -#include "chrome/common/child_process_host.h" -#include "mozilla/ipc/GeckoChildProcessHost.h" - -class nsIRunnable; - -namespace mozilla { -namespace gmp { - -class GMPProcessParent final : public mozilla::ipc::GeckoChildProcessHost -{ -public: - explicit GMPProcessParent(const std::string& aGMPPath); - ~GMPProcessParent(); - - // Synchronously launch the plugin process. If the process fails to launch - // after timeoutMs, this method will return false. - bool Launch(int32_t aTimeoutMs); - - void Delete(nsCOMPtr<nsIRunnable> aCallback = nullptr); - - bool CanShutdown() override { return true; } - const std::string& GetPluginFilePath() { return mGMPPath; } - - using mozilla::ipc::GeckoChildProcessHost::GetChannel; - using mozilla::ipc::GeckoChildProcessHost::GetChildProcessHandle; - -private: - void DoDelete(); - - std::string mGMPPath; - nsCOMPtr<nsIRunnable> mDeletedCallback; - - DISALLOW_COPY_AND_ASSIGN(GMPProcessParent); -}; - -} // namespace gmp -} // namespace mozilla - -#endif // ifndef GMPProcessParent_h diff --git a/dom/media/gmp/GMPService.cpp b/dom/media/gmp/GMPService.cpp deleted file mode 100644 index 1901210da..000000000 --- a/dom/media/gmp/GMPService.cpp +++ /dev/null @@ -1,557 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#include "GMPService.h" -#include "GMPServiceParent.h" -#include "GMPServiceChild.h" -#include "GMPContentParent.h" -#include "prio.h" -#include "mozilla/Logging.h" -#include "GMPParent.h" -#include "GMPVideoDecoderParent.h" -#include "nsIObserverService.h" -#include "GeckoChildProcessHost.h" -#include "mozilla/ClearOnShutdown.h" -#include "mozilla/SyncRunnable.h" -#include "nsXPCOMPrivate.h" -#include "mozilla/Services.h" -#include "nsNativeCharsetUtils.h" -#include "nsIConsoleService.h" -#include "mozilla/Unused.h" -#include "GMPDecryptorParent.h" -#include "GMPAudioDecoderParent.h" -#include "nsComponentManagerUtils.h" -#include "runnable_utils.h" -#include "VideoUtils.h" -#include "nsAppDirectoryServiceDefs.h" -#include "nsDirectoryServiceUtils.h" -#include "nsDirectoryServiceDefs.h" -#include "nsHashKeys.h" -#include "nsIFile.h" -#include "nsISimpleEnumerator.h" -#include "nsThreadUtils.h" - -#include "mozilla/dom/PluginCrashedEvent.h" -#include "mozilla/EventDispatcher.h" -#include "mozilla/Attributes.h" - -namespace mozilla { - -#ifdef LOG -#undef LOG -#endif - -LogModule* -GetGMPLog() -{ - static LazyLogModule sLog("GMP"); - return sLog; -} - -#define LOGD(msg) MOZ_LOG(GetGMPLog(), mozilla::LogLevel::Debug, msg) -#define LOG(level, msg) MOZ_LOG(GetGMPLog(), (level), msg) - -#ifdef __CLASS__ -#undef __CLASS__ -#endif -#define __CLASS__ "GMPService" - -namespace gmp { - -static StaticRefPtr<GeckoMediaPluginService> sSingletonService; - -class GMPServiceCreateHelper final : public mozilla::Runnable -{ - RefPtr<GeckoMediaPluginService> mService; - -public: - static already_AddRefed<GeckoMediaPluginService> - GetOrCreate() - { - RefPtr<GeckoMediaPluginService> service; - - if (NS_IsMainThread()) { - service = GetOrCreateOnMainThread(); - } else { - nsCOMPtr<nsIThread> mainThread = do_GetMainThread(); - MOZ_ASSERT(mainThread); - - RefPtr<GMPServiceCreateHelper> createHelper = new GMPServiceCreateHelper(); - - mozilla::SyncRunnable::DispatchToThread(mainThread, createHelper, true); - - service = createHelper->mService.forget(); - } - - return service.forget(); - } - -private: - GMPServiceCreateHelper() - { - } - - ~GMPServiceCreateHelper() - { - MOZ_ASSERT(!mService); - } - - static already_AddRefed<GeckoMediaPluginService> - GetOrCreateOnMainThread() - { - MOZ_ASSERT(NS_IsMainThread()); - - if (!sSingletonService) { - if (XRE_IsParentProcess()) { - RefPtr<GeckoMediaPluginServiceParent> service = - new GeckoMediaPluginServiceParent(); - service->Init(); - sSingletonService = service; - } else { - RefPtr<GeckoMediaPluginServiceChild> service = - new GeckoMediaPluginServiceChild(); - service->Init(); - sSingletonService = service; - } - - ClearOnShutdown(&sSingletonService); - } - - RefPtr<GeckoMediaPluginService> service = sSingletonService.get(); - return service.forget(); - } - - NS_IMETHOD - Run() override - { - MOZ_ASSERT(NS_IsMainThread()); - - mService = GetOrCreateOnMainThread(); - return NS_OK; - } -}; - -already_AddRefed<GeckoMediaPluginService> -GeckoMediaPluginService::GetGeckoMediaPluginService() -{ - return GMPServiceCreateHelper::GetOrCreate(); -} - -NS_IMPL_ISUPPORTS(GeckoMediaPluginService, mozIGeckoMediaPluginService, nsIObserver) - -GeckoMediaPluginService::GeckoMediaPluginService() - : mMutex("GeckoMediaPluginService::mMutex") - , mGMPThreadShutdown(false) - , mShuttingDownOnGMPThread(false) -{ - MOZ_ASSERT(NS_IsMainThread()); -} - -GeckoMediaPluginService::~GeckoMediaPluginService() -{ -} - -NS_IMETHODIMP -GeckoMediaPluginService::RunPluginCrashCallbacks(uint32_t aPluginId, - const nsACString& aPluginName) -{ - MOZ_ASSERT(NS_IsMainThread()); - LOGD(("%s::%s(%i)", __CLASS__, __FUNCTION__, aPluginId)); - - nsAutoPtr<nsTArray<RefPtr<GMPCrashHelper>>> helpers; - { - MutexAutoLock lock(mMutex); - mPluginCrashHelpers.RemoveAndForget(aPluginId, helpers); - } - if (!helpers) { - LOGD(("%s::%s(%i) No crash helpers, not handling crash.", __CLASS__, __FUNCTION__, aPluginId)); - return NS_OK; - } - - for (const auto& helper : *helpers) { - nsCOMPtr<nsPIDOMWindowInner> window = helper->GetPluginCrashedEventTarget(); - if (NS_WARN_IF(!window)) { - continue; - } - nsCOMPtr<nsIDocument> document(window->GetExtantDoc()); - if (NS_WARN_IF(!document)) { - continue; - } - - dom::PluginCrashedEventInit init; - init.mPluginID = aPluginId; - init.mBubbles = true; - init.mCancelable = true; - init.mGmpPlugin = true; - CopyUTF8toUTF16(aPluginName, init.mPluginName); - init.mSubmittedCrashReport = false; - RefPtr<dom::PluginCrashedEvent> event = - dom::PluginCrashedEvent::Constructor(document, - NS_LITERAL_STRING("PluginCrashed"), - init); - event->SetTrusted(true); - event->WidgetEventPtr()->mFlags.mOnlyChromeDispatch = true; - - EventDispatcher::DispatchDOMEvent(window, nullptr, event, nullptr, nullptr); - } - - return NS_OK; -} - -nsresult -GeckoMediaPluginService::Init() -{ - MOZ_ASSERT(NS_IsMainThread()); - - nsCOMPtr<nsIObserverService> obsService = mozilla::services::GetObserverService(); - MOZ_ASSERT(obsService); - MOZ_ALWAYS_SUCCEEDS(obsService->AddObserver(this, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID, false)); - - // Kick off scanning for plugins - nsCOMPtr<nsIThread> thread; - return GetThread(getter_AddRefs(thread)); -} - -void -GeckoMediaPluginService::ShutdownGMPThread() -{ - LOGD(("%s::%s", __CLASS__, __FUNCTION__)); - nsCOMPtr<nsIThread> gmpThread; - { - MutexAutoLock lock(mMutex); - mGMPThreadShutdown = true; - mGMPThread.swap(gmpThread); - mAbstractGMPThread = nullptr; - } - - if (gmpThread) { - gmpThread->Shutdown(); - } -} - -nsresult -GeckoMediaPluginService::GMPDispatch(nsIRunnable* event, - uint32_t flags) -{ - nsCOMPtr<nsIRunnable> r(event); - return GMPDispatch(r.forget()); -} - -nsresult -GeckoMediaPluginService::GMPDispatch(already_AddRefed<nsIRunnable> event, - uint32_t flags) -{ - nsCOMPtr<nsIRunnable> r(event); - nsCOMPtr<nsIThread> thread; - nsresult rv = GetThread(getter_AddRefs(thread)); - if (NS_FAILED(rv)) { - return rv; - } - return thread->Dispatch(r, flags); -} - -// always call with getter_AddRefs, because it does -NS_IMETHODIMP -GeckoMediaPluginService::GetThread(nsIThread** aThread) -{ - MOZ_ASSERT(aThread); - - // This can be called from any thread. - MutexAutoLock lock(mMutex); - - if (!mGMPThread) { - // Don't allow the thread to be created after shutdown has started. - if (mGMPThreadShutdown) { - return NS_ERROR_FAILURE; - } - - nsresult rv = NS_NewNamedThread("GMPThread", getter_AddRefs(mGMPThread)); - if (NS_FAILED(rv)) { - return rv; - } - - mAbstractGMPThread = AbstractThread::CreateXPCOMThreadWrapper(mGMPThread, false); - - // Tell the thread to initialize plugins - InitializePlugins(mAbstractGMPThread.get()); - } - - nsCOMPtr<nsIThread> copy = mGMPThread; - copy.forget(aThread); - - return NS_OK; -} - -RefPtr<AbstractThread> -GeckoMediaPluginService::GetAbstractGMPThread() -{ - MutexAutoLock lock(mMutex); - return mAbstractGMPThread; -} - -class GetGMPContentParentForAudioDecoderDone : public GetGMPContentParentCallback -{ -public: - explicit GetGMPContentParentForAudioDecoderDone(UniquePtr<GetGMPAudioDecoderCallback>&& aCallback, - GMPCrashHelper* aHelper) - : mCallback(Move(aCallback)) - , mHelper(aHelper) - { - } - - void Done(GMPContentParent* aGMPParent) override - { - GMPAudioDecoderParent* gmpADP = nullptr; - if (aGMPParent && NS_SUCCEEDED(aGMPParent->GetGMPAudioDecoder(&gmpADP))) { - gmpADP->SetCrashHelper(mHelper); - } - mCallback->Done(gmpADP); - } - -private: - UniquePtr<GetGMPAudioDecoderCallback> mCallback; - RefPtr<GMPCrashHelper> mHelper; -}; - -NS_IMETHODIMP -GeckoMediaPluginService::GetGMPAudioDecoder(GMPCrashHelper* aHelper, - nsTArray<nsCString>* aTags, - const nsACString& aNodeId, - UniquePtr<GetGMPAudioDecoderCallback>&& aCallback) -{ - MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); - NS_ENSURE_ARG(aTags && aTags->Length() > 0); - NS_ENSURE_ARG(aCallback); - - if (mShuttingDownOnGMPThread) { - return NS_ERROR_FAILURE; - } - - UniquePtr<GetGMPContentParentCallback> callback( - new GetGMPContentParentForAudioDecoderDone(Move(aCallback), aHelper)); - if (!GetContentParentFrom(aHelper, - aNodeId, - NS_LITERAL_CSTRING(GMP_API_AUDIO_DECODER), - *aTags, - Move(callback))) { - return NS_ERROR_FAILURE; - } - - return NS_OK; -} - -class GetGMPContentParentForVideoDecoderDone : public GetGMPContentParentCallback -{ -public: - explicit GetGMPContentParentForVideoDecoderDone(UniquePtr<GetGMPVideoDecoderCallback>&& aCallback, - GMPCrashHelper* aHelper, - uint32_t aDecryptorId) - : mCallback(Move(aCallback)) - , mHelper(aHelper) - , mDecryptorId(aDecryptorId) - { - } - - void Done(GMPContentParent* aGMPParent) override - { - GMPVideoDecoderParent* gmpVDP = nullptr; - GMPVideoHostImpl* videoHost = nullptr; - if (aGMPParent && NS_SUCCEEDED(aGMPParent->GetGMPVideoDecoder(&gmpVDP, mDecryptorId))) { - videoHost = &gmpVDP->Host(); - gmpVDP->SetCrashHelper(mHelper); - } - mCallback->Done(gmpVDP, videoHost); - } - -private: - UniquePtr<GetGMPVideoDecoderCallback> mCallback; - RefPtr<GMPCrashHelper> mHelper; - const uint32_t mDecryptorId; -}; - -NS_IMETHODIMP -GeckoMediaPluginService::GetDecryptingGMPVideoDecoder(GMPCrashHelper* aHelper, - nsTArray<nsCString>* aTags, - const nsACString& aNodeId, - UniquePtr<GetGMPVideoDecoderCallback>&& aCallback, - uint32_t aDecryptorId) -{ - MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); - NS_ENSURE_ARG(aTags && aTags->Length() > 0); - NS_ENSURE_ARG(aCallback); - - if (mShuttingDownOnGMPThread) { - return NS_ERROR_FAILURE; - } - - UniquePtr<GetGMPContentParentCallback> callback( - new GetGMPContentParentForVideoDecoderDone(Move(aCallback), aHelper, aDecryptorId)); - if (!GetContentParentFrom(aHelper, - aNodeId, - NS_LITERAL_CSTRING(GMP_API_VIDEO_DECODER), - *aTags, - Move(callback))) { - return NS_ERROR_FAILURE; - } - - return NS_OK; -} - -class GetGMPContentParentForVideoEncoderDone : public GetGMPContentParentCallback -{ -public: - explicit GetGMPContentParentForVideoEncoderDone(UniquePtr<GetGMPVideoEncoderCallback>&& aCallback, - GMPCrashHelper* aHelper) - : mCallback(Move(aCallback)) - , mHelper(aHelper) - { - } - - void Done(GMPContentParent* aGMPParent) override - { - GMPVideoEncoderParent* gmpVEP = nullptr; - GMPVideoHostImpl* videoHost = nullptr; - if (aGMPParent && NS_SUCCEEDED(aGMPParent->GetGMPVideoEncoder(&gmpVEP))) { - videoHost = &gmpVEP->Host(); - gmpVEP->SetCrashHelper(mHelper); - } - mCallback->Done(gmpVEP, videoHost); - } - -private: - UniquePtr<GetGMPVideoEncoderCallback> mCallback; - RefPtr<GMPCrashHelper> mHelper; -}; - -NS_IMETHODIMP -GeckoMediaPluginService::GetGMPVideoEncoder(GMPCrashHelper* aHelper, - nsTArray<nsCString>* aTags, - const nsACString& aNodeId, - UniquePtr<GetGMPVideoEncoderCallback>&& aCallback) -{ - MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); - NS_ENSURE_ARG(aTags && aTags->Length() > 0); - NS_ENSURE_ARG(aCallback); - - if (mShuttingDownOnGMPThread) { - return NS_ERROR_FAILURE; - } - - UniquePtr<GetGMPContentParentCallback> callback( - new GetGMPContentParentForVideoEncoderDone(Move(aCallback), aHelper)); - if (!GetContentParentFrom(aHelper, - aNodeId, - NS_LITERAL_CSTRING(GMP_API_VIDEO_ENCODER), - *aTags, - Move(callback))) { - return NS_ERROR_FAILURE; - } - - return NS_OK; -} - -class GetGMPContentParentForDecryptorDone : public GetGMPContentParentCallback -{ -public: - explicit GetGMPContentParentForDecryptorDone(UniquePtr<GetGMPDecryptorCallback>&& aCallback, - GMPCrashHelper* aHelper) - : mCallback(Move(aCallback)) - , mHelper(aHelper) - { - } - - void Done(GMPContentParent* aGMPParent) override - { - GMPDecryptorParent* ksp = nullptr; - if (aGMPParent && NS_SUCCEEDED(aGMPParent->GetGMPDecryptor(&ksp))) { - ksp->SetCrashHelper(mHelper); - } - mCallback->Done(ksp); - } - -private: - UniquePtr<GetGMPDecryptorCallback> mCallback; - RefPtr<GMPCrashHelper> mHelper; -}; - -NS_IMETHODIMP -GeckoMediaPluginService::GetGMPDecryptor(GMPCrashHelper* aHelper, - nsTArray<nsCString>* aTags, - const nsACString& aNodeId, - UniquePtr<GetGMPDecryptorCallback>&& aCallback) -{ - MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); - NS_ENSURE_ARG(aTags && aTags->Length() > 0); - NS_ENSURE_ARG(aCallback); - - if (mShuttingDownOnGMPThread) { - return NS_ERROR_FAILURE; - } - - UniquePtr<GetGMPContentParentCallback> callback( - new GetGMPContentParentForDecryptorDone(Move(aCallback), aHelper)); - if (!GetContentParentFrom(aHelper, - aNodeId, - NS_LITERAL_CSTRING(GMP_API_DECRYPTOR), - *aTags, - Move(callback))) { - return NS_ERROR_FAILURE; - } - - return NS_OK; -} - -void -GeckoMediaPluginService::ConnectCrashHelper(uint32_t aPluginId, GMPCrashHelper* aHelper) -{ - if (!aHelper) { - return; - } - MutexAutoLock lock(mMutex); - nsTArray<RefPtr<GMPCrashHelper>>* helpers; - if (!mPluginCrashHelpers.Get(aPluginId, &helpers)) { - helpers = new nsTArray<RefPtr<GMPCrashHelper>>(); - mPluginCrashHelpers.Put(aPluginId, helpers); - } else if (helpers->Contains(aHelper)) { - return; - } - helpers->AppendElement(aHelper); -} - -void GeckoMediaPluginService::DisconnectCrashHelper(GMPCrashHelper* aHelper) -{ - if (!aHelper) { - return; - } - MutexAutoLock lock(mMutex); - for (auto iter = mPluginCrashHelpers.Iter(); !iter.Done(); iter.Next()) { - nsTArray<RefPtr<GMPCrashHelper>>* helpers = iter.Data(); - if (!helpers->Contains(aHelper)) { - continue; - } - helpers->RemoveElement(aHelper); - MOZ_ASSERT(!helpers->Contains(aHelper)); // Ensure there aren't duplicates. - if (helpers->IsEmpty()) { - iter.Remove(); - } - } -} - -} // namespace gmp -} // namespace mozilla - -NS_IMPL_ADDREF(GMPCrashHelper) -NS_IMPL_RELEASE_WITH_DESTROY(GMPCrashHelper, Destroy()) - -void -GMPCrashHelper::Destroy() -{ - if (NS_IsMainThread()) { - delete this; - } else { - // Don't addref, as then we'd end up releasing after the detele runs! - NS_DispatchToMainThread(mozilla::NewNonOwningRunnableMethod(this, &GMPCrashHelper::Destroy)); - } -} diff --git a/dom/media/gmp/GMPService.h b/dom/media/gmp/GMPService.h deleted file mode 100644 index 7ed318a25..000000000 --- a/dom/media/gmp/GMPService.h +++ /dev/null @@ -1,142 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#ifndef GMPService_h_ -#define GMPService_h_ - -#include "nsString.h" -#include "mozIGeckoMediaPluginService.h" -#include "nsIObserver.h" -#include "nsTArray.h" -#include "mozilla/Attributes.h" -#include "mozilla/Monitor.h" -#include "nsString.h" -#include "nsCOMPtr.h" -#include "nsIThread.h" -#include "nsThreadUtils.h" -#include "nsPIDOMWindow.h" -#include "nsIDocument.h" -#include "nsIWeakReference.h" -#include "mozilla/AbstractThread.h" -#include "nsClassHashtable.h" -#include "nsISupportsImpl.h" - -template <class> struct already_AddRefed; - -// For every GMP actor requested, the caller can specify a crash helper, -// which is an object which supplies the nsPIDOMWindowInner to which we'll -// dispatch the PluginCrashed event if the GMP crashes. -// GMPCrashHelper has threadsafe refcounting. Its release method ensures -// that instances are destroyed on the main thread. -class GMPCrashHelper -{ -public: - NS_METHOD_(MozExternalRefCountType) AddRef(void); - NS_METHOD_(MozExternalRefCountType) Release(void); - - // Called on the main thread. - virtual already_AddRefed<nsPIDOMWindowInner> GetPluginCrashedEventTarget() = 0; - -protected: - virtual ~GMPCrashHelper() - { - MOZ_ASSERT(NS_IsMainThread()); - } - void Destroy(); - mozilla::ThreadSafeAutoRefCnt mRefCnt; - NS_DECL_OWNINGTHREAD -}; - -namespace mozilla { - -extern LogModule* GetGMPLog(); - -namespace gmp { - -class GetGMPContentParentCallback; - -class GeckoMediaPluginService : public mozIGeckoMediaPluginService - , public nsIObserver -{ -public: - static already_AddRefed<GeckoMediaPluginService> GetGeckoMediaPluginService(); - - virtual nsresult Init(); - - NS_DECL_THREADSAFE_ISUPPORTS - - // mozIGeckoMediaPluginService - NS_IMETHOD GetThread(nsIThread** aThread) override; - NS_IMETHOD GetDecryptingGMPVideoDecoder(GMPCrashHelper* aHelper, - nsTArray<nsCString>* aTags, - const nsACString& aNodeId, - UniquePtr<GetGMPVideoDecoderCallback>&& aCallback, - uint32_t aDecryptorId) - override; - NS_IMETHOD GetGMPVideoEncoder(GMPCrashHelper* aHelper, - nsTArray<nsCString>* aTags, - const nsACString& aNodeId, - UniquePtr<GetGMPVideoEncoderCallback>&& aCallback) - override; - NS_IMETHOD GetGMPAudioDecoder(GMPCrashHelper* aHelper, - nsTArray<nsCString>* aTags, - const nsACString& aNodeId, - UniquePtr<GetGMPAudioDecoderCallback>&& aCallback) - override; - NS_IMETHOD GetGMPDecryptor(GMPCrashHelper* aHelper, - nsTArray<nsCString>* aTags, - const nsACString& aNodeId, - UniquePtr<GetGMPDecryptorCallback>&& aCallback) - override; - - // Helper for backwards compatibility with WebRTC/tests. - NS_IMETHOD - GetGMPVideoDecoder(GMPCrashHelper* aHelper, - nsTArray<nsCString>* aTags, - const nsACString& aNodeId, - UniquePtr<GetGMPVideoDecoderCallback>&& aCallback) override - { - return GetDecryptingGMPVideoDecoder(aHelper, aTags, aNodeId, Move(aCallback), 0); - } - - int32_t AsyncShutdownTimeoutMs(); - - NS_IMETHOD RunPluginCrashCallbacks(uint32_t aPluginId, - const nsACString& aPluginName) override; - - RefPtr<AbstractThread> GetAbstractGMPThread(); - - void ConnectCrashHelper(uint32_t aPluginId, GMPCrashHelper* aHelper); - void DisconnectCrashHelper(GMPCrashHelper* aHelper); - -protected: - GeckoMediaPluginService(); - virtual ~GeckoMediaPluginService(); - - virtual void InitializePlugins(AbstractThread* aAbstractGMPThread) = 0; - virtual bool GetContentParentFrom(GMPCrashHelper* aHelper, - const nsACString& aNodeId, - const nsCString& aAPI, - const nsTArray<nsCString>& aTags, - UniquePtr<GetGMPContentParentCallback>&& aCallback) = 0; - - nsresult GMPDispatch(nsIRunnable* event, uint32_t flags = NS_DISPATCH_NORMAL); - nsresult GMPDispatch(already_AddRefed<nsIRunnable> event, uint32_t flags = NS_DISPATCH_NORMAL); - void ShutdownGMPThread(); - - Mutex mMutex; // Protects mGMPThread, mAbstractGMPThread, mPluginCrashHelpers, - // mGMPThreadShutdown and some members in derived classes. - nsCOMPtr<nsIThread> mGMPThread; - RefPtr<AbstractThread> mAbstractGMPThread; - bool mGMPThreadShutdown; - bool mShuttingDownOnGMPThread; - - nsClassHashtable<nsUint32HashKey, nsTArray<RefPtr<GMPCrashHelper>>> mPluginCrashHelpers; -}; - -} // namespace gmp -} // namespace mozilla - -#endif // GMPService_h_ diff --git a/dom/media/gmp/GMPServiceChild.cpp b/dom/media/gmp/GMPServiceChild.cpp deleted file mode 100644 index 08599039f..000000000 --- a/dom/media/gmp/GMPServiceChild.cpp +++ /dev/null @@ -1,478 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#include "GMPServiceChild.h" -#include "mozilla/dom/ContentChild.h" -#include "mozilla/ClearOnShutdown.h" -#include "mozilla/StaticPtr.h" -#include "mozIGeckoMediaPluginService.h" -#include "mozIGeckoMediaPluginChromeService.h" -#include "nsCOMPtr.h" -#include "GMPParent.h" -#include "GMPContentParent.h" -#include "nsXPCOMPrivate.h" -#include "mozilla/SyncRunnable.h" -#include "mozilla/StaticMutex.h" -#include "runnable_utils.h" -#include "base/task.h" -#include "nsIObserverService.h" -#include "nsComponentManagerUtils.h" - -namespace mozilla { - -#ifdef LOG -#undef LOG -#endif - -#define LOGD(msg) MOZ_LOG(GetGMPLog(), mozilla::LogLevel::Debug, msg) -#define LOG(level, msg) MOZ_LOG(GetGMPLog(), (level), msg) - -#ifdef __CLASS__ -#undef __CLASS__ -#endif -#define __CLASS__ "GMPService" - -namespace gmp { - -already_AddRefed<GeckoMediaPluginServiceChild> -GeckoMediaPluginServiceChild::GetSingleton() -{ - MOZ_ASSERT(!XRE_IsParentProcess()); - RefPtr<GeckoMediaPluginService> service( - GeckoMediaPluginService::GetGeckoMediaPluginService()); -#ifdef DEBUG - if (service) { - nsCOMPtr<mozIGeckoMediaPluginChromeService> chromeService; - CallQueryInterface(service.get(), getter_AddRefs(chromeService)); - MOZ_ASSERT(!chromeService); - } -#endif - return service.forget().downcast<GeckoMediaPluginServiceChild>(); -} - -class GetContentParentFromDone : public GetServiceChildCallback -{ -public: - GetContentParentFromDone(GMPCrashHelper* aHelper, const nsACString& aNodeId, const nsCString& aAPI, - const nsTArray<nsCString>& aTags, - UniquePtr<GetGMPContentParentCallback>&& aCallback) - : mHelper(aHelper), - mNodeId(aNodeId), - mAPI(aAPI), - mTags(aTags), - mCallback(Move(aCallback)) - { - } - - void Done(GMPServiceChild* aGMPServiceChild) override - { - if (!aGMPServiceChild) { - mCallback->Done(nullptr); - return; - } - - uint32_t pluginId; - nsresult rv; - bool ok = aGMPServiceChild->SendSelectGMP(mNodeId, mAPI, mTags, &pluginId, &rv); - if (!ok || rv == NS_ERROR_ILLEGAL_DURING_SHUTDOWN) { - mCallback->Done(nullptr); - return; - } - - if (mHelper) { - RefPtr<GeckoMediaPluginService> gmps(GeckoMediaPluginService::GetGeckoMediaPluginService()); - gmps->ConnectCrashHelper(pluginId, mHelper); - } - - nsTArray<base::ProcessId> alreadyBridgedTo; - aGMPServiceChild->GetAlreadyBridgedTo(alreadyBridgedTo); - - base::ProcessId otherProcess; - nsCString displayName; - ok = aGMPServiceChild->SendLaunchGMP(pluginId, alreadyBridgedTo, &otherProcess, - &displayName, &rv); - if (!ok || rv == NS_ERROR_ILLEGAL_DURING_SHUTDOWN) { - mCallback->Done(nullptr); - return; - } - - RefPtr<GMPContentParent> parent; - aGMPServiceChild->GetBridgedGMPContentParent(otherProcess, - getter_AddRefs(parent)); - if (!alreadyBridgedTo.Contains(otherProcess)) { - parent->SetDisplayName(displayName); - parent->SetPluginId(pluginId); - } - - mCallback->Done(parent); - } - -private: - RefPtr<GMPCrashHelper> mHelper; - nsCString mNodeId; - nsCString mAPI; - const nsTArray<nsCString> mTags; - UniquePtr<GetGMPContentParentCallback> mCallback; -}; - -bool -GeckoMediaPluginServiceChild::GetContentParentFrom(GMPCrashHelper* aHelper, - const nsACString& aNodeId, - const nsCString& aAPI, - const nsTArray<nsCString>& aTags, - UniquePtr<GetGMPContentParentCallback>&& aCallback) -{ - MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); - - UniquePtr<GetServiceChildCallback> callback( - new GetContentParentFromDone(aHelper, aNodeId, aAPI, aTags, Move(aCallback))); - GetServiceChild(Move(callback)); - - return true; -} - -typedef mozilla::dom::GMPCapabilityData GMPCapabilityData; -typedef mozilla::dom::GMPAPITags GMPAPITags; - -struct GMPCapabilityAndVersion -{ - explicit GMPCapabilityAndVersion(const GMPCapabilityData& aCapabilities) - : mName(aCapabilities.name()) - , mVersion(aCapabilities.version()) - { - for (const GMPAPITags& tags : aCapabilities.capabilities()) { - GMPCapability cap; - cap.mAPIName = tags.api(); - for (const nsCString& tag : tags.tags()) { - cap.mAPITags.AppendElement(tag); - } - mCapabilities.AppendElement(Move(cap)); - } - } - - nsCString ToString() const - { - nsCString s; - s.Append(mName); - s.Append(" version="); - s.Append(mVersion); - s.Append(" tags=["); - nsCString tags; - for (const GMPCapability& cap : mCapabilities) { - if (!tags.IsEmpty()) { - tags.Append(" "); - } - tags.Append(cap.mAPIName); - for (const nsCString& tag : cap.mAPITags) { - tags.Append(":"); - tags.Append(tag); - } - } - s.Append(tags); - s.Append("]"); - return s; - } - - nsCString mName; - nsCString mVersion; - nsTArray<GMPCapability> mCapabilities; -}; - -StaticMutex sGMPCapabilitiesMutex; -StaticAutoPtr<nsTArray<GMPCapabilityAndVersion>> sGMPCapabilities; - -static nsCString -GMPCapabilitiesToString() -{ - nsCString s; - for (const GMPCapabilityAndVersion& gmp : *sGMPCapabilities) { - if (!s.IsEmpty()) { - s.Append(", "); - } - s.Append(gmp.ToString()); - } - return s; -} - -/* static */ -void -GeckoMediaPluginServiceChild::UpdateGMPCapabilities(nsTArray<GMPCapabilityData>&& aCapabilities) -{ - { - // The mutex should unlock before sending the "gmp-changed" observer service notification. - StaticMutexAutoLock lock(sGMPCapabilitiesMutex); - if (!sGMPCapabilities) { - sGMPCapabilities = new nsTArray<GMPCapabilityAndVersion>(); - ClearOnShutdown(&sGMPCapabilities); - } - sGMPCapabilities->Clear(); - for (const GMPCapabilityData& plugin : aCapabilities) { - sGMPCapabilities->AppendElement(GMPCapabilityAndVersion(plugin)); - } - - LOGD(("UpdateGMPCapabilities {%s}", GMPCapabilitiesToString().get())); - } - - // Fire a notification so that any MediaKeySystemAccess - // requests waiting on a CDM to download will retry. - nsCOMPtr<nsIObserverService> obsService = mozilla::services::GetObserverService(); - MOZ_ASSERT(obsService); - if (obsService) { - obsService->NotifyObservers(nullptr, "gmp-changed", nullptr); - } -} - -NS_IMETHODIMP -GeckoMediaPluginServiceChild::HasPluginForAPI(const nsACString& aAPI, - nsTArray<nsCString>* aTags, - bool* aHasPlugin) -{ - StaticMutexAutoLock lock(sGMPCapabilitiesMutex); - if (!sGMPCapabilities) { - *aHasPlugin = false; - return NS_OK; - } - - nsCString api(aAPI); - for (const GMPCapabilityAndVersion& plugin : *sGMPCapabilities) { - if (GMPCapability::Supports(plugin.mCapabilities, api, *aTags)) { - *aHasPlugin = true; - return NS_OK; - } - } - - *aHasPlugin = false; - return NS_OK; -} - -class GetNodeIdDone : public GetServiceChildCallback -{ -public: - GetNodeIdDone(const nsAString& aOrigin, const nsAString& aTopLevelOrigin, - const nsAString& aGMPName, - bool aInPrivateBrowsing, UniquePtr<GetNodeIdCallback>&& aCallback) - : mOrigin(aOrigin), - mTopLevelOrigin(aTopLevelOrigin), - mGMPName(aGMPName), - mInPrivateBrowsing(aInPrivateBrowsing), - mCallback(Move(aCallback)) - { - } - - void Done(GMPServiceChild* aGMPServiceChild) override - { - if (!aGMPServiceChild) { - mCallback->Done(NS_ERROR_FAILURE, EmptyCString()); - return; - } - - nsCString outId; - if (!aGMPServiceChild->SendGetGMPNodeId(mOrigin, mTopLevelOrigin, - mGMPName, - mInPrivateBrowsing, &outId)) { - mCallback->Done(NS_ERROR_FAILURE, EmptyCString()); - return; - } - - mCallback->Done(NS_OK, outId); - } - -private: - nsString mOrigin; - nsString mTopLevelOrigin; - nsString mGMPName; - bool mInPrivateBrowsing; - UniquePtr<GetNodeIdCallback> mCallback; -}; - -NS_IMETHODIMP -GeckoMediaPluginServiceChild::GetNodeId(const nsAString& aOrigin, - const nsAString& aTopLevelOrigin, - const nsAString& aGMPName, - bool aInPrivateBrowsing, - UniquePtr<GetNodeIdCallback>&& aCallback) -{ - UniquePtr<GetServiceChildCallback> callback( - new GetNodeIdDone(aOrigin, aTopLevelOrigin, aGMPName, aInPrivateBrowsing, Move(aCallback))); - GetServiceChild(Move(callback)); - return NS_OK; -} - -NS_IMETHODIMP -GeckoMediaPluginServiceChild::Observe(nsISupports* aSubject, - const char* aTopic, - const char16_t* aSomeData) -{ - LOGD(("%s::%s: %s", __CLASS__, __FUNCTION__, aTopic)); - if (!strcmp(NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID, aTopic)) { - if (mServiceChild) { - mozilla::SyncRunnable::DispatchToThread(mGMPThread, - WrapRunnable(mServiceChild.get(), - &PGMPServiceChild::Close)); - mServiceChild = nullptr; - } - ShutdownGMPThread(); - } - - return NS_OK; -} - -void -GeckoMediaPluginServiceChild::GetServiceChild(UniquePtr<GetServiceChildCallback>&& aCallback) -{ - MOZ_ASSERT(!NS_IsMainThread()); - - if (!mServiceChild) { - dom::ContentChild* contentChild = dom::ContentChild::GetSingleton(); - if (!contentChild) { - return; - } - mGetServiceChildCallbacks.AppendElement(Move(aCallback)); - if (mGetServiceChildCallbacks.Length() == 1) { - NS_DispatchToMainThread(WrapRunnable(contentChild, - &dom::ContentChild::SendCreateGMPService)); - } - return; - } - - aCallback->Done(mServiceChild.get()); -} - -void -GeckoMediaPluginServiceChild::SetServiceChild(UniquePtr<GMPServiceChild>&& aServiceChild) -{ - mServiceChild = Move(aServiceChild); - nsTArray<UniquePtr<GetServiceChildCallback>> getServiceChildCallbacks; - getServiceChildCallbacks.SwapElements(mGetServiceChildCallbacks); - for (uint32_t i = 0, length = getServiceChildCallbacks.Length(); i < length; ++i) { - getServiceChildCallbacks[i]->Done(mServiceChild.get()); - } -} - -void -GeckoMediaPluginServiceChild::RemoveGMPContentParent(GMPContentParent* aGMPContentParent) -{ - if (mServiceChild) { - mServiceChild->RemoveGMPContentParent(aGMPContentParent); - } -} - -GMPServiceChild::GMPServiceChild() -{ -} - -GMPServiceChild::~GMPServiceChild() -{ -} - -PGMPContentParent* -GMPServiceChild::AllocPGMPContentParent(Transport* aTransport, - ProcessId aOtherPid) -{ - MOZ_ASSERT(!mContentParents.GetWeak(aOtherPid)); - - nsCOMPtr<nsIThread> mainThread = do_GetMainThread(); - MOZ_ASSERT(mainThread); - - RefPtr<GMPContentParent> parent = new GMPContentParent(); - - DebugOnly<bool> ok = parent->Open(aTransport, aOtherPid, - XRE_GetIOMessageLoop(), - mozilla::ipc::ParentSide); - MOZ_ASSERT(ok); - - mContentParents.Put(aOtherPid, parent); - return parent; -} - -void -GMPServiceChild::GetBridgedGMPContentParent(ProcessId aOtherPid, - GMPContentParent** aGMPContentParent) -{ - mContentParents.Get(aOtherPid, aGMPContentParent); -} - -void -GMPServiceChild::RemoveGMPContentParent(GMPContentParent* aGMPContentParent) -{ - for (auto iter = mContentParents.Iter(); !iter.Done(); iter.Next()) { - RefPtr<GMPContentParent>& parent = iter.Data(); - if (parent == aGMPContentParent) { - iter.Remove(); - break; - } - } -} - -void -GMPServiceChild::GetAlreadyBridgedTo(nsTArray<base::ProcessId>& aAlreadyBridgedTo) -{ - aAlreadyBridgedTo.SetCapacity(mContentParents.Count()); - for (auto iter = mContentParents.Iter(); !iter.Done(); iter.Next()) { - const uint64_t& id = iter.Key(); - aAlreadyBridgedTo.AppendElement(id); - } -} - -class OpenPGMPServiceChild : public mozilla::Runnable -{ -public: - OpenPGMPServiceChild(UniquePtr<GMPServiceChild>&& aGMPServiceChild, - mozilla::ipc::Transport* aTransport, - base::ProcessId aOtherPid) - : mGMPServiceChild(Move(aGMPServiceChild)), - mTransport(aTransport), - mOtherPid(aOtherPid) - { - } - - NS_IMETHOD Run() override - { - RefPtr<GeckoMediaPluginServiceChild> gmp = - GeckoMediaPluginServiceChild::GetSingleton(); - MOZ_ASSERT(!gmp->mServiceChild); - if (mGMPServiceChild->Open(mTransport, mOtherPid, XRE_GetIOMessageLoop(), - ipc::ChildSide)) { - gmp->SetServiceChild(Move(mGMPServiceChild)); - } else { - gmp->SetServiceChild(nullptr); - } - return NS_OK; - } - -private: - UniquePtr<GMPServiceChild> mGMPServiceChild; - mozilla::ipc::Transport* mTransport; - base::ProcessId mOtherPid; -}; - -/* static */ -PGMPServiceChild* -GMPServiceChild::Create(Transport* aTransport, ProcessId aOtherPid) -{ - RefPtr<GeckoMediaPluginServiceChild> gmp = - GeckoMediaPluginServiceChild::GetSingleton(); - MOZ_ASSERT(!gmp->mServiceChild); - - UniquePtr<GMPServiceChild> serviceChild(new GMPServiceChild()); - - nsCOMPtr<nsIThread> gmpThread; - nsresult rv = gmp->GetThread(getter_AddRefs(gmpThread)); - NS_ENSURE_SUCCESS(rv, nullptr); - - GMPServiceChild* result = serviceChild.get(); - rv = gmpThread->Dispatch(new OpenPGMPServiceChild(Move(serviceChild), - aTransport, - aOtherPid), - NS_DISPATCH_NORMAL); - if (NS_FAILED(rv)) { - return nullptr; - } - - return result; -} - -} // namespace gmp -} // namespace mozilla diff --git a/dom/media/gmp/GMPServiceChild.h b/dom/media/gmp/GMPServiceChild.h deleted file mode 100644 index 63b1325bb..000000000 --- a/dom/media/gmp/GMPServiceChild.h +++ /dev/null @@ -1,105 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#ifndef GMPServiceChild_h_ -#define GMPServiceChild_h_ - -#include "GMPService.h" -#include "base/process.h" -#include "mozilla/ipc/Transport.h" -#include "mozilla/gmp/PGMPServiceChild.h" -#include "nsRefPtrHashtable.h" -#include "mozilla/dom/ContentChild.h" - -namespace mozilla { -namespace gmp { - -class GMPContentParent; -class GMPServiceChild; - -class GetServiceChildCallback -{ -public: - GetServiceChildCallback() - { - MOZ_COUNT_CTOR(GetServiceChildCallback); - } - virtual ~GetServiceChildCallback() - { - MOZ_COUNT_DTOR(GetServiceChildCallback); - } - virtual void Done(GMPServiceChild* aGMPServiceChild) = 0; -}; - -class GeckoMediaPluginServiceChild : public GeckoMediaPluginService -{ - friend class GMPServiceChild; - -public: - static already_AddRefed<GeckoMediaPluginServiceChild> GetSingleton(); - - NS_IMETHOD HasPluginForAPI(const nsACString& aAPI, - nsTArray<nsCString>* aTags, - bool *aRetVal) override; - NS_IMETHOD GetNodeId(const nsAString& aOrigin, - const nsAString& aTopLevelOrigin, - const nsAString& aGMPName, - bool aInPrivateBrowsingMode, - UniquePtr<GetNodeIdCallback>&& aCallback) override; - - NS_DECL_NSIOBSERVER - - void SetServiceChild(UniquePtr<GMPServiceChild>&& aServiceChild); - - void RemoveGMPContentParent(GMPContentParent* aGMPContentParent); - - static void UpdateGMPCapabilities(nsTArray<mozilla::dom::GMPCapabilityData>&& aCapabilities); - -protected: - void InitializePlugins(AbstractThread*) override - { - // Nothing to do here. - } - bool GetContentParentFrom(GMPCrashHelper* aHelper, - const nsACString& aNodeId, - const nsCString& aAPI, - const nsTArray<nsCString>& aTags, - UniquePtr<GetGMPContentParentCallback>&& aCallback) - override; - -private: - friend class OpenPGMPServiceChild; - - void GetServiceChild(UniquePtr<GetServiceChildCallback>&& aCallback); - - UniquePtr<GMPServiceChild> mServiceChild; - nsTArray<UniquePtr<GetServiceChildCallback>> mGetServiceChildCallbacks; -}; - -class GMPServiceChild : public PGMPServiceChild -{ -public: - explicit GMPServiceChild(); - virtual ~GMPServiceChild(); - - PGMPContentParent* AllocPGMPContentParent(Transport* aTransport, - ProcessId aOtherPid) override; - - void GetBridgedGMPContentParent(ProcessId aOtherPid, - GMPContentParent** aGMPContentParent); - void RemoveGMPContentParent(GMPContentParent* aGMPContentParent); - - void GetAlreadyBridgedTo(nsTArray<ProcessId>& aAlreadyBridgedTo); - - static PGMPServiceChild* Create(Transport* aTransport, ProcessId aOtherPid); - -private: - nsRefPtrHashtable<nsUint64HashKey, GMPContentParent> mContentParents; -}; - -} // namespace gmp -} // namespace mozilla - -#endif // GMPServiceChild_h_ diff --git a/dom/media/gmp/GMPServiceParent.cpp b/dom/media/gmp/GMPServiceParent.cpp deleted file mode 100644 index a4afbdad4..000000000 --- a/dom/media/gmp/GMPServiceParent.cpp +++ /dev/null @@ -1,1933 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#include "GMPServiceParent.h" -#include "GMPService.h" -#include "prio.h" -#include "base/task.h" -#include "mozilla/Logging.h" -#include "mozilla/dom/ContentParent.h" -#include "GMPParent.h" -#include "GMPVideoDecoderParent.h" -#include "nsAutoPtr.h" -#include "nsIObserverService.h" -#include "GeckoChildProcessHost.h" -#include "mozilla/Preferences.h" -#include "mozilla/ClearOnShutdown.h" -#include "mozilla/SyncRunnable.h" -#include "nsXPCOMPrivate.h" -#include "mozilla/Services.h" -#include "nsNativeCharsetUtils.h" -#include "nsIConsoleService.h" -#include "mozilla/Unused.h" -#include "GMPDecryptorParent.h" -#include "GMPAudioDecoderParent.h" -#include "nsComponentManagerUtils.h" -#include "runnable_utils.h" -#include "VideoUtils.h" -#include "nsAppDirectoryServiceDefs.h" -#include "nsDirectoryServiceUtils.h" -#include "nsDirectoryServiceDefs.h" -#include "nsHashKeys.h" -#include "nsIFile.h" -#include "nsISimpleEnumerator.h" -#include "nsIXULRuntime.h" -#include "GMPDecoderModule.h" -#include <limits> -#include "MediaPrefs.h" - -using mozilla::ipc::Transport; - -namespace mozilla { - -#ifdef LOG -#undef LOG -#endif - -#define LOGD(msg) MOZ_LOG(GetGMPLog(), mozilla::LogLevel::Debug, msg) -#define LOG(level, msg) MOZ_LOG(GetGMPLog(), (level), msg) - -#ifdef __CLASS__ -#undef __CLASS__ -#endif -#define __CLASS__ "GMPService" - -namespace gmp { - -static const uint32_t NodeIdSaltLength = 32; - -already_AddRefed<GeckoMediaPluginServiceParent> -GeckoMediaPluginServiceParent::GetSingleton() -{ - MOZ_ASSERT(XRE_IsParentProcess()); - RefPtr<GeckoMediaPluginService> service( - GeckoMediaPluginServiceParent::GetGeckoMediaPluginService()); -#ifdef DEBUG - if (service) { - nsCOMPtr<mozIGeckoMediaPluginChromeService> chromeService; - CallQueryInterface(service.get(), getter_AddRefs(chromeService)); - MOZ_ASSERT(chromeService); - } -#endif - return service.forget().downcast<GeckoMediaPluginServiceParent>(); -} - -NS_IMPL_ISUPPORTS_INHERITED(GeckoMediaPluginServiceParent, - GeckoMediaPluginService, - mozIGeckoMediaPluginChromeService, - nsIAsyncShutdownBlocker) - -GeckoMediaPluginServiceParent::GeckoMediaPluginServiceParent() - : mShuttingDown(false) - , mScannedPluginOnDisk(false) - , mWaitingForPluginsSyncShutdown(false) - , mInitPromiseMonitor("GeckoMediaPluginServiceParent::mInitPromiseMonitor") - , mLoadPluginsFromDiskComplete(false) - , mServiceUserCount(0) -{ - MOZ_ASSERT(NS_IsMainThread()); - mInitPromise.SetMonitor(&mInitPromiseMonitor); -} - -GeckoMediaPluginServiceParent::~GeckoMediaPluginServiceParent() -{ - MOZ_ASSERT(mPlugins.IsEmpty()); - MOZ_ASSERT(mAsyncShutdownPlugins.IsEmpty()); -} - -int32_t -GeckoMediaPluginServiceParent::AsyncShutdownTimeoutMs() -{ - return MediaPrefs::GMPAsyncShutdownTimeout(); -} - -nsresult -GeckoMediaPluginServiceParent::Init() -{ - MOZ_ASSERT(NS_IsMainThread()); - - nsCOMPtr<nsIObserverService> obsService = mozilla::services::GetObserverService(); - MOZ_ASSERT(obsService); - MOZ_ALWAYS_SUCCEEDS(obsService->AddObserver(this, "profile-change-teardown", false)); - MOZ_ALWAYS_SUCCEEDS(obsService->AddObserver(this, "last-pb-context-exited", false)); - MOZ_ALWAYS_SUCCEEDS(obsService->AddObserver(this, "browser:purge-session-history", false)); - -#ifdef DEBUG - MOZ_ALWAYS_SUCCEEDS(obsService->AddObserver(this, "mediakeys-request", false)); -#endif - - nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID); - if (prefs) { - prefs->AddObserver("media.gmp.plugin.crash", this, false); - } - - nsresult rv = InitStorage(); - if (NS_FAILED(rv)) { - return rv; - } - - // Kick off scanning for plugins - nsCOMPtr<nsIThread> thread; - rv = GetThread(getter_AddRefs(thread)); - if (NS_FAILED(rv)) { - return rv; - } - - // Detect if GMP storage has an incompatible version, and if so nuke it. - int32_t version = Preferences::GetInt("media.gmp.storage.version.observed", 0); - int32_t expected = Preferences::GetInt("media.gmp.storage.version.expected", 0); - if (version != expected) { - Preferences::SetInt("media.gmp.storage.version.observed", expected); - return GMPDispatch(NewRunnableMethod( - this, &GeckoMediaPluginServiceParent::ClearStorage)); - } - return NS_OK; -} - -already_AddRefed<nsIFile> -CloneAndAppend(nsIFile* aFile, const nsAString& aDir) -{ - nsCOMPtr<nsIFile> f; - nsresult rv = aFile->Clone(getter_AddRefs(f)); - if (NS_WARN_IF(NS_FAILED(rv))) { - return nullptr; - } - - rv = f->Append(aDir); - if (NS_WARN_IF(NS_FAILED(rv))) { - return nullptr; - } - return f.forget(); -} - -static nsresult -GMPPlatformString(nsAString& aOutPlatform) -{ - // Append the OS and arch so that we don't reuse the storage if the profile is - // copied or used under a different bit-ness, or copied to another platform. - nsCOMPtr<nsIXULRuntime> runtime = do_GetService("@mozilla.org/xre/runtime;1"); - if (!runtime) { - return NS_ERROR_FAILURE; - } - - nsAutoCString OS; - nsresult rv = runtime->GetOS(OS); - if (NS_FAILED(rv)) { - return rv; - } - - nsAutoCString arch; - rv = runtime->GetXPCOMABI(arch); - if (NS_FAILED(rv)) { - return rv; - } - - nsCString platform; - platform.Append(OS); - platform.AppendLiteral("_"); - platform.Append(arch); - - aOutPlatform = NS_ConvertUTF8toUTF16(platform); - - return NS_OK; -} - -nsresult -GeckoMediaPluginServiceParent::InitStorage() -{ - MOZ_ASSERT(NS_IsMainThread()); - - // GMP storage should be used in the chrome process only. - if (!XRE_IsParentProcess()) { - return NS_OK; - } - - // Directory service is main thread only, so cache the profile dir here - // so that we can use it off main thread. - nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(mStorageBaseDir)); - - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - rv = mStorageBaseDir->AppendNative(NS_LITERAL_CSTRING("gmp")); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - rv = mStorageBaseDir->Create(nsIFile::DIRECTORY_TYPE, 0700); - if (NS_WARN_IF(NS_FAILED(rv) && rv != NS_ERROR_FILE_ALREADY_EXISTS)) { - return rv; - } - - nsCOMPtr<nsIFile> gmpDirWithoutPlatform; - rv = mStorageBaseDir->Clone(getter_AddRefs(gmpDirWithoutPlatform)); - if (NS_FAILED(rv)) { - return rv; - } - - nsAutoString platform; - rv = GMPPlatformString(platform); - if (NS_FAILED(rv)) { - return rv; - } - - rv = mStorageBaseDir->Append(platform); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - rv = mStorageBaseDir->Create(nsIFile::DIRECTORY_TYPE, 0700); - if (NS_WARN_IF(NS_FAILED(rv) && rv != NS_ERROR_FILE_ALREADY_EXISTS)) { - return rv; - } - - return GeckoMediaPluginService::Init(); -} - -NS_IMETHODIMP -GeckoMediaPluginServiceParent::Observe(nsISupports* aSubject, - const char* aTopic, - const char16_t* aSomeData) -{ - LOGD(("%s::%s topic='%s' data='%s'", __CLASS__, __FUNCTION__, - aTopic, NS_ConvertUTF16toUTF8(aSomeData).get())); - if (!strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) { - nsCOMPtr<nsIPrefBranch> branch( do_QueryInterface(aSubject) ); - if (branch) { - bool crashNow = false; - if (NS_LITERAL_STRING("media.gmp.plugin.crash").Equals(aSomeData)) { - branch->GetBoolPref("media.gmp.plugin.crash", &crashNow); - } - if (crashNow) { - nsCOMPtr<nsIThread> gmpThread; - { - MutexAutoLock lock(mMutex); - gmpThread = mGMPThread; - } - if (gmpThread) { - gmpThread->Dispatch(WrapRunnable(this, - &GeckoMediaPluginServiceParent::CrashPlugins), - NS_DISPATCH_NORMAL); - } - } - } - } else if (!strcmp("profile-change-teardown", aTopic)) { - - // How shutdown works: - // - // Some GMPs require time to do bookkeeping upon shutdown. These GMPs - // need to be given time to access storage during shutdown. To signal - // that time to shutdown is required, those GMPs implement the - // GMPAsyncShutdown interface. - // - // When we startup the child process, we query the GMP for the - // GMPAsyncShutdown interface, and if it's present, we send a message - // back to the GMPParent, which then registers the GMPParent by calling - // GMPService::AsyncShutdownNeeded(). - // - // On shutdown, we set mWaitingForPluginsSyncShutdown to true, and then - // call UnloadPlugins on the GMPThread, and process events on the main - // thread until 1. An event sets mWaitingForPluginsSyncShutdown=false on - // the main thread; then 2. All async-shutdown plugins have indicated - // they have completed shutdown. - // - // UnloadPlugins() sends close messages for all plugins' API objects to - // the GMP interfaces in the child process, and then sends the async - // shutdown notifications to child GMPs. When a GMP has completed its - // shutdown, it calls GMPAsyncShutdownHost::ShutdownComplete(), which - // sends a message back to the parent, which calls - // GMPService::AsyncShutdownComplete(). If all plugins requiring async - // shutdown have called AsyncShutdownComplete() we stick a dummy event on - // the main thread, where the list of pending plugins is checked. We must - // use an event to do this, as we must ensure the main thread processes an - // event to run its loop. This will unblock the main thread, and shutdown - // of other components will proceed. - // - // During shutdown, each GMPParent starts a timer, and pretends shutdown - // is complete if it is taking too long. - // - // We shutdown in "profile-change-teardown", as the profile dir is - // still writable then, and it's required for GMPStorage. We block the - // shutdown process by spinning the main thread event loop until all GMPs - // have shutdown, or timeout has occurred. - // - // GMPStorage needs to work up until the shutdown-complete notification - // arrives from the GMP process. - - mWaitingForPluginsSyncShutdown = true; - - nsCOMPtr<nsIThread> gmpThread; - { - MutexAutoLock lock(mMutex); - MOZ_ASSERT(!mShuttingDown); - mShuttingDown = true; - gmpThread = mGMPThread; - } - - if (gmpThread) { - LOGD(("%s::%s Starting to unload plugins, waiting for first sync shutdown..." - , __CLASS__, __FUNCTION__)); - gmpThread->Dispatch( - NewRunnableMethod(this, - &GeckoMediaPluginServiceParent::UnloadPlugins), - NS_DISPATCH_NORMAL); - - // Wait for UnloadPlugins() to do initial sync shutdown... - while (mWaitingForPluginsSyncShutdown) { - NS_ProcessNextEvent(NS_GetCurrentThread(), true); - } - - // Wait for other plugins (if any) to do async shutdown... - auto syncShutdownPluginsRemaining = - std::numeric_limits<decltype(mAsyncShutdownPlugins.Length())>::max(); - for (;;) { - { - MutexAutoLock lock(mMutex); - if (mAsyncShutdownPlugins.IsEmpty()) { - LOGD(("%s::%s Finished unloading all plugins" - , __CLASS__, __FUNCTION__)); - break; - } else if (mAsyncShutdownPlugins.Length() < syncShutdownPluginsRemaining) { - // First time here, or number of pending plugins has decreased. - // -> Update list of pending plugins in crash report. - syncShutdownPluginsRemaining = mAsyncShutdownPlugins.Length(); - LOGD(("%s::%s Still waiting for %d plugins to shutdown..." - , __CLASS__, __FUNCTION__, (int)syncShutdownPluginsRemaining)); - } - } - NS_ProcessNextEvent(NS_GetCurrentThread(), true); - } - } else { - // GMP thread has already shutdown. - MOZ_ASSERT(mPlugins.IsEmpty()); - mWaitingForPluginsSyncShutdown = false; - } - - } else if (!strcmp(NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID, aTopic)) { - MOZ_ASSERT(mShuttingDown); - ShutdownGMPThread(); - } else if (!strcmp("last-pb-context-exited", aTopic)) { - // When Private Browsing mode exits, all we need to do is clear - // mTempNodeIds. This drops all the node ids we've cached in memory - // for PB origin-pairs. If we try to open an origin-pair for non-PB - // mode, we'll get the NodeId salt stored on-disk, and if we try to - // open a PB mode origin-pair, we'll re-generate new salt. - mTempNodeIds.Clear(); - } else if (!strcmp("browser:purge-session-history", aTopic)) { - // Clear everything! - if (!aSomeData || nsDependentString(aSomeData).IsEmpty()) { - return GMPDispatch(NewRunnableMethod( - this, &GeckoMediaPluginServiceParent::ClearStorage)); - } - - // Clear nodeIds/records modified after |t|. - nsresult rv; - PRTime t = nsDependentString(aSomeData).ToInteger64(&rv, 10); - if (NS_FAILED(rv)) { - return rv; - } - return GMPDispatch(NewRunnableMethod<PRTime>( - this, &GeckoMediaPluginServiceParent::ClearRecentHistoryOnGMPThread, - t)); - } - - return NS_OK; -} - -RefPtr<GenericPromise> -GeckoMediaPluginServiceParent::EnsureInitialized() { - MonitorAutoLock lock(mInitPromiseMonitor); - if (mLoadPluginsFromDiskComplete) { - return GenericPromise::CreateAndResolve(true, __func__); - } - // We should have an init promise in flight. - MOZ_ASSERT(!mInitPromise.IsEmpty()); - return mInitPromise.Ensure(__func__); -} - -bool -GeckoMediaPluginServiceParent::GetContentParentFrom(GMPCrashHelper* aHelper, - const nsACString& aNodeId, - const nsCString& aAPI, - const nsTArray<nsCString>& aTags, - UniquePtr<GetGMPContentParentCallback>&& aCallback) -{ - RefPtr<AbstractThread> thread(GetAbstractGMPThread()); - if (!thread) { - return false; - } - - RefPtr<GeckoMediaPluginServiceParent> self(this); - nsCString nodeId(aNodeId); - nsTArray<nsCString> tags(aTags); - nsCString api(aAPI); - GetGMPContentParentCallback* rawCallback = aCallback.release(); - RefPtr<GMPCrashHelper> helper(aHelper); - EnsureInitialized()->Then(thread, __func__, - [self, tags, api, nodeId, rawCallback, helper]() -> void { - UniquePtr<GetGMPContentParentCallback> callback(rawCallback); - RefPtr<GMPParent> gmp = self->SelectPluginForAPI(nodeId, api, tags); - LOGD(("%s: %p returning %p for api %s", __FUNCTION__, (void *)self, (void *)gmp, api.get())); - if (!gmp) { - NS_WARNING("GeckoMediaPluginServiceParent::GetContentParentFrom failed"); - callback->Done(nullptr); - return; - } - self->ConnectCrashHelper(gmp->GetPluginId(), helper); - gmp->GetGMPContentParent(Move(callback)); - }, - [rawCallback]() -> void { - UniquePtr<GetGMPContentParentCallback> callback(rawCallback); - NS_WARNING("GMPService::EnsureInitialized failed."); - callback->Done(nullptr); - }); - return true; -} - -void -GeckoMediaPluginServiceParent::InitializePlugins( - AbstractThread* aAbstractGMPThread) -{ - MOZ_ASSERT(aAbstractGMPThread); - MonitorAutoLock lock(mInitPromiseMonitor); - if (mLoadPluginsFromDiskComplete) { - return; - } - - RefPtr<GeckoMediaPluginServiceParent> self(this); - RefPtr<GenericPromise> p = mInitPromise.Ensure(__func__); - InvokeAsync(aAbstractGMPThread, this, __func__, - &GeckoMediaPluginServiceParent::LoadFromEnvironment) - ->Then(aAbstractGMPThread, __func__, - [self]() -> void { - MonitorAutoLock lock(self->mInitPromiseMonitor); - self->mLoadPluginsFromDiskComplete = true; - self->mInitPromise.Resolve(true, __func__); - }, - [self]() -> void { - MonitorAutoLock lock(self->mInitPromiseMonitor); - self->mLoadPluginsFromDiskComplete = true; - self->mInitPromise.Reject(NS_ERROR_FAILURE, __func__); - }); -} - -void -GeckoMediaPluginServiceParent::AsyncShutdownNeeded(GMPParent* aParent) -{ - LOGD(("%s::%s %p", __CLASS__, __FUNCTION__, aParent)); - MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); - - MutexAutoLock lock(mMutex); - MOZ_ASSERT(!mAsyncShutdownPlugins.Contains(aParent)); - mAsyncShutdownPlugins.AppendElement(aParent); -} - -void -GeckoMediaPluginServiceParent::AsyncShutdownComplete(GMPParent* aParent) -{ - LOGD(("%s::%s %p '%s'", __CLASS__, __FUNCTION__, - aParent, aParent->GetDisplayName().get())); - MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); - - { - MutexAutoLock lock(mMutex); - mAsyncShutdownPlugins.RemoveElement(aParent); - } - - if (mShuttingDownOnGMPThread) { - // The main thread may be waiting for async shutdown of plugins, - // one of which has completed. Wake up the main thread by sending a task. - nsCOMPtr<nsIRunnable> task(NewRunnableMethod( - this, &GeckoMediaPluginServiceParent::NotifyAsyncShutdownComplete)); - NS_DispatchToMainThread(task); - } -} - -void -GeckoMediaPluginServiceParent::NotifyAsyncShutdownComplete() -{ - MOZ_ASSERT(NS_IsMainThread()); - // Nothing to do, this task is just used to wake up the event loop in Observe(). -} - -void -GeckoMediaPluginServiceParent::NotifySyncShutdownComplete() -{ - MOZ_ASSERT(NS_IsMainThread()); - mWaitingForPluginsSyncShutdown = false; -} - -bool -GeckoMediaPluginServiceParent::IsShuttingDown() -{ - MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); - return mShuttingDownOnGMPThread; -} - -void -GeckoMediaPluginServiceParent::UnloadPlugins() -{ - MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); - MOZ_ASSERT(!mShuttingDownOnGMPThread); - mShuttingDownOnGMPThread = true; - - nsTArray<RefPtr<GMPParent>> plugins; - { - MutexAutoLock lock(mMutex); - // Move all plugins references to a local array. This way mMutex won't be - // locked when calling CloseActive (to avoid inter-locking). - Swap(plugins, mPlugins); - } - - LOGD(("%s::%s plugins:%u including async:%u", __CLASS__, __FUNCTION__, - plugins.Length(), mAsyncShutdownPlugins.Length())); -#ifdef DEBUG - for (const auto& plugin : plugins) { - LOGD(("%s::%s plugin: '%s'", __CLASS__, __FUNCTION__, - plugin->GetDisplayName().get())); - } - for (const auto& plugin : mAsyncShutdownPlugins) { - LOGD(("%s::%s async plugin: '%s'", __CLASS__, __FUNCTION__, - plugin->GetDisplayName().get())); - } -#endif - // Note: CloseActive may be async; it could actually finish - // shutting down when all the plugins have unloaded. - for (const auto& plugin : plugins) { - plugin->CloseActive(true); - } - - nsCOMPtr<nsIRunnable> task(NewRunnableMethod( - this, &GeckoMediaPluginServiceParent::NotifySyncShutdownComplete)); - NS_DispatchToMainThread(task); -} - -void -GeckoMediaPluginServiceParent::CrashPlugins() -{ - LOGD(("%s::%s", __CLASS__, __FUNCTION__)); - MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); - - MutexAutoLock lock(mMutex); - for (size_t i = 0; i < mPlugins.Length(); i++) { - mPlugins[i]->Crash(); - } -} - -RefPtr<GenericPromise::AllPromiseType> -GeckoMediaPluginServiceParent::LoadFromEnvironment() -{ - MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); - RefPtr<AbstractThread> thread(GetAbstractGMPThread()); - if (!thread) { - return GenericPromise::AllPromiseType::CreateAndReject(NS_ERROR_FAILURE, __func__); - } - - const char* env = PR_GetEnv("MOZ_GMP_PATH"); - if (!env || !*env) { - return GenericPromise::AllPromiseType::CreateAndResolve(true, __func__); - } - - nsString allpaths; - if (NS_WARN_IF(NS_FAILED(NS_CopyNativeToUnicode(nsDependentCString(env), allpaths)))) { - return GenericPromise::AllPromiseType::CreateAndReject(NS_ERROR_FAILURE, __func__); - } - - nsTArray<RefPtr<GenericPromise>> promises; - uint32_t pos = 0; - while (pos < allpaths.Length()) { - // Loop over multiple path entries separated by colons (*nix) or - // semicolons (Windows) - int32_t next = allpaths.FindChar(XPCOM_ENV_PATH_SEPARATOR[0], pos); - if (next == -1) { - promises.AppendElement(AddOnGMPThread(nsString(Substring(allpaths, pos)))); - break; - } else { - promises.AppendElement(AddOnGMPThread(nsString(Substring(allpaths, pos, next - pos)))); - pos = next + 1; - } - } - - mScannedPluginOnDisk = true; - return GenericPromise::All(thread, promises); -} - -class NotifyObserversTask final : public mozilla::Runnable { -public: - explicit NotifyObserversTask(const char* aTopic, nsString aData = EmptyString()) - : mTopic(aTopic) - , mData(aData) - {} - NS_IMETHOD Run() override { - MOZ_ASSERT(NS_IsMainThread()); - nsCOMPtr<nsIObserverService> obsService = mozilla::services::GetObserverService(); - MOZ_ASSERT(obsService); - if (obsService) { - obsService->NotifyObservers(nullptr, mTopic, mData.get()); - } - return NS_OK; - } -private: - ~NotifyObserversTask() {} - const char* mTopic; - const nsString mData; -}; - -NS_IMETHODIMP -GeckoMediaPluginServiceParent::PathRunnable::Run() -{ - mService->RemoveOnGMPThread(mPath, - mOperation == REMOVE_AND_DELETE_FROM_DISK, - mDefer); - - mService->UpdateContentProcessGMPCapabilities(); - return NS_OK; -} - -void -GeckoMediaPluginServiceParent::UpdateContentProcessGMPCapabilities() -{ - if (!NS_IsMainThread()) { - nsCOMPtr<nsIRunnable> task = - NewRunnableMethod(this, &GeckoMediaPluginServiceParent::UpdateContentProcessGMPCapabilities); - NS_DispatchToMainThread(task); - return; - } - - typedef mozilla::dom::GMPCapabilityData GMPCapabilityData; - typedef mozilla::dom::GMPAPITags GMPAPITags; - typedef mozilla::dom::ContentParent ContentParent; - - nsTArray<GMPCapabilityData> caps; - { - MutexAutoLock lock(mMutex); - for (const RefPtr<GMPParent>& gmp : mPlugins) { - // We have multiple instances of a GMPParent for a given GMP in the - // list, one per origin. So filter the list so that we don't include - // the same GMP's capabilities twice. - NS_ConvertUTF16toUTF8 name(gmp->GetPluginBaseName()); - bool found = false; - for (const GMPCapabilityData& cap : caps) { - if (cap.name().Equals(name)) { - found = true; - break; - } - } - if (found) { - continue; - } - GMPCapabilityData x; - x.name() = name; - x.version() = gmp->GetVersion(); - for (const GMPCapability& tag : gmp->GetCapabilities()) { - x.capabilities().AppendElement(GMPAPITags(tag.mAPIName, tag.mAPITags)); - } - caps.AppendElement(Move(x)); - } - } - for (auto* cp : ContentParent::AllProcesses(ContentParent::eLive)) { - Unused << cp->SendGMPsChanged(caps); - } - - // For non-e10s, we must fire a notification so that any MediaKeySystemAccess - // requests waiting on a CDM to download will retry. - nsCOMPtr<nsIObserverService> obsService = mozilla::services::GetObserverService(); - MOZ_ASSERT(obsService); - if (obsService) { - obsService->NotifyObservers(nullptr, "gmp-changed", nullptr); - } -} - -RefPtr<GenericPromise> -GeckoMediaPluginServiceParent::AsyncAddPluginDirectory(const nsAString& aDirectory) -{ - RefPtr<AbstractThread> thread(GetAbstractGMPThread()); - if (!thread) { - return GenericPromise::CreateAndReject(NS_ERROR_FAILURE, __func__); - } - - nsString dir(aDirectory); - RefPtr<GeckoMediaPluginServiceParent> self = this; - return InvokeAsync(thread, this, __func__, &GeckoMediaPluginServiceParent::AddOnGMPThread, dir) - ->Then(AbstractThread::MainThread(), __func__, - [dir, self]() -> void { - LOGD(("GeckoMediaPluginServiceParent::AsyncAddPluginDirectory %s succeeded", - NS_ConvertUTF16toUTF8(dir).get())); - MOZ_ASSERT(NS_IsMainThread()); - self->UpdateContentProcessGMPCapabilities(); - }, - [dir]() -> void { - LOGD(("GeckoMediaPluginServiceParent::AsyncAddPluginDirectory %s failed", - NS_ConvertUTF16toUTF8(dir).get())); - }) - ->CompletionPromise(); -} - -NS_IMETHODIMP -GeckoMediaPluginServiceParent::AddPluginDirectory(const nsAString& aDirectory) -{ - MOZ_ASSERT(NS_IsMainThread()); - RefPtr<GenericPromise> p = AsyncAddPluginDirectory(aDirectory); - Unused << p; - return NS_OK; -} - -NS_IMETHODIMP -GeckoMediaPluginServiceParent::RemovePluginDirectory(const nsAString& aDirectory) -{ - MOZ_ASSERT(NS_IsMainThread()); - return GMPDispatch(new PathRunnable(this, aDirectory, - PathRunnable::EOperation::REMOVE)); -} - -NS_IMETHODIMP -GeckoMediaPluginServiceParent::RemoveAndDeletePluginDirectory( - const nsAString& aDirectory, const bool aDefer) -{ - MOZ_ASSERT(NS_IsMainThread()); - return GMPDispatch( - new PathRunnable(this, aDirectory, - PathRunnable::EOperation::REMOVE_AND_DELETE_FROM_DISK, - aDefer)); -} - -NS_IMETHODIMP -GeckoMediaPluginServiceParent::HasPluginForAPI(const nsACString& aAPI, - nsTArray<nsCString>* aTags, - bool* aHasPlugin) -{ - NS_ENSURE_ARG(aTags && aTags->Length() > 0); - NS_ENSURE_ARG(aHasPlugin); - - nsresult rv = EnsurePluginsOnDiskScanned(); - if (NS_FAILED(rv)) { - NS_WARNING("Failed to load GMPs from disk."); - return rv; - } - - { - MutexAutoLock lock(mMutex); - nsCString api(aAPI); - size_t index = 0; - RefPtr<GMPParent> gmp = FindPluginForAPIFrom(index, api, *aTags, &index); - *aHasPlugin = !!gmp; - } - - return NS_OK; -} - -nsresult -GeckoMediaPluginServiceParent::EnsurePluginsOnDiskScanned() -{ - const char* env = nullptr; - if (!mScannedPluginOnDisk && (env = PR_GetEnv("MOZ_GMP_PATH")) && *env) { - // We have a MOZ_GMP_PATH environment variable which may specify the - // location of plugins to load, and we haven't yet scanned the disk to - // see if there are plugins there. Get the GMP thread, which will - // cause an event to be dispatched to which scans for plugins. We - // dispatch a sync event to the GMP thread here in order to wait until - // after the GMP thread has scanned any paths in MOZ_GMP_PATH. - nsresult rv = GMPDispatch(new mozilla::Runnable(), NS_DISPATCH_SYNC); - NS_ENSURE_SUCCESS(rv, rv); - MOZ_ASSERT(mScannedPluginOnDisk, "Should have scanned MOZ_GMP_PATH by now"); - } - - return NS_OK; -} - -already_AddRefed<GMPParent> -GeckoMediaPluginServiceParent::FindPluginForAPIFrom(size_t aSearchStartIndex, - const nsCString& aAPI, - const nsTArray<nsCString>& aTags, - size_t* aOutPluginIndex) -{ - mMutex.AssertCurrentThreadOwns(); - for (size_t i = aSearchStartIndex; i < mPlugins.Length(); i++) { - RefPtr<GMPParent> gmp = mPlugins[i]; - if (!GMPCapability::Supports(gmp->GetCapabilities(), aAPI, aTags)) { - continue; - } - if (aOutPluginIndex) { - *aOutPluginIndex = i; - } - return gmp.forget(); - } - return nullptr; -} - -already_AddRefed<GMPParent> -GeckoMediaPluginServiceParent::SelectPluginForAPI(const nsACString& aNodeId, - const nsCString& aAPI, - const nsTArray<nsCString>& aTags) -{ - MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread, - "Can't clone GMP plugins on non-GMP threads."); - - GMPParent* gmpToClone = nullptr; - { - MutexAutoLock lock(mMutex); - size_t index = 0; - RefPtr<GMPParent> gmp; - while ((gmp = FindPluginForAPIFrom(index, aAPI, aTags, &index))) { - if (aNodeId.IsEmpty()) { - if (gmp->CanBeSharedCrossNodeIds()) { - return gmp.forget(); - } - } else if (gmp->CanBeUsedFrom(aNodeId)) { - return gmp.forget(); - } - - if (!gmpToClone || - (gmpToClone->IsMarkedForDeletion() && !gmp->IsMarkedForDeletion())) { - // This GMP has the correct type but has the wrong nodeId; hold on to it - // in case we need to clone it. - // Prefer GMPs in-use for the case where an upgraded plugin version is - // waiting for the old one to die. If the old plugin is in use, we - // should continue using it so that any persistent state remains - // consistent. Otherwise, just check that the plugin isn't scheduled - // for deletion. - gmpToClone = gmp; - } - // Loop around and try the next plugin; it may be usable from aNodeId. - index++; - } - } - - // Plugin exists, but we can't use it due to cross-origin separation. Create a - // new one. - if (gmpToClone) { - RefPtr<GMPParent> clone = ClonePlugin(gmpToClone); - { - MutexAutoLock lock(mMutex); - mPlugins.AppendElement(clone); - } - if (!aNodeId.IsEmpty()) { - clone->SetNodeId(aNodeId); - } - return clone.forget(); - } - - return nullptr; -} - -RefPtr<GMPParent> -CreateGMPParent() -{ - return new GMPParent(); -} - -already_AddRefed<GMPParent> -GeckoMediaPluginServiceParent::ClonePlugin(const GMPParent* aOriginal) -{ - MOZ_ASSERT(aOriginal); - - RefPtr<GMPParent> gmp = CreateGMPParent(); - nsresult rv = gmp ? gmp->CloneFrom(aOriginal) : NS_ERROR_NOT_AVAILABLE; - - if (NS_FAILED(rv)) { - NS_WARNING("Can't Create GMPParent"); - return nullptr; - } - - return gmp.forget(); -} - -RefPtr<GenericPromise> -GeckoMediaPluginServiceParent::AddOnGMPThread(nsString aDirectory) -{ - MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); - nsCString dir = NS_ConvertUTF16toUTF8(aDirectory); - RefPtr<AbstractThread> thread(GetAbstractGMPThread()); - if (!thread) { - LOGD(("%s::%s: %s No GMP Thread", __CLASS__, __FUNCTION__, dir.get())); - return GenericPromise::CreateAndReject(NS_ERROR_FAILURE, __func__); - } - LOGD(("%s::%s: %s", __CLASS__, __FUNCTION__, dir.get())); - - nsCOMPtr<nsIFile> directory; - nsresult rv = NS_NewLocalFile(aDirectory, false, getter_AddRefs(directory)); - if (NS_WARN_IF(NS_FAILED(rv))) { - return GenericPromise::CreateAndReject(NS_ERROR_FAILURE, __func__); - } - - RefPtr<GMPParent> gmp = CreateGMPParent(); - if (!gmp) { - NS_WARNING("Can't Create GMPParent"); - return GenericPromise::CreateAndReject(NS_ERROR_FAILURE, __func__); - } - - RefPtr<GeckoMediaPluginServiceParent> self(this); - return gmp->Init(this, directory)->Then(thread, __func__, - [gmp, self, dir]() -> void { - LOGD(("%s::%s: %s Succeeded", __CLASS__, __FUNCTION__, dir.get())); - { - MutexAutoLock lock(self->mMutex); - self->mPlugins.AppendElement(gmp); - } - }, - [dir]() -> void { - LOGD(("%s::%s: %s Failed", __CLASS__, __FUNCTION__, dir.get())); - }) - ->CompletionPromise(); -} - -void -GeckoMediaPluginServiceParent::RemoveOnGMPThread(const nsAString& aDirectory, - const bool aDeleteFromDisk, - const bool aCanDefer) -{ - MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); - LOGD(("%s::%s: %s", __CLASS__, __FUNCTION__, NS_LossyConvertUTF16toASCII(aDirectory).get())); - - nsCOMPtr<nsIFile> directory; - nsresult rv = NS_NewLocalFile(aDirectory, false, getter_AddRefs(directory)); - if (NS_WARN_IF(NS_FAILED(rv))) { - return; - } - - // Plugin destruction can modify |mPlugins|. Put them aside for now and - // destroy them once we're done with |mPlugins|. - nsTArray<RefPtr<GMPParent>> deadPlugins; - - bool inUse = false; - MutexAutoLock lock(mMutex); - for (size_t i = mPlugins.Length(); i-- > 0; ) { - nsCOMPtr<nsIFile> pluginpath = mPlugins[i]->GetDirectory(); - bool equals; - if (NS_FAILED(directory->Equals(pluginpath, &equals)) || !equals) { - continue; - } - - RefPtr<GMPParent> gmp = mPlugins[i]; - if (aDeleteFromDisk && gmp->State() != GMPStateNotLoaded) { - // We have to wait for the child process to release its lib handle - // before we can delete the GMP. - inUse = true; - gmp->MarkForDeletion(); - - if (!mPluginsWaitingForDeletion.Contains(aDirectory)) { - mPluginsWaitingForDeletion.AppendElement(aDirectory); - } - } - - if (gmp->State() == GMPStateNotLoaded || !aCanDefer) { - // GMP not in use or shutdown is being forced; can shut it down now. - deadPlugins.AppendElement(gmp); - mPlugins.RemoveElementAt(i); - } - } - - { - MutexAutoUnlock unlock(mMutex); - for (auto& gmp : deadPlugins) { - gmp->AbortAsyncShutdown(); - gmp->CloseActive(true); - } - } - - if (aDeleteFromDisk && !inUse) { - // Ensure the GMP dir and all files in it are writable, so we have - // permission to delete them. - directory->SetPermissions(0700); - DirectoryEnumerator iter(directory, DirectoryEnumerator::FilesAndDirs); - for (nsCOMPtr<nsIFile> dirEntry; (dirEntry = iter.Next()) != nullptr;) { - dirEntry->SetPermissions(0700); - } - if (NS_SUCCEEDED(directory->Remove(true))) { - mPluginsWaitingForDeletion.RemoveElement(aDirectory); - NS_DispatchToMainThread(new NotifyObserversTask("gmp-directory-deleted", - nsString(aDirectory)), - NS_DISPATCH_NORMAL); - } - } -} - -// May remove when Bug 1043671 is fixed -static void Dummy(RefPtr<GMPParent>& aOnDeathsDoor) -{ - // exists solely to do nothing and let the Runnable kill the GMPParent - // when done. -} - -void -GeckoMediaPluginServiceParent::PluginTerminated(const RefPtr<GMPParent>& aPlugin) -{ - MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); - - if (aPlugin->IsMarkedForDeletion()) { - nsCString path8; - RefPtr<nsIFile> dir = aPlugin->GetDirectory(); - nsresult rv = dir->GetNativePath(path8); - NS_ENSURE_SUCCESS_VOID(rv); - - nsString path = NS_ConvertUTF8toUTF16(path8); - if (mPluginsWaitingForDeletion.Contains(path)) { - RemoveOnGMPThread(path, true /* delete */, true /* can defer */); - } - } -} - -void -GeckoMediaPluginServiceParent::ReAddOnGMPThread(const RefPtr<GMPParent>& aOld) -{ - MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); - LOGD(("%s::%s: %p", __CLASS__, __FUNCTION__, (void*) aOld)); - - RefPtr<GMPParent> gmp; - if (!mShuttingDownOnGMPThread) { - // We're not shutting down, so replace the old plugin in the list with a - // clone which is in a pristine state. Note: We place the plugin in - // the same slot in the array as a hack to ensure if we re-request with - // the same capabilities we get an instance of the same plugin. - gmp = ClonePlugin(aOld); - MutexAutoLock lock(mMutex); - MOZ_ASSERT(mPlugins.Contains(aOld)); - if (mPlugins.Contains(aOld)) { - mPlugins[mPlugins.IndexOf(aOld)] = gmp; - } - } else { - // We're shutting down; don't re-add plugin, let the old plugin die. - MutexAutoLock lock(mMutex); - mPlugins.RemoveElement(aOld); - } - // Schedule aOld to be destroyed. We can't destroy it from here since we - // may be inside ActorDestroyed() for it. - NS_DispatchToCurrentThread(WrapRunnableNM(&Dummy, aOld)); -} - -NS_IMETHODIMP -GeckoMediaPluginServiceParent::GetStorageDir(nsIFile** aOutFile) -{ - if (NS_WARN_IF(!mStorageBaseDir)) { - return NS_ERROR_FAILURE; - } - return mStorageBaseDir->Clone(aOutFile); -} - -static nsresult -WriteToFile(nsIFile* aPath, - const nsCString& aFileName, - const nsCString& aData) -{ - nsCOMPtr<nsIFile> path; - nsresult rv = aPath->Clone(getter_AddRefs(path)); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - rv = path->AppendNative(aFileName); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - PRFileDesc* f = nullptr; - rv = path->OpenNSPRFileDesc(PR_WRONLY | PR_CREATE_FILE, PR_IRWXU, &f); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - int32_t len = PR_Write(f, aData.get(), aData.Length()); - PR_Close(f); - if (NS_WARN_IF(len < 0 || (size_t)len != aData.Length())) { - return NS_ERROR_FAILURE; - } - - return NS_OK; -} - -static nsresult -ReadFromFile(nsIFile* aPath, - const nsACString& aFileName, - nsACString& aOutData, - int32_t aMaxLength) -{ - nsCOMPtr<nsIFile> path; - nsresult rv = aPath->Clone(getter_AddRefs(path)); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - rv = path->AppendNative(aFileName); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - PRFileDesc* f = nullptr; - rv = path->OpenNSPRFileDesc(PR_RDONLY | PR_CREATE_FILE, PR_IRWXU, &f); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - auto size = PR_Seek(f, 0, PR_SEEK_END); - PR_Seek(f, 0, PR_SEEK_SET); - - if (size > aMaxLength) { - return NS_ERROR_FAILURE; - } - aOutData.SetLength(size); - - auto len = PR_Read(f, aOutData.BeginWriting(), size); - PR_Close(f); - if (NS_WARN_IF(len != size)) { - return NS_ERROR_FAILURE; - } - - return NS_OK; -} - -nsresult -ReadSalt(nsIFile* aPath, nsACString& aOutData) -{ - return ReadFromFile(aPath, NS_LITERAL_CSTRING("salt"), - aOutData, NodeIdSaltLength); - -} - -already_AddRefed<GMPStorage> -GeckoMediaPluginServiceParent::GetMemoryStorageFor(const nsACString& aNodeId) -{ - RefPtr<GMPStorage> s; - if (!mTempGMPStorage.Get(aNodeId, getter_AddRefs(s))) { - s = CreateGMPMemoryStorage(); - mTempGMPStorage.Put(aNodeId, s); - } - return s.forget(); -} - -NS_IMETHODIMP -GeckoMediaPluginServiceParent::IsPersistentStorageAllowed(const nsACString& aNodeId, - bool* aOutAllowed) -{ - MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); - NS_ENSURE_ARG(aOutAllowed); - // We disallow persistent storage for the NodeId used for shared GMP - // decoding, to prevent GMP decoding being used to track what a user - // watches somehow. - *aOutAllowed = !aNodeId.Equals(SHARED_GMP_DECODING_NODE_ID) && - mPersistentStorageAllowed.Get(aNodeId); - return NS_OK; -} - -nsresult -GeckoMediaPluginServiceParent::GetNodeId(const nsAString& aOrigin, - const nsAString& aTopLevelOrigin, - const nsAString& aGMPName, - bool aInPrivateBrowsing, - nsACString& aOutId) -{ - MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); - LOGD(("%s::%s: (%s, %s), %s", __CLASS__, __FUNCTION__, - NS_ConvertUTF16toUTF8(aOrigin).get(), - NS_ConvertUTF16toUTF8(aTopLevelOrigin).get(), - (aInPrivateBrowsing ? "PrivateBrowsing" : "NonPrivateBrowsing"))); - - nsresult rv; - - if (aOrigin.EqualsLiteral("null") || - aOrigin.IsEmpty() || - aTopLevelOrigin.EqualsLiteral("null") || - aTopLevelOrigin.IsEmpty()) { - // (origin, topLevelOrigin) is null or empty; this is for an anonymous - // origin, probably a local file, for which we don't provide persistent storage. - // Generate a random node id, and don't store it so that the GMP's storage - // is temporary and the process for this GMP is not shared with GMP - // instances that have the same nodeId. - nsAutoCString salt; - rv = GenerateRandomPathName(salt, NodeIdSaltLength); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - aOutId = salt; - mPersistentStorageAllowed.Put(salt, false); - return NS_OK; - } - - const uint32_t hash = AddToHash(HashString(aOrigin), - HashString(aTopLevelOrigin)); - - if (aInPrivateBrowsing) { - // For PB mode, we store the node id, indexed by the origin pair and GMP name, - // so that if the same origin pair is opened for the same GMP in this session, - // it gets the same node id. - const uint32_t pbHash = AddToHash(HashString(aGMPName), hash); - nsCString* salt = nullptr; - if (!(salt = mTempNodeIds.Get(pbHash))) { - // No salt stored, generate and temporarily store some for this id. - nsAutoCString newSalt; - rv = GenerateRandomPathName(newSalt, NodeIdSaltLength); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - salt = new nsCString(newSalt); - mTempNodeIds.Put(pbHash, salt); - mPersistentStorageAllowed.Put(*salt, false); - } - aOutId = *salt; - return NS_OK; - } - - // Otherwise, try to see if we've previously generated and stored salt - // for this origin pair. - nsCOMPtr<nsIFile> path; // $profileDir/gmp/$platform/ - rv = GetStorageDir(getter_AddRefs(path)); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - rv = path->Append(aGMPName); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - // $profileDir/gmp/$platform/$gmpName/ - rv = path->Create(nsIFile::DIRECTORY_TYPE, 0700); - if (rv != NS_ERROR_FILE_ALREADY_EXISTS && NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - rv = path->AppendNative(NS_LITERAL_CSTRING("id")); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - // $profileDir/gmp/$platform/$gmpName/id/ - rv = path->Create(nsIFile::DIRECTORY_TYPE, 0700); - if (rv != NS_ERROR_FILE_ALREADY_EXISTS && NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - nsAutoCString hashStr; - hashStr.AppendInt((int64_t)hash); - - // $profileDir/gmp/$platform/$gmpName/id/$hash - rv = path->AppendNative(hashStr); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - rv = path->Create(nsIFile::DIRECTORY_TYPE, 0700); - if (rv != NS_ERROR_FILE_ALREADY_EXISTS && NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - nsCOMPtr<nsIFile> saltFile; - rv = path->Clone(getter_AddRefs(saltFile)); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - rv = saltFile->AppendNative(NS_LITERAL_CSTRING("salt")); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - nsAutoCString salt; - bool exists = false; - rv = saltFile->Exists(&exists); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - if (!exists) { - // No stored salt for this origin. Generate salt, and store it and - // the origin on disk. - nsresult rv = GenerateRandomPathName(salt, NodeIdSaltLength); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - MOZ_ASSERT(salt.Length() == NodeIdSaltLength); - - // $profileDir/gmp/$platform/$gmpName/id/$hash/salt - rv = WriteToFile(path, NS_LITERAL_CSTRING("salt"), salt); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - // $profileDir/gmp/$platform/$gmpName/id/$hash/origin - rv = WriteToFile(path, - NS_LITERAL_CSTRING("origin"), - NS_ConvertUTF16toUTF8(aOrigin)); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - // $profileDir/gmp/$platform/$gmpName/id/$hash/topLevelOrigin - rv = WriteToFile(path, - NS_LITERAL_CSTRING("topLevelOrigin"), - NS_ConvertUTF16toUTF8(aTopLevelOrigin)); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - } else { - rv = ReadSalt(path, salt); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - } - - aOutId = salt; - mPersistentStorageAllowed.Put(salt, true); - - return NS_OK; -} - -NS_IMETHODIMP -GeckoMediaPluginServiceParent::GetNodeId(const nsAString& aOrigin, - const nsAString& aTopLevelOrigin, - const nsAString& aGMPName, - bool aInPrivateBrowsing, - UniquePtr<GetNodeIdCallback>&& aCallback) -{ - nsCString nodeId; - nsresult rv = GetNodeId(aOrigin, aTopLevelOrigin, aGMPName, aInPrivateBrowsing, nodeId); - aCallback->Done(rv, nodeId); - return rv; -} - -static bool -ExtractHostName(const nsACString& aOrigin, nsACString& aOutData) -{ - nsCString str; - str.Assign(aOrigin); - int begin = str.Find("://"); - // The scheme is missing! - if (begin == -1) { - return false; - } - - int end = str.RFind(":"); - // Remove the port number - if (end != begin) { - str.SetLength(end); - } - - nsDependentCSubstring host(str, begin + 3); - aOutData.Assign(host); - return true; -} - -bool -MatchOrigin(nsIFile* aPath, - const nsACString& aSite, - const mozilla::OriginAttributesPattern& aPattern) -{ - // http://en.wikipedia.org/wiki/Domain_Name_System#Domain_name_syntax - static const uint32_t MaxDomainLength = 253; - - nsresult rv; - nsCString str; - nsCString originNoSuffix; - mozilla::PrincipalOriginAttributes originAttributes; - - rv = ReadFromFile(aPath, NS_LITERAL_CSTRING("origin"), str, MaxDomainLength); - if (!originAttributes.PopulateFromOrigin(str, originNoSuffix)) { - // Fails on parsing the originAttributes, treat this as a non-match. - return false; - } - - if (NS_SUCCEEDED(rv) && ExtractHostName(originNoSuffix, str) && str.Equals(aSite) && - aPattern.Matches(originAttributes)) { - return true; - } - - mozilla::PrincipalOriginAttributes topLevelOriginAttributes; - rv = ReadFromFile(aPath, NS_LITERAL_CSTRING("topLevelOrigin"), str, MaxDomainLength); - if (!topLevelOriginAttributes.PopulateFromOrigin(str, originNoSuffix)) { - // Fails on paring the originAttributes, treat this as a non-match. - return false; - } - - if (NS_SUCCEEDED(rv) && ExtractHostName(originNoSuffix, str) && str.Equals(aSite) && - aPattern.Matches(topLevelOriginAttributes)) { - return true; - } - return false; -} - -template<typename T> static void -KillPlugins(const nsTArray<RefPtr<GMPParent>>& aPlugins, - Mutex& aMutex, T&& aFilter) -{ - // Shutdown the plugins when |aFilter| evaluates to true. - // After we clear storage data, node IDs will become invalid and shouldn't be - // used anymore. We need to kill plugins with such nodeIDs. - // Note: we can't shut them down while holding the lock, - // as the lock is not re-entrant and shutdown requires taking the lock. - // The plugin list is only edited on the GMP thread, so this should be OK. - nsTArray<RefPtr<GMPParent>> pluginsToKill; - { - MutexAutoLock lock(aMutex); - for (size_t i = 0; i < aPlugins.Length(); i++) { - RefPtr<GMPParent> parent(aPlugins[i]); - if (aFilter(parent)) { - pluginsToKill.AppendElement(parent); - } - } - } - - for (size_t i = 0; i < pluginsToKill.Length(); i++) { - pluginsToKill[i]->CloseActive(false); - // Abort async shutdown because we're going to wipe the plugin's storage, - // so we don't want it writing more data in its async shutdown path. - pluginsToKill[i]->AbortAsyncShutdown(); - } -} - -static nsresult -DeleteDir(nsIFile* aPath) -{ - bool exists = false; - nsresult rv = aPath->Exists(&exists); - if (NS_FAILED(rv)) { - return rv; - } - if (exists) { - return aPath->Remove(true); - } - return NS_OK; -} - -struct NodeFilter { - explicit NodeFilter(const nsTArray<nsCString>& nodeIDs) : mNodeIDs(nodeIDs) {} - bool operator()(GMPParent* aParent) { - return mNodeIDs.Contains(aParent->GetNodeId()); - } -private: - const nsTArray<nsCString>& mNodeIDs; -}; - -void -GeckoMediaPluginServiceParent::ClearNodeIdAndPlugin(DirectoryFilter& aFilter) -{ - // $profileDir/gmp/$platform/ - nsCOMPtr<nsIFile> path; - nsresult rv = GetStorageDir(getter_AddRefs(path)); - if (NS_FAILED(rv)) { - return; - } - - // Iterate all sub-folders of $profileDir/gmp/$platform/, i.e. the dirs in which - // specific GMPs store their data. - DirectoryEnumerator iter(path, DirectoryEnumerator::DirsOnly); - for (nsCOMPtr<nsIFile> pluginDir; (pluginDir = iter.Next()) != nullptr;) { - ClearNodeIdAndPlugin(pluginDir, aFilter); - } -} - -void -GeckoMediaPluginServiceParent::ClearNodeIdAndPlugin(nsIFile* aPluginStorageDir, - DirectoryFilter& aFilter) -{ - // $profileDir/gmp/$platform/$gmpName/id/ - nsCOMPtr<nsIFile> path = CloneAndAppend(aPluginStorageDir, NS_LITERAL_STRING("id")); - if (!path) { - return; - } - - // Iterate all sub-folders of $profileDir/gmp/$platform/$gmpName/id/ - nsTArray<nsCString> nodeIDsToClear; - DirectoryEnumerator iter(path, DirectoryEnumerator::DirsOnly); - for (nsCOMPtr<nsIFile> dirEntry; (dirEntry = iter.Next()) != nullptr;) { - // dirEntry is the hash of origins, i.e.: - // $profileDir/gmp/$platform/$gmpName/id/$originHash/ - if (!aFilter(dirEntry)) { - continue; - } - nsAutoCString salt; - if (NS_SUCCEEDED(ReadSalt(dirEntry, salt))) { - // Keep node IDs to clear data/plugins associated with them later. - nodeIDsToClear.AppendElement(salt); - // Also remove node IDs from the table. - mPersistentStorageAllowed.Remove(salt); - } - // Now we can remove the directory for the origin pair. - if (NS_FAILED(dirEntry->Remove(true))) { - NS_WARNING("Failed to delete the directory for the origin pair"); - } - } - - // Kill plugin instances that have node IDs being cleared. - KillPlugins(mPlugins, mMutex, NodeFilter(nodeIDsToClear)); - - // Clear all storage in $profileDir/gmp/$platform/$gmpName/storage/$nodeId/ - path = CloneAndAppend(aPluginStorageDir, NS_LITERAL_STRING("storage")); - if (!path) { - return; - } - - for (const nsCString& nodeId : nodeIDsToClear) { - nsCOMPtr<nsIFile> dirEntry; - nsresult rv = path->Clone(getter_AddRefs(dirEntry)); - if (NS_FAILED(rv)) { - continue; - } - - rv = dirEntry->AppendNative(nodeId); - if (NS_FAILED(rv)) { - continue; - } - - if (NS_FAILED(DeleteDir(dirEntry))) { - NS_WARNING("Failed to delete GMP storage directory for the node"); - } - } -} - -void -GeckoMediaPluginServiceParent::ForgetThisSiteOnGMPThread(const nsACString& aSite, - const mozilla::OriginAttributesPattern& aPattern) -{ - MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); - LOGD(("%s::%s: origin=%s", __CLASS__, __FUNCTION__, aSite.Data())); - - struct OriginFilter : public DirectoryFilter { - explicit OriginFilter(const nsACString& aSite, - const mozilla::OriginAttributesPattern& aPattern) - : mSite(aSite) - , mPattern(aPattern) - { } - bool operator()(nsIFile* aPath) override { - return MatchOrigin(aPath, mSite, mPattern); - } - private: - const nsACString& mSite; - const mozilla::OriginAttributesPattern& mPattern; - } filter(aSite, aPattern); - - ClearNodeIdAndPlugin(filter); -} - -void -GeckoMediaPluginServiceParent::ClearRecentHistoryOnGMPThread(PRTime aSince) -{ - MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); - LOGD(("%s::%s: since=%lld", __CLASS__, __FUNCTION__, (int64_t)aSince)); - - struct MTimeFilter : public DirectoryFilter { - explicit MTimeFilter(PRTime aSince) - : mSince(aSince) {} - - // Return true if any files under aPath is modified after |mSince|. - bool IsModifiedAfter(nsIFile* aPath) { - PRTime lastModified; - nsresult rv = aPath->GetLastModifiedTime(&lastModified); - if (NS_SUCCEEDED(rv) && lastModified >= mSince) { - return true; - } - DirectoryEnumerator iter(aPath, DirectoryEnumerator::FilesAndDirs); - for (nsCOMPtr<nsIFile> dirEntry; (dirEntry = iter.Next()) != nullptr;) { - if (IsModifiedAfter(dirEntry)) { - return true; - } - } - return false; - } - - // |aPath| is $profileDir/gmp/$platform/$gmpName/id/$originHash/ - bool operator()(nsIFile* aPath) override { - if (IsModifiedAfter(aPath)) { - return true; - } - - nsAutoCString salt; - if (NS_FAILED(ReadSalt(aPath, salt))) { - return false; - } - - // $profileDir/gmp/$platform/$gmpName/id/ - nsCOMPtr<nsIFile> idDir; - if (NS_FAILED(aPath->GetParent(getter_AddRefs(idDir)))) { - return false; - } - // $profileDir/gmp/$platform/$gmpName/ - nsCOMPtr<nsIFile> temp; - if (NS_FAILED(idDir->GetParent(getter_AddRefs(temp)))) { - return false; - } - - // $profileDir/gmp/$platform/$gmpName/storage/ - if (NS_FAILED(temp->Append(NS_LITERAL_STRING("storage")))) { - return false; - } - // $profileDir/gmp/$platform/$gmpName/storage/$originSalt - return NS_SUCCEEDED(temp->AppendNative(salt)) && IsModifiedAfter(temp); - } - private: - const PRTime mSince; - } filter(aSince); - - ClearNodeIdAndPlugin(filter); - - NS_DispatchToMainThread(new NotifyObserversTask("gmp-clear-storage-complete"), NS_DISPATCH_NORMAL); -} - -NS_IMETHODIMP -GeckoMediaPluginServiceParent::ForgetThisSite(const nsAString& aSite, - const nsAString& aPattern) -{ - MOZ_ASSERT(NS_IsMainThread()); - - mozilla::OriginAttributesPattern pattern; - - if (!pattern.Init(aPattern)) { - return NS_ERROR_INVALID_ARG; - } - - return ForgetThisSiteNative(aSite, pattern); -} - -nsresult -GeckoMediaPluginServiceParent::ForgetThisSiteNative(const nsAString& aSite, - const mozilla::OriginAttributesPattern& aPattern) -{ - MOZ_ASSERT(NS_IsMainThread()); - - return GMPDispatch(NewRunnableMethod<nsCString, mozilla::OriginAttributesPattern>( - this, &GeckoMediaPluginServiceParent::ForgetThisSiteOnGMPThread, - NS_ConvertUTF16toUTF8(aSite), aPattern)); -} - -static bool IsNodeIdValid(GMPParent* aParent) { - return !aParent->GetNodeId().IsEmpty(); -} - -static nsCOMPtr<nsIAsyncShutdownClient> -GetShutdownBarrier() -{ - nsCOMPtr<nsIAsyncShutdownService> svc = services::GetAsyncShutdown(); - MOZ_RELEASE_ASSERT(svc); - - nsCOMPtr<nsIAsyncShutdownClient> barrier; - nsresult rv = svc->GetXpcomWillShutdown(getter_AddRefs(barrier)); - - MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv)); - MOZ_RELEASE_ASSERT(barrier); - return barrier.forget(); -} - -NS_IMETHODIMP -GeckoMediaPluginServiceParent::GetName(nsAString& aName) -{ - aName = NS_LITERAL_STRING("GeckoMediaPluginServiceParent: shutdown"); - return NS_OK; -} - -NS_IMETHODIMP -GeckoMediaPluginServiceParent::GetState(nsIPropertyBag**) -{ - return NS_OK; -} - -NS_IMETHODIMP -GeckoMediaPluginServiceParent::BlockShutdown(nsIAsyncShutdownClient*) -{ - return NS_OK; -} - -void -GeckoMediaPluginServiceParent::ServiceUserCreated() -{ - MOZ_ASSERT(mServiceUserCount >= 0); - if (++mServiceUserCount == 1) { - nsresult rv = GetShutdownBarrier()->AddBlocker( - this, NS_LITERAL_STRING(__FILE__), __LINE__, - NS_LITERAL_STRING("GeckoMediaPluginServiceParent shutdown")); - MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv)); - } -} - -void -GeckoMediaPluginServiceParent::ServiceUserDestroyed() -{ - MOZ_ASSERT(mServiceUserCount > 0); - if (--mServiceUserCount == 0) { - nsresult rv = GetShutdownBarrier()->RemoveBlocker(this); - MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv)); - } -} - -void -GeckoMediaPluginServiceParent::ClearStorage() -{ - MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); - LOGD(("%s::%s", __CLASS__, __FUNCTION__)); - - // Kill plugins with valid nodeIDs. - KillPlugins(mPlugins, mMutex, &IsNodeIdValid); - - nsCOMPtr<nsIFile> path; // $profileDir/gmp/$platform/ - nsresult rv = GetStorageDir(getter_AddRefs(path)); - if (NS_WARN_IF(NS_FAILED(rv))) { - return; - } - - if (NS_FAILED(DeleteDir(path))) { - NS_WARNING("Failed to delete GMP storage directory"); - } - - // Clear private-browsing storage. - mTempGMPStorage.Clear(); - - NS_DispatchToMainThread(new NotifyObserversTask("gmp-clear-storage-complete"), NS_DISPATCH_NORMAL); -} - -already_AddRefed<GMPParent> -GeckoMediaPluginServiceParent::GetById(uint32_t aPluginId) -{ - MutexAutoLock lock(mMutex); - for (const RefPtr<GMPParent>& gmp : mPlugins) { - if (gmp->GetPluginId() == aPluginId) { - return do_AddRef(gmp); - } - } - return nullptr; -} - -GMPServiceParent::~GMPServiceParent() -{ - NS_DispatchToMainThread( - NewRunnableMethod(mService.get(), - &GeckoMediaPluginServiceParent::ServiceUserDestroyed)); -} - -bool -GMPServiceParent::RecvSelectGMP(const nsCString& aNodeId, - const nsCString& aAPI, - nsTArray<nsCString>&& aTags, - uint32_t* aOutPluginId, - nsresult* aOutRv) -{ - if (mService->IsShuttingDown()) { - *aOutRv = NS_ERROR_ILLEGAL_DURING_SHUTDOWN; - return true; - } - - RefPtr<GMPParent> gmp = mService->SelectPluginForAPI(aNodeId, aAPI, aTags); - if (gmp) { - *aOutPluginId = gmp->GetPluginId(); - *aOutRv = NS_OK; - } else { - *aOutRv = NS_ERROR_FAILURE; - } - - nsCString api = aTags[0]; - LOGD(("%s: %p returning %p for api %s", __FUNCTION__, (void *)this, (void *)gmp, api.get())); - - return true; -} - -bool -GMPServiceParent::RecvLaunchGMP(const uint32_t& aPluginId, - nsTArray<ProcessId>&& aAlreadyBridgedTo, - ProcessId* aOutProcessId, - nsCString* aOutDisplayName, - nsresult* aOutRv) -{ - *aOutRv = NS_OK; - if (mService->IsShuttingDown()) { - *aOutRv = NS_ERROR_ILLEGAL_DURING_SHUTDOWN; - return true; - } - - RefPtr<GMPParent> gmp(mService->GetById(aPluginId)); - if (!gmp) { - *aOutRv = NS_ERROR_FAILURE; - return true; - } - - if (!gmp->EnsureProcessLoaded(aOutProcessId)) { - return false; - } - - *aOutDisplayName = gmp->GetDisplayName(); - - return aAlreadyBridgedTo.Contains(*aOutProcessId) || gmp->Bridge(this); -} - -bool -GMPServiceParent::RecvGetGMPNodeId(const nsString& aOrigin, - const nsString& aTopLevelOrigin, - const nsString& aGMPName, - const bool& aInPrivateBrowsing, - nsCString* aID) -{ - nsresult rv = mService->GetNodeId(aOrigin, aTopLevelOrigin, aGMPName, - aInPrivateBrowsing, *aID); - return NS_SUCCEEDED(rv); -} - -class DeleteGMPServiceParent : public mozilla::Runnable -{ -public: - explicit DeleteGMPServiceParent(GMPServiceParent* aToDelete) - : mToDelete(aToDelete) - { - } - - NS_IMETHOD Run() override - { - return NS_OK; - } - -private: - nsAutoPtr<GMPServiceParent> mToDelete; -}; - -void GMPServiceParent::CloseTransport(Monitor* aSyncMonitor, bool* aCompleted) -{ - MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop()); - - MonitorAutoLock lock(*aSyncMonitor); - - // This deletes the transport. - SetTransport(nullptr); - - *aCompleted = true; - lock.NotifyAll(); -} - -void -GMPServiceParent::ActorDestroy(ActorDestroyReason aWhy) -{ - Monitor monitor("DeleteGMPServiceParent"); - bool completed = false; - - // Make sure the IPC channel is closed before destroying mToDelete. - MonitorAutoLock lock(monitor); - RefPtr<Runnable> task = - NewNonOwningRunnableMethod<Monitor*, bool*>(this, - &GMPServiceParent::CloseTransport, - &monitor, - &completed); - XRE_GetIOMessageLoop()->PostTask(Move(task.forget())); - - while (!completed) { - lock.Wait(); - } - - NS_DispatchToCurrentThread(new DeleteGMPServiceParent(this)); -} - -class OpenPGMPServiceParent : public mozilla::Runnable -{ -public: - OpenPGMPServiceParent(GMPServiceParent* aGMPServiceParent, - mozilla::ipc::Transport* aTransport, - base::ProcessId aOtherPid, - bool* aResult) - : mGMPServiceParent(aGMPServiceParent), - mTransport(aTransport), - mOtherPid(aOtherPid), - mResult(aResult) - { - } - - NS_IMETHOD Run() override - { - *mResult = mGMPServiceParent->Open(mTransport, mOtherPid, - XRE_GetIOMessageLoop(), ipc::ParentSide); - return NS_OK; - } - -private: - GMPServiceParent* mGMPServiceParent; - mozilla::ipc::Transport* mTransport; - base::ProcessId mOtherPid; - bool* mResult; -}; - -/* static */ -PGMPServiceParent* -GMPServiceParent::Create(Transport* aTransport, ProcessId aOtherPid) -{ - RefPtr<GeckoMediaPluginServiceParent> gmp = - GeckoMediaPluginServiceParent::GetSingleton(); - - if (gmp->mShuttingDown) { - // Shutdown is initiated. There is no point creating a new actor. - return nullptr; - } - - nsCOMPtr<nsIThread> gmpThread; - nsresult rv = gmp->GetThread(getter_AddRefs(gmpThread)); - NS_ENSURE_SUCCESS(rv, nullptr); - - nsAutoPtr<GMPServiceParent> serviceParent(new GMPServiceParent(gmp)); - - bool ok; - rv = gmpThread->Dispatch(new OpenPGMPServiceParent(serviceParent, - aTransport, - aOtherPid, &ok), - NS_DISPATCH_SYNC); - if (NS_FAILED(rv) || !ok) { - return nullptr; - } - - return serviceParent.forget(); -} - -} // namespace gmp -} // namespace mozilla diff --git a/dom/media/gmp/GMPServiceParent.h b/dom/media/gmp/GMPServiceParent.h deleted file mode 100644 index 49d81055b..000000000 --- a/dom/media/gmp/GMPServiceParent.h +++ /dev/null @@ -1,261 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#ifndef GMPServiceParent_h_ -#define GMPServiceParent_h_ - -#include "GMPService.h" -#include "mozilla/gmp/PGMPServiceParent.h" -#include "mozIGeckoMediaPluginChromeService.h" -#include "nsClassHashtable.h" -#include "nsDataHashtable.h" -#include "mozilla/Atomics.h" -#include "nsIAsyncShutdown.h" -#include "nsThreadUtils.h" -#include "mozilla/MozPromise.h" -#include "GMPStorage.h" - -template <class> struct already_AddRefed; - -namespace mozilla { -namespace gmp { - -class GMPParent; - -class GeckoMediaPluginServiceParent final : public GeckoMediaPluginService - , public mozIGeckoMediaPluginChromeService - , public nsIAsyncShutdownBlocker -{ -public: - static already_AddRefed<GeckoMediaPluginServiceParent> GetSingleton(); - - GeckoMediaPluginServiceParent(); - nsresult Init() override; - - NS_DECL_ISUPPORTS_INHERITED - NS_DECL_NSIASYNCSHUTDOWNBLOCKER - - // mozIGeckoMediaPluginService - NS_IMETHOD HasPluginForAPI(const nsACString& aAPI, - nsTArray<nsCString>* aTags, - bool *aRetVal) override; - NS_IMETHOD GetNodeId(const nsAString& aOrigin, - const nsAString& aTopLevelOrigin, - const nsAString& aGMPName, - bool aInPrivateBrowsingMode, - UniquePtr<GetNodeIdCallback>&& aCallback) override; - - NS_DECL_MOZIGECKOMEDIAPLUGINCHROMESERVICE - NS_DECL_NSIOBSERVER - - void AsyncShutdownNeeded(GMPParent* aParent); - void AsyncShutdownComplete(GMPParent* aParent); - - int32_t AsyncShutdownTimeoutMs(); - RefPtr<GenericPromise> EnsureInitialized(); - RefPtr<GenericPromise> AsyncAddPluginDirectory(const nsAString& aDirectory); - - // GMP thread access only - bool IsShuttingDown(); - - already_AddRefed<GMPStorage> GetMemoryStorageFor(const nsACString& aNodeId); - nsresult ForgetThisSiteNative(const nsAString& aSite, - const mozilla::OriginAttributesPattern& aPattern); - - // Notifies that some user of this class is created/destroyed. - void ServiceUserCreated(); - void ServiceUserDestroyed(); - - void UpdateContentProcessGMPCapabilities(); - -private: - friend class GMPServiceParent; - - virtual ~GeckoMediaPluginServiceParent(); - - void ClearStorage(); - - already_AddRefed<GMPParent> SelectPluginForAPI(const nsACString& aNodeId, - const nsCString& aAPI, - const nsTArray<nsCString>& aTags); - - already_AddRefed<GMPParent> FindPluginForAPIFrom(size_t aSearchStartIndex, - const nsCString& aAPI, - const nsTArray<nsCString>& aTags, - size_t* aOutPluginIndex); - - nsresult GetNodeId(const nsAString& aOrigin, const nsAString& aTopLevelOrigin, - const nsAString& aGMPName, - bool aInPrivateBrowsing, nsACString& aOutId); - - void UnloadPlugins(); - void CrashPlugins(); - void NotifySyncShutdownComplete(); - void NotifyAsyncShutdownComplete(); - - void ProcessPossiblePlugin(nsIFile* aDir); - - void RemoveOnGMPThread(const nsAString& aDirectory, - const bool aDeleteFromDisk, - const bool aCanDefer); - - nsresult SetAsyncShutdownTimeout(); - - struct DirectoryFilter { - virtual bool operator()(nsIFile* aPath) = 0; - ~DirectoryFilter() {} - }; - void ClearNodeIdAndPlugin(DirectoryFilter& aFilter); - void ClearNodeIdAndPlugin(nsIFile* aPluginStorageDir, - DirectoryFilter& aFilter); - void ForgetThisSiteOnGMPThread(const nsACString& aOrigin, - const mozilla::OriginAttributesPattern& aPattern); - void ClearRecentHistoryOnGMPThread(PRTime aSince); - - already_AddRefed<GMPParent> GetById(uint32_t aPluginId); - -protected: - friend class GMPParent; - void ReAddOnGMPThread(const RefPtr<GMPParent>& aOld); - void PluginTerminated(const RefPtr<GMPParent>& aOld); - void InitializePlugins(AbstractThread* aAbstractGMPThread) override; - RefPtr<GenericPromise::AllPromiseType> LoadFromEnvironment(); - RefPtr<GenericPromise> AddOnGMPThread(nsString aDirectory); - bool GetContentParentFrom(GMPCrashHelper* aHelper, - const nsACString& aNodeId, - const nsCString& aAPI, - const nsTArray<nsCString>& aTags, - UniquePtr<GetGMPContentParentCallback>&& aCallback) - override; -private: - // Creates a copy of aOriginal. Note that the caller is responsible for - // adding this to GeckoMediaPluginServiceParent::mPlugins. - already_AddRefed<GMPParent> ClonePlugin(const GMPParent* aOriginal); - nsresult EnsurePluginsOnDiskScanned(); - nsresult InitStorage(); - - class PathRunnable : public Runnable - { - public: - enum EOperation { - REMOVE, - REMOVE_AND_DELETE_FROM_DISK, - }; - - PathRunnable(GeckoMediaPluginServiceParent* aService, const nsAString& aPath, - EOperation aOperation, bool aDefer = false) - : mService(aService) - , mPath(aPath) - , mOperation(aOperation) - , mDefer(aDefer) - { } - - NS_DECL_NSIRUNNABLE - - private: - RefPtr<GeckoMediaPluginServiceParent> mService; - nsString mPath; - EOperation mOperation; - bool mDefer; - }; - - // Protected by mMutex from the base class. - nsTArray<RefPtr<GMPParent>> mPlugins; - bool mShuttingDown; - nsTArray<RefPtr<GMPParent>> mAsyncShutdownPlugins; - - // True if we've inspected MOZ_GMP_PATH on the GMP thread and loaded any - // plugins found there into mPlugins. - Atomic<bool> mScannedPluginOnDisk; - - template<typename T> - class MainThreadOnly { - public: - MOZ_IMPLICIT MainThreadOnly(T aValue) - : mValue(aValue) - {} - operator T&() { - MOZ_ASSERT(NS_IsMainThread()); - return mValue; - } - - private: - T mValue; - }; - - MainThreadOnly<bool> mWaitingForPluginsSyncShutdown; - - nsTArray<nsString> mPluginsWaitingForDeletion; - - nsCOMPtr<nsIFile> mStorageBaseDir; - - // Hashes of (origin,topLevelOrigin) to the node id for - // non-persistent sessions. - nsClassHashtable<nsUint32HashKey, nsCString> mTempNodeIds; - - // Hashes node id to whether that node id is allowed to store data - // persistently on disk. - nsDataHashtable<nsCStringHashKey, bool> mPersistentStorageAllowed; - - // Synchronization for barrier that ensures we've loaded GMPs from - // MOZ_GMP_PATH before allowing GetContentParentFrom() to proceed. - Monitor mInitPromiseMonitor; - MozPromiseHolder<GenericPromise> mInitPromise; - bool mLoadPluginsFromDiskComplete; - - // Hashes nodeId to the hashtable of storage for that nodeId. - nsRefPtrHashtable<nsCStringHashKey, GMPStorage> mTempGMPStorage; - - // Tracks how many users are running (on the GMP thread). Only when this count - // drops to 0 can we safely shut down the thread. - MainThreadOnly<int32_t> mServiceUserCount; -}; - -nsresult ReadSalt(nsIFile* aPath, nsACString& aOutData); -bool MatchOrigin(nsIFile* aPath, - const nsACString& aSite, - const mozilla::OriginAttributesPattern& aPattern); - -class GMPServiceParent final : public PGMPServiceParent -{ -public: - explicit GMPServiceParent(GeckoMediaPluginServiceParent* aService) - : mService(aService) - { - mService->ServiceUserCreated(); - } - virtual ~GMPServiceParent(); - - bool RecvGetGMPNodeId(const nsString& aOrigin, - const nsString& aTopLevelOrigin, - const nsString& aGMPName, - const bool& aInPrivateBrowsing, - nsCString* aID) override; - void ActorDestroy(ActorDestroyReason aWhy) override; - - static PGMPServiceParent* Create(Transport* aTransport, ProcessId aOtherPid); - - bool RecvSelectGMP(const nsCString& aNodeId, - const nsCString& aAPI, - nsTArray<nsCString>&& aTags, - uint32_t* aOutPluginId, - nsresult* aOutRv) override; - - bool RecvLaunchGMP(const uint32_t& aPluginId, - nsTArray<ProcessId>&& aAlreadyBridgedTo, - ProcessId* aOutID, - nsCString* aOutDisplayName, - nsresult* aOutRv) override; - -private: - void CloseTransport(Monitor* aSyncMonitor, bool* aCompleted); - - RefPtr<GeckoMediaPluginServiceParent> mService; -}; - -} // namespace gmp -} // namespace mozilla - -#endif // GMPServiceParent_h_ diff --git a/dom/media/gmp/GMPSharedMemManager.cpp b/dom/media/gmp/GMPSharedMemManager.cpp deleted file mode 100644 index 86b5f9810..000000000 --- a/dom/media/gmp/GMPSharedMemManager.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#include "GMPSharedMemManager.h" -#include "GMPMessageUtils.h" -#include "mozilla/ipc/SharedMemory.h" -#include "mozilla/StaticPtr.h" -#include "mozilla/ClearOnShutdown.h" - -namespace mozilla { -namespace gmp { - -// Really one set of pools on each side of the plugin API. - -// YUV buffers go from Encoder parent to child; pool there, and then return -// with Decoded() frames to the Decoder parent and goes into the parent pool. -// Compressed (encoded) data goes from the Decoder parent to the child; -// pool there, and then return with Encoded() frames and goes into the parent -// pool. -bool -GMPSharedMemManager::MgrAllocShmem(GMPSharedMem::GMPMemoryClasses aClass, size_t aSize, - ipc::Shmem::SharedMemory::SharedMemoryType aType, - ipc::Shmem* aMem) -{ - mData->CheckThread(); - - // first look to see if we have a free buffer large enough - for (uint32_t i = 0; i < GetGmpFreelist(aClass).Length(); i++) { - MOZ_ASSERT(GetGmpFreelist(aClass)[i].IsWritable()); - if (aSize <= GetGmpFreelist(aClass)[i].Size<uint8_t>()) { - *aMem = GetGmpFreelist(aClass)[i]; - GetGmpFreelist(aClass).RemoveElementAt(i); - return true; - } - } - - // Didn't find a buffer free with enough space; allocate one - size_t pagesize = ipc::SharedMemory::SystemPageSize(); - aSize = (aSize + (pagesize-1)) & ~(pagesize-1); // round up to page size - bool retval = Alloc(aSize, aType, aMem); - if (retval) { - // The allocator (or NeedsShmem call) should never return less than we ask for... - MOZ_ASSERT(aMem->Size<uint8_t>() >= aSize); - mData->mGmpAllocated[aClass]++; - } - return retval; -} - -bool -GMPSharedMemManager::MgrDeallocShmem(GMPSharedMem::GMPMemoryClasses aClass, ipc::Shmem& aMem) -{ - mData->CheckThread(); - - size_t size = aMem.Size<uint8_t>(); - size_t total = 0; - - // XXX Bug NNNNNNN Until we put better guards on ipc::shmem, verify we - // weren't fed an shmem we already had. - for (uint32_t i = 0; i < GetGmpFreelist(aClass).Length(); i++) { - if (NS_WARN_IF(aMem == GetGmpFreelist(aClass)[i])) { - // Safest to crash in this case; should never happen in normal - // operation. - MOZ_CRASH("Deallocating Shmem we already have in our cache!"); - //return true; - } - } - - // XXX This works; there are better pool algorithms. We need to avoid - // "falling off a cliff" with too low a number - if (GetGmpFreelist(aClass).Length() > 10) { - Dealloc(GetGmpFreelist(aClass)[0]); - GetGmpFreelist(aClass).RemoveElementAt(0); - // The allocation numbers will be fubar on the Child! - mData->mGmpAllocated[aClass]--; - } - for (uint32_t i = 0; i < GetGmpFreelist(aClass).Length(); i++) { - MOZ_ASSERT(GetGmpFreelist(aClass)[i].IsWritable()); - total += GetGmpFreelist(aClass)[i].Size<uint8_t>(); - if (size < GetGmpFreelist(aClass)[i].Size<uint8_t>()) { - GetGmpFreelist(aClass).InsertElementAt(i, aMem); - return true; - } - } - GetGmpFreelist(aClass).AppendElement(aMem); - - return true; -} - -uint32_t -GMPSharedMemManager::NumInUse(GMPSharedMem::GMPMemoryClasses aClass) -{ - return mData->mGmpAllocated[aClass] - GetGmpFreelist(aClass).Length(); -} - -} // namespace gmp -} // namespace mozilla diff --git a/dom/media/gmp/GMPSharedMemManager.h b/dom/media/gmp/GMPSharedMemManager.h deleted file mode 100644 index cc36f3fc0..000000000 --- a/dom/media/gmp/GMPSharedMemManager.h +++ /dev/null @@ -1,82 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#ifndef GMPSharedMemManager_h_ -#define GMPSharedMemManager_h_ - -#include "mozilla/ipc/Shmem.h" -#include "nsTArray.h" - -namespace mozilla { -namespace gmp { - -class GMPSharedMemManager; - -class GMPSharedMem -{ -public: - typedef enum { - kGMPFrameData = 0, - kGMPEncodedData, - kGMPNumTypes - } GMPMemoryClasses; - - // This is a heuristic - max of 10 free in the Child pool, plus those - // in-use for the encoder and decoder at the given moment and not yet - // returned to the parent pool (which is not included). If more than - // this are needed, we presume the client has either crashed or hung - // (perhaps temporarily). - static const uint32_t kGMPBufLimit = 20; - - GMPSharedMem() - { - for (size_t i = 0; i < sizeof(mGmpAllocated)/sizeof(mGmpAllocated[0]); i++) { - mGmpAllocated[i] = 0; - } - } - virtual ~GMPSharedMem() {} - - // Parent and child impls will differ here - virtual void CheckThread() = 0; - -protected: - friend class GMPSharedMemManager; - - nsTArray<ipc::Shmem> mGmpFreelist[GMPSharedMem::kGMPNumTypes]; - uint32_t mGmpAllocated[GMPSharedMem::kGMPNumTypes]; -}; - -class GMPSharedMemManager -{ -public: - explicit GMPSharedMemManager(GMPSharedMem *aData) : mData(aData) {} - virtual ~GMPSharedMemManager() {} - - virtual bool MgrAllocShmem(GMPSharedMem::GMPMemoryClasses aClass, size_t aSize, - ipc::Shmem::SharedMemory::SharedMemoryType aType, - ipc::Shmem* aMem); - virtual bool MgrDeallocShmem(GMPSharedMem::GMPMemoryClasses aClass, ipc::Shmem& aMem); - - // So we can know if data is "piling up" for the plugin - I.e. it's hung or crashed - virtual uint32_t NumInUse(GMPSharedMem::GMPMemoryClasses aClass); - - // These have to be implemented using the AllocShmem/etc provided by the IPDL-generated interfaces, - // so have the Parent/Child implement them. - virtual bool Alloc(size_t aSize, ipc::Shmem::SharedMemory::SharedMemoryType aType, ipc::Shmem* aMem) = 0; - virtual void Dealloc(ipc::Shmem& aMem) = 0; - -private: - nsTArray<ipc::Shmem>& GetGmpFreelist(GMPSharedMem::GMPMemoryClasses aTypes) - { - return mData->mGmpFreelist[aTypes]; - } - - GMPSharedMem *mData; -}; - -} // namespace gmp -} // namespace mozilla - -#endif // GMPSharedMemManager_h_ diff --git a/dom/media/gmp/GMPStorage.h b/dom/media/gmp/GMPStorage.h deleted file mode 100644 index db3aebc8c..000000000 --- a/dom/media/gmp/GMPStorage.h +++ /dev/null @@ -1,41 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#ifndef GMPStorage_h_ -#define GMPStorage_h_ - -#include "gmp-storage.h" -#include "mozilla/AlreadyAddRefed.h" -#include "nsISupportsImpl.h" -#include "nsString.h" -#include "nsTArray.h" - -namespace mozilla { -namespace gmp { - -class GMPStorage { -public: - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GMPStorage) - - virtual GMPErr Open(const nsCString& aRecordName) = 0; - virtual bool IsOpen(const nsCString& aRecordName) const = 0; - virtual GMPErr Read(const nsCString& aRecordName, - nsTArray<uint8_t>& aOutBytes) = 0; - virtual GMPErr Write(const nsCString& aRecordName, - const nsTArray<uint8_t>& aBytes) = 0; - virtual GMPErr GetRecordNames(nsTArray<nsCString>& aOutRecordNames) const = 0; - virtual void Close(const nsCString& aRecordName) = 0; -protected: - virtual ~GMPStorage() {} -}; - -already_AddRefed<GMPStorage> CreateGMPMemoryStorage(); -already_AddRefed<GMPStorage> CreateGMPDiskStorage(const nsCString& aNodeId, - const nsString& aGMPName); - -} // namespace gmp -} // namespace mozilla - -#endif
\ No newline at end of file diff --git a/dom/media/gmp/GMPStorageChild.cpp b/dom/media/gmp/GMPStorageChild.cpp deleted file mode 100644 index 052b56d1b..000000000 --- a/dom/media/gmp/GMPStorageChild.cpp +++ /dev/null @@ -1,380 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#include "GMPStorageChild.h" -#include "GMPChild.h" -#include "gmp-storage.h" -#include "base/task.h" - -#define ON_GMP_THREAD() (mPlugin->GMPMessageLoop() == MessageLoop::current()) - -#define CALL_ON_GMP_THREAD(_func, ...) \ - do { \ - if (ON_GMP_THREAD()) { \ - _func(__VA_ARGS__); \ - } else { \ - mPlugin->GMPMessageLoop()->PostTask( \ - dont_add_new_uses_of_this::NewRunnableMethod(this, &GMPStorageChild::_func, ##__VA_ARGS__) \ - ); \ - } \ - } while(false) - -static nsTArray<uint8_t> -ToArray(const uint8_t* aData, uint32_t aDataSize) -{ - nsTArray<uint8_t> data; - data.AppendElements(aData, aDataSize); - return mozilla::Move(data); -} - -namespace mozilla { -namespace gmp { - -GMPRecordImpl::GMPRecordImpl(GMPStorageChild* aOwner, - const nsCString& aName, - GMPRecordClient* aClient) - : mName(aName) - , mClient(aClient) - , mOwner(aOwner) -{ -} - -GMPErr -GMPRecordImpl::Open() -{ - return mOwner->Open(this); -} - -void -GMPRecordImpl::OpenComplete(GMPErr aStatus) -{ - mClient->OpenComplete(aStatus); -} - -GMPErr -GMPRecordImpl::Read() -{ - return mOwner->Read(this); -} - -void -GMPRecordImpl::ReadComplete(GMPErr aStatus, - const uint8_t* aBytes, - uint32_t aLength) -{ - mClient->ReadComplete(aStatus, aBytes, aLength); -} - -GMPErr -GMPRecordImpl::Write(const uint8_t* aData, uint32_t aDataSize) -{ - return mOwner->Write(this, aData, aDataSize); -} - -void -GMPRecordImpl::WriteComplete(GMPErr aStatus) -{ - mClient->WriteComplete(aStatus); -} - -GMPErr -GMPRecordImpl::Close() -{ - RefPtr<GMPRecordImpl> kungfuDeathGrip(this); - // Delete our self reference. - Release(); - mOwner->Close(this->Name()); - return GMPNoErr; -} - -GMPStorageChild::GMPStorageChild(GMPChild* aPlugin) - : mMonitor("GMPStorageChild") - , mPlugin(aPlugin) - , mShutdown(false) -{ - MOZ_ASSERT(ON_GMP_THREAD()); -} - -GMPErr -GMPStorageChild::CreateRecord(const nsCString& aRecordName, - GMPRecord** aOutRecord, - GMPRecordClient* aClient) -{ - MonitorAutoLock lock(mMonitor); - - if (mShutdown) { - NS_WARNING("GMPStorage used after it's been shutdown!"); - return GMPClosedErr; - } - - MOZ_ASSERT(aRecordName.Length() && aOutRecord); - - if (HasRecord(aRecordName)) { - return GMPRecordInUse; - } - - RefPtr<GMPRecordImpl> record(new GMPRecordImpl(this, aRecordName, aClient)); - mRecords.Put(aRecordName, record); // Addrefs - - // The GMPRecord holds a self reference until the GMP calls Close() on - // it. This means the object is always valid (even if neutered) while - // the GMP expects it to be. - record.forget(aOutRecord); - - return GMPNoErr; -} - -bool -GMPStorageChild::HasRecord(const nsCString& aRecordName) -{ - mMonitor.AssertCurrentThreadOwns(); - return mRecords.Contains(aRecordName); -} - -already_AddRefed<GMPRecordImpl> -GMPStorageChild::GetRecord(const nsCString& aRecordName) -{ - MonitorAutoLock lock(mMonitor); - RefPtr<GMPRecordImpl> record; - mRecords.Get(aRecordName, getter_AddRefs(record)); - return record.forget(); -} - -GMPErr -GMPStorageChild::Open(GMPRecordImpl* aRecord) -{ - MonitorAutoLock lock(mMonitor); - - if (mShutdown) { - NS_WARNING("GMPStorage used after it's been shutdown!"); - return GMPClosedErr; - } - - if (!HasRecord(aRecord->Name())) { - // Trying to re-open a record that has already been closed. - return GMPClosedErr; - } - - CALL_ON_GMP_THREAD(SendOpen, aRecord->Name()); - - return GMPNoErr; -} - -GMPErr -GMPStorageChild::Read(GMPRecordImpl* aRecord) -{ - MonitorAutoLock lock(mMonitor); - - if (mShutdown) { - NS_WARNING("GMPStorage used after it's been shutdown!"); - return GMPClosedErr; - } - - if (!HasRecord(aRecord->Name())) { - // Record not opened. - return GMPClosedErr; - } - - CALL_ON_GMP_THREAD(SendRead, aRecord->Name()); - - return GMPNoErr; -} - -GMPErr -GMPStorageChild::Write(GMPRecordImpl* aRecord, - const uint8_t* aData, - uint32_t aDataSize) -{ - if (aDataSize > GMP_MAX_RECORD_SIZE) { - return GMPQuotaExceededErr; - } - - MonitorAutoLock lock(mMonitor); - - if (mShutdown) { - NS_WARNING("GMPStorage used after it's been shutdown!"); - return GMPClosedErr; - } - - if (!HasRecord(aRecord->Name())) { - // Record not opened. - return GMPClosedErr; - } - - CALL_ON_GMP_THREAD(SendWrite, aRecord->Name(), ToArray(aData, aDataSize)); - - return GMPNoErr; -} - -GMPErr -GMPStorageChild::Close(const nsCString& aRecordName) -{ - MonitorAutoLock lock(mMonitor); - - if (!HasRecord(aRecordName)) { - // Already closed. - return GMPClosedErr; - } - - mRecords.Remove(aRecordName); - - if (!mShutdown) { - CALL_ON_GMP_THREAD(SendClose, aRecordName); - } - - return GMPNoErr; -} - -bool -GMPStorageChild::RecvOpenComplete(const nsCString& aRecordName, - const GMPErr& aStatus) -{ - // We don't need a lock to read |mShutdown| since it is only changed in - // the GMP thread. - if (mShutdown) { - return true; - } - RefPtr<GMPRecordImpl> record = GetRecord(aRecordName); - if (!record) { - // Not fatal. - return true; - } - record->OpenComplete(aStatus); - return true; -} - -bool -GMPStorageChild::RecvReadComplete(const nsCString& aRecordName, - const GMPErr& aStatus, - InfallibleTArray<uint8_t>&& aBytes) -{ - if (mShutdown) { - return true; - } - RefPtr<GMPRecordImpl> record = GetRecord(aRecordName); - if (!record) { - // Not fatal. - return true; - } - record->ReadComplete(aStatus, aBytes.Elements(), aBytes.Length()); - return true; -} - -bool -GMPStorageChild::RecvWriteComplete(const nsCString& aRecordName, - const GMPErr& aStatus) -{ - if (mShutdown) { - return true; - } - RefPtr<GMPRecordImpl> record = GetRecord(aRecordName); - if (!record) { - // Not fatal. - return true; - } - record->WriteComplete(aStatus); - return true; -} - -GMPErr -GMPStorageChild::EnumerateRecords(RecvGMPRecordIteratorPtr aRecvIteratorFunc, - void* aUserArg) -{ - MonitorAutoLock lock(mMonitor); - - if (mShutdown) { - NS_WARNING("GMPStorage used after it's been shutdown!"); - return GMPClosedErr; - } - - MOZ_ASSERT(aRecvIteratorFunc); - mPendingRecordIterators.push(RecordIteratorContext(aRecvIteratorFunc, aUserArg)); - - CALL_ON_GMP_THREAD(SendGetRecordNames); - - return GMPNoErr; -} - -class GMPRecordIteratorImpl : public GMPRecordIterator { -public: - explicit GMPRecordIteratorImpl(const InfallibleTArray<nsCString>& aRecordNames) - : mRecordNames(aRecordNames) - , mIndex(0) - { - mRecordNames.Sort(); - } - - GMPErr GetName(const char** aOutName, uint32_t* aOutNameLength) override { - if (!aOutName || !aOutNameLength) { - return GMPInvalidArgErr; - } - if (mIndex == mRecordNames.Length()) { - return GMPEndOfEnumeration; - } - *aOutName = mRecordNames[mIndex].get(); - *aOutNameLength = mRecordNames[mIndex].Length(); - return GMPNoErr; - } - - GMPErr NextRecord() override { - if (mIndex < mRecordNames.Length()) { - mIndex++; - } - return (mIndex < mRecordNames.Length()) ? GMPNoErr - : GMPEndOfEnumeration; - } - - void Close() override { - delete this; - } - -private: - nsTArray<nsCString> mRecordNames; - size_t mIndex; -}; - -bool -GMPStorageChild::RecvRecordNames(InfallibleTArray<nsCString>&& aRecordNames, - const GMPErr& aStatus) -{ - RecordIteratorContext ctx; - { - MonitorAutoLock lock(mMonitor); - if (mShutdown || mPendingRecordIterators.empty()) { - return true; - } - ctx = mPendingRecordIterators.front(); - mPendingRecordIterators.pop(); - } - - if (GMP_FAILED(aStatus)) { - ctx.mFunc(nullptr, ctx.mUserArg, aStatus); - } else { - ctx.mFunc(new GMPRecordIteratorImpl(aRecordNames), ctx.mUserArg, GMPNoErr); - } - - return true; -} - -bool -GMPStorageChild::RecvShutdown() -{ - // Block any new storage requests, and thus any messages back to the - // parent. We don't delete any objects here, as that may invalidate - // GMPRecord pointers held by the GMP. - MonitorAutoLock lock(mMonitor); - mShutdown = true; - while (!mPendingRecordIterators.empty()) { - mPendingRecordIterators.pop(); - } - return true; -} - -} // namespace gmp -} // namespace mozilla - -// avoid redefined macro in unified build -#undef ON_GMP_THREAD -#undef CALL_ON_GMP_THREAD diff --git a/dom/media/gmp/GMPStorageChild.h b/dom/media/gmp/GMPStorageChild.h deleted file mode 100644 index 3c5948a30..000000000 --- a/dom/media/gmp/GMPStorageChild.h +++ /dev/null @@ -1,118 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#ifndef GMPStorageChild_h_ -#define GMPStorageChild_h_ - -#include "mozilla/gmp/PGMPStorageChild.h" -#include "gmp-storage.h" -#include "nsTHashtable.h" -#include "nsRefPtrHashtable.h" -#include "gmp-platform.h" - -#include <queue> - -namespace mozilla { -namespace gmp { - -class GMPChild; -class GMPStorageChild; - -class GMPRecordImpl : public GMPRecord -{ -public: - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GMPRecordImpl) - - GMPRecordImpl(GMPStorageChild* aOwner, - const nsCString& aName, - GMPRecordClient* aClient); - - // GMPRecord. - GMPErr Open() override; - GMPErr Read() override; - GMPErr Write(const uint8_t* aData, - uint32_t aDataSize) override; - GMPErr Close() override; - - const nsCString& Name() const { return mName; } - - void OpenComplete(GMPErr aStatus); - void ReadComplete(GMPErr aStatus, const uint8_t* aBytes, uint32_t aLength); - void WriteComplete(GMPErr aStatus); - -private: - ~GMPRecordImpl() {} - const nsCString mName; - GMPRecordClient* const mClient; - GMPStorageChild* const mOwner; -}; - -class GMPStorageChild : public PGMPStorageChild -{ -public: - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GMPStorageChild) - - explicit GMPStorageChild(GMPChild* aPlugin); - - GMPErr CreateRecord(const nsCString& aRecordName, - GMPRecord** aOutRecord, - GMPRecordClient* aClient); - - GMPErr Open(GMPRecordImpl* aRecord); - - GMPErr Read(GMPRecordImpl* aRecord); - - GMPErr Write(GMPRecordImpl* aRecord, - const uint8_t* aData, - uint32_t aDataSize); - - GMPErr Close(const nsCString& aRecordName); - - GMPErr EnumerateRecords(RecvGMPRecordIteratorPtr aRecvIteratorFunc, - void* aUserArg); - -private: - bool HasRecord(const nsCString& aRecordName); - already_AddRefed<GMPRecordImpl> GetRecord(const nsCString& aRecordName); - -protected: - ~GMPStorageChild() {} - - // PGMPStorageChild - bool RecvOpenComplete(const nsCString& aRecordName, - const GMPErr& aStatus) override; - bool RecvReadComplete(const nsCString& aRecordName, - const GMPErr& aStatus, - InfallibleTArray<uint8_t>&& aBytes) override; - bool RecvWriteComplete(const nsCString& aRecordName, - const GMPErr& aStatus) override; - bool RecvRecordNames(InfallibleTArray<nsCString>&& aRecordNames, - const GMPErr& aStatus) override; - bool RecvShutdown() override; - -private: - Monitor mMonitor; - nsRefPtrHashtable<nsCStringHashKey, GMPRecordImpl> mRecords; - GMPChild* mPlugin; - - struct RecordIteratorContext { - explicit RecordIteratorContext(RecvGMPRecordIteratorPtr aFunc, - void* aUserArg) - : mFunc(aFunc) - , mUserArg(aUserArg) - {} - RecordIteratorContext() {} - RecvGMPRecordIteratorPtr mFunc; - void* mUserArg; - }; - - std::queue<RecordIteratorContext> mPendingRecordIterators; - bool mShutdown; -}; - -} // namespace gmp -} // namespace mozilla - -#endif // GMPStorageChild_h_ diff --git a/dom/media/gmp/GMPStorageParent.cpp b/dom/media/gmp/GMPStorageParent.cpp deleted file mode 100644 index e3eadeccf..000000000 --- a/dom/media/gmp/GMPStorageParent.cpp +++ /dev/null @@ -1,220 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#include "GMPStorageParent.h" -#include "GMPParent.h" -#include "gmp-storage.h" -#include "mozilla/Unused.h" -#include "mozIGeckoMediaPluginService.h" - -namespace mozilla { - -#ifdef LOG -#undef LOG -#endif - -extern LogModule* GetGMPLog(); - -#define LOGD(msg) MOZ_LOG(GetGMPLog(), mozilla::LogLevel::Debug, msg) -#define LOG(level, msg) MOZ_LOG(GetGMPLog(), (level), msg) - -namespace gmp { - -GMPStorageParent::GMPStorageParent(const nsCString& aNodeId, - GMPParent* aPlugin) - : mNodeId(aNodeId) - , mPlugin(aPlugin) - , mShutdown(true) -{ -} - -nsresult -GMPStorageParent::Init() -{ - LOGD(("GMPStorageParent[%p]::Init()", this)); - - if (NS_WARN_IF(mNodeId.IsEmpty())) { - return NS_ERROR_FAILURE; - } - RefPtr<GeckoMediaPluginServiceParent> mps(GeckoMediaPluginServiceParent::GetSingleton()); - if (NS_WARN_IF(!mps)) { - return NS_ERROR_FAILURE; - } - - bool persistent = false; - if (NS_WARN_IF(NS_FAILED(mps->IsPersistentStorageAllowed(mNodeId, &persistent)))) { - return NS_ERROR_FAILURE; - } - if (persistent) { - mStorage = CreateGMPDiskStorage(mNodeId, mPlugin->GetPluginBaseName()); - } else { - mStorage = mps->GetMemoryStorageFor(mNodeId); - } - if (!mStorage) { - return NS_ERROR_FAILURE; - } - - mShutdown = false; - return NS_OK; -} - -bool -GMPStorageParent::RecvOpen(const nsCString& aRecordName) -{ - LOGD(("GMPStorageParent[%p]::RecvOpen(record='%s')", - this, aRecordName.get())); - - if (mShutdown) { - return false; - } - - if (mNodeId.EqualsLiteral("null")) { - // Refuse to open storage if the page is opened from local disk, - // or shared across origin. - LOGD(("GMPStorageParent[%p]::RecvOpen(record='%s') failed; null nodeId", - this, aRecordName.get())); - Unused << SendOpenComplete(aRecordName, GMPGenericErr); - return true; - } - - if (aRecordName.IsEmpty()) { - LOGD(("GMPStorageParent[%p]::RecvOpen(record='%s') failed; record name empty", - this, aRecordName.get())); - Unused << SendOpenComplete(aRecordName, GMPGenericErr); - return true; - } - - if (mStorage->IsOpen(aRecordName)) { - LOGD(("GMPStorageParent[%p]::RecvOpen(record='%s') failed; record in use", - this, aRecordName.get())); - Unused << SendOpenComplete(aRecordName, GMPRecordInUse); - return true; - } - - auto err = mStorage->Open(aRecordName); - MOZ_ASSERT(GMP_FAILED(err) || mStorage->IsOpen(aRecordName)); - LOGD(("GMPStorageParent[%p]::RecvOpen(record='%s') complete; rv=%d", - this, aRecordName.get(), err)); - Unused << SendOpenComplete(aRecordName, err); - - return true; -} - -bool -GMPStorageParent::RecvRead(const nsCString& aRecordName) -{ - LOGD(("GMPStorageParent[%p]::RecvRead(record='%s')", - this, aRecordName.get())); - - if (mShutdown) { - return false; - } - - nsTArray<uint8_t> data; - if (!mStorage->IsOpen(aRecordName)) { - LOGD(("GMPStorageParent[%p]::RecvRead(record='%s') failed; record not open", - this, aRecordName.get())); - Unused << SendReadComplete(aRecordName, GMPClosedErr, data); - } else { - GMPErr rv = mStorage->Read(aRecordName, data); - LOGD(("GMPStorageParent[%p]::RecvRead(record='%s') read %d bytes rv=%d", - this, aRecordName.get(), data.Length(), rv)); - Unused << SendReadComplete(aRecordName, rv, data); - } - - return true; -} - -bool -GMPStorageParent::RecvWrite(const nsCString& aRecordName, - InfallibleTArray<uint8_t>&& aBytes) -{ - LOGD(("GMPStorageParent[%p]::RecvWrite(record='%s') %d bytes", - this, aRecordName.get(), aBytes.Length())); - - if (mShutdown) { - return false; - } - - if (!mStorage->IsOpen(aRecordName)) { - LOGD(("GMPStorageParent[%p]::RecvWrite(record='%s') failed record not open", - this, aRecordName.get())); - Unused << SendWriteComplete(aRecordName, GMPClosedErr); - return true; - } - - if (aBytes.Length() > GMP_MAX_RECORD_SIZE) { - LOGD(("GMPStorageParent[%p]::RecvWrite(record='%s') failed record too big", - this, aRecordName.get())); - Unused << SendWriteComplete(aRecordName, GMPQuotaExceededErr); - return true; - } - - GMPErr rv = mStorage->Write(aRecordName, aBytes); - LOGD(("GMPStorageParent[%p]::RecvWrite(record='%s') write complete rv=%d", - this, aRecordName.get(), rv)); - - Unused << SendWriteComplete(aRecordName, rv); - - return true; -} - -bool -GMPStorageParent::RecvGetRecordNames() -{ - if (mShutdown) { - return true; - } - - nsTArray<nsCString> recordNames; - GMPErr status = mStorage->GetRecordNames(recordNames); - - LOGD(("GMPStorageParent[%p]::RecvGetRecordNames() status=%d numRecords=%d", - this, status, recordNames.Length())); - - Unused << SendRecordNames(recordNames, status); - - return true; -} - -bool -GMPStorageParent::RecvClose(const nsCString& aRecordName) -{ - LOGD(("GMPStorageParent[%p]::RecvClose(record='%s')", - this, aRecordName.get())); - - if (mShutdown) { - return true; - } - - mStorage->Close(aRecordName); - - return true; -} - -void -GMPStorageParent::ActorDestroy(ActorDestroyReason aWhy) -{ - LOGD(("GMPStorageParent[%p]::ActorDestroy(reason=%d)", this, aWhy)); - Shutdown(); -} - -void -GMPStorageParent::Shutdown() -{ - LOGD(("GMPStorageParent[%p]::Shutdown()", this)); - - if (mShutdown) { - return; - } - mShutdown = true; - Unused << SendShutdown(); - - mStorage = nullptr; - -} - -} // namespace gmp -} // namespace mozilla diff --git a/dom/media/gmp/GMPStorageParent.h b/dom/media/gmp/GMPStorageParent.h deleted file mode 100644 index 3d2ea69ac..000000000 --- a/dom/media/gmp/GMPStorageParent.h +++ /dev/null @@ -1,49 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#ifndef GMPStorageParent_h_ -#define GMPStorageParent_h_ - -#include "mozilla/gmp/PGMPStorageParent.h" -#include "GMPStorage.h" - -namespace mozilla { -namespace gmp { - -class GMPParent; - -class GMPStorageParent : public PGMPStorageParent { -public: - NS_INLINE_DECL_REFCOUNTING(GMPStorageParent) - GMPStorageParent(const nsCString& aNodeId, - GMPParent* aPlugin); - - nsresult Init(); - void Shutdown(); - -protected: - bool RecvOpen(const nsCString& aRecordName) override; - bool RecvRead(const nsCString& aRecordName) override; - bool RecvWrite(const nsCString& aRecordName, - InfallibleTArray<uint8_t>&& aBytes) override; - bool RecvGetRecordNames() override; - bool RecvClose(const nsCString& aRecordName) override; - void ActorDestroy(ActorDestroyReason aWhy) override; - -private: - ~GMPStorageParent() {} - - RefPtr<GMPStorage> mStorage; - - const nsCString mNodeId; - RefPtr<GMPParent> mPlugin; - // True after Shutdown(), or if Init() has not completed successfully. - bool mShutdown; -}; - -} // namespace gmp -} // namespace mozilla - -#endif // GMPStorageParent_h_ diff --git a/dom/media/gmp/GMPTimerChild.cpp b/dom/media/gmp/GMPTimerChild.cpp deleted file mode 100644 index 0b2b55c79..000000000 --- a/dom/media/gmp/GMPTimerChild.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#include "GMPTimerChild.h" -#include "GMPPlatform.h" -#include "GMPChild.h" - -#define MAX_NUM_TIMERS 1000 - -namespace mozilla { -namespace gmp { - -GMPTimerChild::GMPTimerChild(GMPChild* aPlugin) - : mTimerCount(1) - , mPlugin(aPlugin) -{ - MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current()); -} - -GMPTimerChild::~GMPTimerChild() -{ - MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current()); -} - -GMPErr -GMPTimerChild::SetTimer(GMPTask* aTask, int64_t aTimeoutMS) -{ - if (!aTask) { - NS_WARNING("Tried to set timer with null task!"); - return GMPGenericErr; - } - - if (mPlugin->GMPMessageLoop() != MessageLoop::current()) { - NS_WARNING("Tried to set GMP timer on non-main thread."); - return GMPGenericErr; - } - - if (mTimers.Count() > MAX_NUM_TIMERS) { - return GMPQuotaExceededErr; - } - uint32_t timerId = mTimerCount; - mTimers.Put(timerId, aTask); - mTimerCount++; - - if (!SendSetTimer(timerId, aTimeoutMS)) { - return GMPGenericErr; - } - return GMPNoErr; -} - -bool -GMPTimerChild::RecvTimerExpired(const uint32_t& aTimerId) -{ - MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current()); - - GMPTask* task = mTimers.Get(aTimerId); - mTimers.Remove(aTimerId); - if (task) { - RunOnMainThread(task); - } - return true; -} - -} // namespace gmp -} // namespace mozilla diff --git a/dom/media/gmp/GMPTimerChild.h b/dom/media/gmp/GMPTimerChild.h deleted file mode 100644 index c63a49480..000000000 --- a/dom/media/gmp/GMPTimerChild.h +++ /dev/null @@ -1,46 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#ifndef GMPTimerChild_h_ -#define GMPTimerChild_h_ - -#include "mozilla/gmp/PGMPTimerChild.h" -#include "mozilla/Monitor.h" -#include "nsDataHashtable.h" -#include "nsHashKeys.h" -#include "gmp-errors.h" -#include "gmp-platform.h" - -namespace mozilla { -namespace gmp { - -class GMPChild; - -class GMPTimerChild : public PGMPTimerChild -{ -public: - NS_INLINE_DECL_REFCOUNTING(GMPTimerChild) - - explicit GMPTimerChild(GMPChild* aPlugin); - - GMPErr SetTimer(GMPTask* aTask, int64_t aTimeoutMS); - -protected: - // GMPTimerChild - bool RecvTimerExpired(const uint32_t& aTimerId) override; - -private: - ~GMPTimerChild(); - - nsDataHashtable<nsUint32HashKey, GMPTask*> mTimers; - uint32_t mTimerCount; - - GMPChild* mPlugin; -}; - -} // namespace gmp -} // namespace mozilla - -#endif // GMPTimerChild_h_ diff --git a/dom/media/gmp/GMPTimerParent.cpp b/dom/media/gmp/GMPTimerParent.cpp deleted file mode 100644 index 50861b97f..000000000 --- a/dom/media/gmp/GMPTimerParent.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#include "GMPTimerParent.h" -#include "nsComponentManagerUtils.h" -#include "mozilla/Unused.h" -#include "nsAutoPtr.h" - -namespace mozilla { - -#ifdef LOG -#undef LOG -#endif - -extern LogModule* GetGMPLog(); - -#define LOGD(msg) MOZ_LOG(GetGMPLog(), mozilla::LogLevel::Debug, msg) -#define LOG(level, msg) MOZ_LOG(GetGMPLog(), (level), msg) - -#ifdef __CLASS__ -#undef __CLASS__ -#endif -#define __CLASS__ "GMPParent" - -namespace gmp { - -GMPTimerParent::GMPTimerParent(nsIThread* aGMPThread) - : mGMPThread(aGMPThread) - , mIsOpen(true) -{ -} - -bool -GMPTimerParent::RecvSetTimer(const uint32_t& aTimerId, - const uint32_t& aTimeoutMs) -{ - LOGD(("%s::%s: %p mIsOpen=%d", __CLASS__, __FUNCTION__, this, mIsOpen)); - - MOZ_ASSERT(mGMPThread == NS_GetCurrentThread()); - - if (!mIsOpen) { - return true; - } - - nsresult rv; - nsAutoPtr<Context> ctx(new Context()); - ctx->mTimer = do_CreateInstance("@mozilla.org/timer;1", &rv); - NS_ENSURE_SUCCESS(rv, true); - - ctx->mId = aTimerId; - rv = ctx->mTimer->SetTarget(mGMPThread); - NS_ENSURE_SUCCESS(rv, true); - ctx->mParent = this; - - rv = ctx->mTimer->InitWithFuncCallback(&GMPTimerParent::GMPTimerExpired, - ctx, - aTimeoutMs, - nsITimer::TYPE_ONE_SHOT); - NS_ENSURE_SUCCESS(rv, true); - - mTimers.PutEntry(ctx.forget()); - - return true; -} - -void -GMPTimerParent::Shutdown() -{ - LOGD(("%s::%s: %p mIsOpen=%d", __CLASS__, __FUNCTION__, this, mIsOpen)); - - MOZ_ASSERT(mGMPThread == NS_GetCurrentThread()); - - for (auto iter = mTimers.Iter(); !iter.Done(); iter.Next()) { - Context* context = iter.Get()->GetKey(); - context->mTimer->Cancel(); - delete context; - } - - mTimers.Clear(); - mIsOpen = false; -} - -void -GMPTimerParent::ActorDestroy(ActorDestroyReason aWhy) -{ - LOGD(("%s::%s: %p mIsOpen=%d", __CLASS__, __FUNCTION__, this, mIsOpen)); - - Shutdown(); -} - -/* static */ -void -GMPTimerParent::GMPTimerExpired(nsITimer *aTimer, void *aClosure) -{ - MOZ_ASSERT(aClosure); - nsAutoPtr<Context> ctx(static_cast<Context*>(aClosure)); - MOZ_ASSERT(ctx->mParent); - if (ctx->mParent) { - ctx->mParent->TimerExpired(ctx); - } -} - -void -GMPTimerParent::TimerExpired(Context* aContext) -{ - LOGD(("%s::%s: %p mIsOpen=%d", __CLASS__, __FUNCTION__, this, mIsOpen)); - MOZ_ASSERT(mGMPThread == NS_GetCurrentThread()); - - if (!mIsOpen) { - return; - } - - uint32_t id = aContext->mId; - mTimers.RemoveEntry(aContext); - if (id) { - Unused << SendTimerExpired(id); - } -} - -} // namespace gmp -} // namespace mozilla diff --git a/dom/media/gmp/GMPTimerParent.h b/dom/media/gmp/GMPTimerParent.h deleted file mode 100644 index 0aad36121..000000000 --- a/dom/media/gmp/GMPTimerParent.h +++ /dev/null @@ -1,61 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#ifndef GMPTimerParent_h_ -#define GMPTimerParent_h_ - -#include "mozilla/gmp/PGMPTimerParent.h" -#include "nsITimer.h" -#include "nsCOMPtr.h" -#include "nsClassHashtable.h" -#include "nsHashKeys.h" -#include "mozilla/Monitor.h" -#include "nsIThread.h" - -namespace mozilla { -namespace gmp { - -class GMPTimerParent : public PGMPTimerParent { -public: - NS_INLINE_DECL_REFCOUNTING(GMPTimerParent) - explicit GMPTimerParent(nsIThread* aGMPThread); - - void Shutdown(); - -protected: - bool RecvSetTimer(const uint32_t& aTimerId, - const uint32_t& aTimeoutMs) override; - void ActorDestroy(ActorDestroyReason aWhy) override; - -private: - ~GMPTimerParent() {} - - static void GMPTimerExpired(nsITimer *aTimer, void *aClosure); - - struct Context { - Context() { - MOZ_COUNT_CTOR(Context); - } - ~Context() { - MOZ_COUNT_DTOR(Context); - } - nsCOMPtr<nsITimer> mTimer; - RefPtr<GMPTimerParent> mParent; // Note: live timers keep the GMPTimerParent alive. - uint32_t mId; - }; - - void TimerExpired(Context* aContext); - - nsTHashtable<nsPtrHashKey<Context>> mTimers; - - nsCOMPtr<nsIThread> mGMPThread; - - bool mIsOpen; -}; - -} // namespace gmp -} // namespace mozilla - -#endif // GMPTimerParent_h_ diff --git a/dom/media/gmp/GMPTypes.ipdlh b/dom/media/gmp/GMPTypes.ipdlh deleted file mode 100644 index 44df5fc3d..000000000 --- a/dom/media/gmp/GMPTypes.ipdlh +++ /dev/null @@ -1,86 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -using GMPBufferType from "gmp-video-codec.h"; -using GMPAudioCodecType from "gmp-audio-codec.h"; -using GMPMediaKeyStatus from "gmp-decryption.h"; - -namespace mozilla { -namespace gmp { - -struct GMPDecryptionData { - uint8_t[] mKeyId; - uint8_t[] mIV; - uint16_t[] mClearBytes; - uint32_t[] mCipherBytes; - nsCString[] mSessionIds; -}; - -struct GMPVideoEncodedFrameData -{ - uint32_t mEncodedWidth; - uint32_t mEncodedHeight; - uint64_t mTimestamp; // microseconds - uint64_t mDuration; // microseconds - uint32_t mFrameType; - uint32_t mSize; - GMPBufferType mBufferType; - Shmem mBuffer; - bool mCompleteFrame; - GMPDecryptionData mDecryptionData; -}; - -struct GMPPlaneData -{ - int32_t mSize; - int32_t mStride; - Shmem mBuffer; -}; - -struct GMPVideoi420FrameData -{ - GMPPlaneData mYPlane; - GMPPlaneData mUPlane; - GMPPlaneData mVPlane; - int32_t mWidth; - int32_t mHeight; - uint64_t mTimestamp; // microseconds - uint64_t mDuration; // microseconds -}; - -struct GMPAudioCodecData -{ - GMPAudioCodecType mCodecType; - uint32_t mChannelCount; - uint32_t mBitsPerChannel; - uint32_t mSamplesPerSecond; - - uint8_t[] mExtraData; -}; - -struct GMPAudioEncodedSampleData -{ - uint8_t[] mData; - uint64_t mTimeStamp; // microseconds. - GMPDecryptionData mDecryptionData; - uint32_t mChannelCount; - uint32_t mSamplesPerSecond; -}; - -struct GMPAudioDecodedSampleData -{ - int16_t[] mData; - uint64_t mTimeStamp; // microseconds. - uint32_t mChannelCount; - uint32_t mSamplesPerSecond; -}; - -struct GMPKeyInformation { - uint8_t[] keyId; - GMPMediaKeyStatus status; -}; - -} -} diff --git a/dom/media/gmp/GMPUtils.cpp b/dom/media/gmp/GMPUtils.cpp deleted file mode 100644 index d5863516a..000000000 --- a/dom/media/gmp/GMPUtils.cpp +++ /dev/null @@ -1,230 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#include "GMPUtils.h" -#include "nsDirectoryServiceDefs.h" -#include "nsIFile.h" -#include "nsCOMPtr.h" -#include "nsLiteralString.h" -#include "nsCRTGlue.h" -#include "mozIGeckoMediaPluginService.h" -#include "mozilla/Base64.h" -#include "nsISimpleEnumerator.h" -#include "prio.h" - -namespace mozilla { - -bool -GetEMEVoucherPath(nsIFile** aPath) -{ - nsCOMPtr<nsIFile> path; - NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(path)); - if (!path) { - NS_WARNING("GetEMEVoucherPath can't get NS_GRE_DIR!"); - return false; - } - path->AppendNative(NS_LITERAL_CSTRING("voucher.bin")); - path.forget(aPath); - return true; -} - -bool -EMEVoucherFileExists() -{ - nsCOMPtr<nsIFile> path; - bool exists; - return GetEMEVoucherPath(getter_AddRefs(path)) && - NS_SUCCEEDED(path->Exists(&exists)) && - exists; -} - -void -SplitAt(const char* aDelims, - const nsACString& aInput, - nsTArray<nsCString>& aOutTokens) -{ - nsAutoCString str(aInput); - char* end = str.BeginWriting(); - const char* start = nullptr; - while (!!(start = NS_strtok(aDelims, &end))) { - aOutTokens.AppendElement(nsCString(start)); - } -} - -nsCString -ToBase64(const nsTArray<uint8_t>& aBytes) -{ - nsAutoCString base64; - nsDependentCSubstring raw(reinterpret_cast<const char*>(aBytes.Elements()), - aBytes.Length()); - nsresult rv = Base64Encode(raw, base64); - if (NS_WARN_IF(NS_FAILED(rv))) { - return NS_LITERAL_CSTRING("[Base64EncodeFailed]"); - } - return base64; -} - -bool -FileExists(nsIFile* aFile) -{ - bool exists = false; - return aFile && NS_SUCCEEDED(aFile->Exists(&exists)) && exists; -} - -DirectoryEnumerator::DirectoryEnumerator(nsIFile* aPath, Mode aMode) - : mMode(aMode) -{ - aPath->GetDirectoryEntries(getter_AddRefs(mIter)); -} - -already_AddRefed<nsIFile> -DirectoryEnumerator::Next() -{ - if (!mIter) { - return nullptr; - } - bool hasMore = false; - while (NS_SUCCEEDED(mIter->HasMoreElements(&hasMore)) && hasMore) { - nsCOMPtr<nsISupports> supports; - nsresult rv = mIter->GetNext(getter_AddRefs(supports)); - if (NS_FAILED(rv)) { - continue; - } - - nsCOMPtr<nsIFile> path(do_QueryInterface(supports, &rv)); - if (NS_FAILED(rv)) { - continue; - } - - if (mMode == DirsOnly) { - bool isDirectory = false; - rv = path->IsDirectory(&isDirectory); - if (NS_FAILED(rv) || !isDirectory) { - continue; - } - } - return path.forget(); - } - return nullptr; -} - -bool -ReadIntoArray(nsIFile* aFile, - nsTArray<uint8_t>& aOutDst, - size_t aMaxLength) -{ - if (!FileExists(aFile)) { - return false; - } - - PRFileDesc* fd = nullptr; - nsresult rv = aFile->OpenNSPRFileDesc(PR_RDONLY, 0, &fd); - if (NS_FAILED(rv)) { - return false; - } - - int32_t length = PR_Seek(fd, 0, PR_SEEK_END); - PR_Seek(fd, 0, PR_SEEK_SET); - - if (length < 0 || (size_t)length > aMaxLength) { - NS_WARNING("EME file is longer than maximum allowed length"); - PR_Close(fd); - return false; - } - aOutDst.SetLength(length); - int32_t bytesRead = PR_Read(fd, aOutDst.Elements(), length); - PR_Close(fd); - return (bytesRead == length); -} - -bool -ReadIntoString(nsIFile* aFile, - nsCString& aOutDst, - size_t aMaxLength) -{ - nsTArray<uint8_t> buf; - bool rv = ReadIntoArray(aFile, buf, aMaxLength); - if (rv) { - buf.AppendElement(0); // Append null terminator, required by nsC*String. - aOutDst = nsDependentCString((const char*)buf.Elements(), buf.Length() - 1); - } - return rv; -} - -bool -GMPInfoFileParser::Init(nsIFile* aInfoFile) -{ - nsTArray<nsCString> lines; - static const size_t MAX_GMP_INFO_FILE_LENGTH = 5 * 1024; - - nsAutoCString info; - if (!ReadIntoString(aInfoFile, info, MAX_GMP_INFO_FILE_LENGTH)) { - NS_WARNING("Failed to read info file in GMP process."); - return false; - } - - // Note: we pass "\r\n" to SplitAt so that we'll split lines delimited - // by \n (Unix), \r\n (Windows) and \r (old MacOSX). - SplitAt("\r\n", info, lines); - - for (nsCString line : lines) { - // Field name is the string up to but not including the first ':' - // character on the line. - int32_t colon = line.FindChar(':'); - if (colon <= 0) { - // Not allowed to be the first character. - // Info field name must be at least one character. - continue; - } - nsAutoCString key(Substring(line, 0, colon)); - ToLowerCase(key); - key.Trim(" "); - - nsCString* value = new nsCString(Substring(line, colon + 1)); - value->Trim(" "); - mValues.Put(key, value); // Hashtable assumes ownership of value. - } - - return true; -} - -bool -GMPInfoFileParser::Contains(const nsCString& aKey) const { - nsCString key(aKey); - ToLowerCase(key); - return mValues.Contains(key); -} - -nsCString -GMPInfoFileParser::Get(const nsCString& aKey) const { - MOZ_ASSERT(Contains(aKey)); - nsCString key(aKey); - ToLowerCase(key); - nsCString* p = nullptr; - if (mValues.Get(key, &p)) { - return nsCString(*p); - } - return EmptyCString(); -} - -bool -HaveGMPFor(const nsCString& aAPI, - nsTArray<nsCString>&& aTags) -{ - nsCOMPtr<mozIGeckoMediaPluginService> mps = - do_GetService("@mozilla.org/gecko-media-plugin-service;1"); - if (NS_WARN_IF(!mps)) { - return false; - } - - bool hasPlugin = false; - if (NS_FAILED(mps->HasPluginForAPI(aAPI, &aTags, &hasPlugin))) { - return false; - } - return hasPlugin; -} - - -} // namespace mozilla diff --git a/dom/media/gmp/GMPUtils.h b/dom/media/gmp/GMPUtils.h deleted file mode 100644 index 7e7b9f26f..000000000 --- a/dom/media/gmp/GMPUtils.h +++ /dev/null @@ -1,89 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#ifndef GMPUtils_h_ -#define GMPUtils_h_ - -#include "mozilla/UniquePtr.h" -#include "nsTArray.h" -#include "nsCOMPtr.h" -#include "nsClassHashtable.h" - -class nsIFile; -class nsCString; -class nsISimpleEnumerator; - -namespace mozilla { - -template<typename T> -struct DestroyPolicy -{ - void operator()(T* aGMPObject) const { - aGMPObject->Destroy(); - } -}; - -template<typename T> -using GMPUniquePtr = mozilla::UniquePtr<T, DestroyPolicy<T>>; - -bool GetEMEVoucherPath(nsIFile** aPath); - -bool EMEVoucherFileExists(); - -void -SplitAt(const char* aDelims, - const nsACString& aInput, - nsTArray<nsCString>& aOutTokens); - -nsCString -ToBase64(const nsTArray<uint8_t>& aBytes); - -bool -FileExists(nsIFile* aFile); - -// Enumerate directory entries for a specified path. -class DirectoryEnumerator { -public: - - enum Mode { - DirsOnly, // Enumeration only includes directories. - FilesAndDirs // Enumeration includes directories and non-directory files. - }; - - DirectoryEnumerator(nsIFile* aPath, Mode aMode); - - already_AddRefed<nsIFile> Next(); - -private: - Mode mMode; - nsCOMPtr<nsISimpleEnumerator> mIter; -}; - -class GMPInfoFileParser { -public: - bool Init(nsIFile* aFile); - bool Contains(const nsCString& aKey) const; - nsCString Get(const nsCString& aKey) const; -private: - nsClassHashtable<nsCStringHashKey, nsCString> mValues; -}; - -bool -ReadIntoArray(nsIFile* aFile, - nsTArray<uint8_t>& aOutDst, - size_t aMaxLength); - -bool -ReadIntoString(nsIFile* aFile, - nsCString& aOutDst, - size_t aMaxLength); - -bool -HaveGMPFor(const nsCString& aAPI, - nsTArray<nsCString>&& aTags); - -} // namespace mozilla - -#endif diff --git a/dom/media/gmp/GMPVideoDecoderChild.cpp b/dom/media/gmp/GMPVideoDecoderChild.cpp deleted file mode 100644 index f9c1956e7..000000000 --- a/dom/media/gmp/GMPVideoDecoderChild.cpp +++ /dev/null @@ -1,254 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#include "GMPVideoDecoderChild.h" -#include "GMPVideoi420FrameImpl.h" -#include "GMPContentChild.h" -#include <stdio.h> -#include "mozilla/Unused.h" -#include "GMPVideoEncodedFrameImpl.h" -#include "runnable_utils.h" - -namespace mozilla { -namespace gmp { - -GMPVideoDecoderChild::GMPVideoDecoderChild(GMPContentChild* aPlugin) - : GMPSharedMemManager(aPlugin) - , mPlugin(aPlugin) - , mVideoDecoder(nullptr) - , mVideoHost(this) - , mNeedShmemIntrCount(0) - , mPendingDecodeComplete(false) -{ - MOZ_ASSERT(mPlugin); -} - -GMPVideoDecoderChild::~GMPVideoDecoderChild() -{ - MOZ_ASSERT(!mNeedShmemIntrCount); -} - -void -GMPVideoDecoderChild::Init(GMPVideoDecoder* aDecoder) -{ - MOZ_ASSERT(aDecoder, "Cannot initialize video decoder child without a video decoder!"); - mVideoDecoder = aDecoder; -} - -GMPVideoHostImpl& -GMPVideoDecoderChild::Host() -{ - return mVideoHost; -} - -void -GMPVideoDecoderChild::Decoded(GMPVideoi420Frame* aDecodedFrame) -{ - MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current()); - - if (!aDecodedFrame) { - MOZ_CRASH("Not given a decoded frame!"); - } - - auto df = static_cast<GMPVideoi420FrameImpl*>(aDecodedFrame); - - GMPVideoi420FrameData frameData; - df->InitFrameData(frameData); - SendDecoded(frameData); - - aDecodedFrame->Destroy(); -} - -void -GMPVideoDecoderChild::ReceivedDecodedReferenceFrame(const uint64_t aPictureId) -{ - MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current()); - - SendReceivedDecodedReferenceFrame(aPictureId); -} - -void -GMPVideoDecoderChild::ReceivedDecodedFrame(const uint64_t aPictureId) -{ - MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current()); - - SendReceivedDecodedFrame(aPictureId); -} - -void -GMPVideoDecoderChild::InputDataExhausted() -{ - MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current()); - - SendInputDataExhausted(); -} - -void -GMPVideoDecoderChild::DrainComplete() -{ - MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current()); - - SendDrainComplete(); -} - -void -GMPVideoDecoderChild::ResetComplete() -{ - MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current()); - - SendResetComplete(); -} - -void -GMPVideoDecoderChild::Error(GMPErr aError) -{ - MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current()); - - SendError(aError); -} - -bool -GMPVideoDecoderChild::RecvInitDecode(const GMPVideoCodec& aCodecSettings, - InfallibleTArray<uint8_t>&& aCodecSpecific, - const int32_t& aCoreCount) -{ - if (!mVideoDecoder) { - return false; - } - - // Ignore any return code. It is OK for this to fail without killing the process. - mVideoDecoder->InitDecode(aCodecSettings, - aCodecSpecific.Elements(), - aCodecSpecific.Length(), - this, - aCoreCount); - return true; -} - -bool -GMPVideoDecoderChild::RecvDecode(const GMPVideoEncodedFrameData& aInputFrame, - const bool& aMissingFrames, - InfallibleTArray<uint8_t>&& aCodecSpecificInfo, - const int64_t& aRenderTimeMs) -{ - if (!mVideoDecoder) { - return false; - } - - auto f = new GMPVideoEncodedFrameImpl(aInputFrame, &mVideoHost); - - // Ignore any return code. It is OK for this to fail without killing the process. - mVideoDecoder->Decode(f, - aMissingFrames, - aCodecSpecificInfo.Elements(), - aCodecSpecificInfo.Length(), - aRenderTimeMs); - - return true; -} - -bool -GMPVideoDecoderChild::RecvChildShmemForPool(Shmem&& aFrameBuffer) -{ - if (aFrameBuffer.IsWritable()) { - mVideoHost.SharedMemMgr()->MgrDeallocShmem(GMPSharedMem::kGMPFrameData, - aFrameBuffer); - } - return true; -} - -bool -GMPVideoDecoderChild::RecvReset() -{ - if (!mVideoDecoder) { - return false; - } - - // Ignore any return code. It is OK for this to fail without killing the process. - mVideoDecoder->Reset(); - - return true; -} - -bool -GMPVideoDecoderChild::RecvDrain() -{ - if (!mVideoDecoder) { - return false; - } - - // Ignore any return code. It is OK for this to fail without killing the process. - mVideoDecoder->Drain(); - - return true; -} - -bool -GMPVideoDecoderChild::RecvDecodingComplete() -{ - MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current()); - - if (mNeedShmemIntrCount) { - // There's a GMP blocked in Alloc() waiting for the CallNeedShem() to - // return a frame they can use. Don't call the GMP's DecodingComplete() - // now and don't delete the GMPVideoDecoderChild, defer processing the - // DecodingComplete() until once the Alloc() finishes. - mPendingDecodeComplete = true; - return true; - } - if (mVideoDecoder) { - // Ignore any return code. It is OK for this to fail without killing the process. - mVideoDecoder->DecodingComplete(); - mVideoDecoder = nullptr; - } - - mVideoHost.DoneWithAPI(); - - mPlugin = nullptr; - - Unused << Send__delete__(this); - - return true; -} - -bool -GMPVideoDecoderChild::Alloc(size_t aSize, - Shmem::SharedMemory::SharedMemoryType aType, - Shmem* aMem) -{ - MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current()); - - bool rv; -#ifndef SHMEM_ALLOC_IN_CHILD - ++mNeedShmemIntrCount; - rv = CallNeedShmem(aSize, aMem); - --mNeedShmemIntrCount; - if (mPendingDecodeComplete && mNeedShmemIntrCount == 0) { - mPendingDecodeComplete = false; - mPlugin->GMPMessageLoop()->PostTask( - NewRunnableMethod(this, &GMPVideoDecoderChild::RecvDecodingComplete)); - } -#else -#ifdef GMP_SAFE_SHMEM - rv = AllocShmem(aSize, aType, aMem); -#else - rv = AllocUnsafeShmem(aSize, aType, aMem); -#endif -#endif - return rv; -} - -void -GMPVideoDecoderChild::Dealloc(Shmem& aMem) -{ -#ifndef SHMEM_ALLOC_IN_CHILD - SendParentShmemForPool(aMem); -#else - DeallocShmem(aMem); -#endif -} - -} // namespace gmp -} // namespace mozilla diff --git a/dom/media/gmp/GMPVideoDecoderChild.h b/dom/media/gmp/GMPVideoDecoderChild.h deleted file mode 100644 index 2271a70a1..000000000 --- a/dom/media/gmp/GMPVideoDecoderChild.h +++ /dev/null @@ -1,75 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#ifndef GMPVideoDecoderChild_h_ -#define GMPVideoDecoderChild_h_ - -#include "nsString.h" -#include "mozilla/gmp/PGMPVideoDecoderChild.h" -#include "gmp-video-decode.h" -#include "GMPSharedMemManager.h" -#include "GMPVideoHost.h" -#include "mozilla/gmp/GMPTypes.h" - -namespace mozilla { -namespace gmp { - -class GMPContentChild; - -class GMPVideoDecoderChild : public PGMPVideoDecoderChild, - public GMPVideoDecoderCallback, - public GMPSharedMemManager -{ -public: - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GMPVideoDecoderChild); - - explicit GMPVideoDecoderChild(GMPContentChild* aPlugin); - - void Init(GMPVideoDecoder* aDecoder); - GMPVideoHostImpl& Host(); - - // GMPVideoDecoderCallback - void Decoded(GMPVideoi420Frame* decodedFrame) override; - void ReceivedDecodedReferenceFrame(const uint64_t pictureId) override; - void ReceivedDecodedFrame(const uint64_t pictureId) override; - void InputDataExhausted() override; - void DrainComplete() override; - void ResetComplete() override; - void Error(GMPErr aError) override; - - // GMPSharedMemManager - bool Alloc(size_t aSize, Shmem::SharedMemory::SharedMemoryType aType, Shmem* aMem) override; - void Dealloc(Shmem& aMem) override; - -private: - virtual ~GMPVideoDecoderChild(); - - // PGMPVideoDecoderChild - bool RecvInitDecode(const GMPVideoCodec& aCodecSettings, - InfallibleTArray<uint8_t>&& aCodecSpecific, - const int32_t& aCoreCount) override; - bool RecvDecode(const GMPVideoEncodedFrameData& aInputFrame, - const bool& aMissingFrames, - InfallibleTArray<uint8_t>&& aCodecSpecificInfo, - const int64_t& aRenderTimeMs) override; - bool RecvChildShmemForPool(Shmem&& aFrameBuffer) override; - bool RecvReset() override; - bool RecvDrain() override; - bool RecvDecodingComplete() override; - - GMPContentChild* mPlugin; - GMPVideoDecoder* mVideoDecoder; - GMPVideoHostImpl mVideoHost; - - // Non-zero when a GMP is blocked spinning the IPC message loop while - // waiting on an NeedShmem to complete. - int mNeedShmemIntrCount; - bool mPendingDecodeComplete; -}; - -} // namespace gmp -} // namespace mozilla - -#endif // GMPVideoDecoderChild_h_ diff --git a/dom/media/gmp/GMPVideoDecoderParent.cpp b/dom/media/gmp/GMPVideoDecoderParent.cpp deleted file mode 100644 index bd5408adb..000000000 --- a/dom/media/gmp/GMPVideoDecoderParent.cpp +++ /dev/null @@ -1,513 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#include "GMPVideoDecoderParent.h" -#include "mozilla/Logging.h" -#include "mozilla/Unused.h" -#include "nsAutoRef.h" -#include "nsThreadUtils.h" -#include "GMPUtils.h" -#include "GMPVideoEncodedFrameImpl.h" -#include "GMPVideoi420FrameImpl.h" -#include "GMPContentParent.h" -#include "GMPMessageUtils.h" -#include "mozilla/gmp/GMPTypes.h" - -namespace mozilla { - -#ifdef LOG -#undef LOG -#endif - -extern LogModule* GetGMPLog(); - -#define LOGV(msg) MOZ_LOG(GetGMPLog(), mozilla::LogLevel::Verbose, msg) -#define LOGD(msg) MOZ_LOG(GetGMPLog(), mozilla::LogLevel::Debug, msg) -#define LOGE(msg) MOZ_LOG(GetGMPLog(), mozilla::LogLevel::Error, msg) -#define LOG(level, msg) MOZ_LOG(GetGMPLog(), (level), msg) - -namespace gmp { - -// States: -// Initial: mIsOpen == false -// on InitDecode success -> Open -// on Shutdown -> Dead -// Open: mIsOpen == true -// on Close -> Dead -// on ActorDestroy -> Dead -// on Shutdown -> Dead -// Dead: mIsOpen == false - -GMPVideoDecoderParent::GMPVideoDecoderParent(GMPContentParent* aPlugin) - : GMPSharedMemManager(aPlugin) - , mIsOpen(false) - , mShuttingDown(false) - , mActorDestroyed(false) - , mIsAwaitingResetComplete(false) - , mIsAwaitingDrainComplete(false) - , mPlugin(aPlugin) - , mCallback(nullptr) - , mVideoHost(this) - , mPluginId(aPlugin->GetPluginId()) - , mFrameCount(0) -{ - MOZ_ASSERT(mPlugin); -} - -GMPVideoDecoderParent::~GMPVideoDecoderParent() -{ -} - -GMPVideoHostImpl& -GMPVideoDecoderParent::Host() -{ - return mVideoHost; -} - -// Note: may be called via Terminated() -void -GMPVideoDecoderParent::Close() -{ - LOGD(("GMPVideoDecoderParent[%p]::Close()", this)); - MOZ_ASSERT(!mPlugin || mPlugin->GMPThread() == NS_GetCurrentThread()); - - // Ensure if we've received a Close while waiting for a ResetComplete - // or DrainComplete notification, we'll unblock the caller before processing - // the close. This seems unlikely to happen, but better to be careful. - UnblockResetAndDrain(); - - // Consumer is done with us; we can shut down. No more callbacks should - // be made to mCallback. Note: do this before Shutdown()! - mCallback = nullptr; - // Let Shutdown mark us as dead so it knows if we had been alive - - // In case this is the last reference - RefPtr<GMPVideoDecoderParent> kungfudeathgrip(this); - Release(); - Shutdown(); -} - -nsresult -GMPVideoDecoderParent::InitDecode(const GMPVideoCodec& aCodecSettings, - const nsTArray<uint8_t>& aCodecSpecific, - GMPVideoDecoderCallbackProxy* aCallback, - int32_t aCoreCount) -{ - LOGD(("GMPVideoDecoderParent[%p]::InitDecode()", this)); - - if (mActorDestroyed) { - NS_WARNING("Trying to use a destroyed GMP video decoder!"); - return NS_ERROR_FAILURE; - } - if (mIsOpen) { - NS_WARNING("Trying to re-init an in-use GMP video decoder!"); - return NS_ERROR_FAILURE; - } - - MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread()); - - if (!aCallback) { - return NS_ERROR_FAILURE; - } - mCallback = aCallback; - - if (!SendInitDecode(aCodecSettings, aCodecSpecific, aCoreCount)) { - return NS_ERROR_FAILURE; - } - mIsOpen = true; - - // Async IPC, we don't have access to a return value. - return NS_OK; -} - -nsresult -GMPVideoDecoderParent::Decode(GMPUniquePtr<GMPVideoEncodedFrame> aInputFrame, - bool aMissingFrames, - const nsTArray<uint8_t>& aCodecSpecificInfo, - int64_t aRenderTimeMs) -{ - LOGV(("GMPVideoDecoderParent[%p]::Decode() timestamp=%lld keyframe=%d", - this, aInputFrame->TimeStamp(), - aInputFrame->FrameType() == kGMPKeyFrame)); - - if (!mIsOpen) { - LOGE(("GMPVideoDecoderParent[%p]::Decode() ERROR; dead GMPVideoDecoder", this)); - NS_WARNING("Trying to use an dead GMP video decoder"); - return NS_ERROR_FAILURE; - } - - MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread()); - - GMPUniquePtr<GMPVideoEncodedFrameImpl> inputFrameImpl( - static_cast<GMPVideoEncodedFrameImpl*>(aInputFrame.release())); - - // Very rough kill-switch if the plugin stops processing. If it's merely - // hung and continues, we'll come back to life eventually. - // 3* is because we're using 3 buffers per frame for i420 data for now. - if ((NumInUse(GMPSharedMem::kGMPFrameData) > 3*GMPSharedMem::kGMPBufLimit) || - (NumInUse(GMPSharedMem::kGMPEncodedData) > GMPSharedMem::kGMPBufLimit)) { - LOGE(("GMPVideoDecoderParent[%p]::Decode() ERROR; shmem buffer limit hit frame=%d encoded=%d", - this, NumInUse(GMPSharedMem::kGMPFrameData), NumInUse(GMPSharedMem::kGMPEncodedData))); - return NS_ERROR_FAILURE; - } - - GMPVideoEncodedFrameData frameData; - inputFrameImpl->RelinquishFrameData(frameData); - - if (!SendDecode(frameData, - aMissingFrames, - aCodecSpecificInfo, - aRenderTimeMs)) { - LOGE(("GMPVideoDecoderParent[%p]::Decode() ERROR; SendDecode() failure.", this)); - return NS_ERROR_FAILURE; - } - mFrameCount++; - - // Async IPC, we don't have access to a return value. - return NS_OK; -} - -nsresult -GMPVideoDecoderParent::Reset() -{ - LOGD(("GMPVideoDecoderParent[%p]::Reset()", this)); - - if (!mIsOpen) { - NS_WARNING("Trying to use an dead GMP video decoder"); - return NS_ERROR_FAILURE; - } - - MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread()); - - if (!SendReset()) { - return NS_ERROR_FAILURE; - } - - mIsAwaitingResetComplete = true; - - RefPtr<GMPVideoDecoderParent> self(this); - nsCOMPtr<nsIRunnable> task = NS_NewRunnableFunction([self]() -> void - { - LOGD(("GMPVideoDecoderParent[%p]::ResetCompleteTimeout() timed out waiting for ResetComplete", self.get())); - self->mResetCompleteTimeout = nullptr; - LogToBrowserConsole(NS_LITERAL_STRING("GMPVideoDecoderParent timed out waiting for ResetComplete()")); - }); - CancelResetCompleteTimeout(); - mResetCompleteTimeout = SimpleTimer::Create(task, 5000, mPlugin->GMPThread()); - - // Async IPC, we don't have access to a return value. - return NS_OK; -} - -void -GMPVideoDecoderParent::CancelResetCompleteTimeout() -{ - if (mResetCompleteTimeout) { - mResetCompleteTimeout->Cancel(); - mResetCompleteTimeout = nullptr; - } -} - -nsresult -GMPVideoDecoderParent::Drain() -{ - LOGD(("GMPVideoDecoderParent[%p]::Drain() frameCount=%d", this, mFrameCount)); - - if (!mIsOpen) { - NS_WARNING("Trying to use an dead GMP video decoder"); - return NS_ERROR_FAILURE; - } - - MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread()); - - if (!SendDrain()) { - return NS_ERROR_FAILURE; - } - - mIsAwaitingDrainComplete = true; - - // Async IPC, we don't have access to a return value. - return NS_OK; -} - -const nsCString& -GMPVideoDecoderParent::GetDisplayName() const -{ - if (!mIsOpen) { - NS_WARNING("Trying to use an dead GMP video decoder"); - } - - MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread()); - - return mPlugin->GetDisplayName(); -} - -// Note: Consider keeping ActorDestroy sync'd up when making changes here. -nsresult -GMPVideoDecoderParent::Shutdown() -{ - LOGD(("GMPVideoDecoderParent[%p]::Shutdown()", this)); - MOZ_ASSERT(!mPlugin || mPlugin->GMPThread() == NS_GetCurrentThread()); - - if (mShuttingDown) { - return NS_OK; - } - mShuttingDown = true; - - // Ensure if we've received a shutdown while waiting for a ResetComplete - // or DrainComplete notification, we'll unblock the caller before processing - // the shutdown. - UnblockResetAndDrain(); - - // Notify client we're gone! Won't occur after Close() - if (mCallback) { - mCallback->Terminated(); - mCallback = nullptr; - } - - mIsOpen = false; - if (!mActorDestroyed) { - Unused << SendDecodingComplete(); - } - - return NS_OK; -} - -// Note: Keep this sync'd up with Shutdown -void -GMPVideoDecoderParent::ActorDestroy(ActorDestroyReason aWhy) -{ - LOGD(("GMPVideoDecoderParent[%p]::ActorDestroy reason=%d", this, aWhy)); - - mIsOpen = false; - mActorDestroyed = true; - - // Ensure if we've received a destroy while waiting for a ResetComplete - // or DrainComplete notification, we'll unblock the caller before processing - // the error. - UnblockResetAndDrain(); - - if (mCallback) { - // May call Close() (and Shutdown()) immediately or with a delay - mCallback->Terminated(); - mCallback = nullptr; - } - if (mPlugin) { - // Ignore any return code. It is OK for this to fail without killing the process. - mPlugin->VideoDecoderDestroyed(this); - mPlugin = nullptr; - } - mVideoHost.ActorDestroyed(); - MaybeDisconnect(aWhy == AbnormalShutdown); -} - -bool -GMPVideoDecoderParent::RecvDecoded(const GMPVideoi420FrameData& aDecodedFrame) -{ - --mFrameCount; - LOGV(("GMPVideoDecoderParent[%p]::RecvDecoded() timestamp=%lld frameCount=%d", - this, aDecodedFrame.mTimestamp(), mFrameCount)); - - if (!mCallback) { - return false; - } - - if (!GMPVideoi420FrameImpl::CheckFrameData(aDecodedFrame)) { - LOGE(("GMPVideoDecoderParent[%p]::RecvDecoded() " - "timestamp=%lld decoded frame corrupt, ignoring")); - return false; - } - auto f = new GMPVideoi420FrameImpl(aDecodedFrame, &mVideoHost); - - // Ignore any return code. It is OK for this to fail without killing the process. - mCallback->Decoded(f); - - return true; -} - -bool -GMPVideoDecoderParent::RecvReceivedDecodedReferenceFrame(const uint64_t& aPictureId) -{ - if (!mCallback) { - return false; - } - - // Ignore any return code. It is OK for this to fail without killing the process. - mCallback->ReceivedDecodedReferenceFrame(aPictureId); - - return true; -} - -bool -GMPVideoDecoderParent::RecvReceivedDecodedFrame(const uint64_t& aPictureId) -{ - if (!mCallback) { - return false; - } - - // Ignore any return code. It is OK for this to fail without killing the process. - mCallback->ReceivedDecodedFrame(aPictureId); - - return true; -} - -bool -GMPVideoDecoderParent::RecvInputDataExhausted() -{ - LOGV(("GMPVideoDecoderParent[%p]::RecvInputDataExhausted()", this)); - - if (!mCallback) { - return false; - } - - // Ignore any return code. It is OK for this to fail without killing the process. - mCallback->InputDataExhausted(); - - return true; -} - -bool -GMPVideoDecoderParent::RecvDrainComplete() -{ - LOGD(("GMPVideoDecoderParent[%p]::RecvDrainComplete() frameCount=%d", this, mFrameCount)); - nsAutoString msg; - msg.AppendLiteral("GMPVideoDecoderParent::RecvDrainComplete() outstanding frames="); - msg.AppendInt(mFrameCount); - LogToBrowserConsole(msg); - if (!mCallback) { - return false; - } - - if (!mIsAwaitingDrainComplete) { - return true; - } - mIsAwaitingDrainComplete = false; - - // Ignore any return code. It is OK for this to fail without killing the process. - mCallback->DrainComplete(); - - return true; -} - -bool -GMPVideoDecoderParent::RecvResetComplete() -{ - LOGD(("GMPVideoDecoderParent[%p]::RecvResetComplete()", this)); - - CancelResetCompleteTimeout(); - - if (!mCallback) { - return false; - } - - if (!mIsAwaitingResetComplete) { - return true; - } - mIsAwaitingResetComplete = false; - mFrameCount = 0; - - // Ignore any return code. It is OK for this to fail without killing the process. - mCallback->ResetComplete(); - - return true; -} - -bool -GMPVideoDecoderParent::RecvError(const GMPErr& aError) -{ - LOGD(("GMPVideoDecoderParent[%p]::RecvError(error=%d)", this, aError)); - - if (!mCallback) { - return false; - } - - // Ensure if we've received an error while waiting for a ResetComplete - // or DrainComplete notification, we'll unblock the caller before processing - // the error. - UnblockResetAndDrain(); - - // Ignore any return code. It is OK for this to fail without killing the process. - mCallback->Error(aError); - - return true; -} - -bool -GMPVideoDecoderParent::RecvShutdown() -{ - LOGD(("GMPVideoDecoderParent[%p]::RecvShutdown()", this)); - - Shutdown(); - return true; -} - -bool -GMPVideoDecoderParent::RecvParentShmemForPool(Shmem&& aEncodedBuffer) -{ - if (aEncodedBuffer.IsWritable()) { - mVideoHost.SharedMemMgr()->MgrDeallocShmem(GMPSharedMem::kGMPEncodedData, - aEncodedBuffer); - } - return true; -} - -bool -GMPVideoDecoderParent::AnswerNeedShmem(const uint32_t& aFrameBufferSize, - Shmem* aMem) -{ - ipc::Shmem mem; - - if (!mVideoHost.SharedMemMgr()->MgrAllocShmem(GMPSharedMem::kGMPFrameData, - aFrameBufferSize, - ipc::SharedMemory::TYPE_BASIC, &mem)) - { - LOGE(("%s: Failed to get a shared mem buffer for Child! size %u", - __FUNCTION__, aFrameBufferSize)); - return false; - } - *aMem = mem; - mem = ipc::Shmem(); - return true; -} - -bool -GMPVideoDecoderParent::Recv__delete__() -{ - LOGD(("GMPVideoDecoderParent[%p]::Recv__delete__()", this)); - - if (mPlugin) { - // Ignore any return code. It is OK for this to fail without killing the process. - mPlugin->VideoDecoderDestroyed(this); - mPlugin = nullptr; - } - - return true; -} - -void -GMPVideoDecoderParent::UnblockResetAndDrain() -{ - LOGD(("GMPVideoDecoderParent[%p]::UnblockResetAndDrain() " - "awaitingResetComplete=%d awaitingDrainComplete=%d", - this, mIsAwaitingResetComplete, mIsAwaitingDrainComplete)); - - if (!mCallback) { - MOZ_ASSERT(!mIsAwaitingResetComplete); - MOZ_ASSERT(!mIsAwaitingDrainComplete); - return; - } - if (mIsAwaitingResetComplete) { - mIsAwaitingResetComplete = false; - mCallback->ResetComplete(); - } - if (mIsAwaitingDrainComplete) { - mIsAwaitingDrainComplete = false; - mCallback->DrainComplete(); - } - CancelResetCompleteTimeout(); -} - -} // namespace gmp -} // namespace mozilla diff --git a/dom/media/gmp/GMPVideoDecoderParent.h b/dom/media/gmp/GMPVideoDecoderParent.h deleted file mode 100644 index 215c784c1..000000000 --- a/dom/media/gmp/GMPVideoDecoderParent.h +++ /dev/null @@ -1,104 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#ifndef GMPVideoDecoderParent_h_ -#define GMPVideoDecoderParent_h_ - -#include "mozilla/RefPtr.h" -#include "gmp-video-decode.h" -#include "mozilla/gmp/PGMPVideoDecoderParent.h" -#include "GMPMessageUtils.h" -#include "GMPSharedMemManager.h" -#include "GMPUtils.h" -#include "GMPVideoHost.h" -#include "GMPVideoDecoderProxy.h" -#include "VideoUtils.h" -#include "GMPCrashHelperHolder.h" - -namespace mozilla { -namespace gmp { - -class GMPContentParent; - -class GMPVideoDecoderParent final : public PGMPVideoDecoderParent - , public GMPVideoDecoderProxy - , public GMPSharedMemManager - , public GMPCrashHelperHolder -{ -public: - NS_INLINE_DECL_REFCOUNTING(GMPVideoDecoderParent) - - explicit GMPVideoDecoderParent(GMPContentParent *aPlugin); - - GMPVideoHostImpl& Host(); - nsresult Shutdown(); - - // GMPVideoDecoder - void Close() override; - nsresult InitDecode(const GMPVideoCodec& aCodecSettings, - const nsTArray<uint8_t>& aCodecSpecific, - GMPVideoDecoderCallbackProxy* aCallback, - int32_t aCoreCount) override; - nsresult Decode(GMPUniquePtr<GMPVideoEncodedFrame> aInputFrame, - bool aMissingFrames, - const nsTArray<uint8_t>& aCodecSpecificInfo, - int64_t aRenderTimeMs = -1) override; - nsresult Reset() override; - nsresult Drain() override; - uint32_t GetPluginId() const override { return mPluginId; } - const nsCString& GetDisplayName() const override; - - // GMPSharedMemManager - bool Alloc(size_t aSize, Shmem::SharedMemory::SharedMemoryType aType, Shmem* aMem) override - { -#ifdef GMP_SAFE_SHMEM - return AllocShmem(aSize, aType, aMem); -#else - return AllocUnsafeShmem(aSize, aType, aMem); -#endif - } - void Dealloc(Shmem& aMem) override - { - DeallocShmem(aMem); - } - -private: - ~GMPVideoDecoderParent(); - - // PGMPVideoDecoderParent - void ActorDestroy(ActorDestroyReason aWhy) override; - bool RecvDecoded(const GMPVideoi420FrameData& aDecodedFrame) override; - bool RecvReceivedDecodedReferenceFrame(const uint64_t& aPictureId) override; - bool RecvReceivedDecodedFrame(const uint64_t& aPictureId) override; - bool RecvInputDataExhausted() override; - bool RecvDrainComplete() override; - bool RecvResetComplete() override; - bool RecvError(const GMPErr& aError) override; - bool RecvShutdown() override; - bool RecvParentShmemForPool(Shmem&& aEncodedBuffer) override; - bool AnswerNeedShmem(const uint32_t& aFrameBufferSize, - Shmem* aMem) override; - bool Recv__delete__() override; - - void UnblockResetAndDrain(); - void CancelResetCompleteTimeout(); - - bool mIsOpen; - bool mShuttingDown; - bool mActorDestroyed; - bool mIsAwaitingResetComplete; - bool mIsAwaitingDrainComplete; - RefPtr<GMPContentParent> mPlugin; - GMPVideoDecoderCallbackProxy* mCallback; - GMPVideoHostImpl mVideoHost; - const uint32_t mPluginId; - int32_t mFrameCount; - RefPtr<SimpleTimer> mResetCompleteTimeout; -}; - -} // namespace gmp -} // namespace mozilla - -#endif // GMPVideoDecoderParent_h_ diff --git a/dom/media/gmp/GMPVideoDecoderProxy.h b/dom/media/gmp/GMPVideoDecoderProxy.h deleted file mode 100644 index b9596fd21..000000000 --- a/dom/media/gmp/GMPVideoDecoderProxy.h +++ /dev/null @@ -1,56 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#ifndef GMPVideoDecoderProxy_h_ -#define GMPVideoDecoderProxy_h_ - -#include "nsTArray.h" -#include "gmp-video-decode.h" -#include "gmp-video-frame-i420.h" -#include "gmp-video-frame-encoded.h" - -#include "GMPCallbackBase.h" -#include "GMPUtils.h" - -class GMPVideoDecoderCallbackProxy : public GMPCallbackBase, - public GMPVideoDecoderCallback -{ -public: - virtual ~GMPVideoDecoderCallbackProxy() {} -}; - -// A proxy to GMPVideoDecoder in the child process. -// GMPVideoDecoderParent exposes this to users the GMP. -// This enables Gecko to pass nsTArrays to the child GMP and avoid -// an extra copy when doing so. - -// The consumer must call Close() when done with the codec, or when -// Terminated() is called by the GMP plugin indicating an abnormal shutdown -// of the underlying plugin. After calling Close(), the consumer must -// not access this again. - -// This interface is not thread-safe and must only be used from GMPThread. -class GMPVideoDecoderProxy { -public: - virtual nsresult InitDecode(const GMPVideoCodec& aCodecSettings, - const nsTArray<uint8_t>& aCodecSpecific, - GMPVideoDecoderCallbackProxy* aCallback, - int32_t aCoreCount) = 0; - virtual nsresult Decode(mozilla::GMPUniquePtr<GMPVideoEncodedFrame> aInputFrame, - bool aMissingFrames, - const nsTArray<uint8_t>& aCodecSpecificInfo, - int64_t aRenderTimeMs = -1) = 0; - virtual nsresult Reset() = 0; - virtual nsresult Drain() = 0; - virtual uint32_t GetPluginId() const = 0; - - // Call to tell GMP/plugin the consumer will no longer use this - // interface/codec. - virtual void Close() = 0; - - virtual const nsCString& GetDisplayName() const = 0; -}; - -#endif diff --git a/dom/media/gmp/GMPVideoEncodedFrameImpl.cpp b/dom/media/gmp/GMPVideoEncodedFrameImpl.cpp deleted file mode 100644 index 7725c5521..000000000 --- a/dom/media/gmp/GMPVideoEncodedFrameImpl.cpp +++ /dev/null @@ -1,324 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#include "GMPVideoEncodedFrameImpl.h" -#include "GMPVideoHost.h" -#include "mozilla/gmp/GMPTypes.h" -#include "GMPSharedMemManager.h" -#include "GMPEncryptedBufferDataImpl.h" - -namespace mozilla { -namespace gmp { - -GMPVideoEncodedFrameImpl::GMPVideoEncodedFrameImpl(GMPVideoHostImpl* aHost) -: mEncodedWidth(0), - mEncodedHeight(0), - mTimeStamp(0ll), - mDuration(0ll), - mFrameType(kGMPDeltaFrame), - mSize(0), - mCompleteFrame(false), - mHost(aHost), - mBufferType(GMP_BufferSingle) -{ - MOZ_ASSERT(aHost); - aHost->EncodedFrameCreated(this); -} - -GMPVideoEncodedFrameImpl::GMPVideoEncodedFrameImpl(const GMPVideoEncodedFrameData& aFrameData, - GMPVideoHostImpl* aHost) -: mEncodedWidth(aFrameData.mEncodedWidth()), - mEncodedHeight(aFrameData.mEncodedHeight()), - mTimeStamp(aFrameData.mTimestamp()), - mDuration(aFrameData.mDuration()), - mFrameType(static_cast<GMPVideoFrameType>(aFrameData.mFrameType())), - mSize(aFrameData.mSize()), - mCompleteFrame(aFrameData.mCompleteFrame()), - mHost(aHost), - mBuffer(aFrameData.mBuffer()), - mBufferType(aFrameData.mBufferType()) -{ - MOZ_ASSERT(aHost); - if (aFrameData.mDecryptionData().mKeyId().Length() > 0) { - mCrypto = new GMPEncryptedBufferDataImpl(aFrameData.mDecryptionData()); - } - aHost->EncodedFrameCreated(this); -} - -GMPVideoEncodedFrameImpl::~GMPVideoEncodedFrameImpl() -{ - DestroyBuffer(); - if (mHost) { - mHost->EncodedFrameDestroyed(this); - } -} - -void -GMPVideoEncodedFrameImpl::InitCrypto(const CryptoSample& aCrypto) -{ - mCrypto = new GMPEncryptedBufferDataImpl(aCrypto); -} - -const GMPEncryptedBufferMetadata* -GMPVideoEncodedFrameImpl::GetDecryptionData() const -{ - return mCrypto; -} - -GMPVideoFrameFormat -GMPVideoEncodedFrameImpl::GetFrameFormat() -{ - return kGMPEncodedVideoFrame; -} - -void -GMPVideoEncodedFrameImpl::DoneWithAPI() -{ - DestroyBuffer(); - - // Do this after destroying the buffer because destruction - // involves deallocation, which requires a host. - mHost = nullptr; -} - -void -GMPVideoEncodedFrameImpl::ActorDestroyed() -{ - // Simply clear out Shmem reference, do not attempt to - // properly free it. It has already been freed. - mBuffer = ipc::Shmem(); - // No more host. - mHost = nullptr; -} - -bool -GMPVideoEncodedFrameImpl::RelinquishFrameData(GMPVideoEncodedFrameData& aFrameData) -{ - aFrameData.mEncodedWidth() = mEncodedWidth; - aFrameData.mEncodedHeight() = mEncodedHeight; - aFrameData.mTimestamp() = mTimeStamp; - aFrameData.mDuration() = mDuration; - aFrameData.mFrameType() = mFrameType; - aFrameData.mSize() = mSize; - aFrameData.mCompleteFrame() = mCompleteFrame; - aFrameData.mBuffer() = mBuffer; - aFrameData.mBufferType() = mBufferType; - if (mCrypto) { - mCrypto->RelinquishData(aFrameData.mDecryptionData()); - } - - // This method is called right before Shmem is sent to another process. - // We need to effectively zero out our member copy so that we don't - // try to delete Shmem we don't own later. - mBuffer = ipc::Shmem(); - - return true; -} - -void -GMPVideoEncodedFrameImpl::DestroyBuffer() -{ - if (mHost && mBuffer.IsWritable()) { - mHost->SharedMemMgr()->MgrDeallocShmem(GMPSharedMem::kGMPEncodedData, mBuffer); - } - mBuffer = ipc::Shmem(); -} - -GMPErr -GMPVideoEncodedFrameImpl::CreateEmptyFrame(uint32_t aSize) -{ - if (aSize == 0) { - DestroyBuffer(); - } else if (aSize > AllocatedSize()) { - DestroyBuffer(); - if (!mHost->SharedMemMgr()->MgrAllocShmem(GMPSharedMem::kGMPEncodedData, aSize, - ipc::SharedMemory::TYPE_BASIC, &mBuffer) || - !Buffer()) { - return GMPAllocErr; - } - } - mSize = aSize; - - return GMPNoErr; -} - -GMPErr -GMPVideoEncodedFrameImpl::CopyFrame(const GMPVideoEncodedFrame& aFrame) -{ - auto& f = static_cast<const GMPVideoEncodedFrameImpl&>(aFrame); - - if (f.mSize != 0) { - GMPErr err = CreateEmptyFrame(f.mSize); - if (err != GMPNoErr) { - return err; - } - memcpy(Buffer(), f.Buffer(), f.mSize); - } - mEncodedWidth = f.mEncodedWidth; - mEncodedHeight = f.mEncodedHeight; - mTimeStamp = f.mTimeStamp; - mDuration = f.mDuration; - mFrameType = f.mFrameType; - mSize = f.mSize; // already set... - mCompleteFrame = f.mCompleteFrame; - mBufferType = f.mBufferType; - mCrypto = new GMPEncryptedBufferDataImpl(*(f.mCrypto)); - // Don't copy host, that should have been set properly on object creation via host. - - return GMPNoErr; -} - -void -GMPVideoEncodedFrameImpl::SetEncodedWidth(uint32_t aEncodedWidth) -{ - mEncodedWidth = aEncodedWidth; -} - -uint32_t -GMPVideoEncodedFrameImpl::EncodedWidth() -{ - return mEncodedWidth; -} - -void -GMPVideoEncodedFrameImpl::SetEncodedHeight(uint32_t aEncodedHeight) -{ - mEncodedHeight = aEncodedHeight; -} - -uint32_t -GMPVideoEncodedFrameImpl::EncodedHeight() -{ - return mEncodedHeight; -} - -void -GMPVideoEncodedFrameImpl::SetTimeStamp(uint64_t aTimeStamp) -{ - mTimeStamp = aTimeStamp; -} - -uint64_t -GMPVideoEncodedFrameImpl::TimeStamp() -{ - return mTimeStamp; -} - -void -GMPVideoEncodedFrameImpl::SetDuration(uint64_t aDuration) -{ - mDuration = aDuration; -} - -uint64_t -GMPVideoEncodedFrameImpl::Duration() const -{ - return mDuration; -} - -void -GMPVideoEncodedFrameImpl::SetFrameType(GMPVideoFrameType aFrameType) -{ - mFrameType = aFrameType; -} - -GMPVideoFrameType -GMPVideoEncodedFrameImpl::FrameType() -{ - return mFrameType; -} - -void -GMPVideoEncodedFrameImpl::SetAllocatedSize(uint32_t aNewSize) -{ - if (aNewSize <= AllocatedSize()) { - return; - } - - if (!mHost) { - return; - } - - ipc::Shmem new_mem; - if (!mHost->SharedMemMgr()->MgrAllocShmem(GMPSharedMem::kGMPEncodedData, aNewSize, - ipc::SharedMemory::TYPE_BASIC, &new_mem) || - !new_mem.get<uint8_t>()) { - return; - } - - if (mBuffer.IsReadable()) { - memcpy(new_mem.get<uint8_t>(), Buffer(), mSize); - } - - DestroyBuffer(); - - mBuffer = new_mem; -} - -uint32_t -GMPVideoEncodedFrameImpl::AllocatedSize() -{ - if (mBuffer.IsWritable()) { - return mBuffer.Size<uint8_t>(); - } - return 0; -} - -void -GMPVideoEncodedFrameImpl::SetSize(uint32_t aSize) -{ - mSize = aSize; -} - -uint32_t -GMPVideoEncodedFrameImpl::Size() -{ - return mSize; -} - -void -GMPVideoEncodedFrameImpl::SetCompleteFrame(bool aCompleteFrame) -{ - mCompleteFrame = aCompleteFrame; -} - -bool -GMPVideoEncodedFrameImpl::CompleteFrame() -{ - return mCompleteFrame; -} - -const uint8_t* -GMPVideoEncodedFrameImpl::Buffer() const -{ - return mBuffer.get<uint8_t>(); -} - -uint8_t* -GMPVideoEncodedFrameImpl::Buffer() -{ - return mBuffer.get<uint8_t>(); -} - -void -GMPVideoEncodedFrameImpl::Destroy() -{ - delete this; -} - -GMPBufferType -GMPVideoEncodedFrameImpl::BufferType() const -{ - return mBufferType; -} - -void -GMPVideoEncodedFrameImpl::SetBufferType(GMPBufferType aBufferType) -{ - mBufferType = aBufferType; -} - -} // namespace gmp -} // namespace mozilla diff --git a/dom/media/gmp/GMPVideoEncodedFrameImpl.h b/dom/media/gmp/GMPVideoEncodedFrameImpl.h deleted file mode 100644 index 69858f1c6..000000000 --- a/dom/media/gmp/GMPVideoEncodedFrameImpl.h +++ /dev/null @@ -1,122 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* Copyright (c) 2014, Mozilla Corporation - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef GMPVideoEncodedFrameImpl_h_ -#define GMPVideoEncodedFrameImpl_h_ - -#include "gmp-errors.h" -#include "gmp-video-frame.h" -#include "gmp-video-frame-encoded.h" -#include "gmp-decryption.h" -#include "mozilla/ipc/Shmem.h" -#include "nsAutoPtr.h" - -namespace mozilla { -class CryptoSample; - -namespace gmp { - -class GMPVideoHostImpl; -class GMPVideoEncodedFrameData; -class GMPEncryptedBufferDataImpl; - -class GMPVideoEncodedFrameImpl: public GMPVideoEncodedFrame -{ - friend struct IPC::ParamTraits<mozilla::gmp::GMPVideoEncodedFrameImpl>; -public: - explicit GMPVideoEncodedFrameImpl(GMPVideoHostImpl* aHost); - GMPVideoEncodedFrameImpl(const GMPVideoEncodedFrameData& aFrameData, GMPVideoHostImpl* aHost); - virtual ~GMPVideoEncodedFrameImpl(); - - void InitCrypto(const CryptoSample& aCrypto); - - // This is called during a normal destroy sequence, which is - // when a consumer is finished or during XPCOM shutdown. - void DoneWithAPI(); - // Does not attempt to release Shmem, as the Shmem has already been released. - void ActorDestroyed(); - - bool RelinquishFrameData(GMPVideoEncodedFrameData& aFrameData); - - // GMPVideoFrame - GMPVideoFrameFormat GetFrameFormat() override; - void Destroy() override; - - // GMPVideoEncodedFrame - GMPErr CreateEmptyFrame(uint32_t aSize) override; - GMPErr CopyFrame(const GMPVideoEncodedFrame& aFrame) override; - void SetEncodedWidth(uint32_t aEncodedWidth) override; - uint32_t EncodedWidth() override; - void SetEncodedHeight(uint32_t aEncodedHeight) override; - uint32_t EncodedHeight() override; - // Microseconds - void SetTimeStamp(uint64_t aTimeStamp) override; - uint64_t TimeStamp() override; - // Set frame duration (microseconds) - // NOTE: next-frame's Timestamp() != this-frame's TimeStamp()+Duration() - // depending on rounding to avoid having to track roundoff errors - // and dropped/missing frames(!) (which may leave a large gap) - void SetDuration(uint64_t aDuration) override; - uint64_t Duration() const override; - void SetFrameType(GMPVideoFrameType aFrameType) override; - GMPVideoFrameType FrameType() override; - void SetAllocatedSize(uint32_t aNewSize) override; - uint32_t AllocatedSize() override; - void SetSize(uint32_t aSize) override; - uint32_t Size() override; - void SetCompleteFrame(bool aCompleteFrame) override; - bool CompleteFrame() override; - const uint8_t* Buffer() const override; - uint8_t* Buffer() override; - GMPBufferType BufferType() const override; - void SetBufferType(GMPBufferType aBufferType) override; - const GMPEncryptedBufferMetadata* GetDecryptionData() const override; - -private: - void DestroyBuffer(); - - uint32_t mEncodedWidth; - uint32_t mEncodedHeight; - uint64_t mTimeStamp; - uint64_t mDuration; - GMPVideoFrameType mFrameType; - uint32_t mSize; - bool mCompleteFrame; - GMPVideoHostImpl* mHost; - ipc::Shmem mBuffer; - GMPBufferType mBufferType; - nsAutoPtr<GMPEncryptedBufferDataImpl> mCrypto; -}; - -} // namespace gmp - -} // namespace mozilla - -#endif // GMPVideoEncodedFrameImpl_h_ diff --git a/dom/media/gmp/GMPVideoEncoderChild.cpp b/dom/media/gmp/GMPVideoEncoderChild.cpp deleted file mode 100644 index f5c3dda95..000000000 --- a/dom/media/gmp/GMPVideoEncoderChild.cpp +++ /dev/null @@ -1,235 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#include "GMPVideoEncoderChild.h" -#include "GMPContentChild.h" -#include <stdio.h> -#include "mozilla/Unused.h" -#include "GMPVideoEncodedFrameImpl.h" -#include "GMPVideoi420FrameImpl.h" -#include "runnable_utils.h" - -namespace mozilla { -namespace gmp { - -GMPVideoEncoderChild::GMPVideoEncoderChild(GMPContentChild* aPlugin) - : GMPSharedMemManager(aPlugin) - , mPlugin(aPlugin) - , mVideoEncoder(nullptr) - , mVideoHost(this) - , mNeedShmemIntrCount(0) - , mPendingEncodeComplete(false) -{ - MOZ_ASSERT(mPlugin); -} - -GMPVideoEncoderChild::~GMPVideoEncoderChild() -{ - MOZ_ASSERT(!mNeedShmemIntrCount); -} - -void -GMPVideoEncoderChild::Init(GMPVideoEncoder* aEncoder) -{ - MOZ_ASSERT(aEncoder, "Cannot initialize video encoder child without a video encoder!"); - mVideoEncoder = aEncoder; -} - -GMPVideoHostImpl& -GMPVideoEncoderChild::Host() -{ - return mVideoHost; -} - -void -GMPVideoEncoderChild::Encoded(GMPVideoEncodedFrame* aEncodedFrame, - const uint8_t* aCodecSpecificInfo, - uint32_t aCodecSpecificInfoLength) -{ - MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current()); - - auto ef = static_cast<GMPVideoEncodedFrameImpl*>(aEncodedFrame); - - GMPVideoEncodedFrameData frameData; - ef->RelinquishFrameData(frameData); - - nsTArray<uint8_t> codecSpecific; - codecSpecific.AppendElements(aCodecSpecificInfo, aCodecSpecificInfoLength); - SendEncoded(frameData, codecSpecific); - - aEncodedFrame->Destroy(); -} - -void -GMPVideoEncoderChild::Error(GMPErr aError) -{ - MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current()); - - SendError(aError); -} - -bool -GMPVideoEncoderChild::RecvInitEncode(const GMPVideoCodec& aCodecSettings, - InfallibleTArray<uint8_t>&& aCodecSpecific, - const int32_t& aNumberOfCores, - const uint32_t& aMaxPayloadSize) -{ - if (!mVideoEncoder) { - return false; - } - - // Ignore any return code. It is OK for this to fail without killing the process. - mVideoEncoder->InitEncode(aCodecSettings, - aCodecSpecific.Elements(), - aCodecSpecific.Length(), - this, - aNumberOfCores, - aMaxPayloadSize); - - return true; -} - -bool -GMPVideoEncoderChild::RecvEncode(const GMPVideoi420FrameData& aInputFrame, - InfallibleTArray<uint8_t>&& aCodecSpecificInfo, - InfallibleTArray<GMPVideoFrameType>&& aFrameTypes) -{ - if (!mVideoEncoder) { - return false; - } - - auto f = new GMPVideoi420FrameImpl(aInputFrame, &mVideoHost); - - // Ignore any return code. It is OK for this to fail without killing the process. - mVideoEncoder->Encode(f, - aCodecSpecificInfo.Elements(), - aCodecSpecificInfo.Length(), - aFrameTypes.Elements(), - aFrameTypes.Length()); - - return true; -} - -bool -GMPVideoEncoderChild::RecvChildShmemForPool(Shmem&& aEncodedBuffer) -{ - if (aEncodedBuffer.IsWritable()) { - mVideoHost.SharedMemMgr()->MgrDeallocShmem(GMPSharedMem::kGMPEncodedData, - aEncodedBuffer); - } - return true; -} - -bool -GMPVideoEncoderChild::RecvSetChannelParameters(const uint32_t& aPacketLoss, - const uint32_t& aRTT) -{ - if (!mVideoEncoder) { - return false; - } - - // Ignore any return code. It is OK for this to fail without killing the process. - mVideoEncoder->SetChannelParameters(aPacketLoss, aRTT); - - return true; -} - -bool -GMPVideoEncoderChild::RecvSetRates(const uint32_t& aNewBitRate, - const uint32_t& aFrameRate) -{ - if (!mVideoEncoder) { - return false; - } - - // Ignore any return code. It is OK for this to fail without killing the process. - mVideoEncoder->SetRates(aNewBitRate, aFrameRate); - - return true; -} - -bool -GMPVideoEncoderChild::RecvSetPeriodicKeyFrames(const bool& aEnable) -{ - if (!mVideoEncoder) { - return false; - } - - // Ignore any return code. It is OK for this to fail without killing the process. - mVideoEncoder->SetPeriodicKeyFrames(aEnable); - - return true; -} - -bool -GMPVideoEncoderChild::RecvEncodingComplete() -{ - MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current()); - - if (mNeedShmemIntrCount) { - // There's a GMP blocked in Alloc() waiting for the CallNeedShem() to - // return a frame they can use. Don't call the GMP's EncodingComplete() - // now and don't delete the GMPVideoEncoderChild, defer processing the - // EncodingComplete() until once the Alloc() finishes. - mPendingEncodeComplete = true; - return true; - } - - if (!mVideoEncoder) { - Unused << Send__delete__(this); - return false; - } - - // Ignore any return code. It is OK for this to fail without killing the process. - mVideoEncoder->EncodingComplete(); - - mVideoHost.DoneWithAPI(); - - mPlugin = nullptr; - - Unused << Send__delete__(this); - - return true; -} - -bool -GMPVideoEncoderChild::Alloc(size_t aSize, - Shmem::SharedMemory::SharedMemoryType aType, - Shmem* aMem) -{ - MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current()); - - bool rv; -#ifndef SHMEM_ALLOC_IN_CHILD - ++mNeedShmemIntrCount; - rv = CallNeedShmem(aSize, aMem); - --mNeedShmemIntrCount; - if (mPendingEncodeComplete && mNeedShmemIntrCount == 0) { - mPendingEncodeComplete = false; - mPlugin->GMPMessageLoop()->PostTask( - NewRunnableMethod(this, &GMPVideoEncoderChild::RecvEncodingComplete)); - } -#else -#ifdef GMP_SAFE_SHMEM - rv = AllocShmem(aSize, aType, aMem); -#else - rv = AllocUnsafeShmem(aSize, aType, aMem); -#endif -#endif - return rv; -} - -void -GMPVideoEncoderChild::Dealloc(Shmem& aMem) -{ -#ifndef SHMEM_ALLOC_IN_CHILD - SendParentShmemForPool(aMem); -#else - DeallocShmem(aMem); -#endif -} - -} // namespace gmp -} // namespace mozilla diff --git a/dom/media/gmp/GMPVideoEncoderChild.h b/dom/media/gmp/GMPVideoEncoderChild.h deleted file mode 100644 index 44e2fe605..000000000 --- a/dom/media/gmp/GMPVideoEncoderChild.h +++ /dev/null @@ -1,75 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#ifndef GMPVideoEncoderChild_h_ -#define GMPVideoEncoderChild_h_ - -#include "nsString.h" -#include "mozilla/gmp/PGMPVideoEncoderChild.h" -#include "gmp-video-encode.h" -#include "GMPSharedMemManager.h" -#include "GMPVideoHost.h" - -namespace mozilla { -namespace gmp { - -class GMPContentChild; - -class GMPVideoEncoderChild : public PGMPVideoEncoderChild, - public GMPVideoEncoderCallback, - public GMPSharedMemManager -{ -public: - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GMPVideoEncoderChild); - - explicit GMPVideoEncoderChild(GMPContentChild* aPlugin); - - void Init(GMPVideoEncoder* aEncoder); - GMPVideoHostImpl& Host(); - - // GMPVideoEncoderCallback - void Encoded(GMPVideoEncodedFrame* aEncodedFrame, - const uint8_t* aCodecSpecificInfo, - uint32_t aCodecSpecificInfoLength) override; - void Error(GMPErr aError) override; - - // GMPSharedMemManager - bool Alloc(size_t aSize, Shmem::SharedMemory::SharedMemoryType aType, - Shmem* aMem) override; - void Dealloc(Shmem& aMem) override; - -private: - virtual ~GMPVideoEncoderChild(); - - // PGMPVideoEncoderChild - bool RecvInitEncode(const GMPVideoCodec& aCodecSettings, - InfallibleTArray<uint8_t>&& aCodecSpecific, - const int32_t& aNumberOfCores, - const uint32_t& aMaxPayloadSize) override; - bool RecvEncode(const GMPVideoi420FrameData& aInputFrame, - InfallibleTArray<uint8_t>&& aCodecSpecificInfo, - InfallibleTArray<GMPVideoFrameType>&& aFrameTypes) override; - bool RecvChildShmemForPool(Shmem&& aEncodedBuffer) override; - bool RecvSetChannelParameters(const uint32_t& aPacketLoss, - const uint32_t& aRTT) override; - bool RecvSetRates(const uint32_t& aNewBitRate, - const uint32_t& aFrameRate) override; - bool RecvSetPeriodicKeyFrames(const bool& aEnable) override; - bool RecvEncodingComplete() override; - - GMPContentChild* mPlugin; - GMPVideoEncoder* mVideoEncoder; - GMPVideoHostImpl mVideoHost; - - // Non-zero when a GMP is blocked spinning the IPC message loop while - // waiting on an NeedShmem to complete. - int mNeedShmemIntrCount; - bool mPendingEncodeComplete; -}; - -} // namespace gmp -} // namespace mozilla - -#endif // GMPVideoEncoderChild_h_ diff --git a/dom/media/gmp/GMPVideoEncoderParent.cpp b/dom/media/gmp/GMPVideoEncoderParent.cpp deleted file mode 100644 index 95583cd6e..000000000 --- a/dom/media/gmp/GMPVideoEncoderParent.cpp +++ /dev/null @@ -1,382 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#include "GMPVideoEncoderParent.h" -#include "mozilla/Logging.h" -#include "GMPVideoi420FrameImpl.h" -#include "GMPVideoEncodedFrameImpl.h" -#include "mozilla/Unused.h" -#include "GMPMessageUtils.h" -#include "nsAutoRef.h" -#include "GMPContentParent.h" -#include "mozilla/gmp/GMPTypes.h" -#include "nsThread.h" -#include "nsThreadUtils.h" -#include "runnable_utils.h" -#include "GMPUtils.h" - -namespace mozilla { - -#ifdef LOG -#undef LOG -#endif - -extern LogModule* GetGMPLog(); - -#define LOGD(msg) MOZ_LOG(GetGMPLog(), mozilla::LogLevel::Debug, msg) -#define LOG(level, msg) MOZ_LOG(GetGMPLog(), (level), msg) - -#ifdef __CLASS__ -#undef __CLASS__ -#endif -#define __CLASS__ "GMPVideoEncoderParent" - -namespace gmp { - -// States: -// Initial: mIsOpen == false -// on InitDecode success -> Open -// on Shutdown -> Dead -// Open: mIsOpen == true -// on Close -> Dead -// on ActorDestroy -> Dead -// on Shutdown -> Dead -// Dead: mIsOpen == false - -GMPVideoEncoderParent::GMPVideoEncoderParent(GMPContentParent *aPlugin) -: GMPSharedMemManager(aPlugin), - mIsOpen(false), - mShuttingDown(false), - mActorDestroyed(false), - mPlugin(aPlugin), - mCallback(nullptr), - mVideoHost(this), - mPluginId(aPlugin->GetPluginId()) -{ - MOZ_ASSERT(mPlugin); - - nsresult rv = NS_NewNamedThread("GMPEncoded", getter_AddRefs(mEncodedThread)); - if (NS_FAILED(rv)) { - MOZ_CRASH(); - } -} - -GMPVideoEncoderParent::~GMPVideoEncoderParent() -{ - if (mEncodedThread) { - mEncodedThread->Shutdown(); - } -} - -GMPVideoHostImpl& -GMPVideoEncoderParent::Host() -{ - return mVideoHost; -} - -// Note: may be called via Terminated() -void -GMPVideoEncoderParent::Close() -{ - LOGD(("%s::%s: %p", __CLASS__, __FUNCTION__, this)); - MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread()); - // Consumer is done with us; we can shut down. No more callbacks should - // be made to mCallback. Note: do this before Shutdown()! - mCallback = nullptr; - // Let Shutdown mark us as dead so it knows if we had been alive - - // In case this is the last reference - RefPtr<GMPVideoEncoderParent> kungfudeathgrip(this); - Release(); - Shutdown(); -} - -GMPErr -GMPVideoEncoderParent::InitEncode(const GMPVideoCodec& aCodecSettings, - const nsTArray<uint8_t>& aCodecSpecific, - GMPVideoEncoderCallbackProxy* aCallback, - int32_t aNumberOfCores, - uint32_t aMaxPayloadSize) -{ - LOGD(("%s::%s: %p", __CLASS__, __FUNCTION__, this)); - if (mIsOpen) { - NS_WARNING("Trying to re-init an in-use GMP video encoder!"); - return GMPGenericErr;; - } - - MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread()); - - if (!aCallback) { - return GMPGenericErr; - } - mCallback = aCallback; - - if (!SendInitEncode(aCodecSettings, aCodecSpecific, aNumberOfCores, aMaxPayloadSize)) { - return GMPGenericErr; - } - mIsOpen = true; - - // Async IPC, we don't have access to a return value. - return GMPNoErr; -} - -GMPErr -GMPVideoEncoderParent::Encode(GMPUniquePtr<GMPVideoi420Frame> aInputFrame, - const nsTArray<uint8_t>& aCodecSpecificInfo, - const nsTArray<GMPVideoFrameType>& aFrameTypes) -{ - if (!mIsOpen) { - NS_WARNING("Trying to use an dead GMP video encoder"); - return GMPGenericErr; - } - - MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread()); - - GMPUniquePtr<GMPVideoi420FrameImpl> inputFrameImpl( - static_cast<GMPVideoi420FrameImpl*>(aInputFrame.release())); - - // Very rough kill-switch if the plugin stops processing. If it's merely - // hung and continues, we'll come back to life eventually. - // 3* is because we're using 3 buffers per frame for i420 data for now. - if ((NumInUse(GMPSharedMem::kGMPFrameData) > 3*GMPSharedMem::kGMPBufLimit) || - (NumInUse(GMPSharedMem::kGMPEncodedData) > GMPSharedMem::kGMPBufLimit)) { - return GMPGenericErr; - } - - GMPVideoi420FrameData frameData; - inputFrameImpl->InitFrameData(frameData); - - if (!SendEncode(frameData, - aCodecSpecificInfo, - aFrameTypes)) { - return GMPGenericErr; - } - - // Async IPC, we don't have access to a return value. - return GMPNoErr; -} - -GMPErr -GMPVideoEncoderParent::SetChannelParameters(uint32_t aPacketLoss, uint32_t aRTT) -{ - if (!mIsOpen) { - NS_WARNING("Trying to use an invalid GMP video encoder!"); - return GMPGenericErr; - } - - MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread()); - - if (!SendSetChannelParameters(aPacketLoss, aRTT)) { - return GMPGenericErr; - } - - // Async IPC, we don't have access to a return value. - return GMPNoErr; -} - -GMPErr -GMPVideoEncoderParent::SetRates(uint32_t aNewBitRate, uint32_t aFrameRate) -{ - if (!mIsOpen) { - NS_WARNING("Trying to use an dead GMP video decoder"); - return GMPGenericErr; - } - - MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread()); - - if (!SendSetRates(aNewBitRate, aFrameRate)) { - return GMPGenericErr; - } - - // Async IPC, we don't have access to a return value. - return GMPNoErr; -} - -GMPErr -GMPVideoEncoderParent::SetPeriodicKeyFrames(bool aEnable) -{ - if (!mIsOpen) { - NS_WARNING("Trying to use an invalid GMP video encoder!"); - return GMPGenericErr; - } - - MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread()); - - if (!SendSetPeriodicKeyFrames(aEnable)) { - return GMPGenericErr; - } - - // Async IPC, we don't have access to a return value. - return GMPNoErr; -} - -// Note: Consider keeping ActorDestroy sync'd up when making changes here. -void -GMPVideoEncoderParent::Shutdown() -{ - LOGD(("%s::%s: %p", __CLASS__, __FUNCTION__, this)); - MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread()); - - if (mShuttingDown) { - return; - } - mShuttingDown = true; - - // Notify client we're gone! Won't occur after Close() - if (mCallback) { - mCallback->Terminated(); - mCallback = nullptr; - } - - mIsOpen = false; - if (!mActorDestroyed) { - Unused << SendEncodingComplete(); - } -} - -static void -ShutdownEncodedThread(nsCOMPtr<nsIThread>& aThread) -{ - aThread->Shutdown(); -} - -// Note: Keep this sync'd up with Shutdown -void -GMPVideoEncoderParent::ActorDestroy(ActorDestroyReason aWhy) -{ - LOGD(("%s::%s: %p (%d)", __CLASS__, __FUNCTION__, this, (int) aWhy)); - mIsOpen = false; - mActorDestroyed = true; - if (mCallback) { - // May call Close() (and Shutdown()) immediately or with a delay - mCallback->Terminated(); - mCallback = nullptr; - } - // Must be shut down before VideoEncoderDestroyed(), since this can recurse - // the GMPThread event loop. See bug 1049501 - if (mEncodedThread) { - // Can't get it to allow me to use WrapRunnable with a nsCOMPtr<nsIThread>() - NS_DispatchToMainThread( - WrapRunnableNM<decltype(&ShutdownEncodedThread), - nsCOMPtr<nsIThread> >(&ShutdownEncodedThread, mEncodedThread)); - mEncodedThread = nullptr; - } - if (mPlugin) { - // Ignore any return code. It is OK for this to fail without killing the process. - mPlugin->VideoEncoderDestroyed(this); - mPlugin = nullptr; - } - mVideoHost.ActorDestroyed(); // same as DoneWithAPI - MaybeDisconnect(aWhy == AbnormalShutdown); -} - -static void -EncodedCallback(GMPVideoEncoderCallbackProxy* aCallback, - GMPVideoEncodedFrame* aEncodedFrame, - nsTArray<uint8_t>* aCodecSpecificInfo, - nsCOMPtr<nsIThread> aThread) -{ - aCallback->Encoded(aEncodedFrame, *aCodecSpecificInfo); - delete aCodecSpecificInfo; - // Ugh. Must destroy the frame on GMPThread. - // XXX add locks to the ShmemManager instead? - aThread->Dispatch(WrapRunnable(aEncodedFrame, - &GMPVideoEncodedFrame::Destroy), - NS_DISPATCH_NORMAL); -} - -bool -GMPVideoEncoderParent::RecvEncoded(const GMPVideoEncodedFrameData& aEncodedFrame, - InfallibleTArray<uint8_t>&& aCodecSpecificInfo) -{ - if (!mCallback) { - return false; - } - - auto f = new GMPVideoEncodedFrameImpl(aEncodedFrame, &mVideoHost); - nsTArray<uint8_t> *codecSpecificInfo = new nsTArray<uint8_t>; - codecSpecificInfo->AppendElements((uint8_t*)aCodecSpecificInfo.Elements(), aCodecSpecificInfo.Length()); - nsCOMPtr<nsIThread> thread = NS_GetCurrentThread(); - - mEncodedThread->Dispatch(WrapRunnableNM(&EncodedCallback, - mCallback, f, codecSpecificInfo, thread), - NS_DISPATCH_NORMAL); - - return true; -} - -bool -GMPVideoEncoderParent::RecvError(const GMPErr& aError) -{ - if (!mCallback) { - return false; - } - - // Ignore any return code. It is OK for this to fail without killing the process. - mCallback->Error(aError); - - return true; -} - -bool -GMPVideoEncoderParent::RecvShutdown() -{ - Shutdown(); - return true; -} - -bool -GMPVideoEncoderParent::RecvParentShmemForPool(Shmem&& aFrameBuffer) -{ - if (aFrameBuffer.IsWritable()) { - // This test may be paranoia now that we don't shut down the VideoHost - // in ::Shutdown, but doesn't hurt - if (mVideoHost.SharedMemMgr()) { - mVideoHost.SharedMemMgr()->MgrDeallocShmem(GMPSharedMem::kGMPFrameData, - aFrameBuffer); - } else { - LOGD(("%s::%s: %p Called in shutdown, ignoring and freeing directly", __CLASS__, __FUNCTION__, this)); - DeallocShmem(aFrameBuffer); - } - } - return true; -} - -bool -GMPVideoEncoderParent::AnswerNeedShmem(const uint32_t& aEncodedBufferSize, - Shmem* aMem) -{ - ipc::Shmem mem; - - // This test may be paranoia now that we don't shut down the VideoHost - // in ::Shutdown, but doesn't hurt - if (!mVideoHost.SharedMemMgr() || - !mVideoHost.SharedMemMgr()->MgrAllocShmem(GMPSharedMem::kGMPEncodedData, - aEncodedBufferSize, - ipc::SharedMemory::TYPE_BASIC, &mem)) - { - LOG(LogLevel::Error, ("%s::%s: Failed to get a shared mem buffer for Child! size %u", - __CLASS__, __FUNCTION__, aEncodedBufferSize)); - return false; - } - *aMem = mem; - mem = ipc::Shmem(); - return true; -} - -bool -GMPVideoEncoderParent::Recv__delete__() -{ - if (mPlugin) { - // Ignore any return code. It is OK for this to fail without killing the process. - mPlugin->VideoEncoderDestroyed(this); - mPlugin = nullptr; - } - - return true; -} - -} // namespace gmp -} // namespace mozilla diff --git a/dom/media/gmp/GMPVideoEncoderParent.h b/dom/media/gmp/GMPVideoEncoderParent.h deleted file mode 100644 index e7dade692..000000000 --- a/dom/media/gmp/GMPVideoEncoderParent.h +++ /dev/null @@ -1,93 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#ifndef GMPVideoEncoderParent_h_ -#define GMPVideoEncoderParent_h_ - -#include "mozilla/RefPtr.h" -#include "gmp-video-encode.h" -#include "mozilla/gmp/PGMPVideoEncoderParent.h" -#include "GMPMessageUtils.h" -#include "GMPSharedMemManager.h" -#include "GMPUtils.h" -#include "GMPVideoHost.h" -#include "GMPVideoEncoderProxy.h" -#include "GMPCrashHelperHolder.h" - -namespace mozilla { -namespace gmp { - -class GMPContentParent; - -class GMPVideoEncoderParent : public GMPVideoEncoderProxy, - public PGMPVideoEncoderParent, - public GMPSharedMemManager, - public GMPCrashHelperHolder -{ -public: - NS_INLINE_DECL_REFCOUNTING(GMPVideoEncoderParent) - - explicit GMPVideoEncoderParent(GMPContentParent *aPlugin); - - GMPVideoHostImpl& Host(); - void Shutdown(); - - // GMPVideoEncoderProxy - void Close() override; - GMPErr InitEncode(const GMPVideoCodec& aCodecSettings, - const nsTArray<uint8_t>& aCodecSpecific, - GMPVideoEncoderCallbackProxy* aCallback, - int32_t aNumberOfCores, - uint32_t aMaxPayloadSize) override; - GMPErr Encode(GMPUniquePtr<GMPVideoi420Frame> aInputFrame, - const nsTArray<uint8_t>& aCodecSpecificInfo, - const nsTArray<GMPVideoFrameType>& aFrameTypes) override; - GMPErr SetChannelParameters(uint32_t aPacketLoss, uint32_t aRTT) override; - GMPErr SetRates(uint32_t aNewBitRate, uint32_t aFrameRate) override; - GMPErr SetPeriodicKeyFrames(bool aEnable) override; - uint32_t GetPluginId() const override { return mPluginId; } - - // GMPSharedMemManager - bool Alloc(size_t aSize, Shmem::SharedMemory::SharedMemoryType aType, Shmem* aMem) override - { -#ifdef GMP_SAFE_SHMEM - return AllocShmem(aSize, aType, aMem); -#else - return AllocUnsafeShmem(aSize, aType, aMem); -#endif - } - void Dealloc(Shmem& aMem) override - { - DeallocShmem(aMem); - } - -private: - virtual ~GMPVideoEncoderParent(); - - // PGMPVideoEncoderParent - void ActorDestroy(ActorDestroyReason aWhy) override; - bool RecvEncoded(const GMPVideoEncodedFrameData& aEncodedFrame, - InfallibleTArray<uint8_t>&& aCodecSpecificInfo) override; - bool RecvError(const GMPErr& aError) override; - bool RecvShutdown() override; - bool RecvParentShmemForPool(Shmem&& aFrameBuffer) override; - bool AnswerNeedShmem(const uint32_t& aEncodedBufferSize, - Shmem* aMem) override; - bool Recv__delete__() override; - - bool mIsOpen; - bool mShuttingDown; - bool mActorDestroyed; - RefPtr<GMPContentParent> mPlugin; - GMPVideoEncoderCallbackProxy* mCallback; - GMPVideoHostImpl mVideoHost; - nsCOMPtr<nsIThread> mEncodedThread; - const uint32_t mPluginId; -}; - -} // namespace gmp -} // namespace mozilla - -#endif // GMPVideoEncoderParent_h_ diff --git a/dom/media/gmp/GMPVideoEncoderProxy.h b/dom/media/gmp/GMPVideoEncoderProxy.h deleted file mode 100644 index 655b1e9ae..000000000 --- a/dom/media/gmp/GMPVideoEncoderProxy.h +++ /dev/null @@ -1,56 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#ifndef GMPVideoEncoderProxy_h_ -#define GMPVideoEncoderProxy_h_ - -#include "nsTArray.h" -#include "gmp-video-encode.h" -#include "gmp-video-frame-i420.h" -#include "gmp-video-frame-encoded.h" - -#include "GMPCallbackBase.h" -#include "GMPUtils.h" - -class GMPVideoEncoderCallbackProxy : public GMPCallbackBase { -public: - virtual ~GMPVideoEncoderCallbackProxy() {} - virtual void Encoded(GMPVideoEncodedFrame* aEncodedFrame, - const nsTArray<uint8_t>& aCodecSpecificInfo) = 0; - virtual void Error(GMPErr aError) = 0; -}; - -// A proxy to GMPVideoEncoder in the child process. -// GMPVideoEncoderParent exposes this to users the GMP. -// This enables Gecko to pass nsTArrays to the child GMP and avoid -// an extra copy when doing so. - -// The consumer must call Close() when done with the codec, or when -// Terminated() is called by the GMP plugin indicating an abnormal shutdown -// of the underlying plugin. After calling Close(), the consumer must -// not access this again. - -// This interface is not thread-safe and must only be used from GMPThread. -class GMPVideoEncoderProxy { -public: - virtual GMPErr InitEncode(const GMPVideoCodec& aCodecSettings, - const nsTArray<uint8_t>& aCodecSpecific, - GMPVideoEncoderCallbackProxy* aCallback, - int32_t aNumberOfCores, - uint32_t aMaxPayloadSize) = 0; - virtual GMPErr Encode(mozilla::GMPUniquePtr<GMPVideoi420Frame> aInputFrame, - const nsTArray<uint8_t>& aCodecSpecificInfo, - const nsTArray<GMPVideoFrameType>& aFrameTypes) = 0; - virtual GMPErr SetChannelParameters(uint32_t aPacketLoss, uint32_t aRTT) = 0; - virtual GMPErr SetRates(uint32_t aNewBitRate, uint32_t aFrameRate) = 0; - virtual GMPErr SetPeriodicKeyFrames(bool aEnable) = 0; - virtual uint32_t GetPluginId() const = 0; - - // Call to tell GMP/plugin the consumer will no longer use this - // interface/codec. - virtual void Close() = 0; -}; - -#endif // GMPVideoEncoderProxy_h_ diff --git a/dom/media/gmp/GMPVideoHost.cpp b/dom/media/gmp/GMPVideoHost.cpp deleted file mode 100644 index db40ebdae..000000000 --- a/dom/media/gmp/GMPVideoHost.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#include "GMPVideoHost.h" -#include "mozilla/Assertions.h" -#include "GMPVideoi420FrameImpl.h" -#include "GMPVideoEncodedFrameImpl.h" - -namespace mozilla { -namespace gmp { - -GMPVideoHostImpl::GMPVideoHostImpl(GMPSharedMemManager* aSharedMemMgr) -: mSharedMemMgr(aSharedMemMgr) -{ -} - -GMPVideoHostImpl::~GMPVideoHostImpl() -{ -} - -GMPErr -GMPVideoHostImpl::CreateFrame(GMPVideoFrameFormat aFormat, GMPVideoFrame** aFrame) -{ - if (!mSharedMemMgr) { - return GMPGenericErr; - } - - if (!aFrame) { - return GMPGenericErr; - } - *aFrame = nullptr; - - switch (aFormat) { - case kGMPI420VideoFrame: - *aFrame = new GMPVideoi420FrameImpl(this); - return GMPNoErr; - case kGMPEncodedVideoFrame: - *aFrame = new GMPVideoEncodedFrameImpl(this); - return GMPNoErr; - default: - NS_NOTREACHED("Unknown frame format!"); - } - - return GMPGenericErr; -} - -GMPErr -GMPVideoHostImpl::CreatePlane(GMPPlane** aPlane) -{ - if (!mSharedMemMgr) { - return GMPGenericErr; - } - - if (!aPlane) { - return GMPGenericErr; - } - *aPlane = nullptr; - - auto p = new GMPPlaneImpl(this); - - *aPlane = p; - - return GMPNoErr; -} - -GMPSharedMemManager* -GMPVideoHostImpl::SharedMemMgr() -{ - return mSharedMemMgr; -} - -// XXX This should merge with ActorDestroyed -void -GMPVideoHostImpl::DoneWithAPI() -{ - ActorDestroyed(); -} - -void -GMPVideoHostImpl::ActorDestroyed() -{ - for (uint32_t i = mPlanes.Length(); i > 0; i--) { - mPlanes[i - 1]->DoneWithAPI(); - mPlanes.RemoveElementAt(i - 1); - } - for (uint32_t i = mEncodedFrames.Length(); i > 0; i--) { - mEncodedFrames[i - 1]->DoneWithAPI(); - mEncodedFrames.RemoveElementAt(i - 1); - } - mSharedMemMgr = nullptr; -} - -void -GMPVideoHostImpl::PlaneCreated(GMPPlaneImpl* aPlane) -{ - mPlanes.AppendElement(aPlane); -} - -void -GMPVideoHostImpl::PlaneDestroyed(GMPPlaneImpl* aPlane) -{ - MOZ_ALWAYS_TRUE(mPlanes.RemoveElement(aPlane)); -} - -void -GMPVideoHostImpl::EncodedFrameCreated(GMPVideoEncodedFrameImpl* aEncodedFrame) -{ - mEncodedFrames.AppendElement(aEncodedFrame); -} - -void -GMPVideoHostImpl::EncodedFrameDestroyed(GMPVideoEncodedFrameImpl* aFrame) -{ - MOZ_ALWAYS_TRUE(mEncodedFrames.RemoveElement(aFrame)); -} - -} // namespace gmp -} // namespace mozilla diff --git a/dom/media/gmp/GMPVideoHost.h b/dom/media/gmp/GMPVideoHost.h deleted file mode 100644 index b3e42f08e..000000000 --- a/dom/media/gmp/GMPVideoHost.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#ifndef GMPVideoHost_h_ -#define GMPVideoHost_h_ - -#include "gmp-video-host.h" -#include "gmp-video-plane.h" -#include "gmp-video-frame.h" -#include "gmp-video-host.h" -#include "nsTArray.h" - -namespace mozilla { -namespace gmp { - -class GMPSharedMemManager; -class GMPPlaneImpl; -class GMPVideoEncodedFrameImpl; - -class GMPVideoHostImpl : public GMPVideoHost -{ -public: - explicit GMPVideoHostImpl(GMPSharedMemManager* aSharedMemMgr); - virtual ~GMPVideoHostImpl(); - - // Used for shared memory allocation and deallocation. - GMPSharedMemManager* SharedMemMgr(); - void DoneWithAPI(); - void ActorDestroyed(); - void PlaneCreated(GMPPlaneImpl* aPlane); - void PlaneDestroyed(GMPPlaneImpl* aPlane); - void EncodedFrameCreated(GMPVideoEncodedFrameImpl* aEncodedFrame); - void EncodedFrameDestroyed(GMPVideoEncodedFrameImpl* aFrame); - - // GMPVideoHost - GMPErr CreateFrame(GMPVideoFrameFormat aFormat, GMPVideoFrame** aFrame) override; - GMPErr CreatePlane(GMPPlane** aPlane) override; - -private: - // All shared memory allocations have to be made by an IPDL actor. - // This is a reference to the owning actor. If this reference is - // null then the actor has died and all allocations must fail. - GMPSharedMemManager* mSharedMemMgr; - - // We track all of these things because they need to handle further - // allocations through us and we need to notify them when they - // can't use us any more. - nsTArray<GMPPlaneImpl*> mPlanes; - nsTArray<GMPVideoEncodedFrameImpl*> mEncodedFrames; -}; - -} // namespace gmp -} // namespace mozilla - -#endif // GMPVideoHost_h_ diff --git a/dom/media/gmp/GMPVideoPlaneImpl.cpp b/dom/media/gmp/GMPVideoPlaneImpl.cpp deleted file mode 100644 index 074a965e8..000000000 --- a/dom/media/gmp/GMPVideoPlaneImpl.cpp +++ /dev/null @@ -1,225 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#include "GMPVideoPlaneImpl.h" -#include "mozilla/gmp/GMPTypes.h" -#include "GMPVideoHost.h" -#include "GMPSharedMemManager.h" - -namespace mozilla { -namespace gmp { - -GMPPlaneImpl::GMPPlaneImpl(GMPVideoHostImpl* aHost) -: mSize(0), - mStride(0), - mHost(aHost) -{ - MOZ_ASSERT(mHost); - mHost->PlaneCreated(this); -} - -GMPPlaneImpl::GMPPlaneImpl(const GMPPlaneData& aPlaneData, GMPVideoHostImpl* aHost) -: mBuffer(aPlaneData.mBuffer()), - mSize(aPlaneData.mSize()), - mStride(aPlaneData.mStride()), - mHost(aHost) -{ - MOZ_ASSERT(mHost); - mHost->PlaneCreated(this); -} - -GMPPlaneImpl::~GMPPlaneImpl() -{ - DestroyBuffer(); - if (mHost) { - mHost->PlaneDestroyed(this); - } -} - -void -GMPPlaneImpl::DoneWithAPI() -{ - DestroyBuffer(); - - // Do this after destroying the buffer because destruction - // involves deallocation, which requires a host. - mHost = nullptr; -} - -void -GMPPlaneImpl::ActorDestroyed() -{ - // Simply clear out Shmem reference, do not attempt to - // properly free it. It has already been freed. - mBuffer = ipc::Shmem(); - // No more host. - mHost = nullptr; -} - -bool -GMPPlaneImpl::InitPlaneData(GMPPlaneData& aPlaneData) -{ - aPlaneData.mBuffer() = mBuffer; - aPlaneData.mSize() = mSize; - aPlaneData.mStride() = mStride; - - // This method is called right before Shmem is sent to another process. - // We need to effectively zero out our member copy so that we don't - // try to delete memory we don't own later. - mBuffer = ipc::Shmem(); - - return true; -} - -GMPErr -GMPPlaneImpl::MaybeResize(int32_t aNewSize) { - if (aNewSize <= AllocatedSize()) { - return GMPNoErr; - } - - if (!mHost) { - return GMPGenericErr; - } - - ipc::Shmem new_mem; - if (!mHost->SharedMemMgr()->MgrAllocShmem(GMPSharedMem::kGMPFrameData, aNewSize, - ipc::SharedMemory::TYPE_BASIC, &new_mem) || - !new_mem.get<uint8_t>()) { - return GMPAllocErr; - } - - if (mBuffer.IsReadable()) { - memcpy(new_mem.get<uint8_t>(), Buffer(), mSize); - } - - DestroyBuffer(); - - mBuffer = new_mem; - - return GMPNoErr; -} - -void -GMPPlaneImpl::DestroyBuffer() -{ - if (mHost && mBuffer.IsWritable()) { - mHost->SharedMemMgr()->MgrDeallocShmem(GMPSharedMem::kGMPFrameData, mBuffer); - } - mBuffer = ipc::Shmem(); -} - -GMPErr -GMPPlaneImpl::CreateEmptyPlane(int32_t aAllocatedSize, int32_t aStride, int32_t aPlaneSize) -{ - if (aAllocatedSize < 1 || aStride < 1 || aPlaneSize < 1) { - return GMPGenericErr; - } - - GMPErr err = MaybeResize(aAllocatedSize); - if (err != GMPNoErr) { - return err; - } - - mSize = aPlaneSize; - mStride = aStride; - - return GMPNoErr; -} - -GMPErr -GMPPlaneImpl::Copy(const GMPPlane& aPlane) -{ - auto& planeimpl = static_cast<const GMPPlaneImpl&>(aPlane); - - GMPErr err = MaybeResize(planeimpl.mSize); - if (err != GMPNoErr) { - return err; - } - - if (planeimpl.Buffer() && planeimpl.mSize > 0) { - memcpy(Buffer(), planeimpl.Buffer(), mSize); - } - - mSize = planeimpl.mSize; - mStride = planeimpl.mStride; - - return GMPNoErr; -} - -GMPErr -GMPPlaneImpl::Copy(int32_t aSize, int32_t aStride, const uint8_t* aBuffer) -{ - GMPErr err = MaybeResize(aSize); - if (err != GMPNoErr) { - return err; - } - - if (aBuffer && aSize > 0) { - memcpy(Buffer(), aBuffer, aSize); - } - - mSize = aSize; - mStride = aStride; - - return GMPNoErr; -} - -void -GMPPlaneImpl::Swap(GMPPlane& aPlane) -{ - auto& planeimpl = static_cast<GMPPlaneImpl&>(aPlane); - - std::swap(mStride, planeimpl.mStride); - std::swap(mSize, planeimpl.mSize); - std::swap(mBuffer, planeimpl.mBuffer); -} - -int32_t -GMPPlaneImpl::AllocatedSize() const -{ - if (mBuffer.IsWritable()) { - return mBuffer.Size<uint8_t>(); - } - return 0; -} - -void -GMPPlaneImpl::ResetSize() -{ - mSize = 0; -} - -bool -GMPPlaneImpl::IsZeroSize() const -{ - return (mSize == 0); -} - -int32_t -GMPPlaneImpl::Stride() const -{ - return mStride; -} - -const uint8_t* -GMPPlaneImpl::Buffer() const -{ - return mBuffer.get<uint8_t>(); -} - -uint8_t* -GMPPlaneImpl::Buffer() -{ - return mBuffer.get<uint8_t>(); -} - -void -GMPPlaneImpl::Destroy() -{ - delete this; -} - -} // namespace gmp -} // namespace mozilla diff --git a/dom/media/gmp/GMPVideoPlaneImpl.h b/dom/media/gmp/GMPVideoPlaneImpl.h deleted file mode 100644 index d3a0d753a..000000000 --- a/dom/media/gmp/GMPVideoPlaneImpl.h +++ /dev/null @@ -1,66 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#ifndef GMPVideoPlaneImpl_h_ -#define GMPVideoPlaneImpl_h_ - -#include "gmp-video-plane.h" -#include "mozilla/ipc/Shmem.h" - -namespace mozilla { -namespace gmp { - -class GMPVideoHostImpl; -class GMPPlaneData; - -class GMPPlaneImpl : public GMPPlane -{ - friend struct IPC::ParamTraits<mozilla::gmp::GMPPlaneImpl>; -public: - explicit GMPPlaneImpl(GMPVideoHostImpl* aHost); - GMPPlaneImpl(const GMPPlaneData& aPlaneData, GMPVideoHostImpl* aHost); - virtual ~GMPPlaneImpl(); - - // This is called during a normal destroy sequence, which is - // when a consumer is finished or during XPCOM shutdown. - void DoneWithAPI(); - // This is called when something has gone wrong - specicifically, - // a child process has crashed. Does not attempt to release Shmem, - // as the Shmem has already been released. - void ActorDestroyed(); - - bool InitPlaneData(GMPPlaneData& aPlaneData); - - // GMPPlane - GMPErr CreateEmptyPlane(int32_t aAllocatedSize, - int32_t aStride, - int32_t aPlaneSize) override; - GMPErr Copy(const GMPPlane& aPlane) override; - GMPErr Copy(int32_t aSize, - int32_t aStride, - const uint8_t* aBuffer) override; - void Swap(GMPPlane& aPlane) override; - int32_t AllocatedSize() const override; - void ResetSize() override; - bool IsZeroSize() const override; - int32_t Stride() const override; - const uint8_t* Buffer() const override; - uint8_t* Buffer() override; - void Destroy() override; - -private: - GMPErr MaybeResize(int32_t aNewSize); - void DestroyBuffer(); - - ipc::Shmem mBuffer; - int32_t mSize; - int32_t mStride; - GMPVideoHostImpl* mHost; -}; - -} // namespace gmp -} // namespace mozilla - -#endif // GMPVideoPlaneImpl_h_ diff --git a/dom/media/gmp/GMPVideoi420FrameImpl.cpp b/dom/media/gmp/GMPVideoi420FrameImpl.cpp deleted file mode 100644 index fdbb9a962..000000000 --- a/dom/media/gmp/GMPVideoi420FrameImpl.cpp +++ /dev/null @@ -1,365 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#include "GMPVideoi420FrameImpl.h" -#include "mozilla/gmp/GMPTypes.h" -#include "mozilla/CheckedInt.h" - -namespace mozilla { -namespace gmp { - -GMPVideoi420FrameImpl::GMPVideoi420FrameImpl(GMPVideoHostImpl* aHost) -: mYPlane(aHost), - mUPlane(aHost), - mVPlane(aHost), - mWidth(0), - mHeight(0), - mTimestamp(0ll), - mDuration(0ll) -{ - MOZ_ASSERT(aHost); -} - -GMPVideoi420FrameImpl::GMPVideoi420FrameImpl(const GMPVideoi420FrameData& aFrameData, - GMPVideoHostImpl* aHost) -: mYPlane(aFrameData.mYPlane(), aHost), - mUPlane(aFrameData.mUPlane(), aHost), - mVPlane(aFrameData.mVPlane(), aHost), - mWidth(aFrameData.mWidth()), - mHeight(aFrameData.mHeight()), - mTimestamp(aFrameData.mTimestamp()), - mDuration(aFrameData.mDuration()) -{ - MOZ_ASSERT(aHost); -} - -GMPVideoi420FrameImpl::~GMPVideoi420FrameImpl() -{ -} - -bool -GMPVideoi420FrameImpl::InitFrameData(GMPVideoi420FrameData& aFrameData) -{ - mYPlane.InitPlaneData(aFrameData.mYPlane()); - mUPlane.InitPlaneData(aFrameData.mUPlane()); - mVPlane.InitPlaneData(aFrameData.mVPlane()); - aFrameData.mWidth() = mWidth; - aFrameData.mHeight() = mHeight; - aFrameData.mTimestamp() = mTimestamp; - aFrameData.mDuration() = mDuration; - return true; -} - -GMPVideoFrameFormat -GMPVideoi420FrameImpl::GetFrameFormat() -{ - return kGMPI420VideoFrame; -} - -void -GMPVideoi420FrameImpl::Destroy() -{ - delete this; -} - -/* static */ bool -GMPVideoi420FrameImpl::CheckFrameData(const GMPVideoi420FrameData& aFrameData) -{ - // We may be passed the "wrong" shmem (one smaller than the actual size). - // This implies a bug or serious error on the child size. Ignore this frame if so. - // Note: Size() greater than expected is also an error, but with no negative consequences - int32_t half_width = (aFrameData.mWidth() + 1) / 2; - if ((aFrameData.mYPlane().mStride() <= 0) || (aFrameData.mYPlane().mSize() <= 0) || - (aFrameData.mUPlane().mStride() <= 0) || (aFrameData.mUPlane().mSize() <= 0) || - (aFrameData.mVPlane().mStride() <= 0) || (aFrameData.mVPlane().mSize() <= 0) || - (aFrameData.mYPlane().mSize() > (int32_t) aFrameData.mYPlane().mBuffer().Size<uint8_t>()) || - (aFrameData.mUPlane().mSize() > (int32_t) aFrameData.mUPlane().mBuffer().Size<uint8_t>()) || - (aFrameData.mVPlane().mSize() > (int32_t) aFrameData.mVPlane().mBuffer().Size<uint8_t>()) || - (aFrameData.mYPlane().mStride() < aFrameData.mWidth()) || - (aFrameData.mUPlane().mStride() < half_width) || - (aFrameData.mVPlane().mStride() < half_width) || - (aFrameData.mYPlane().mSize() < aFrameData.mYPlane().mStride() * aFrameData.mHeight()) || - (aFrameData.mUPlane().mSize() < aFrameData.mUPlane().mStride() * ((aFrameData.mHeight()+1)/2)) || - (aFrameData.mVPlane().mSize() < aFrameData.mVPlane().mStride() * ((aFrameData.mHeight()+1)/2))) - { - return false; - } - return true; -} - -bool -GMPVideoi420FrameImpl::CheckDimensions(int32_t aWidth, int32_t aHeight, - int32_t aStride_y, int32_t aStride_u, int32_t aStride_v) -{ - int32_t half_width = (aWidth + 1) / 2; - if (aWidth < 1 || aHeight < 1 || - aStride_y < aWidth || aStride_u < half_width || aStride_v < half_width || - !(CheckedInt<int32_t>(aHeight) * aStride_y - + ((CheckedInt<int32_t>(aHeight) + 1) / 2) - * (CheckedInt<int32_t>(aStride_u) + aStride_v)).isValid()) { - return false; - } - return true; -} - -const GMPPlaneImpl* -GMPVideoi420FrameImpl::GetPlane(GMPPlaneType aType) const { - switch (aType) { - case kGMPYPlane: - return &mYPlane; - case kGMPUPlane: - return &mUPlane; - case kGMPVPlane: - return &mVPlane; - default: - MOZ_CRASH("Unknown plane type!"); - } - return nullptr; -} - -GMPPlaneImpl* -GMPVideoi420FrameImpl::GetPlane(GMPPlaneType aType) { - switch (aType) { - case kGMPYPlane : - return &mYPlane; - case kGMPUPlane : - return &mUPlane; - case kGMPVPlane : - return &mVPlane; - default: - MOZ_CRASH("Unknown plane type!"); - } - return nullptr; -} - -GMPErr -GMPVideoi420FrameImpl::CreateEmptyFrame(int32_t aWidth, int32_t aHeight, - int32_t aStride_y, int32_t aStride_u, int32_t aStride_v) -{ - if (!CheckDimensions(aWidth, aHeight, aStride_y, aStride_u, aStride_v)) { - return GMPGenericErr; - } - - int32_t size_y = aStride_y * aHeight; - int32_t half_height = (aHeight + 1) / 2; - int32_t size_u = aStride_u * half_height; - int32_t size_v = aStride_v * half_height; - - GMPErr err = mYPlane.CreateEmptyPlane(size_y, aStride_y, size_y); - if (err != GMPNoErr) { - return err; - } - err = mUPlane.CreateEmptyPlane(size_u, aStride_u, size_u); - if (err != GMPNoErr) { - return err; - } - err = mVPlane.CreateEmptyPlane(size_v, aStride_v, size_v); - if (err != GMPNoErr) { - return err; - } - - mWidth = aWidth; - mHeight = aHeight; - mTimestamp = 0ll; - mDuration = 0ll; - - return GMPNoErr; -} - -GMPErr -GMPVideoi420FrameImpl::CreateFrame(int32_t aSize_y, const uint8_t* aBuffer_y, - int32_t aSize_u, const uint8_t* aBuffer_u, - int32_t aSize_v, const uint8_t* aBuffer_v, - int32_t aWidth, int32_t aHeight, - int32_t aStride_y, int32_t aStride_u, int32_t aStride_v) -{ - MOZ_ASSERT(aBuffer_y); - MOZ_ASSERT(aBuffer_u); - MOZ_ASSERT(aBuffer_v); - - if (aSize_y < 1 || aSize_u < 1 || aSize_v < 1) { - return GMPGenericErr; - } - - if (!CheckDimensions(aWidth, aHeight, aStride_y, aStride_u, aStride_v)) { - return GMPGenericErr; - } - - GMPErr err = mYPlane.Copy(aSize_y, aStride_y, aBuffer_y); - if (err != GMPNoErr) { - return err; - } - err = mUPlane.Copy(aSize_u, aStride_u, aBuffer_u); - if (err != GMPNoErr) { - return err; - } - err = mVPlane.Copy(aSize_v, aStride_v, aBuffer_v); - if (err != GMPNoErr) { - return err; - } - - mWidth = aWidth; - mHeight = aHeight; - - return GMPNoErr; -} - -GMPErr -GMPVideoi420FrameImpl::CopyFrame(const GMPVideoi420Frame& aFrame) -{ - auto& f = static_cast<const GMPVideoi420FrameImpl&>(aFrame); - - GMPErr err = mYPlane.Copy(f.mYPlane); - if (err != GMPNoErr) { - return err; - } - - err = mUPlane.Copy(f.mUPlane); - if (err != GMPNoErr) { - return err; - } - - err = mVPlane.Copy(f.mVPlane); - if (err != GMPNoErr) { - return err; - } - - mWidth = f.mWidth; - mHeight = f.mHeight; - mTimestamp = f.mTimestamp; - mDuration = f.mDuration; - - return GMPNoErr; -} - -void -GMPVideoi420FrameImpl::SwapFrame(GMPVideoi420Frame* aFrame) -{ - auto f = static_cast<GMPVideoi420FrameImpl*>(aFrame); - mYPlane.Swap(f->mYPlane); - mUPlane.Swap(f->mUPlane); - mVPlane.Swap(f->mVPlane); - std::swap(mWidth, f->mWidth); - std::swap(mHeight, f->mHeight); - std::swap(mTimestamp, f->mTimestamp); - std::swap(mDuration, f->mDuration); -} - -uint8_t* -GMPVideoi420FrameImpl::Buffer(GMPPlaneType aType) -{ - GMPPlane* p = GetPlane(aType); - if (p) { - return p->Buffer(); - } - return nullptr; -} - -const uint8_t* -GMPVideoi420FrameImpl::Buffer(GMPPlaneType aType) const -{ - const GMPPlane* p = GetPlane(aType); - if (p) { - return p->Buffer(); - } - return nullptr; -} - -int32_t -GMPVideoi420FrameImpl::AllocatedSize(GMPPlaneType aType) const -{ - const GMPPlane* p = GetPlane(aType); - if (p) { - return p->AllocatedSize(); - } - return -1; -} - -int32_t -GMPVideoi420FrameImpl::Stride(GMPPlaneType aType) const -{ - const GMPPlane* p = GetPlane(aType); - if (p) { - return p->Stride(); - } - return -1; -} - -GMPErr -GMPVideoi420FrameImpl::SetWidth(int32_t aWidth) -{ - if (!CheckDimensions(aWidth, mHeight, - mYPlane.Stride(), mUPlane.Stride(), - mVPlane.Stride())) { - return GMPGenericErr; - } - mWidth = aWidth; - return GMPNoErr; -} - -GMPErr -GMPVideoi420FrameImpl::SetHeight(int32_t aHeight) -{ - if (!CheckDimensions(mWidth, aHeight, - mYPlane.Stride(), mUPlane.Stride(), - mVPlane.Stride())) { - return GMPGenericErr; - } - mHeight = aHeight; - return GMPNoErr; -} - -int32_t -GMPVideoi420FrameImpl::Width() const -{ - return mWidth; -} - -int32_t -GMPVideoi420FrameImpl::Height() const -{ - return mHeight; -} - -void -GMPVideoi420FrameImpl::SetTimestamp(uint64_t aTimestamp) -{ - mTimestamp = aTimestamp; -} - -uint64_t -GMPVideoi420FrameImpl::Timestamp() const -{ - return mTimestamp; -} - -void -GMPVideoi420FrameImpl::SetDuration(uint64_t aDuration) -{ - mDuration = aDuration; -} - -uint64_t -GMPVideoi420FrameImpl::Duration() const -{ - return mDuration; -} - -bool -GMPVideoi420FrameImpl::IsZeroSize() const -{ - return (mYPlane.IsZeroSize() && mUPlane.IsZeroSize() && mVPlane.IsZeroSize()); -} - -void -GMPVideoi420FrameImpl::ResetSize() -{ - mYPlane.ResetSize(); - mUPlane.ResetSize(); - mVPlane.ResetSize(); -} - -} // namespace gmp -} // namespace mozilla diff --git a/dom/media/gmp/GMPVideoi420FrameImpl.h b/dom/media/gmp/GMPVideoi420FrameImpl.h deleted file mode 100644 index f5cb0254b..000000000 --- a/dom/media/gmp/GMPVideoi420FrameImpl.h +++ /dev/null @@ -1,84 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#ifndef GMPVideoi420FrameImpl_h_ -#define GMPVideoi420FrameImpl_h_ - -#include "gmp-video-frame-i420.h" -#include "mozilla/ipc/Shmem.h" -#include "GMPVideoPlaneImpl.h" - -namespace mozilla { -namespace gmp { - -class GMPVideoi420FrameData; - -class GMPVideoi420FrameImpl : public GMPVideoi420Frame -{ - friend struct IPC::ParamTraits<mozilla::gmp::GMPVideoi420FrameImpl>; -public: - explicit GMPVideoi420FrameImpl(GMPVideoHostImpl* aHost); - GMPVideoi420FrameImpl(const GMPVideoi420FrameData& aFrameData, GMPVideoHostImpl* aHost); - virtual ~GMPVideoi420FrameImpl(); - - static bool CheckFrameData(const GMPVideoi420FrameData& aFrameData); - - bool InitFrameData(GMPVideoi420FrameData& aFrameData); - const GMPPlaneImpl* GetPlane(GMPPlaneType aType) const; - GMPPlaneImpl* GetPlane(GMPPlaneType aType); - - // GMPVideoFrame - GMPVideoFrameFormat GetFrameFormat() override; - void Destroy() override; - - // GMPVideoi420Frame - GMPErr CreateEmptyFrame(int32_t aWidth, - int32_t aHeight, - int32_t aStride_y, - int32_t aStride_u, - int32_t aStride_v) override; - GMPErr CreateFrame(int32_t aSize_y, const uint8_t* aBuffer_y, - int32_t aSize_u, const uint8_t* aBuffer_u, - int32_t aSize_v, const uint8_t* aBuffer_v, - int32_t aWidth, - int32_t aHeight, - int32_t aStride_y, - int32_t aStride_u, - int32_t aStride_v) override; - GMPErr CopyFrame(const GMPVideoi420Frame& aFrame) override; - void SwapFrame(GMPVideoi420Frame* aFrame) override; - uint8_t* Buffer(GMPPlaneType aType) override; - const uint8_t* Buffer(GMPPlaneType aType) const override; - int32_t AllocatedSize(GMPPlaneType aType) const override; - int32_t Stride(GMPPlaneType aType) const override; - GMPErr SetWidth(int32_t aWidth) override; - GMPErr SetHeight(int32_t aHeight) override; - int32_t Width() const override; - int32_t Height() const override; - void SetTimestamp(uint64_t aTimestamp) override; - uint64_t Timestamp() const override; - void SetDuration(uint64_t aDuration) override; - uint64_t Duration() const override; - bool IsZeroSize() const override; - void ResetSize() override; - -private: - bool CheckDimensions(int32_t aWidth, int32_t aHeight, - int32_t aStride_y, int32_t aStride_u, int32_t aStride_v); - - GMPPlaneImpl mYPlane; - GMPPlaneImpl mUPlane; - GMPPlaneImpl mVPlane; - int32_t mWidth; - int32_t mHeight; - uint64_t mTimestamp; - uint64_t mDuration; -}; - -} // namespace gmp - -} // namespace mozilla - -#endif // GMPVideoi420FrameImpl_h_ diff --git a/dom/media/gmp/PGMP.ipdl b/dom/media/gmp/PGMP.ipdl deleted file mode 100644 index e1738d010..000000000 --- a/dom/media/gmp/PGMP.ipdl +++ /dev/null @@ -1,41 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -include protocol PGMPContent; -include protocol PGMPTimer; -include protocol PGMPStorage; - -using mozilla::dom::NativeThreadId from "mozilla/dom/TabMessageUtils.h"; - -namespace mozilla { -namespace gmp { - -intr protocol PGMP -{ - parent opens PGMPContent; - - manages PGMPTimer; - manages PGMPStorage; - -parent: - async PGMPTimer(); - async PGMPStorage(); - - async PGMPContentChildDestroyed(); - - async AsyncShutdownComplete(); - async AsyncShutdownRequired(); - -child: - async BeginAsyncShutdown(); - async CrashPluginNow(); - intr StartPlugin(nsString adapter); - async SetNodeId(nsCString nodeId); - async PreloadLibs(nsCString libs); - async CloseActive(); -}; - -} // namespace gmp -} // namespace mozilla diff --git a/dom/media/gmp/PGMPAudioDecoder.ipdl b/dom/media/gmp/PGMPAudioDecoder.ipdl deleted file mode 100644 index 9af9415c8..000000000 --- a/dom/media/gmp/PGMPAudioDecoder.ipdl +++ /dev/null @@ -1,37 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -include protocol PGMPContent; -include GMPTypes; - -using GMPCodecSpecificInfo from "gmp-audio-codec.h"; -using GMPErr from "gmp-errors.h"; - -include "GMPMessageUtils.h"; - -namespace mozilla { -namespace gmp { - -async protocol PGMPAudioDecoder -{ - manager PGMPContent; -child: - async InitDecode(GMPAudioCodecData aCodecSettings); - async Decode(GMPAudioEncodedSampleData aInput); - async Reset(); - async Drain(); - async DecodingComplete(); -parent: - async __delete__(); - async Decoded(GMPAudioDecodedSampleData aDecoded); - async InputDataExhausted(); - async DrainComplete(); - async ResetComplete(); - async Error(GMPErr aErr); - async Shutdown(); -}; - -} // namespace gmp -} // namespace mozilla diff --git a/dom/media/gmp/PGMPContent.ipdl b/dom/media/gmp/PGMPContent.ipdl deleted file mode 100644 index 00e16c02f..000000000 --- a/dom/media/gmp/PGMPContent.ipdl +++ /dev/null @@ -1,33 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -include protocol PGMP; -include protocol PGMPService; -include protocol PGMPVideoDecoder; -include protocol PGMPVideoEncoder; -include protocol PGMPDecryptor; -include protocol PGMPAudioDecoder; - -namespace mozilla { -namespace gmp { - -intr protocol PGMPContent -{ - bridges PGMPService, PGMP; - - manages PGMPAudioDecoder; - manages PGMPDecryptor; - manages PGMPVideoDecoder; - manages PGMPVideoEncoder; - -child: - async PGMPAudioDecoder(); - async PGMPDecryptor(); - async PGMPVideoDecoder(uint32_t aDecryptorId); - async PGMPVideoEncoder(); -}; - -} // namespace gmp -} // namespace mozilla diff --git a/dom/media/gmp/PGMPDecryptor.ipdl b/dom/media/gmp/PGMPDecryptor.ipdl deleted file mode 100644 index 06b9b9cb6..000000000 --- a/dom/media/gmp/PGMPDecryptor.ipdl +++ /dev/null @@ -1,92 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -include protocol PGMPContent; -include GMPTypes; - -using GMPSessionMessageType from "gmp-decryption.h"; -using GMPSessionType from "gmp-decryption.h"; -using GMPDOMException from "gmp-decryption.h"; -using GMPErr from "gmp-errors.h"; - -namespace mozilla { -namespace gmp { - -async protocol PGMPDecryptor -{ - manager PGMPContent; -child: - - async Init(bool aDistinctiveIdentifierRequired, - bool aPersistentStateRequired); - - async CreateSession(uint32_t aCreateSessionToken, - uint32_t aPromiseId, - nsCString aInitDataType, - uint8_t[] aInitData, - GMPSessionType aSessionType); - - async LoadSession(uint32_t aPromiseId, - nsCString aSessionId); - - async UpdateSession(uint32_t aPromiseId, - nsCString aSessionId, - uint8_t[] aResponse); - - async CloseSession(uint32_t aPromiseId, - nsCString aSessionId); - - async RemoveSession(uint32_t aPromiseId, - nsCString aSessionId); - - async SetServerCertificate(uint32_t aPromiseId, - uint8_t[] aServerCert); - - async Decrypt(uint32_t aId, - uint8_t[] aBuffer, - GMPDecryptionData aMetadata); - - async DecryptingComplete(); - -parent: - async __delete__(); - - async SetDecryptorId(uint32_t aId); - - async SetSessionId(uint32_t aCreateSessionToken, - nsCString aSessionId); - - async ResolveLoadSessionPromise(uint32_t aPromiseId, - bool aSuccess); - - async ResolvePromise(uint32_t aPromiseId); - - async RejectPromise(uint32_t aPromiseId, - GMPDOMException aDOMExceptionCode, - nsCString aMessage); - - async SessionMessage(nsCString aSessionId, - GMPSessionMessageType aMessageType, - uint8_t[] aMessage); - - async ExpirationChange(nsCString aSessionId, double aExpiryTime); - - async SessionClosed(nsCString aSessionId); - - async SessionError(nsCString aSessionId, - GMPDOMException aDOMExceptionCode, - uint32_t aSystemCode, - nsCString aMessage); - - async Decrypted(uint32_t aId, GMPErr aResult, uint8_t[] aBuffer); - - async Shutdown(); - - async BatchedKeyStatusChanged(nsCString aSessionId, - GMPKeyInformation[] aKeyInfos); -}; - -} // namespace gmp -} // namespace mozilla diff --git a/dom/media/gmp/PGMPService.ipdl b/dom/media/gmp/PGMPService.ipdl deleted file mode 100644 index db3fb6388..000000000 --- a/dom/media/gmp/PGMPService.ipdl +++ /dev/null @@ -1,32 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -include protocol PGMP; - -using base::ProcessId from "base/process.h"; - -namespace mozilla { -namespace gmp { - -sync protocol PGMPService -{ - parent spawns PGMP as child; - -parent: - - sync SelectGMP(nsCString nodeId, nsCString api, nsCString[] tags) - returns (uint32_t pluginId, nsresult aResult); - - sync LaunchGMP(uint32_t pluginId, ProcessId[] alreadyBridgedTo) - returns (ProcessId id, nsCString displayName, nsresult aResult); - - sync GetGMPNodeId(nsString origin, nsString topLevelOrigin, - nsString gmpName, - bool inPrivateBrowsing) - returns (nsCString id); -}; - -} // namespace gmp -} // namespace mozilla diff --git a/dom/media/gmp/PGMPStorage.ipdl b/dom/media/gmp/PGMPStorage.ipdl deleted file mode 100644 index 4d858312a..000000000 --- a/dom/media/gmp/PGMPStorage.ipdl +++ /dev/null @@ -1,36 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -include protocol PGMP; -include GMPTypes; - -using GMPErr from "gmp-errors.h"; - -namespace mozilla { -namespace gmp { - -async protocol PGMPStorage -{ - manager PGMP; - -child: - async OpenComplete(nsCString aRecordName, GMPErr aStatus); - async ReadComplete(nsCString aRecordName, GMPErr aStatus, uint8_t[] aBytes); - async WriteComplete(nsCString aRecordName, GMPErr aStatus); - async RecordNames(nsCString[] aRecordNames, GMPErr aStatus); - async Shutdown(); - -parent: - async Open(nsCString aRecordName); - async Read(nsCString aRecordName); - async Write(nsCString aRecordName, uint8_t[] aBytes); - async Close(nsCString aRecordName); - async GetRecordNames(); - async __delete__(); - -}; - -} // namespace gmp -} // namespace mozilla diff --git a/dom/media/gmp/PGMPTimer.ipdl b/dom/media/gmp/PGMPTimer.ipdl deleted file mode 100644 index 7a486bc3a..000000000 --- a/dom/media/gmp/PGMPTimer.ipdl +++ /dev/null @@ -1,22 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -include protocol PGMP; - -namespace mozilla { -namespace gmp { - -async protocol PGMPTimer -{ - manager PGMP; -child: - async TimerExpired(uint32_t aTimerId); -parent: - async SetTimer(uint32_t aTimerId, uint32_t aTimeoutMs); - async __delete__(); -}; - -} // namespace gmp -} // namespace mozilla diff --git a/dom/media/gmp/PGMPVideoDecoder.ipdl b/dom/media/gmp/PGMPVideoDecoder.ipdl deleted file mode 100644 index 83ad8f700..000000000 --- a/dom/media/gmp/PGMPVideoDecoder.ipdl +++ /dev/null @@ -1,50 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -include protocol PGMPContent; -include GMPTypes; - -using GMPVideoCodec from "gmp-video-codec.h"; -using GMPErr from "gmp-errors.h"; - -include "GMPMessageUtils.h"; - -namespace mozilla { -namespace gmp { - -intr protocol PGMPVideoDecoder -{ - manager PGMPContent; -child: - async InitDecode(GMPVideoCodec aCodecSettings, - uint8_t[] aCodecSpecific, - int32_t aCoreCount); - async Decode(GMPVideoEncodedFrameData aInputFrame, - bool aMissingFrames, - uint8_t[] aCodecSpecificInfo, - int64_t aRenderTimeMs); - async Reset(); - async Drain(); - async DecodingComplete(); - async ChildShmemForPool(Shmem aFrameBuffer); - -parent: - async __delete__(); - async Decoded(GMPVideoi420FrameData aDecodedFrame); - async ReceivedDecodedReferenceFrame(uint64_t aPictureId); - async ReceivedDecodedFrame(uint64_t aPictureId); - async InputDataExhausted(); - async DrainComplete(); - async ResetComplete(); - async Error(GMPErr aErr); - async Shutdown(); - async ParentShmemForPool(Shmem aEncodedBuffer); - // MUST be intr - if sync and we create a new Shmem, when the returned - // Shmem is received in the Child it will fail to Deserialize - intr NeedShmem(uint32_t aFrameBufferSize) returns (Shmem aMem); -}; - -} // namespace gmp -} // namespace mozilla diff --git a/dom/media/gmp/PGMPVideoEncoder.ipdl b/dom/media/gmp/PGMPVideoEncoder.ipdl deleted file mode 100644 index ef013352a..000000000 --- a/dom/media/gmp/PGMPVideoEncoder.ipdl +++ /dev/null @@ -1,48 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -include protocol PGMPContent; -include GMPTypes; - -using GMPVideoCodec from "gmp-video-codec.h"; -using GMPVideoFrameType from "gmp-video-frame-encoded.h"; -using GMPErr from "gmp-errors.h"; - -include "GMPMessageUtils.h"; - -namespace mozilla { -namespace gmp { - -intr protocol PGMPVideoEncoder -{ - manager PGMPContent; -child: - async InitEncode(GMPVideoCodec aCodecSettings, - uint8_t[] aCodecSpecific, - int32_t aNumberOfCores, - uint32_t aMaxPayloadSize); - async Encode(GMPVideoi420FrameData aInputFrame, - uint8_t[] aCodecSpecificInfo, - GMPVideoFrameType[] aFrameTypes); - async SetChannelParameters(uint32_t aPacketLoss, uint32_t aRTT); - async SetRates(uint32_t aNewBitRate, uint32_t aFrameRate); - async SetPeriodicKeyFrames(bool aEnable); - async EncodingComplete(); - async ChildShmemForPool(Shmem aEncodedBuffer); - -parent: - async __delete__(); - async Encoded(GMPVideoEncodedFrameData aEncodedFrame, - uint8_t[] aCodecSpecificInfo); - async Error(GMPErr aErr); - async Shutdown(); - async ParentShmemForPool(Shmem aFrameBuffer); - // MUST be intr - if sync and we create a new Shmem, when the returned - // Shmem is received in the Child it will fail to Deserialize - intr NeedShmem(uint32_t aEncodedBufferSize) returns (Shmem aMem); -}; - -} // namespace gmp -} // namespace mozilla diff --git a/dom/media/gmp/README.txt b/dom/media/gmp/README.txt deleted file mode 100644 index 189cf3b30..000000000 --- a/dom/media/gmp/README.txt +++ /dev/null @@ -1 +0,0 @@ -This directory contains code supporting Gecko Media Plugins (GMPs). The GMP API is not the same thing as the Media Plugin API (MPAPI). diff --git a/dom/media/gmp/gmp-api/gmp-async-shutdown.h b/dom/media/gmp/gmp-api/gmp-async-shutdown.h deleted file mode 100644 index 42268668f..000000000 --- a/dom/media/gmp/gmp-api/gmp-async-shutdown.h +++ /dev/null @@ -1,54 +0,0 @@ -/* -* Copyright 2013, Mozilla Foundation and contributors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -#ifndef GMP_ASYNC_SHUTDOWN_H_ -#define GMP_ASYNC_SHUTDOWN_H_ - -#define GMP_API_ASYNC_SHUTDOWN "async-shutdown" - -// API exposed by the plugin library to manage asynchronous shutdown. -// Some plugins require special cleanup which may need to make calls -// to host services and wait for async responses. -// -// To enable a plugins to block shutdown until its async shutdown is -// complete, implement the GMPAsyncShutdown interface and return it when -// your plugin's GMPGetAPI function is called with "async-shutdown". -// When your GMPAsyncShutdown's BeginShutdown() implementation is called -// by the GMP host, you should initate your async shutdown process. -// Once you have completed shutdown, call the ShutdownComplete() function -// of the GMPAsyncShutdownHost that is passed as the host argument to the -// GMPGetAPI() call. -// -// Note: Your GMP's GMPShutdown function will still be called after your -// call to ShutdownComplete(). -// -// API name macro: GMP_API_ASYNC_SHUTDOWN -// Host API: GMPAsyncShutdownHost -class GMPAsyncShutdown { -public: - virtual ~GMPAsyncShutdown() {} - - virtual void BeginShutdown() = 0; -}; - -class GMPAsyncShutdownHost { -public: - virtual ~GMPAsyncShutdownHost() {} - - virtual void ShutdownComplete() = 0; -}; - -#endif // GMP_ASYNC_SHUTDOWN_H_ diff --git a/dom/media/gmp/gmp-api/gmp-audio-codec.h b/dom/media/gmp/gmp-api/gmp-audio-codec.h deleted file mode 100644 index 5a5c17bb9..000000000 --- a/dom/media/gmp/gmp-api/gmp-audio-codec.h +++ /dev/null @@ -1,43 +0,0 @@ -/* -* Copyright 2013, Mozilla Foundation and contributors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -#ifndef GMP_AUDIO_CODEC_h_ -#define GMP_AUDIO_CODEC_h_ - -#include <stdint.h> - -enum GMPAudioCodecType -{ - kGMPAudioCodecAAC, - kGMPAudioCodecVorbis, - kGMPAudioCodecInvalid // Should always be last. -}; - -struct GMPAudioCodec -{ - GMPAudioCodecType mCodecType; - uint32_t mChannelCount; - uint32_t mBitsPerChannel; - uint32_t mSamplesPerSecond; - - // Codec extra data, such as vorbis setup header, or - // AAC AudioSpecificConfig. - // These are null/0 if not externally negotiated - const uint8_t* mExtraData; - uint32_t mExtraDataLen; -}; - -#endif // GMP_AUDIO_CODEC_h_ diff --git a/dom/media/gmp/gmp-api/gmp-audio-decode.h b/dom/media/gmp/gmp-api/gmp-audio-decode.h deleted file mode 100644 index 8b017c0af..000000000 --- a/dom/media/gmp/gmp-api/gmp-audio-decode.h +++ /dev/null @@ -1,84 +0,0 @@ -/* -* Copyright 2013, Mozilla Foundation and contributors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -#ifndef GMP_AUDIO_DECODE_h_ -#define GMP_AUDIO_DECODE_h_ - -#include "gmp-errors.h" -#include "gmp-audio-samples.h" -#include "gmp-audio-codec.h" -#include <stdint.h> - -// ALL METHODS MUST BE CALLED ON THE MAIN THREAD -class GMPAudioDecoderCallback -{ -public: - virtual ~GMPAudioDecoderCallback() {} - - virtual void Decoded(GMPAudioSamples* aDecodedSamples) = 0; - - virtual void InputDataExhausted() = 0; - - virtual void DrainComplete() = 0; - - virtual void ResetComplete() = 0; - - // Called when the decoder encounters a catestrophic error and cannot - // continue. Gecko will not send any more input for decoding. - virtual void Error(GMPErr aError) = 0; -}; - -#define GMP_API_AUDIO_DECODER "decode-audio" - -// Audio decoding for a single stream. A GMP may be asked to create multiple -// decoders concurrently. -// -// API name macro: GMP_API_AUDIO_DECODER -// Host API: GMPAudioHost -// -// ALL METHODS MUST BE CALLED ON THE MAIN THREAD -class GMPAudioDecoder -{ -public: - virtual ~GMPAudioDecoder() {} - - // aCallback: Subclass should retain reference to it until DecodingComplete - // is called. Do not attempt to delete it, host retains ownership. - // TODO: Pass AudioHost so decoder can create GMPAudioEncodedFrame objects? - virtual void InitDecode(const GMPAudioCodec& aCodecSettings, - GMPAudioDecoderCallback* aCallback) = 0; - - // Decode encoded audio frames (as a part of an audio stream). The decoded - // frames must be returned to the user through the decode complete callback. - virtual void Decode(GMPAudioSamples* aEncodedSamples) = 0; - - // Reset decoder state and prepare for a new call to Decode(...). - // Flushes the decoder pipeline. - // The decoder should enqueue a task to run ResetComplete() on the main - // thread once the reset has finished. - virtual void Reset() = 0; - - // Output decoded frames for any data in the pipeline, regardless of ordering. - // All remaining decoded frames should be immediately returned via callback. - // The decoder should enqueue a task to run DrainComplete() on the main - // thread once the reset has finished. - virtual void Drain() = 0; - - // May free decoder memory. - virtual void DecodingComplete() = 0; -}; - -#endif // GMP_VIDEO_DECODE_h_ diff --git a/dom/media/gmp/gmp-api/gmp-audio-host.h b/dom/media/gmp/gmp-api/gmp-audio-host.h deleted file mode 100644 index fe3641938..000000000 --- a/dom/media/gmp/gmp-api/gmp-audio-host.h +++ /dev/null @@ -1,32 +0,0 @@ -/* -* Copyright 2013, Mozilla Foundation and contributors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -#ifndef GMP_AUDIO_HOST_h_ -#define GMP_AUDIO_HOST_h_ - -#include "gmp-errors.h" -#include "gmp-audio-samples.h" - -class GMPAudioHost -{ -public: - // Construct various Audio API objects. Host does not retain reference, - // caller is owner and responsible for deleting. - virtual GMPErr CreateSamples(GMPAudioFormat aFormat, - GMPAudioSamples** aSamples) = 0; -}; - -#endif // GMP_AUDIO_HOST_h_ diff --git a/dom/media/gmp/gmp-api/gmp-audio-samples.h b/dom/media/gmp/gmp-api/gmp-audio-samples.h deleted file mode 100644 index a47fc74b9..000000000 --- a/dom/media/gmp/gmp-api/gmp-audio-samples.h +++ /dev/null @@ -1,74 +0,0 @@ -/* -* Copyright 2013, Mozilla Foundation and contributors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -#ifndef GMP_AUDIO_FRAME_h_ -#define GMP_AUDIO_FRAME_h_ - -#include <stdint.h> -#include "gmp-errors.h" -#include "gmp-decryption.h" - -enum GMPAudioFormat -{ - kGMPAudioEncodedSamples, // Raw compressed data, i.e. an AAC/Vorbis packet. - kGMPAudioIS16Samples, // Interleaved int16_t PCM samples. - kGMPAudioSamplesFormatInvalid // Should always be last. -}; - -class GMPAudioSamples { -public: - // The format of the buffer. - virtual GMPAudioFormat GetFormat() = 0; - virtual void Destroy() = 0; - - // MAIN THREAD ONLY - // Buffer size must be exactly what's required to contain all samples in - // the buffer; every byte is assumed to be part of a sample. - virtual GMPErr SetBufferSize(uint32_t aSize) = 0; - - // Size of the buffer in bytes. - virtual uint32_t Size() = 0; - - // Timestamps are in microseconds, and are the playback start time of the - // first sample in the buffer. - virtual void SetTimeStamp(uint64_t aTimeStamp) = 0; - virtual uint64_t TimeStamp() = 0; - virtual const uint8_t* Buffer() const = 0; - virtual uint8_t* Buffer() = 0; - - // Get metadata describing how this frame is encrypted, or nullptr if the - // buffer is not encrypted. - virtual const GMPEncryptedBufferMetadata* GetDecryptionData() const = 0; - - virtual uint32_t Channels() const = 0; - virtual void SetChannels(uint32_t aChannels) = 0; - - // Rate; the number of frames per second, where a "frame" is one sample for - // each channel. - // - // For IS16 samples, the number of samples should be: - // Size() / (Channels() * sizeof(int16_t)). - // - // Note: Channels() and Rate() may not be constant across a decoding - // session. For example the rate for decoded samples may be different - // than the rate advertised by the MP4 container for encoded samples - // for HE-AAC streams with SBR/PS, and an EME-GMP may need to downsample - // to satisfy DRM requirements. - virtual uint32_t Rate() const = 0; - virtual void SetRate(uint32_t aRate) = 0; -}; - -#endif // GMP_AUDIO_FRAME_h_ diff --git a/dom/media/gmp/gmp-api/gmp-decryption.h b/dom/media/gmp/gmp-api/gmp-decryption.h deleted file mode 100644 index 046a05759..000000000 --- a/dom/media/gmp/gmp-api/gmp-decryption.h +++ /dev/null @@ -1,459 +0,0 @@ -/* -* Copyright 2013, Mozilla Foundation and contributors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -#ifndef GMP_DECRYPTION_h_ -#define GMP_DECRYPTION_h_ - -#include "gmp-platform.h" - -class GMPStringList { -public: - virtual uint32_t Size() const = 0; - - virtual void StringAt(uint32_t aIndex, - const char** aOutString, uint32_t* aOutLength) const = 0; - - virtual ~GMPStringList() { } -}; - -class GMPEncryptedBufferMetadata { -public: - // Key ID to identify the decryption key. - virtual const uint8_t* KeyId() const = 0; - - // Size (in bytes) of |KeyId()|. - virtual uint32_t KeyIdSize() const = 0; - - // Initialization vector. - virtual const uint8_t* IV() const = 0; - - // Size (in bytes) of |IV|. - virtual uint32_t IVSize() const = 0; - - // Number of entries returned by ClearBytes() and CipherBytes(). - virtual uint32_t NumSubsamples() const = 0; - - virtual const uint16_t* ClearBytes() const = 0; - - virtual const uint32_t* CipherBytes() const = 0; - - virtual ~GMPEncryptedBufferMetadata() {} - - // The set of MediaKeySession IDs associated with this decryption key in - // the current stream. - virtual const GMPStringList* SessionIds() const = 0; -}; - -class GMPBuffer { -public: - virtual uint32_t Id() const = 0; - virtual uint8_t* Data() = 0; - virtual uint32_t Size() const = 0; - virtual void Resize(uint32_t aSize) = 0; - virtual ~GMPBuffer() {} -}; - -// These match to the DOMException codes as per: -// http://www.w3.org/TR/dom/#domexception -enum GMPDOMException { - kGMPNoModificationAllowedError = 7, - kGMPNotFoundError = 8, - kGMPNotSupportedError = 9, - kGMPInvalidStateError = 11, - kGMPSyntaxError = 12, - kGMPInvalidModificationError = 13, - kGMPInvalidAccessError = 15, - kGMPSecurityError = 18, - kGMPAbortError = 20, - kGMPQuotaExceededError = 22, - kGMPTimeoutError = 23, - kGMPTypeError = 52 -}; - -enum GMPSessionMessageType { - kGMPLicenseRequest = 0, - kGMPLicenseRenewal = 1, - kGMPLicenseRelease = 2, - kGMPIndividualizationRequest = 3, - kGMPMessageInvalid = 4 // Must always be last. -}; - -enum GMPMediaKeyStatus { - kGMPUsable = 0, - kGMPExpired = 1, - kGMPOutputDownscaled = 2, - kGMPOutputRestricted = 3, - kGMPInternalError = 4, - kGMPUnknown = 5, // Removes key from MediaKeyStatusMap - kGMPReleased = 6, - kGMPStatusPending = 7, - kGMPMediaKeyStatusInvalid = 8 // Must always be last. -}; - -struct GMPMediaKeyInfo { - GMPMediaKeyInfo() {} - GMPMediaKeyInfo(const uint8_t* aKeyId, - uint32_t aKeyIdSize, - GMPMediaKeyStatus aStatus) - : keyid(aKeyId) - , keyid_size(aKeyIdSize) - , status(aStatus) - {} - const uint8_t* keyid; - uint32_t keyid_size; - GMPMediaKeyStatus status; -}; - -// Time in milliseconds, as offset from epoch, 1 Jan 1970. -typedef int64_t GMPTimestamp; - -// Callbacks to be called from the CDM. Threadsafe. -class GMPDecryptorCallback { -public: - - // The GMPDecryptor should call this in response to a call to - // GMPDecryptor::CreateSession(). The GMP host calls CreateSession() when - // MediaKeySession.generateRequest() is called by JavaScript. - // After CreateSession() is called, the GMPDecryptor should call - // GMPDecryptorCallback::SetSessionId() to set the sessionId exposed to - // JavaScript on the MediaKeySession on which the generateRequest() was - // called. SetSessionId() must be called before - // GMPDecryptorCallback::SessionMessage() will work. - // aSessionId must be null terminated. - // Note: pass the aCreateSessionToken from the CreateSession() call, - // and then once the session has sent any messages required for the - // license request to be sent, then resolve the aPromiseId that was passed - // to GMPDecryptor::CreateSession(). - // Note: GMPDecryptor::LoadSession() does *not* need to call SetSessionId() - // for GMPDecryptorCallback::SessionMessage() to work. - virtual void SetSessionId(uint32_t aCreateSessionToken, - const char* aSessionId, - uint32_t aSessionIdLength) = 0; - - // Resolves a promise for a session loaded. - // Resolves to false if we don't have any session data stored for the given - // session ID. - // Must be called before SessionMessage(). - virtual void ResolveLoadSessionPromise(uint32_t aPromiseId, - bool aSuccess) = 0; - - // Called to resolve a specified promise with "undefined". - virtual void ResolvePromise(uint32_t aPromiseId) = 0; - - // Called to reject a promise with a DOMException. - // aMessage is logged to the WebConsole. - // aMessage is optional, but if present must be null terminated. - virtual void RejectPromise(uint32_t aPromiseId, - GMPDOMException aException, - const char* aMessage, - uint32_t aMessageLength) = 0; - - // Called by the CDM when it has a message for a session. - // Length parameters should not include null termination. - // aSessionId must be null terminated. - virtual void SessionMessage(const char* aSessionId, - uint32_t aSessionIdLength, - GMPSessionMessageType aMessageType, - const uint8_t* aMessage, - uint32_t aMessageLength) = 0; - - // aSessionId must be null terminated. - virtual void ExpirationChange(const char* aSessionId, - uint32_t aSessionIdLength, - GMPTimestamp aExpiryTime) = 0; - - // Called by the GMP when a session is closed. All file IO - // that a session requires should be complete before calling this. - // aSessionId must be null terminated. - virtual void SessionClosed(const char* aSessionId, - uint32_t aSessionIdLength) = 0; - - // Called by the GMP when an error occurs in a session. - // aSessionId must be null terminated. - // aMessage is logged to the WebConsole. - // aMessage is optional, but if present must be null terminated. - virtual void SessionError(const char* aSessionId, - uint32_t aSessionIdLength, - GMPDOMException aException, - uint32_t aSystemCode, - const char* aMessage, - uint32_t aMessageLength) = 0; - - // Notifies the status of a key. Gecko will not call into the CDM to decrypt - // or decode content encrypted with a key unless the CDM has marked it - // usable first. So a CDM *MUST* mark its usable keys as usable! - virtual void KeyStatusChanged(const char* aSessionId, - uint32_t aSessionIdLength, - const uint8_t* aKeyId, - uint32_t aKeyIdLength, - GMPMediaKeyStatus aStatus) = 0; - - // DEPRECATED; this function has no affect. - virtual void SetCapabilities(uint64_t aCaps) = 0; - - // Returns decrypted buffer to Gecko, or reports failure. - virtual void Decrypted(GMPBuffer* aBuffer, GMPErr aResult) = 0; - - // To aggregate KeyStatusChanged into single callback per session id. - virtual void BatchedKeyStatusChanged(const char* aSessionId, - uint32_t aSessionIdLength, - const GMPMediaKeyInfo* aKeyInfos, - uint32_t aKeyInfosLength) = 0; - - virtual ~GMPDecryptorCallback() {} -}; - -// Host interface, passed to GetAPIFunc(), with "decrypt". -class GMPDecryptorHost { -public: - virtual void GetSandboxVoucher(const uint8_t** aVoucher, - uint32_t* aVoucherLength) = 0; - - virtual void GetPluginVoucher(const uint8_t** aVoucher, - uint32_t* aVoucherLength) = 0; - - virtual ~GMPDecryptorHost() {} -}; - -enum GMPSessionType { - kGMPTemporySession = 0, - kGMPPersistentSession = 1, - kGMPSessionInvalid = 2 // Must always be last. -}; - -// Gecko supports the current GMPDecryptor version, and the obsolete -// version that the Adobe GMP still uses. -#define GMP_API_DECRYPTOR "eme-decrypt-v9" -#define GMP_API_DECRYPTOR_BACKWARDS_COMPAT "eme-decrypt-v7" - -// API exposed by plugin library to manage decryption sessions. -// When the Host requests this by calling GMPGetAPIFunc(). -// -// API name macro: GMP_API_DECRYPTOR -// Host API: GMPDecryptorHost -class GMPDecryptor { -public: - - // Sets the callback to use with the decryptor to return results - // to Gecko. - virtual void Init(GMPDecryptorCallback* aCallback, - bool aDistinctiveIdentifierRequired, - bool aPersistentStateRequired) = 0; - - // Initiates the creation of a session given |aType| and |aInitData|, and - // the generation of a license request message. - // - // This corresponds to a MediaKeySession.generateRequest() call in JS. - // - // The GMPDecryptor must do the following, in order, upon this method - // being called: - // - // 1. Generate a sessionId to expose to JS, and call - // GMPDecryptorCallback::SetSessionId(aCreateSessionToken, sessionId...) - // with the sessionId to be exposed to JS/EME on the MediaKeySession - // object on which generateRequest() was called, and then - // 2. send any messages to JS/EME required to generate a license request - // given the supplied initData, and then - // 3. generate a license request message, and send it to JS/EME, and then - // 4. call GMPDecryptorCallback::ResolvePromise(). - // - // Note: GMPDecryptorCallback::SetSessionId(aCreateSessionToken, sessionId, ...) - // *must* be called before GMPDecryptorCallback::SendMessage(sessionId, ...) - // will work. - // - // If generating the request fails, reject aPromiseId by calling - // GMPDecryptorCallback::RejectPromise(). - virtual void CreateSession(uint32_t aCreateSessionToken, - uint32_t aPromiseId, - const char* aInitDataType, - uint32_t aInitDataTypeSize, - const uint8_t* aInitData, - uint32_t aInitDataSize, - GMPSessionType aSessionType) = 0; - - // Loads a previously loaded persistent session. - // - // This corresponds to a MediaKeySession.load() call in JS. - // - // The GMPDecryptor must do the following, in order, upon this method - // being called: - // - // 1. Send any messages to JS/EME, or read from storage, whatever is - // required to load the session, and then - // 2. if there is no session with the given sessionId loadable, call - // ResolveLoadSessionPromise(aPromiseId, false), otherwise - // 2. mark the session's keys as usable, and then - // 3. update the session's expiration, and then - // 4. call GMPDecryptorCallback::ResolveLoadSessionPromise(aPromiseId, true). - // - // If loading the session fails due to error, reject aPromiseId by calling - // GMPDecryptorCallback::RejectPromise(). - virtual void LoadSession(uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength) = 0; - - // Updates the session with |aResponse|. - // This corresponds to a MediaKeySession.update() call in JS. - virtual void UpdateSession(uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength, - const uint8_t* aResponse, - uint32_t aResponseSize) = 0; - - // Releases the resources (keys) for the specified session. - // This corresponds to a MediaKeySession.close() call in JS. - virtual void CloseSession(uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength) = 0; - - // Removes the resources (keys) for the specified session. - // This corresponds to a MediaKeySession.remove() call in JS. - virtual void RemoveSession(uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength) = 0; - - // Resolve/reject promise on completion. - // This corresponds to a MediaKeySession.setServerCertificate() call in JS. - virtual void SetServerCertificate(uint32_t aPromiseId, - const uint8_t* aServerCert, - uint32_t aServerCertSize) = 0; - - // Asynchronously decrypts aBuffer in place. When the decryption is - // complete, GMPDecryptor should write the decrypted data back into the - // same GMPBuffer object and return it to Gecko by calling Decrypted(), - // with the GMPNoErr successcode. If decryption fails, call Decrypted() - // with a failure code, and an error event will fire on the media element. - // Note: When Decrypted() is called and aBuffer is passed back, aBuffer - // is deleted. Don't forget to call Decrypted(), as otherwise aBuffer's - // memory will leak! - virtual void Decrypt(GMPBuffer* aBuffer, - GMPEncryptedBufferMetadata* aMetadata) = 0; - - // Called when the decryption operations are complete. - // Do not call the GMPDecryptorCallback's functions after this is called. - virtual void DecryptingComplete() = 0; - - virtual ~GMPDecryptor() {} -}; - -// v7 is the latest decryptor version supported by the Adobe GMP. -// -// API name macro: GMP_API_DECRYPTOR_BACKWARDS_COMPAT -// Host API: GMPDecryptorHost -class GMPDecryptor7 { -public: - - // Sets the callback to use with the decryptor to return results - // to Gecko. - virtual void Init(GMPDecryptorCallback* aCallback) = 0; - - // Initiates the creation of a session given |aType| and |aInitData|, and - // the generation of a license request message. - // - // This corresponds to a MediaKeySession.generateRequest() call in JS. - // - // The GMPDecryptor must do the following, in order, upon this method - // being called: - // - // 1. Generate a sessionId to expose to JS, and call - // GMPDecryptorCallback::SetSessionId(aCreateSessionToken, sessionId...) - // with the sessionId to be exposed to JS/EME on the MediaKeySession - // object on which generateRequest() was called, and then - // 2. send any messages to JS/EME required to generate a license request - // given the supplied initData, and then - // 3. generate a license request message, and send it to JS/EME, and then - // 4. call GMPDecryptorCallback::ResolvePromise(). - // - // Note: GMPDecryptorCallback::SetSessionId(aCreateSessionToken, sessionId, ...) - // *must* be called before GMPDecryptorCallback::SendMessage(sessionId, ...) - // will work. - // - // If generating the request fails, reject aPromiseId by calling - // GMPDecryptorCallback::RejectPromise(). - virtual void CreateSession(uint32_t aCreateSessionToken, - uint32_t aPromiseId, - const char* aInitDataType, - uint32_t aInitDataTypeSize, - const uint8_t* aInitData, - uint32_t aInitDataSize, - GMPSessionType aSessionType) = 0; - - // Loads a previously loaded persistent session. - // - // This corresponds to a MediaKeySession.load() call in JS. - // - // The GMPDecryptor must do the following, in order, upon this method - // being called: - // - // 1. Send any messages to JS/EME, or read from storage, whatever is - // required to load the session, and then - // 2. if there is no session with the given sessionId loadable, call - // ResolveLoadSessionPromise(aPromiseId, false), otherwise - // 2. mark the session's keys as usable, and then - // 3. update the session's expiration, and then - // 4. call GMPDecryptorCallback::ResolveLoadSessionPromise(aPromiseId, true). - // - // If loading the session fails due to error, reject aPromiseId by calling - // GMPDecryptorCallback::RejectPromise(). - virtual void LoadSession(uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength) = 0; - - // Updates the session with |aResponse|. - // This corresponds to a MediaKeySession.update() call in JS. - virtual void UpdateSession(uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength, - const uint8_t* aResponse, - uint32_t aResponseSize) = 0; - - // Releases the resources (keys) for the specified session. - // This corresponds to a MediaKeySession.close() call in JS. - virtual void CloseSession(uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength) = 0; - - // Removes the resources (keys) for the specified session. - // This corresponds to a MediaKeySession.remove() call in JS. - virtual void RemoveSession(uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength) = 0; - - // Resolve/reject promise on completion. - // This corresponds to a MediaKeySession.setServerCertificate() call in JS. - virtual void SetServerCertificate(uint32_t aPromiseId, - const uint8_t* aServerCert, - uint32_t aServerCertSize) = 0; - - // Asynchronously decrypts aBuffer in place. When the decryption is - // complete, GMPDecryptor should write the decrypted data back into the - // same GMPBuffer object and return it to Gecko by calling Decrypted(), - // with the GMPNoErr successcode. If decryption fails, call Decrypted() - // with a failure code, and an error event will fire on the media element. - // Note: When Decrypted() is called and aBuffer is passed back, aBuffer - // is deleted. Don't forget to call Decrypted(), as otherwise aBuffer's - // memory will leak! - virtual void Decrypt(GMPBuffer* aBuffer, - GMPEncryptedBufferMetadata* aMetadata) = 0; - - // Called when the decryption operations are complete. - // Do not call the GMPDecryptorCallback's functions after this is called. - virtual void DecryptingComplete() = 0; - - virtual ~GMPDecryptor7() {} -}; - -#endif // GMP_DECRYPTION_h_ diff --git a/dom/media/gmp/gmp-api/gmp-entrypoints.h b/dom/media/gmp/gmp-api/gmp-entrypoints.h deleted file mode 100644 index 214c9dbfc..000000000 --- a/dom/media/gmp/gmp-api/gmp-entrypoints.h +++ /dev/null @@ -1,75 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* Copyright (c) 2011, The WebRTC project authors. All rights reserved. - * Copyright (c) 2014, Mozilla - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - ** Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - ** Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - ** Neither the name of Google nor the names of its contributors may - * be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef GMP_ENTRYPOINTS_h_ -#define GMP_ENTRYPOINTS_h_ - -#include "gmp-errors.h" -#include "gmp-platform.h" - -/* C functions exposed by Gecko Media Plugin shared library. */ - -// GMPInit -// - Called once after plugin library is loaded, before GMPGetAPI or GMPShutdown are called. -// - Called on main thread. -// - 'aPlatformAPI' is a structure containing platform-provided APIs. It is valid until -// 'GMPShutdown' is called. Owned and must be deleted by plugin. -typedef GMPErr (*GMPInitFunc)(const GMPPlatformAPI* aPlatformAPI); - -// GMPGetAPI -// - Called when host wants to use an API. -// - Called on main thread. -// - 'aAPIName' is a string indicating the API being requested. This should -// match one of the GMP_API_* macros. Subsequent iterations of the GMP_APIs -// may change the value of the GMP_API_* macros when ABI changes occur. So -// make sure you compare aAPIName against the corresponding GMP_API_* macro! -// - 'aHostAPI' is the host API which is specific to the API being requested -// from the plugin. It is valid so long as the API object requested from the -// plugin is valid. It is owned by the host, plugin should not attempt to delete. -// May be null. -// - 'aPluginAPI' is for returning the requested API. Destruction of the requsted -// API object is defined by the API. -typedef GMPErr (*GMPGetAPIFunc)(const char* aAPIName, void* aHostAPI, void** aPluginAPI); - -// GMPShutdown -// - Called once before exiting process (unloading library). -// - Called on main thread. -typedef void (*GMPShutdownFunc)(void); - -// GMPSetNodeId -// - Optional, not required to be implemented. Only useful for EME plugins. -// - Called after GMPInit to set the device-bound origin-specific node id -// that this GMP instance is running under. -typedef void (*GMPSetNodeIdFunc)(const char* aNodeId, uint32_t aLength); - -#endif // GMP_ENTRYPOINTS_h_ diff --git a/dom/media/gmp/gmp-api/gmp-errors.h b/dom/media/gmp/gmp-api/gmp-errors.h deleted file mode 100644 index 7f20e2a79..000000000 --- a/dom/media/gmp/gmp-api/gmp-errors.h +++ /dev/null @@ -1,58 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* Copyright (c) 2014, Mozilla - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - ** Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - ** Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - ** Neither the name of Google nor the names of its contributors may - * be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef GMP_ERRORS_h_ -#define GMP_ERRORS_h_ - -typedef enum { - GMPNoErr = 0, - GMPGenericErr = 1, - GMPClosedErr = 2, - GMPAllocErr = 3, - GMPNotImplementedErr = 4, - GMPRecordInUse = 5, - GMPQuotaExceededErr = 6, - GMPDecodeErr = 7, - GMPEncodeErr = 8, - GMPNoKeyErr = 9, - GMPCryptoErr = 10, - GMPEndOfEnumeration = 11, - GMPInvalidArgErr = 12, - GMPAbortedErr = 13, - GMPRecordCorrupted = 14, - GMPLastErr // Placeholder, must be last. This enum's values must remain consecutive! -} GMPErr; - -#define GMP_SUCCEEDED(x) ((x) == GMPNoErr) -#define GMP_FAILED(x) ((x) != GMPNoErr) - -#endif // GMP_ERRORS_h_ diff --git a/dom/media/gmp/gmp-api/gmp-platform.h b/dom/media/gmp/gmp-api/gmp-platform.h deleted file mode 100644 index f915050b3..000000000 --- a/dom/media/gmp/gmp-api/gmp-platform.h +++ /dev/null @@ -1,118 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* Copyright (c) 2014, Mozilla - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - ** Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - ** Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - ** Neither the name of Google nor the names of its contributors may - * be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef GMP_PLATFORM_h_ -#define GMP_PLATFORM_h_ - -#include "gmp-errors.h" -#include "gmp-storage.h" -#include <stdint.h> - -/* Platform helper API. */ - -class GMPTask { -public: - virtual void Destroy() = 0; // Deletes object. - virtual ~GMPTask() {} - virtual void Run() = 0; -}; - -class GMPThread { -public: - virtual ~GMPThread() {} - virtual void Post(GMPTask* aTask) = 0; - virtual void Join() = 0; // Deletes object after join completes. -}; - -// A re-entrant monitor; can be locked from the same thread multiple times. -// Must be unlocked the same number of times it's locked. -class GMPMutex { -public: - virtual ~GMPMutex() {} - virtual void Acquire() = 0; - virtual void Release() = 0; - virtual void Destroy() = 0; // Deletes object. -}; - -// Time is defined as the number of milliseconds since the -// Epoch (00:00:00 UTC, January 1, 1970). -typedef int64_t GMPTimestamp; - -typedef GMPErr (*GMPCreateThreadPtr)(GMPThread** aThread); -typedef GMPErr (*GMPRunOnMainThreadPtr)(GMPTask* aTask); -typedef GMPErr (*GMPSyncRunOnMainThreadPtr)(GMPTask* aTask); -typedef GMPErr (*GMPCreateMutexPtr)(GMPMutex** aMutex); - -// Call on main thread only. -typedef GMPErr (*GMPCreateRecordPtr)(const char* aRecordName, - uint32_t aRecordNameSize, - GMPRecord** aOutRecord, - GMPRecordClient* aClient); - -// Call on main thread only. -typedef GMPErr (*GMPSetTimerOnMainThreadPtr)(GMPTask* aTask, int64_t aTimeoutMS); -typedef GMPErr (*GMPGetCurrentTimePtr)(GMPTimestamp* aOutTime); - -typedef void (*RecvGMPRecordIteratorPtr)(GMPRecordIterator* aRecordIterator, - void* aUserArg, - GMPErr aStatus); - -// Creates a GMPCreateRecordIterator to enumerate the records in storage. -// When the iterator is ready, the function at aRecvIteratorFunc -// is called with the GMPRecordIterator as an argument. If the operation -// fails, RecvGMPRecordIteratorPtr is called with a failure aStatus code. -// The list that the iterator is covering is fixed when -// GMPCreateRecordIterator is called, it is *not* updated when changes are -// made to storage. -// Iterator begins pointing at first record. -// aUserArg is passed to the aRecvIteratorFunc upon completion. -typedef GMPErr (*GMPCreateRecordIteratorPtr)(RecvGMPRecordIteratorPtr aRecvIteratorFunc, - void* aUserArg); - -struct GMPPlatformAPI { - // Increment the version when things change. Can only add to the struct, - // do not change what already exists. Pointers to functions may be NULL - // when passed to plugins, but beware backwards compat implications of - // doing that. - uint16_t version; // Currently version 0 - - GMPCreateThreadPtr createthread; - GMPRunOnMainThreadPtr runonmainthread; - GMPSyncRunOnMainThreadPtr syncrunonmainthread; - GMPCreateMutexPtr createmutex; - GMPCreateRecordPtr createrecord; - GMPSetTimerOnMainThreadPtr settimer; - GMPGetCurrentTimePtr getcurrenttime; - GMPCreateRecordIteratorPtr getrecordenumerator; -}; - -#endif // GMP_PLATFORM_h_ diff --git a/dom/media/gmp/gmp-api/gmp-storage.h b/dom/media/gmp/gmp-api/gmp-storage.h deleted file mode 100644 index 43ad12b01..000000000 --- a/dom/media/gmp/gmp-api/gmp-storage.h +++ /dev/null @@ -1,141 +0,0 @@ -/* -* Copyright 2013, Mozilla Foundation and contributors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -#ifndef GMP_STORAGE_h_ -#define GMP_STORAGE_h_ - -#include "gmp-errors.h" -#include <stdint.h> - -// Maximum size of a record, in bytes; 10 megabytes. -#define GMP_MAX_RECORD_SIZE (10 * 1024 * 1024) - -// Maximum length of a record name in bytes. -#define GMP_MAX_RECORD_NAME_SIZE 2000 - -// Provides basic per-origin storage for CDMs. GMPRecord instances can be -// retrieved by calling GMPPlatformAPI->openstorage. Multiple GMPRecords -// with different names can be open at once, but a single record can only -// be opened by one client at a time. This interface is asynchronous, with -// results being returned via callbacks to the GMPRecordClient pointer -// provided to the GMPPlatformAPI->openstorage call, on the main thread. -// -// Lifecycle: Once opened, the GMPRecord object remains allocated until -// GMPRecord::Close() is called. If any GMPRecord function, either -// synchronously or asynchronously through a GMPRecordClient callback, -// returns an error, the GMP is responsible for calling Close() on the -// GMPRecord to delete the GMPRecord object's memory. If your GMP does not -// call Close(), the GMPRecord's memory will leak. -class GMPRecord { -public: - - // Opens the record. Calls OpenComplete() once the record is open. - // Note: Only work when GMP is loading content from a webserver. - // Does not work for web pages on loaded from disk. - // Note: OpenComplete() is only called if this returns GMPNoErr. - virtual GMPErr Open() = 0; - - // Reads the entire contents of the record, and calls - // GMPRecordClient::ReadComplete() once the operation is complete. - // Note: ReadComplete() is only called if this returns GMPNoErr. - virtual GMPErr Read() = 0; - - // Writes aDataSize bytes of aData into the record, overwriting the - // contents of the record, truncating it to aDataSize length. - // Overwriting with 0 bytes "deletes" the record. - // Note: WriteComplete is only called if this returns GMPNoErr. - virtual GMPErr Write(const uint8_t* aData, uint32_t aDataSize) = 0; - - // Closes a record, deletes the GMPRecord object. The GMPRecord object - // must not be used after this is called, request a new one with - // GMPPlatformAPI->openstorage to re-open this record. Cancels all - // callbacks. - virtual GMPErr Close() = 0; - - virtual ~GMPRecord() {} -}; - -// Callback object that receives the results of GMPRecord calls. Callbacks -// run asynchronously to the GMPRecord call, on the main thread. -class GMPRecordClient { - public: - - // Response to a GMPRecord::Open() call with the open |status|. - // aStatus values: - // - GMPNoErr - Record opened successfully. Record may be empty. - // - GMPRecordInUse - This record is in use by another client. - // - GMPGenericErr - Unspecified error. - // If aStatus is not GMPNoErr, the GMPRecord is unusable, and you must - // call Close() on the GMPRecord to dispose of it. - virtual void OpenComplete(GMPErr aStatus) = 0; - - // Response to a GMPRecord::Read() call, where aData is the record contents, - // of length aDataSize. - // aData is only valid for the duration of the call to ReadComplete. - // Copy it if you want to hang onto it! - // aStatus values: - // - GMPNoErr - Record contents read successfully, aDataSize 0 means record - // is empty. - // - GMPRecordInUse - There are other operations or clients in use on - // this record. - // - GMPGenericErr - Unspecified error. - // If aStatus is not GMPNoErr, the GMPRecord is unusable, and you must - // call Close() on the GMPRecord to dispose of it. - virtual void ReadComplete(GMPErr aStatus, - const uint8_t* aData, - uint32_t aDataSize) = 0; - - // Response to a GMPRecord::Write() call. - // - GMPNoErr - File contents written successfully. - // - GMPRecordInUse - There are other operations or clients in use on - // this record. - // - GMPGenericErr - Unspecified error. - // If aStatus is not GMPNoErr, the GMPRecord is unusable, and you must - // call Close() on the GMPRecord to dispose of it. - virtual void WriteComplete(GMPErr aStatus) = 0; - - virtual ~GMPRecordClient() {} -}; - -// Iterates over the records that are available. Note: this list maintains -// a snapshot of the records that were present when the iterator was created. -// Create by calling the GMPCreateRecordIteratorPtr function on the -// GMPPlatformAPI struct. -// Iteration is in alphabetical order. -class GMPRecordIterator { -public: - // Retrieve the name for the current record. - // aOutName is null terminated at character at index (*aOutNameLength). - // Returns GMPNoErr if successful, or GMPEndOfEnumeration if iteration has - // reached the end. - virtual GMPErr GetName(const char ** aOutName, uint32_t * aOutNameLength) = 0; - - // Advance iteration to the next record. - // Returns GMPNoErr if successful, or GMPEndOfEnumeration if iteration has - // reached the end. - virtual GMPErr NextRecord() = 0; - - // Signals to the GMP host that the GMP is finished with the - // GMPRecordIterator. GMPs must call this to release memory held by - // the GMPRecordIterator. Do not access the GMPRecordIterator pointer - // after calling this! - // Memory retrieved by GetName is *not* valid after calling Close()! - virtual void Close() = 0; - - virtual ~GMPRecordIterator() {} -}; - -#endif // GMP_STORAGE_h_ diff --git a/dom/media/gmp/gmp-api/gmp-video-codec.h b/dom/media/gmp/gmp-api/gmp-video-codec.h deleted file mode 100644 index e068ab43d..000000000 --- a/dom/media/gmp/gmp-api/gmp-video-codec.h +++ /dev/null @@ -1,226 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* Copyright (c) 2011, The WebRTC project authors. All rights reserved. - * Copyright (c) 2014, Mozilla - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - ** Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - ** Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - ** Neither the name of Google nor the names of its contributors may - * be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef GMP_VIDEO_CODEC_h_ -#define GMP_VIDEO_CODEC_h_ - -#include <stdint.h> -#include <stddef.h> - -enum { kGMPPayloadNameSize = 32}; -enum { kGMPMaxSimulcastStreams = 4}; - -enum GMPVideoCodecComplexity -{ - kGMPComplexityNormal = 0, - kGMPComplexityHigh = 1, - kGMPComplexityHigher = 2, - kGMPComplexityMax = 3, - kGMPComplexityInvalid // Should always be last -}; - -enum GMPVP8ResilienceMode { - kResilienceOff, // The stream produced by the encoder requires a - // recovery frame (typically a key frame) to be - // decodable after a packet loss. - kResilientStream, // A stream produced by the encoder is resilient to - // packet losses, but packets within a frame subsequent - // to a loss can't be decoded. - kResilientFrames, // Same as kResilientStream but with added resilience - // within a frame. - kResilienceInvalid // Should always be last. -}; - -// VP8 specific -struct GMPVideoCodecVP8 -{ - bool mPictureLossIndicationOn; - bool mFeedbackModeOn; - GMPVideoCodecComplexity mComplexity; - GMPVP8ResilienceMode mResilience; - uint32_t mNumberOfTemporalLayers; - bool mDenoisingOn; - bool mErrorConcealmentOn; - bool mAutomaticResizeOn; -}; - -// H264 specific - -// Needs to match a binary spec for this structure. -// Note: the mSPS at the end of this structure is variable length. -struct GMPVideoCodecH264AVCC -{ - uint8_t mVersion; // == 0x01 - uint8_t mProfile; // these 3 are profile_level_id - uint8_t mConstraints; - uint8_t mLevel; - uint8_t mLengthSizeMinusOne; // lower 2 bits (== GMPBufferType-1). Top 6 reserved (1's) - - // SPS/PPS will not generally be present for interactive use unless SDP - // parameter-sets are used. - uint8_t mNumSPS; // lower 5 bits; top 5 reserved (1's) - - /*** uint8_t mSPS[]; (Not defined due to compiler warnings and warnings-as-errors ...) **/ - // Following mNumSPS is a variable number of bytes, which is the SPS and PPS. - // Each SPS == 16 bit size, ("N"), then "N" bytes, - // then uint8_t mNumPPS, then each PPS == 16 bit size ("N"), then "N" bytes. -}; - -// Codec specific data for H.264 decoding/encoding. -// Cast the "aCodecSpecific" parameter of GMPVideoDecoder::InitDecode() and -// GMPVideoEncoder::InitEncode() to this structure. -struct GMPVideoCodecH264 -{ - uint8_t mPacketizationMode; // 0 or 1 - struct GMPVideoCodecH264AVCC mAVCC; // holds a variable-sized struct GMPVideoCodecH264AVCC mAVCC; -}; - -enum GMPVideoCodecType -{ - kGMPVideoCodecVP8, - - // Encoded frames are in AVCC format; NAL length field of 4 bytes, followed - // by frame data. May be multiple NALUs per sample. Codec specific extra data - // is the AVCC extra data (in AVCC format). - kGMPVideoCodecH264, - kGMPVideoCodecVP9, - kGMPVideoCodecInvalid // Should always be last. -}; - -// Simulcast is when the same stream is encoded multiple times with different -// settings such as resolution. -struct GMPSimulcastStream -{ - uint32_t mWidth; - uint32_t mHeight; - uint32_t mNumberOfTemporalLayers; - uint32_t mMaxBitrate; // kilobits/sec. - uint32_t mTargetBitrate; // kilobits/sec. - uint32_t mMinBitrate; // kilobits/sec. - uint32_t mQPMax; // minimum quality -}; - -enum GMPVideoCodecMode { - kGMPRealtimeVideo, - kGMPScreensharing, - kGMPStreamingVideo, - kGMPCodecModeInvalid // Should always be last. -}; - -enum GMPApiVersion { - kGMPVersion32 = 1, // leveraging that V32 had mCodecType first, and only supported H264 - kGMPVersion33 = 33, -}; - -struct GMPVideoCodec -{ - uint32_t mGMPApiVersion; - - GMPVideoCodecType mCodecType; - char mPLName[kGMPPayloadNameSize]; // Must be NULL-terminated! - uint32_t mPLType; - - uint32_t mWidth; - uint32_t mHeight; - - uint32_t mStartBitrate; // kilobits/sec. - uint32_t mMaxBitrate; // kilobits/sec. - uint32_t mMinBitrate; // kilobits/sec. - uint32_t mMaxFramerate; - - bool mFrameDroppingOn; - int32_t mKeyFrameInterval; - - uint32_t mQPMax; - uint32_t mNumberOfSimulcastStreams; - GMPSimulcastStream mSimulcastStream[kGMPMaxSimulcastStreams]; - - GMPVideoCodecMode mMode; -}; - -// Either single encoded unit, or multiple units separated by 8/16/24/32 -// bit lengths, all with the same timestamp. Note there is no final 0-length -// entry; one should check the overall end-of-buffer against where the next -// length would be. -enum GMPBufferType { - GMP_BufferSingle = 0, - GMP_BufferLength8, - GMP_BufferLength16, - GMP_BufferLength24, - GMP_BufferLength32, - GMP_BufferInvalid, -}; - -struct GMPCodecSpecificInfoGeneric { - uint8_t mSimulcastIdx; -}; - -struct GMPCodecSpecificInfoH264 { - uint8_t mSimulcastIdx; -}; - -// Note: if any pointers are added to this struct, it must be fitted -// with a copy-constructor. See below. -struct GMPCodecSpecificInfoVP8 -{ - bool mHasReceivedSLI; - uint8_t mPictureIdSLI; - bool mHasReceivedRPSI; - uint64_t mPictureIdRPSI; - int16_t mPictureId; // negative value to skip pictureId - bool mNonReference; - uint8_t mSimulcastIdx; - uint8_t mTemporalIdx; - bool mLayerSync; - int32_t mTL0PicIdx; // negative value to skip tl0PicIdx - int8_t mKeyIdx; // negative value to skip keyIdx -}; - -union GMPCodecSpecificInfoUnion -{ - GMPCodecSpecificInfoGeneric mGeneric; - GMPCodecSpecificInfoVP8 mVP8; - GMPCodecSpecificInfoH264 mH264; -}; - -// Note: if any pointers are added to this struct or its sub-structs, it -// must be fitted with a copy-constructor. This is because it is copied -// in the copy-constructor of VCMEncodedFrame. -struct GMPCodecSpecificInfo -{ - GMPVideoCodecType mCodecType; - GMPBufferType mBufferType; - GMPCodecSpecificInfoUnion mCodecSpecific; -}; - -#endif // GMP_VIDEO_CODEC_h_ diff --git a/dom/media/gmp/gmp-api/gmp-video-decode.h b/dom/media/gmp/gmp-api/gmp-video-decode.h deleted file mode 100644 index e07a7525e..000000000 --- a/dom/media/gmp/gmp-api/gmp-video-decode.h +++ /dev/null @@ -1,127 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* Copyright (c) 2011, The WebRTC project authors. All rights reserved. - * Copyright (c) 2014, Mozilla - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - ** Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - ** Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - ** Neither the name of Google nor the names of its contributors may - * be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef GMP_VIDEO_DECODE_h_ -#define GMP_VIDEO_DECODE_h_ - -#include "gmp-errors.h" -#include "gmp-video-frame-i420.h" -#include "gmp-video-frame-encoded.h" -#include "gmp-video-codec.h" -#include <stdint.h> - -// ALL METHODS MUST BE CALLED ON THE MAIN THREAD -class GMPVideoDecoderCallback -{ -public: - virtual ~GMPVideoDecoderCallback() {} - - virtual void Decoded(GMPVideoi420Frame* aDecodedFrame) = 0; - - virtual void ReceivedDecodedReferenceFrame(const uint64_t aPictureId) = 0; - - virtual void ReceivedDecodedFrame(const uint64_t aPictureId) = 0; - - virtual void InputDataExhausted() = 0; - - virtual void DrainComplete() = 0; - - virtual void ResetComplete() = 0; - - // Called when the decoder encounters a catestrophic error and cannot - // continue. Gecko will not send any more input for decoding. - virtual void Error(GMPErr aError) = 0; -}; - -#define GMP_API_VIDEO_DECODER "decode-video" - -// Video decoding for a single stream. A GMP may be asked to create multiple -// decoders concurrently. -// -// API name macro: GMP_API_VIDEO_DECODER -// Host API: GMPVideoHost -// -// ALL METHODS MUST BE CALLED ON THE MAIN THREAD -class GMPVideoDecoder -{ -public: - virtual ~GMPVideoDecoder() {} - - // - aCodecSettings: Details of decoder to create. - // - aCodecSpecific: codec specific data, cast to a GMPVideoCodecXXX struct - // to get codec specific config data. - // - aCodecSpecificLength: number of bytes in aCodecSpecific. - // - aCallback: Subclass should retain reference to it until DecodingComplete - // is called. Do not attempt to delete it, host retains ownership. - // aCoreCount: number of CPU cores. - virtual void InitDecode(const GMPVideoCodec& aCodecSettings, - const uint8_t* aCodecSpecific, - uint32_t aCodecSpecificLength, - GMPVideoDecoderCallback* aCallback, - int32_t aCoreCount) = 0; - - // Decode encoded frame (as a part of a video stream). The decoded frame - // will be returned to the user through the decode complete callback. - // - // - aInputFrame: Frame to decode. Call Destroy() on frame when it's decoded. - // - aMissingFrames: True if one or more frames have been lost since the - // previous decode call. - // - aCodecSpecificInfo : codec specific data, pointer to a - // GMPCodecSpecificInfo structure appropriate for - // this codec type. - // - aCodecSpecificInfoLength : number of bytes in aCodecSpecificInfo - // - renderTimeMs : System time to render in milliseconds. Only used by - // decoders with internal rendering. - virtual void Decode(GMPVideoEncodedFrame* aInputFrame, - bool aMissingFrames, - const uint8_t* aCodecSpecificInfo, - uint32_t aCodecSpecificInfoLength, - int64_t aRenderTimeMs = -1) = 0; - - // Reset decoder state and prepare for a new call to Decode(...). - // Flushes the decoder pipeline. - // The decoder should enqueue a task to run ResetComplete() on the main - // thread once the reset has finished. - virtual void Reset() = 0; - - // Output decoded frames for any data in the pipeline, regardless of ordering. - // All remaining decoded frames should be immediately returned via callback. - // The decoder should enqueue a task to run DrainComplete() on the main - // thread once the reset has finished. - virtual void Drain() = 0; - - // May free decoder memory. - virtual void DecodingComplete() = 0; -}; - -#endif // GMP_VIDEO_DECODE_h_ diff --git a/dom/media/gmp/gmp-api/gmp-video-encode.h b/dom/media/gmp/gmp-api/gmp-video-encode.h deleted file mode 100644 index 5c9cde39c..000000000 --- a/dom/media/gmp/gmp-api/gmp-video-encode.h +++ /dev/null @@ -1,135 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* Copyright (c) 2011, The WebRTC project authors. All rights reserved. - * Copyright (c) 2014, Mozilla - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - ** Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - ** Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - ** Neither the name of Google nor the names of its contributors may - * be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef GMP_VIDEO_ENCODE_h_ -#define GMP_VIDEO_ENCODE_h_ - -#include <vector> -#include <stdint.h> - -#include "gmp-errors.h" -#include "gmp-video-frame-i420.h" -#include "gmp-video-frame-encoded.h" -#include "gmp-video-codec.h" - -// ALL METHODS MUST BE CALLED ON THE MAIN THREAD -class GMPVideoEncoderCallback -{ -public: - virtual ~GMPVideoEncoderCallback() {} - - virtual void Encoded(GMPVideoEncodedFrame* aEncodedFrame, - const uint8_t* aCodecSpecificInfo, - uint32_t aCodecSpecificInfoLength) = 0; - - // Called when the encoder encounters a catestrophic error and cannot - // continue. Gecko will not send any more input for encoding. - virtual void Error(GMPErr aError) = 0; -}; - -#define GMP_API_VIDEO_ENCODER "encode-video" - -// Video encoding for a single stream. A GMP may be asked to create multiple -// encoders concurrently. -// -// API name macro: GMP_API_VIDEO_ENCODER -// Host API: GMPVideoHost -// -// ALL METHODS MUST BE CALLED ON THE MAIN THREAD -class GMPVideoEncoder -{ -public: - virtual ~GMPVideoEncoder() {} - - // Initialize the encoder with the information from the VideoCodec. - // - // Input: - // - codecSettings : Codec settings - // - aCodecSpecific : codec specific data, pointer to a - // GMPCodecSpecific structure appropriate for - // this codec type. - // - aCodecSpecificLength : number of bytes in aCodecSpecific - // - aCallback: Subclass should retain reference to it until EncodingComplete - // is called. Do not attempt to delete it, host retains ownership. - // - aNnumberOfCores : Number of cores available for the encoder - // - aMaxPayloadSize : The maximum size each payload is allowed - // to have. Usually MTU - overhead. - virtual void InitEncode(const GMPVideoCodec& aCodecSettings, - const uint8_t* aCodecSpecific, - uint32_t aCodecSpecificLength, - GMPVideoEncoderCallback* aCallback, - int32_t aNumberOfCores, - uint32_t aMaxPayloadSize) = 0; - - // Encode an I420 frame (as a part of a video stream). The encoded frame - // will be returned to the user through the encode complete callback. - // - // Input: - // - aInputFrame : Frame to be encoded - // - aCodecSpecificInfo : codec specific data, pointer to a - // GMPCodecSpecificInfo structure appropriate for - // this codec type. - // - aCodecSpecificInfoLength : number of bytes in aCodecSpecific - // - aFrameTypes : The frame type to encode - // - aFrameTypesLength : The number of elements in aFrameTypes array. - virtual void Encode(GMPVideoi420Frame* aInputFrame, - const uint8_t* aCodecSpecificInfo, - uint32_t aCodecSpecificInfoLength, - const GMPVideoFrameType* aFrameTypes, - uint32_t aFrameTypesLength) = 0; - - // Inform the encoder about the packet loss and round trip time on the - // network used to decide the best pattern and signaling. - // - // - packetLoss : Fraction lost (loss rate in percent = - // 100 * packetLoss / 255) - // - rtt : Round-trip time in milliseconds - virtual void SetChannelParameters(uint32_t aPacketLoss, uint32_t aRTT) = 0; - - // Inform the encoder about the new target bit rate. - // - // - newBitRate : New target bit rate - // - frameRate : The target frame rate - virtual void SetRates(uint32_t aNewBitRate, uint32_t aFrameRate) = 0; - - // Use this function to enable or disable periodic key frames. Can be useful for codecs - // which have other ways of stopping error propagation. - // - // - enable : Enable or disable periodic key frames - virtual void SetPeriodicKeyFrames(bool aEnable) = 0; - - // May free Encoder memory. - virtual void EncodingComplete() = 0; -}; - -#endif // GMP_VIDEO_ENCODE_h_ diff --git a/dom/media/gmp/gmp-api/gmp-video-frame-encoded.h b/dom/media/gmp/gmp-api/gmp-video-frame-encoded.h deleted file mode 100644 index 76af7349f..000000000 --- a/dom/media/gmp/gmp-api/gmp-video-frame-encoded.h +++ /dev/null @@ -1,99 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* Copyright (c) 2011, The WebRTC project authors. All rights reserved. - * Copyright (c) 2014, Mozilla - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - ** Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - ** Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - ** Neither the name of Google nor the names of its contributors may - * be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef GMP_VIDEO_FRAME_ENCODED_h_ -#define GMP_VIDEO_FRAME_ENCODED_h_ - -#include <stdint.h> -#include "gmp-decryption.h" -#include "gmp-video-frame.h" -#include "gmp-video-codec.h" - -enum GMPVideoFrameType -{ - kGMPKeyFrame = 0, - kGMPDeltaFrame = 1, - kGMPGoldenFrame = 2, - kGMPAltRefFrame = 3, - kGMPSkipFrame = 4, - kGMPVideoFrameInvalid = 5 // Must always be last. -}; - -// The implementation backing this interface uses shared memory for the -// buffer(s). This means it can only be used by the "owning" process. -// At first the process which created the object owns it. When the object -// is passed to an interface the creator loses ownership and must Destroy() -// the object. Further attempts to use it may fail due to not being able to -// access the underlying buffer(s). -// -// Methods that create or destroy shared memory must be called on the main -// thread. They are marked below. -class GMPVideoEncodedFrame : public GMPVideoFrame -{ -public: - // MAIN THREAD ONLY - virtual GMPErr CreateEmptyFrame(uint32_t aSize) = 0; - // MAIN THREAD ONLY - virtual GMPErr CopyFrame(const GMPVideoEncodedFrame& aVideoFrame) = 0; - virtual void SetEncodedWidth(uint32_t aEncodedWidth) = 0; - virtual uint32_t EncodedWidth() = 0; - virtual void SetEncodedHeight(uint32_t aEncodedHeight) = 0; - virtual uint32_t EncodedHeight() = 0; - // Microseconds - virtual void SetTimeStamp(uint64_t aTimeStamp) = 0; - virtual uint64_t TimeStamp() = 0; - // Set frame duration (microseconds) - // NOTE: next-frame's Timestamp() != this-frame's TimeStamp()+Duration() - // depending on rounding to avoid having to track roundoff errors - // and dropped/missing frames(!) (which may leave a large gap) - virtual void SetDuration(uint64_t aDuration) = 0; - virtual uint64_t Duration() const = 0; - virtual void SetFrameType(GMPVideoFrameType aFrameType) = 0; - virtual GMPVideoFrameType FrameType() = 0; - virtual void SetAllocatedSize(uint32_t aNewSize) = 0; - virtual uint32_t AllocatedSize() = 0; - virtual void SetSize(uint32_t aSize) = 0; - virtual uint32_t Size() = 0; - virtual void SetCompleteFrame(bool aCompleteFrame) = 0; - virtual bool CompleteFrame() = 0; - virtual const uint8_t* Buffer() const = 0; - virtual uint8_t* Buffer() = 0; - virtual GMPBufferType BufferType() const = 0; - virtual void SetBufferType(GMPBufferType aBufferType) = 0; - - // Get metadata describing how this frame is encrypted, or nullptr if the - // frame is not encrypted. - virtual const GMPEncryptedBufferMetadata* GetDecryptionData() const = 0; -}; - -#endif // GMP_VIDEO_FRAME_ENCODED_h_ diff --git a/dom/media/gmp/gmp-api/gmp-video-frame-i420.h b/dom/media/gmp/gmp-api/gmp-video-frame-i420.h deleted file mode 100644 index 14c2c33cd..000000000 --- a/dom/media/gmp/gmp-api/gmp-video-frame-i420.h +++ /dev/null @@ -1,132 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* Copyright (c) 2011, The WebRTC project authors. All rights reserved. - * Copyright (c) 2014, Mozilla - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - ** Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - ** Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - ** Neither the name of Google nor the names of its contributors may - * be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef GMP_VIDEO_FRAME_I420_h_ -#define GMP_VIDEO_FRAME_I420_h_ - -#include "gmp-errors.h" -#include "gmp-video-frame.h" -#include "gmp-video-plane.h" - -#include <stdint.h> - -enum GMPPlaneType { - kGMPYPlane = 0, - kGMPUPlane = 1, - kGMPVPlane = 2, - kGMPNumOfPlanes = 3 -}; - -// The implementation backing this interface uses shared memory for the -// buffer(s). This means it can only be used by the "owning" process. -// At first the process which created the object owns it. When the object -// is passed to an interface the creator loses ownership and must Destroy() -// the object. Further attempts to use it may fail due to not being able to -// access the underlying buffer(s). -// -// Methods that create or destroy shared memory must be called on the main -// thread. They are marked below. -class GMPVideoi420Frame : public GMPVideoFrame { -public: - // MAIN THREAD ONLY - // CreateEmptyFrame: Sets frame dimensions and allocates buffers based - // on set dimensions - height and plane stride. - // If required size is bigger than the allocated one, new buffers of adequate - // size will be allocated. - virtual GMPErr CreateEmptyFrame(int32_t aWidth, int32_t aHeight, - int32_t aStride_y, int32_t aStride_u, int32_t aStride_v) = 0; - - // MAIN THREAD ONLY - // CreateFrame: Sets the frame's members and buffers. If required size is - // bigger than allocated one, new buffers of adequate size will be allocated. - virtual GMPErr CreateFrame(int32_t aSize_y, const uint8_t* aBuffer_y, - int32_t aSize_u, const uint8_t* aBuffer_u, - int32_t aSize_v, const uint8_t* aBuffer_v, - int32_t aWidth, int32_t aHeight, - int32_t aStride_y, int32_t aStride_u, int32_t aStride_v) = 0; - - // MAIN THREAD ONLY - // Copy frame: If required size is bigger than allocated one, new buffers of - // adequate size will be allocated. - virtual GMPErr CopyFrame(const GMPVideoi420Frame& aVideoFrame) = 0; - - // Swap Frame. - virtual void SwapFrame(GMPVideoi420Frame* aVideoFrame) = 0; - - // Get pointer to buffer per plane. - virtual uint8_t* Buffer(GMPPlaneType aType) = 0; - - // Overloading with const. - virtual const uint8_t* Buffer(GMPPlaneType aType) const = 0; - - // Get allocated size per plane. - virtual int32_t AllocatedSize(GMPPlaneType aType) const = 0; - - // Get allocated stride per plane. - virtual int32_t Stride(GMPPlaneType aType) const = 0; - - // Set frame width. - virtual GMPErr SetWidth(int32_t aWidth) = 0; - - // Set frame height. - virtual GMPErr SetHeight(int32_t aHeight) = 0; - - // Get frame width. - virtual int32_t Width() const = 0; - - // Get frame height. - virtual int32_t Height() const = 0; - - // Set frame timestamp (microseconds) - virtual void SetTimestamp(uint64_t aTimestamp) = 0; - - // Get frame timestamp (microseconds) - virtual uint64_t Timestamp() const = 0; - - // Set frame duration (microseconds) - // NOTE: next-frame's Timestamp() != this-frame's TimeStamp()+Duration() - // depending on rounding to avoid having to track roundoff errors - // and dropped/missing frames(!) (which may leave a large gap) - virtual void SetDuration(uint64_t aDuration) = 0; - - // Get frame duration (microseconds) - virtual uint64_t Duration() const = 0; - - // Return true if underlying plane buffers are of zero size, false if not. - virtual bool IsZeroSize() const = 0; - - // Reset underlying plane buffers sizes to 0. This function doesn't clear memory. - virtual void ResetSize() = 0; -}; - -#endif // GMP_VIDEO_FRAME_I420_h_ diff --git a/dom/media/gmp/gmp-api/gmp-video-frame.h b/dom/media/gmp/gmp-api/gmp-video-frame.h deleted file mode 100644 index b3c9f53ab..000000000 --- a/dom/media/gmp/gmp-api/gmp-video-frame.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* Copyright (c) 2011, The WebRTC project authors. All rights reserved. - * Copyright (c) 2014, Mozilla - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - ** Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - ** Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - ** Neither the name of Google nor the names of its contributors may - * be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef GMP_VIDEO_FRAME_h_ -#define GMP_VIDEO_FRAME_h_ - -#include "gmp-video-plane.h" - -enum GMPVideoFrameFormat { - kGMPEncodedVideoFrame = 0, - kGMPI420VideoFrame = 1 -}; - -class GMPVideoFrame { -public: - virtual GMPVideoFrameFormat GetFrameFormat() = 0; - // MAIN THREAD ONLY IF OWNING PROCESS - virtual void Destroy() = 0; -}; - -#endif // GMP_VIDEO_FRAME_h_ diff --git a/dom/media/gmp/gmp-api/gmp-video-host.h b/dom/media/gmp/gmp-api/gmp-video-host.h deleted file mode 100644 index cf20e3f46..000000000 --- a/dom/media/gmp/gmp-api/gmp-video-host.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* Copyright (c) 2011, The WebRTC project authors. All rights reserved. - * Copyright (c) 2014, Mozilla - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - ** Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - ** Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - ** Neither the name of Google nor the names of its contributors may - * be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef GMP_VIDEO_HOST_h_ -#define GMP_VIDEO_HOST_h_ - -#include "gmp-errors.h" -#include "gmp-video-frame-i420.h" -#include "gmp-video-frame-encoded.h" -#include "gmp-video-codec.h" - -// This interface must be called on the main thread only. -class GMPVideoHost -{ -public: - // Construct various video API objects. Host does not retain reference, - // caller is owner and responsible for deleting. - // MAIN THREAD ONLY - virtual GMPErr CreateFrame(GMPVideoFrameFormat aFormat, GMPVideoFrame** aFrame) = 0; - virtual GMPErr CreatePlane(GMPPlane** aPlane) = 0; -}; - -#endif // GMP_VIDEO_HOST_h_ diff --git a/dom/media/gmp/gmp-api/gmp-video-plane.h b/dom/media/gmp/gmp-api/gmp-video-plane.h deleted file mode 100644 index 777cc2495..000000000 --- a/dom/media/gmp/gmp-api/gmp-video-plane.h +++ /dev/null @@ -1,94 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* Copyright (c) 2011, The WebRTC project authors. All rights reserved. - * Copyright (c) 2014, Mozilla - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - ** Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - ** Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - ** Neither the name of Google nor the names of its contributors may - * be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef GMP_VIDEO_PLANE_h_ -#define GMP_VIDEO_PLANE_h_ - -#include "gmp-errors.h" -#include <stdint.h> - -// The implementation backing this interface uses shared memory for the -// buffer(s). This means it can only be used by the "owning" process. -// At first the process which created the object owns it. When the object -// is passed to an interface the creator loses ownership and must Destroy() -// the object. Further attempts to use it may fail due to not being able to -// access the underlying buffer(s). -// -// Methods that create or destroy shared memory must be called on the main -// thread. They are marked below. -class GMPPlane { -public: - // MAIN THREAD ONLY - // CreateEmptyPlane - set allocated size, actual plane size and stride: - // If current size is smaller than current size, then a buffer of sufficient - // size will be allocated. - virtual GMPErr CreateEmptyPlane(int32_t aAllocatedSize, - int32_t aStride, - int32_t aPlaneSize) = 0; - - // MAIN THREAD ONLY - // Copy the entire plane data. - virtual GMPErr Copy(const GMPPlane& aPlane) = 0; - - // MAIN THREAD ONLY - // Copy buffer: If current size is smaller - // than current size, then a buffer of sufficient size will be allocated. - virtual GMPErr Copy(int32_t aSize, int32_t aStride, const uint8_t* aBuffer) = 0; - - // Swap plane data. - virtual void Swap(GMPPlane& aPlane) = 0; - - // Get allocated size. - virtual int32_t AllocatedSize() const = 0; - - // Set actual size. - virtual void ResetSize() = 0; - - // Return true is plane size is zero, false if not. - virtual bool IsZeroSize() const = 0; - - // Get stride value. - virtual int32_t Stride() const = 0; - - // Return data pointer. - virtual const uint8_t* Buffer() const = 0; - - // Overloading with non-const. - virtual uint8_t* Buffer() = 0; - - // MAIN THREAD ONLY IF OWNING PROCESS - // Call this when done with the object. This may delete it. - virtual void Destroy() = 0; -}; - -#endif // GMP_VIDEO_PLANE_h_ diff --git a/dom/media/gmp/moz.build b/dom/media/gmp/moz.build deleted file mode 100644 index 3ff90b2c8..000000000 --- a/dom/media/gmp/moz.build +++ /dev/null @@ -1,140 +0,0 @@ -# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- -# 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/. - -XPIDL_MODULE = 'content_geckomediaplugins' - -XPIDL_SOURCES += [ - 'mozIGeckoMediaPluginChromeService.idl', - 'mozIGeckoMediaPluginService.idl', -] - -EXPORTS += [ - 'gmp-api/gmp-async-shutdown.h', - 'gmp-api/gmp-audio-codec.h', - 'gmp-api/gmp-audio-decode.h', - 'gmp-api/gmp-audio-host.h', - 'gmp-api/gmp-audio-samples.h', - 'gmp-api/gmp-decryption.h', - 'gmp-api/gmp-entrypoints.h', - 'gmp-api/gmp-errors.h', - 'gmp-api/gmp-platform.h', - 'gmp-api/gmp-storage.h', - 'gmp-api/gmp-video-codec.h', - 'gmp-api/gmp-video-decode.h', - 'gmp-api/gmp-video-encode.h', - 'gmp-api/gmp-video-frame-encoded.h', - 'gmp-api/gmp-video-frame-i420.h', - 'gmp-api/gmp-video-frame.h', - 'gmp-api/gmp-video-host.h', - 'gmp-api/gmp-video-plane.h', - 'GMPAudioDecoderChild.h', - 'GMPAudioDecoderParent.h', - 'GMPAudioDecoderProxy.h', - 'GMPAudioHost.h', - 'GMPCallbackBase.h', - 'GMPChild.h', - 'GMPContentChild.h', - 'GMPContentParent.h', - 'GMPCrashHelperHolder.h', - 'GMPDecryptorChild.h', - 'GMPDecryptorParent.h', - 'GMPDecryptorProxy.h', - 'GMPEncryptedBufferDataImpl.h', - 'GMPLoader.h', - 'GMPMessageUtils.h', - 'GMPParent.h', - 'GMPPlatform.h', - 'GMPProcessChild.h', - 'GMPProcessParent.h', - 'GMPService.h', - 'GMPServiceChild.h', - 'GMPServiceParent.h', - 'GMPSharedMemManager.h', - 'GMPStorage.h', - 'GMPStorageChild.h', - 'GMPStorageParent.h', - 'GMPTimerChild.h', - 'GMPTimerParent.h', - 'GMPUtils.h', - 'GMPVideoDecoderChild.h', - 'GMPVideoDecoderParent.h', - 'GMPVideoDecoderProxy.h', - 'GMPVideoEncodedFrameImpl.h', - 'GMPVideoEncoderChild.h', - 'GMPVideoEncoderParent.h', - 'GMPVideoEncoderProxy.h', - 'GMPVideoHost.h', - 'GMPVideoi420FrameImpl.h', - 'GMPVideoPlaneImpl.h', -] - -SOURCES += [ - 'GMPAudioDecoderChild.cpp', - 'GMPAudioDecoderParent.cpp', - 'GMPAudioHost.cpp', - 'GMPChild.cpp', - 'GMPContentChild.cpp', - 'GMPContentParent.cpp', - 'GMPDecryptorChild.cpp', - 'GMPDecryptorParent.cpp', - 'GMPDiskStorage.cpp', - 'GMPEncryptedBufferDataImpl.cpp', - 'GMPMemoryStorage.cpp', - 'GMPParent.cpp', - 'GMPPlatform.cpp', - 'GMPProcessChild.cpp', - 'GMPProcessParent.cpp', - 'GMPService.cpp', - 'GMPServiceChild.cpp', - 'GMPServiceParent.cpp', - 'GMPSharedMemManager.cpp', - 'GMPStorageChild.cpp', - 'GMPStorageParent.cpp', - 'GMPTimerChild.cpp', - 'GMPTimerParent.cpp', - 'GMPUtils.cpp', - 'GMPVideoDecoderChild.cpp', - 'GMPVideoDecoderParent.cpp', - 'GMPVideoEncodedFrameImpl.cpp', - 'GMPVideoEncoderChild.cpp', - 'GMPVideoEncoderParent.cpp', - 'GMPVideoHost.cpp', - 'GMPVideoi420FrameImpl.cpp', - 'GMPVideoPlaneImpl.cpp', -] - -DIRS += ['rlz'] - -IPDL_SOURCES += [ - 'GMPTypes.ipdlh', - 'PGMP.ipdl', - 'PGMPAudioDecoder.ipdl', - 'PGMPContent.ipdl', - 'PGMPDecryptor.ipdl', - 'PGMPService.ipdl', - 'PGMPStorage.ipdl', - 'PGMPTimer.ipdl', - 'PGMPVideoDecoder.ipdl', - 'PGMPVideoEncoder.ipdl', -] - -if CONFIG['GKMEDIAS_SHARED_LIBRARY']: - NO_VISIBILITY_FLAGS = True - -# comment this out to use Unsafe Shmem for more performance -DEFINES['GMP_SAFE_SHMEM'] = True - -include('/ipc/chromium/chromium-config.mozbuild') - -FINAL_LIBRARY = 'xul' - -LOCAL_INCLUDES += [ - '/xpcom/base', - '/xpcom/build', - '/xpcom/threads', -] - -if CONFIG['GNU_CXX']: - CXXFLAGS += ['-Wno-error=shadow'] diff --git a/dom/media/gmp/mozIGeckoMediaPluginChromeService.idl b/dom/media/gmp/mozIGeckoMediaPluginChromeService.idl deleted file mode 100644 index 9e3286485..000000000 --- a/dom/media/gmp/mozIGeckoMediaPluginChromeService.idl +++ /dev/null @@ -1,51 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#include "nsISupports.idl" -#include "nsIFile.idl" - -[scriptable, uuid(32d35d21-181f-4630-8caa-a431e2ebad72)] -interface mozIGeckoMediaPluginChromeService : nsISupports -{ - /** - * Add a directory to scan for gecko media plugins. - * @note Main-thread API. - */ - void addPluginDirectory(in AString directory); - - /** - * Remove a directory for gecko media plugins. - * @note Main-thread API. - */ - void removePluginDirectory(in AString directory); - - /** - * Remove a directory for gecko media plugins and delete it from disk. - * If |defer| is true, wait until the plugin is unused before removing. - * @note Main-thread API. - */ - void removeAndDeletePluginDirectory(in AString directory, - [optional] in bool defer); - - /** - * Clears storage data associated with the site and the originAttributes - * pattern in JSON format. - */ - void forgetThisSite(in AString site, - in DOMString aPattern); - - /** - * Returns true if the given node id is allowed to store things - * persistently on disk. Private Browsing and local content are not - * allowed to store persistent data. - */ - bool isPersistentStorageAllowed(in ACString nodeId); - - /** - * Returns the directory to use as the base for storing data about GMPs. - */ - nsIFile getStorageDir(); - -}; diff --git a/dom/media/gmp/mozIGeckoMediaPluginService.idl b/dom/media/gmp/mozIGeckoMediaPluginService.idl deleted file mode 100644 index 388c58142..000000000 --- a/dom/media/gmp/mozIGeckoMediaPluginService.idl +++ /dev/null @@ -1,169 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#include "nsISupports.idl" -#include "nsIThread.idl" - -%{C++ -#include "mozilla/UniquePtr.h" -#include "nsTArray.h" -#include "nsStringGlue.h" -class GMPAudioDecoderProxy; -class GMPDecryptorProxy; -class GMPVideoDecoderProxy; -class GMPVideoEncoderProxy; -class GMPVideoHost; -class GMPCrashHelper; - -template<class T> -class GMPGetterCallback -{ -public: - GMPGetterCallback() { MOZ_COUNT_CTOR(GMPGetterCallback<T>); } - virtual ~GMPGetterCallback() { MOZ_COUNT_DTOR(GMPGetterCallback<T>); } - virtual void Done(T*) = 0; -}; -template<class T> -class GMPVideoGetterCallback -{ -public: - GMPVideoGetterCallback() { MOZ_COUNT_CTOR(GMPVideoGetterCallback<T>); } - virtual ~GMPVideoGetterCallback() { MOZ_COUNT_DTOR(GMPVideoGetterCallback<T>); } - virtual void Done(T*, GMPVideoHost*) = 0; -}; -typedef GMPGetterCallback<GMPDecryptorProxy> GetGMPDecryptorCallback; -typedef GMPGetterCallback<GMPAudioDecoderProxy> GetGMPAudioDecoderCallback; -typedef GMPVideoGetterCallback<GMPVideoDecoderProxy> GetGMPVideoDecoderCallback; -typedef GMPVideoGetterCallback<GMPVideoEncoderProxy> GetGMPVideoEncoderCallback; -class GetNodeIdCallback -{ -public: - GetNodeIdCallback() { MOZ_COUNT_CTOR(GetNodeIdCallback); } - virtual ~GetNodeIdCallback() { MOZ_COUNT_DTOR(GetNodeIdCallback); } - virtual void Done(nsresult aResult, const nsACString& aNodeId) = 0; -}; -%} - -[ptr] native TagArray(nsTArray<nsCString>); -native GetGMPDecryptorCallback(mozilla::UniquePtr<GetGMPDecryptorCallback>&&); -native GetGMPAudioDecoderCallback(mozilla::UniquePtr<GetGMPAudioDecoderCallback>&&); -native GetGMPVideoDecoderCallback(mozilla::UniquePtr<GetGMPVideoDecoderCallback>&&); -native GetGMPVideoEncoderCallback(mozilla::UniquePtr<GetGMPVideoEncoderCallback>&&); -native GetNodeIdCallback(mozilla::UniquePtr<GetNodeIdCallback>&&); -native GMPCrashHelperPtr(GMPCrashHelper*); - -[scriptable, uuid(44d362ae-937a-4803-bee6-f2512a0149d1)] -interface mozIGeckoMediaPluginService : nsISupports -{ - - /** - * The GMP thread. Callable from any thread. - */ - readonly attribute nsIThread thread; - - /** - * Run through windows registered registered for pluginId, sending - * 'PluginCrashed' chrome-only event - */ - void RunPluginCrashCallbacks(in unsigned long pluginId, in ACString pluginName); - - /** - * Get a plugin that supports the specified tags. - * Callable on any thread - */ - [noscript] - boolean hasPluginForAPI(in ACString api, in TagArray tags); - - /** - * Get a video decoder that supports the specified tags. - * The array of tags should at least contain a codec tag, and optionally - * other tags such as for EME keysystem. - * Callable only on GMP thread. - * This is an asynchronous operation, the Done method of the callback object - * will be called on the GMP thread with the result (which might be null in - * the case of failure). This method always takes ownership of the callback - * object, but if this method returns an error then the Done method of the - * callback object will not be called at all. - */ - [noscript] - void getGMPVideoDecoder(in GMPCrashHelperPtr helper, - in TagArray tags, - [optional] in ACString nodeId, - in GetGMPVideoDecoderCallback callback); - - /** - * Gets a video decoder as per getGMPVideoDecoder, except it is linked to - * with a corresponding GMPDecryptor via the decryptor's ID. - * This is a temporary measure, until we can implement a Chromium CDM - * GMP protocol which does both decryption and decoding. - */ - [noscript] - void getDecryptingGMPVideoDecoder(in GMPCrashHelperPtr helper, - in TagArray tags, - in ACString nodeId, - in GetGMPVideoDecoderCallback callback, - in uint32_t decryptorId); - - /** - * Get a video encoder that supports the specified tags. - * The array of tags should at least contain a codec tag, and optionally - * other tags. - * Callable only on GMP thread. - * This is an asynchronous operation, the Done method of the callback object - * will be called on the GMP thread with the result (which might be null in - * the case of failure). This method always takes ownership of the callback - * object, but if this method returns an error then the Done method of the - * callback object will not be called at all. - */ - [noscript] - void getGMPVideoEncoder(in GMPCrashHelperPtr helper, - in TagArray tags, - [optional] in ACString nodeId, - in GetGMPVideoEncoderCallback callback); - - /** - * Returns an audio decoder that supports the specified tags. - * The array of tags should at least contain a codec tag, and optionally - * other tags such as for EME keysystem. - * Callable only on GMP thread. - * This is an asynchronous operation, the Done method of the callback object - * will be called on the GMP thread with the result (which might be null in - * the case of failure). This method always takes ownership of the callback - * object, but if this method returns an error then the Done method of the - * callback object will not be called at all. - */ - [noscript] - void getGMPAudioDecoder(in GMPCrashHelperPtr helper, - in TagArray tags, - [optional] in ACString nodeId, - in GetGMPAudioDecoderCallback callback); - - /** - * Returns a decryption session manager that supports the specified tags. - * The array of tags should at least contain a key system tag, and optionally - * other tags. - * Callable only on GMP thread. - * This is an asynchronous operation, the Done method of the callback object - * will be called on the GMP thread with the result (which might be null in - * the case of failure). This method always takes ownership of the callback - * object, but if this method returns an error then the Done method of the - * callback object will not be called at all. - */ - [noscript] - void getGMPDecryptor(in GMPCrashHelperPtr helper, - in TagArray tags, - in ACString nodeId, - in GetGMPDecryptorCallback callback); - - /** - * Gets the NodeId for a (origin, urlbarOrigin, isInprivateBrowsing) tuple. - */ - [noscript] - void getNodeId(in AString origin, - in AString topLevelOrigin, - in AString gmpName, - in bool inPrivateBrowsingMode, - in GetNodeIdCallback callback); -}; diff --git a/dom/media/gmp/rlz/COPYING b/dom/media/gmp/rlz/COPYING deleted file mode 100644 index b89042ace..000000000 --- a/dom/media/gmp/rlz/COPYING +++ /dev/null @@ -1,14 +0,0 @@ -Copyright 2010 Google Inc. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - diff --git a/dom/media/gmp/rlz/GMPDeviceBinding.cpp b/dom/media/gmp/rlz/GMPDeviceBinding.cpp deleted file mode 100644 index 0871d2e4e..000000000 --- a/dom/media/gmp/rlz/GMPDeviceBinding.cpp +++ /dev/null @@ -1,152 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#include "GMPDeviceBinding.h" -#include "mozilla/Attributes.h" -#include "prenv.h" - -#include <string> - -#ifdef XP_WIN -#include "windows.h" -#endif - -#if defined(HASH_NODE_ID_WITH_DEVICE_ID) - -// In order to provide EME plugins with a "device binding" capability, -// in the parent we generate and store some random bytes as salt for every -// (origin, urlBarOrigin) pair that uses EME. We store these bytes so -// that every time we revisit the same origin we get the same salt. -// We send this salt to the child on startup. The child collects some -// device specific data and munges that with the salt to create the -// "node id" that we expose to EME plugins. It then overwrites the device -// specific data, and activates the sandbox. - -#include "rlz/lib/machine_id.h" -#include "rlz/lib/string_utils.h" -#include "sha256.h" - -#ifdef XP_WIN -#include "windows.h" -#endif - - -#endif // HASH_NODE_ID_WITH_DEVICE_ID - -namespace mozilla { -namespace gmp { - -#if defined(XP_WIN) && defined(HASH_NODE_ID_WITH_DEVICE_ID) -MOZ_NEVER_INLINE -static bool -GetStackAfterCurrentFrame(uint8_t** aOutTop, uint8_t** aOutBottom) -{ - // "Top" of the free space on the stack is directly after the memory - // holding our return address. - uint8_t* top = (uint8_t*)_AddressOfReturnAddress(); - - // Look down the stack until we find the guard page... - MEMORY_BASIC_INFORMATION memInfo = {0}; - uint8_t* bottom = top; - while (1) { - if (!VirtualQuery(bottom, &memInfo, sizeof(memInfo))) { - return false; - } - if ((memInfo.Protect & PAGE_GUARD) == PAGE_GUARD) { - bottom = (uint8_t*)memInfo.BaseAddress + memInfo.RegionSize; -#ifdef DEBUG - if (!VirtualQuery(bottom, &memInfo, sizeof(memInfo))) { - return false; - } - assert(!(memInfo.Protect & PAGE_GUARD)); // Should have found boundary. -#endif - break; - } else if (memInfo.State != MEM_COMMIT || - (memInfo.AllocationProtect & PAGE_READWRITE) != PAGE_READWRITE) { - return false; - } - bottom = (uint8_t*)memInfo.BaseAddress - 1; - } - *aOutTop = top; - *aOutBottom = bottom; - return true; -} -#endif - -#ifdef HASH_NODE_ID_WITH_DEVICE_ID -static void SecureMemset(void* start, uint8_t value, size_t size) -{ - // Inline instructions equivalent to RtlSecureZeroMemory(). - for (size_t i = 0; i < size; ++i) { - volatile uint8_t* p = static_cast<volatile uint8_t*>(start) + i; - *p = value; - } -} -#endif - -bool -CalculateGMPDeviceId(char* aOriginSalt, - uint32_t aOriginSaltLen, - std::string& aOutNodeId) -{ -#ifdef HASH_NODE_ID_WITH_DEVICE_ID - if (aOriginSaltLen > 0) { - std::vector<uint8_t> deviceId; - int volumeId; - if (!rlz_lib::GetRawMachineId(&deviceId, &volumeId)) { - return false; - } - - SHA256Context ctx; - SHA256_Begin(&ctx); - SHA256_Update(&ctx, (const uint8_t*)aOriginSalt, aOriginSaltLen); - SHA256_Update(&ctx, deviceId.data(), deviceId.size()); - SHA256_Update(&ctx, (const uint8_t*)&volumeId, sizeof(int)); - uint8_t digest[SHA256_LENGTH] = {0}; - unsigned int digestLen = 0; - SHA256_End(&ctx, digest, &digestLen, SHA256_LENGTH); - - // Overwrite all data involved in calculation as it could potentially - // identify the user, so there's no chance a GMP can read it and use - // it for identity tracking. - SecureMemset(&ctx, 0, sizeof(ctx)); - SecureMemset(aOriginSalt, 0, aOriginSaltLen); - SecureMemset(&volumeId, 0, sizeof(volumeId)); - SecureMemset(deviceId.data(), '*', deviceId.size()); - deviceId.clear(); - - if (!rlz_lib::BytesToString(digest, SHA256_LENGTH, &aOutNodeId)) { - return false; - } - - if (!PR_GetEnv("MOZ_GMP_DISABLE_NODE_ID_CLEANUP")) { - // We've successfully bound the origin salt to node id. - // rlz_lib::GetRawMachineId and/or the system functions it - // called could have left user identifiable data on the stack, - // so carefully zero the stack down to the guard page. - uint8_t* top; - uint8_t* bottom; - if (!GetStackAfterCurrentFrame(&top, &bottom)) { - return false; - } - assert(top >= bottom); - // Inline instructions equivalent to RtlSecureZeroMemory(). - // We can't just use RtlSecureZeroMemory here directly, as in debug - // builds, RtlSecureZeroMemory() can't be inlined, and the stack - // memory it uses would get wiped by itself running, causing crashes. - for (volatile uint8_t* p = (volatile uint8_t*)bottom; p < top; p++) { - *p = 0; - } - } - } else -#endif - { - aOutNodeId = std::string(aOriginSalt, aOriginSalt + aOriginSaltLen); - } - return true; -} - -} // namespace gmp -} // namespace mozilla diff --git a/dom/media/gmp/rlz/GMPDeviceBinding.h b/dom/media/gmp/rlz/GMPDeviceBinding.h deleted file mode 100644 index ee1664466..000000000 --- a/dom/media/gmp/rlz/GMPDeviceBinding.h +++ /dev/null @@ -1,21 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#ifndef GMP_DEVICE_BINDING_h_ -#define GMP_DEVICE_BINDING_h_ - -#include <string> - -namespace mozilla { -namespace gmp { - -bool CalculateGMPDeviceId(char* aOriginSalt, - uint32_t aOriginSaltLen, - std::string& aOutNodeId); - -} // namespace gmp -} // namespace mozilla - -#endif // GMP_DEVICE_BINDING_h_ diff --git a/dom/media/gmp/rlz/README.mozilla b/dom/media/gmp/rlz/README.mozilla deleted file mode 100644 index fffc5deb5..000000000 --- a/dom/media/gmp/rlz/README.mozilla +++ /dev/null @@ -1,6 +0,0 @@ -Code taken from rlz project: https://code.google.com/p/rlz/ - -Revision: 134, then with unused code stripped out. - -Note: base/ contains wrappers/dummies to provide implementations of the -Chromium APIs that this code relies upon. diff --git a/dom/media/gmp/rlz/lib/assert.h b/dom/media/gmp/rlz/lib/assert.h deleted file mode 100644 index 68737b1e2..000000000 --- a/dom/media/gmp/rlz/lib/assert.h +++ /dev/null @@ -1,14 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* 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/. */
-
-#ifndef FAKE_ASSERT_H_
-#define FAKE_ASSERT_H_
-
-#include <assert.h>
-
-#define ASSERT_STRING(x) { assert(false); }
-#define VERIFY(x) { assert(x); };
-
-#endif
diff --git a/dom/media/gmp/rlz/lib/machine_id.h b/dom/media/gmp/rlz/lib/machine_id.h deleted file mode 100644 index 67661cfce..000000000 --- a/dom/media/gmp/rlz/lib/machine_id.h +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// Use of this source code is governed by an Apache-style license that can be -// found in the COPYING file. - -#ifndef RLZ_LIB_MACHINE_ID_H_ -#define RLZ_LIB_MACHINE_ID_H_ - -#include <vector> - -namespace rlz_lib { - -// Retrieves a raw machine identifier string and a machine-specific -// 4 byte value. GetMachineId() will SHA1 |data|, append |more_data|, compute -// the Crc8 of that, and return a hex-encoded string of that data. -bool GetRawMachineId(std::vector<uint8_t>* data, int* more_data); - -} // namespace rlz_lib - -#endif // RLZ_LIB_MACHINE_ID_H_ diff --git a/dom/media/gmp/rlz/lib/string_utils.cc b/dom/media/gmp/rlz/lib/string_utils.cc deleted file mode 100644 index b6a71acdb..000000000 --- a/dom/media/gmp/rlz/lib/string_utils.cc +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2010 Google Inc. All Rights Reserved. -// Use of this source code is governed by an Apache-style license that can be -// found in the COPYING file. -// -// String manipulation functions used in the RLZ library. - -#include "rlz/lib/string_utils.h" - -namespace rlz_lib { - -bool BytesToString(const unsigned char* data, - int data_len, - std::string* string) { - if (!string) - return false; - - string->clear(); - if (data_len < 1 || !data) - return false; - - static const char kHex[] = "0123456789ABCDEF"; - - // Fix the buffer size to begin with to avoid repeated re-allocation. - string->resize(data_len * 2); - int index = data_len; - while (index--) { - string->at(2 * index) = kHex[data[index] >> 4]; // high digit - string->at(2 * index + 1) = kHex[data[index] & 0x0F]; // low digit - } - - return true; -} - -} // namespace rlz_lib diff --git a/dom/media/gmp/rlz/lib/string_utils.h b/dom/media/gmp/rlz/lib/string_utils.h deleted file mode 100644 index 294f1b2d9..000000000 --- a/dom/media/gmp/rlz/lib/string_utils.h +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2010 Google Inc. All Rights Reserved. -// Use of this source code is governed by an Apache-style license that can be -// found in the COPYING file. -// -// String manipulation functions used in the RLZ library. - -#ifndef RLZ_LIB_STRING_UTILS_H_ -#define RLZ_LIB_STRING_UTILS_H_ - -#include <string> - -namespace rlz_lib { - -bool BytesToString(const unsigned char* data, - int data_len, - std::string* string); - -}; // namespace - -#endif // RLZ_LIB_STRING_UTILS_H_ diff --git a/dom/media/gmp/rlz/mac/lib/machine_id_mac.cc b/dom/media/gmp/rlz/mac/lib/machine_id_mac.cc deleted file mode 100644 index 2bea0f55f..000000000 --- a/dom/media/gmp/rlz/mac/lib/machine_id_mac.cc +++ /dev/null @@ -1,320 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <CoreFoundation/CoreFoundation.h> -#include <IOKit/IOKitLib.h> -#include <IOKit/network/IOEthernetController.h> -#include <IOKit/network/IOEthernetInterface.h> -#include <IOKit/network/IONetworkInterface.h> -#include <vector> -#include <string> - -// Note: The original machine_id_mac.cc code is in namespace rlz_lib below. -// It depends on some external files, which would bring in a log of Chromium -// code if imported as well. -// Instead only the necessary code has been extracted from the relevant files, -// and further combined and reduced to limit the maintenance burden. - -// [Extracted from base/logging.h] -#define DCHECK assert - -namespace base { - -// [Extracted from base/mac/scoped_typeref.h and base/mac/scoped_cftyperef.h] -template<typename T> -class ScopedCFTypeRef { - public: - typedef T element_type; - - explicit ScopedCFTypeRef(T object) - : object_(object) { - } - - ScopedCFTypeRef(const ScopedCFTypeRef<T>& that) = delete; - ScopedCFTypeRef(ScopedCFTypeRef<T>&& that) = delete; - - ~ScopedCFTypeRef() { - if (object_) - CFRelease(object_); - } - - ScopedCFTypeRef& operator=(const ScopedCFTypeRef<T>& that) = delete; - ScopedCFTypeRef& operator=(ScopedCFTypeRef<T>&& that) = delete; - - operator T() const { - return object_; - } - - // ScopedCFTypeRef<>::release() is like scoped_ptr<>::release. It is NOT - // a wrapper for CFRelease(). - T release() { - T temp = object_; - object_ = NULL; - return temp; - } - - private: - T object_; -}; - -namespace mac { - -// [Extracted from base/mac/scoped_ioobject.h] -// Just like ScopedCFTypeRef but for io_object_t and subclasses. -template<typename IOT> -class ScopedIOObject { - public: - typedef IOT element_type; - - explicit ScopedIOObject(IOT object = IO_OBJECT_NULL) - : object_(object) { - } - - ~ScopedIOObject() { - if (object_) - IOObjectRelease(object_); - } - - ScopedIOObject(const ScopedIOObject&) = delete; - void operator=(const ScopedIOObject&) = delete; - - void reset(IOT object = IO_OBJECT_NULL) { - if (object_) - IOObjectRelease(object_); - object_ = object; - } - - operator IOT() const { - return object_; - } - - private: - IOT object_; -}; - -// [Extracted from base/mac/foundation_util.h] -template<typename T> -T CFCast(const CFTypeRef& cf_val); - -template<> -CFDataRef -CFCast<CFDataRef>(const CFTypeRef& cf_val) { - if (cf_val == NULL) { - return NULL; - } - if (CFGetTypeID(cf_val) == CFDataGetTypeID()) { - return (CFDataRef)(cf_val); - } - return NULL; -} - -template<> -CFStringRef -CFCast<CFStringRef>(const CFTypeRef& cf_val) { - if (cf_val == NULL) { - return NULL; - } - if (CFGetTypeID(cf_val) == CFStringGetTypeID()) { - return (CFStringRef)(cf_val); - } - return NULL; -} - -} // namespace mac - -// [Extracted from base/strings/sys_string_conversions_mac.mm] -static const CFStringEncoding kNarrowStringEncoding = kCFStringEncodingUTF8; - -template<typename StringType> -static StringType CFStringToSTLStringWithEncodingT(CFStringRef cfstring, - CFStringEncoding encoding) { - CFIndex length = CFStringGetLength(cfstring); - if (length == 0) - return StringType(); - - CFRange whole_string = CFRangeMake(0, length); - CFIndex out_size; - CFIndex converted = CFStringGetBytes(cfstring, - whole_string, - encoding, - 0, // lossByte - false, // isExternalRepresentation - NULL, // buffer - 0, // maxBufLen - &out_size); - if (converted == 0 || out_size == 0) - return StringType(); - - // out_size is the number of UInt8-sized units needed in the destination. - // A buffer allocated as UInt8 units might not be properly aligned to - // contain elements of StringType::value_type. Use a container for the - // proper value_type, and convert out_size by figuring the number of - // value_type elements per UInt8. Leave room for a NUL terminator. - typename StringType::size_type elements = - out_size * sizeof(UInt8) / sizeof(typename StringType::value_type) + 1; - - std::vector<typename StringType::value_type> out_buffer(elements); - converted = CFStringGetBytes(cfstring, - whole_string, - encoding, - 0, // lossByte - false, // isExternalRepresentation - reinterpret_cast<UInt8*>(&out_buffer[0]), - out_size, - NULL); // usedBufLen - if (converted == 0) - return StringType(); - - out_buffer[elements - 1] = '\0'; - return StringType(&out_buffer[0], elements - 1); -} - -std::string SysCFStringRefToUTF8(CFStringRef ref) -{ - return CFStringToSTLStringWithEncodingT<std::string>(ref, - kNarrowStringEncoding); -} - -} // namespace base - - -namespace rlz_lib { - -namespace { - -// See http://developer.apple.com/library/mac/#technotes/tn1103/_index.html - -// The caller is responsible for freeing |matching_services|. -bool FindEthernetInterfaces(io_iterator_t* matching_services) { - base::ScopedCFTypeRef<CFMutableDictionaryRef> matching_dict( - IOServiceMatching(kIOEthernetInterfaceClass)); - if (!matching_dict) - return false; - - base::ScopedCFTypeRef<CFMutableDictionaryRef> primary_interface( - CFDictionaryCreateMutable(kCFAllocatorDefault, - 0, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks)); - if (!primary_interface) - return false; - - CFDictionarySetValue( - primary_interface, CFSTR(kIOPrimaryInterface), kCFBooleanTrue); - CFDictionarySetValue( - matching_dict, CFSTR(kIOPropertyMatchKey), primary_interface); - - kern_return_t kern_result = IOServiceGetMatchingServices( - kIOMasterPortDefault, matching_dict.release(), matching_services); - - return kern_result == KERN_SUCCESS; -} - -bool GetMACAddressFromIterator(io_iterator_t primary_interface_iterator, - uint8_t* buffer, size_t buffer_size) { - if (buffer_size < kIOEthernetAddressSize) - return false; - - bool success = false; - - bzero(buffer, buffer_size); - base::mac::ScopedIOObject<io_object_t> primary_interface; - while (primary_interface.reset(IOIteratorNext(primary_interface_iterator)), - primary_interface) { - io_object_t primary_interface_parent; - kern_return_t kern_result = IORegistryEntryGetParentEntry( - primary_interface, kIOServicePlane, &primary_interface_parent); - base::mac::ScopedIOObject<io_object_t> primary_interface_parent_deleter( - primary_interface_parent); - success = kern_result == KERN_SUCCESS; - - if (!success) - continue; - - base::ScopedCFTypeRef<CFTypeRef> mac_data( - IORegistryEntryCreateCFProperty(primary_interface_parent, - CFSTR(kIOMACAddress), - kCFAllocatorDefault, - 0)); - CFDataRef mac_data_data = base::mac::CFCast<CFDataRef>(mac_data); - if (mac_data_data) { - CFDataGetBytes( - mac_data_data, CFRangeMake(0, kIOEthernetAddressSize), buffer); - } - } - - return success; -} - -bool GetMacAddress(unsigned char* buffer, size_t size) { - io_iterator_t primary_interface_iterator; - if (!FindEthernetInterfaces(&primary_interface_iterator)) - return false; - bool result = GetMACAddressFromIterator( - primary_interface_iterator, buffer, size); - IOObjectRelease(primary_interface_iterator); - return result; -} - -CFStringRef CopySerialNumber() { - base::mac::ScopedIOObject<io_service_t> expert_device( - IOServiceGetMatchingService(kIOMasterPortDefault, - IOServiceMatching("IOPlatformExpertDevice"))); - if (!expert_device) - return NULL; - - base::ScopedCFTypeRef<CFTypeRef> serial_number( - IORegistryEntryCreateCFProperty(expert_device, - CFSTR(kIOPlatformSerialNumberKey), - kCFAllocatorDefault, - 0)); - CFStringRef serial_number_cfstring = - base::mac::CFCast<CFStringRef>(serial_number.release()); - if (!serial_number_cfstring) - return NULL; - - return serial_number_cfstring; -} - -} // namespace - -bool GetRawMachineId(std::vector<uint8_t>* data, int* more_data) { - uint8_t mac_address[kIOEthernetAddressSize]; - - std::string id; - if (GetMacAddress(mac_address, sizeof(mac_address))) { - id += "mac:"; - static const char hex[] = - { '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; - for (int i = 0; i < kIOEthernetAddressSize; ++i) { - uint8_t byte = mac_address[i]; - id += hex[byte >> 4]; - id += hex[byte & 0xF]; - } - } - - // A MAC address is enough to uniquely identify a machine, but it's only 6 - // bytes, 3 of which are manufacturer-determined. To make brute-forcing the - // SHA1 of this harder, also append the system's serial number. - CFStringRef serial = CopySerialNumber(); - if (serial) { - if (!id.empty()) { - id += ' '; - } - id += "serial:"; - id += base::SysCFStringRefToUTF8(serial); - CFRelease(serial); - } - - // Get the contents of the string 'id' as a bunch of bytes. - data->assign(&id[0], &id[id.size()]); - - // On windows, this is set to the volume id. Since it's not scrambled before - // being sent, just set it to 1. - *more_data = 1; - return true; -} - -} // namespace rlz_lib diff --git a/dom/media/gmp/rlz/moz.build b/dom/media/gmp/rlz/moz.build deleted file mode 100644 index aa6f5fece..000000000 --- a/dom/media/gmp/rlz/moz.build +++ /dev/null @@ -1,34 +0,0 @@ -# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- -# 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/. - -# Note: build rlz in its own moz.build, so it doesn't pickup any of -# Chromium IPC's headers used in the moz.build of the parent file. - -Library('rlz') - -UNIFIED_SOURCES += [ - 'GMPDeviceBinding.cpp', -] - -if CONFIG['OS_TARGET'] == 'WINNT': - UNIFIED_SOURCES += [ - 'win/lib/machine_id_win.cc', - ] - -if CONFIG['OS_TARGET'] == 'Darwin': - UNIFIED_SOURCES += [ - 'mac/lib/machine_id_mac.cc', - ] - OS_LIBS += [ - '-framework IOKit', - ] - -LOCAL_INCLUDES += [ - '..', -] - -EXPORTS += [ - 'GMPDeviceBinding.h', -] diff --git a/dom/media/gmp/rlz/sha256.c b/dom/media/gmp/rlz/sha256.c deleted file mode 100644 index 072de5195..000000000 --- a/dom/media/gmp/rlz/sha256.c +++ /dev/null @@ -1,469 +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/. */ - -// Stripped down version of security/nss/lib/freebl/sha512.c -// and related headers. - -#include "sha256.h" -#include "string.h" -#include "prcpucfg.h" -#if defined(NSS_X86) || defined(SHA_NO_LONG_LONG) -#define NOUNROLL512 1 -#undef HAVE_LONG_LONG -#endif -
-#define SHA256_BLOCK_LENGTH 64 /* bytes */
-
-typedef enum _SECStatus {
- SECWouldBlock = -2,
- SECFailure = -1,
- SECSuccess = 0
-} SECStatus; - -/* ============= Common constants and defines ======================= */ - -#define W ctx->u.w -#define B ctx->u.b -#define H ctx->h - -#define SHR(x,n) (x >> n) -#define SHL(x,n) (x << n) -#define Ch(x,y,z) ((x & y) ^ (~x & z)) -#define Maj(x,y,z) ((x & y) ^ (x & z) ^ (y & z)) -#define SHA_MIN(a,b) (a < b ? a : b) - -/* Padding used with all flavors of SHA */ -static const PRUint8 pad[240] = { -0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - /* compiler will fill the rest in with zeros */ -}; - -/* ============= SHA256 implementation ================================== */ - -/* SHA-256 constants, K256. */ -static const PRUint32 K256[64] = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, - 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, - 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, - 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, - 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, - 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 -}; - -/* SHA-256 initial hash values */ -static const PRUint32 H256[8] = { - 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, - 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 -}; - -#if defined(_MSC_VER) -#include <stdlib.h> -#pragma intrinsic(_byteswap_ulong) -#define SHA_HTONL(x) _byteswap_ulong(x) -#define BYTESWAP4(x) x = SHA_HTONL(x) -#elif defined(__GNUC__) && defined(NSS_X86_OR_X64) -static __inline__ PRUint32 swap4b(PRUint32 value) -{ - __asm__("bswap %0" : "+r" (value)); - return (value); -} -#define SHA_HTONL(x) swap4b(x) -#define BYTESWAP4(x) x = SHA_HTONL(x) - -#elif defined(__GNUC__) && (defined(__thumb2__) || \ - (!defined(__thumb__) && \ - (defined(__ARM_ARCH_6__) || \ - defined(__ARM_ARCH_6J__) || \ - defined(__ARM_ARCH_6K__) || \ - defined(__ARM_ARCH_6Z__) || \ - defined(__ARM_ARCH_6ZK__) || \ - defined(__ARM_ARCH_6T2__) || \ - defined(__ARM_ARCH_7__) || \ - defined(__ARM_ARCH_7A__) || \ - defined(__ARM_ARCH_7R__)))) -static __inline__ PRUint32 swap4b(PRUint32 value) -{ - PRUint32 ret; - __asm__("rev %0, %1" : "=r" (ret) : "r"(value)); - return ret; -} -#define SHA_HTONL(x) swap4b(x) -#define BYTESWAP4(x) x = SHA_HTONL(x) - -#else -#define SWAP4MASK 0x00FF00FF -#define SHA_HTONL(x) (t1 = (x), t1 = (t1 << 16) | (t1 >> 16), \ - ((t1 & SWAP4MASK) << 8) | ((t1 >> 8) & SWAP4MASK)) -#define BYTESWAP4(x) x = SHA_HTONL(x) -#endif - -#if defined(_MSC_VER) -#pragma intrinsic (_lrotr, _lrotl) -#define ROTR32(x,n) _lrotr(x,n) -#define ROTL32(x,n) _lrotl(x,n) -#else -#define ROTR32(x,n) ((x >> n) | (x << ((8 * sizeof x) - n))) -#define ROTL32(x,n) ((x << n) | (x >> ((8 * sizeof x) - n))) -#endif - -/* Capitol Sigma and lower case sigma functions */ -#define S0(x) (ROTR32(x, 2) ^ ROTR32(x,13) ^ ROTR32(x,22)) -#define S1(x) (ROTR32(x, 6) ^ ROTR32(x,11) ^ ROTR32(x,25)) -#define s0(x) (t1 = x, ROTR32(t1, 7) ^ ROTR32(t1,18) ^ SHR(t1, 3)) -#define s1(x) (t2 = x, ROTR32(t2,17) ^ ROTR32(t2,19) ^ SHR(t2,10)) - -void -SHA256_Begin(SHA256Context *ctx) -{ - memset(ctx, 0, sizeof *ctx); - memcpy(H, H256, sizeof H256); -} - -static void -SHA256_Compress(SHA256Context *ctx) -{ - { - register PRUint32 t1, t2; - -#if defined(IS_LITTLE_ENDIAN) - BYTESWAP4(W[0]); - BYTESWAP4(W[1]); - BYTESWAP4(W[2]); - BYTESWAP4(W[3]); - BYTESWAP4(W[4]); - BYTESWAP4(W[5]); - BYTESWAP4(W[6]); - BYTESWAP4(W[7]); - BYTESWAP4(W[8]); - BYTESWAP4(W[9]); - BYTESWAP4(W[10]); - BYTESWAP4(W[11]); - BYTESWAP4(W[12]); - BYTESWAP4(W[13]); - BYTESWAP4(W[14]); - BYTESWAP4(W[15]); -#endif - -#define INITW(t) W[t] = (s1(W[t-2]) + W[t-7] + s0(W[t-15]) + W[t-16]) - - /* prepare the "message schedule" */ -#ifdef NOUNROLL256 - { - int t; - for (t = 16; t < 64; ++t) { - INITW(t); - } - } -#else - INITW(16); - INITW(17); - INITW(18); - INITW(19); - - INITW(20); - INITW(21); - INITW(22); - INITW(23); - INITW(24); - INITW(25); - INITW(26); - INITW(27); - INITW(28); - INITW(29); - - INITW(30); - INITW(31); - INITW(32); - INITW(33); - INITW(34); - INITW(35); - INITW(36); - INITW(37); - INITW(38); - INITW(39); - - INITW(40); - INITW(41); - INITW(42); - INITW(43); - INITW(44); - INITW(45); - INITW(46); - INITW(47); - INITW(48); - INITW(49); - - INITW(50); - INITW(51); - INITW(52); - INITW(53); - INITW(54); - INITW(55); - INITW(56); - INITW(57); - INITW(58); - INITW(59); - - INITW(60); - INITW(61); - INITW(62); - INITW(63); - -#endif -#undef INITW - } - { - PRUint32 a, b, c, d, e, f, g, h; - - a = H[0]; - b = H[1]; - c = H[2]; - d = H[3]; - e = H[4]; - f = H[5]; - g = H[6]; - h = H[7]; - -#define ROUND(n,a,b,c,d,e,f,g,h) \ - h += S1(e) + Ch(e,f,g) + K256[n] + W[n]; \ - d += h; \ - h += S0(a) + Maj(a,b,c); - -#ifdef NOUNROLL256 - { - int t; - for (t = 0; t < 64; t+= 8) { - ROUND(t+0,a,b,c,d,e,f,g,h) - ROUND(t+1,h,a,b,c,d,e,f,g) - ROUND(t+2,g,h,a,b,c,d,e,f) - ROUND(t+3,f,g,h,a,b,c,d,e) - ROUND(t+4,e,f,g,h,a,b,c,d) - ROUND(t+5,d,e,f,g,h,a,b,c) - ROUND(t+6,c,d,e,f,g,h,a,b) - ROUND(t+7,b,c,d,e,f,g,h,a) - } - } -#else - ROUND( 0,a,b,c,d,e,f,g,h) - ROUND( 1,h,a,b,c,d,e,f,g) - ROUND( 2,g,h,a,b,c,d,e,f) - ROUND( 3,f,g,h,a,b,c,d,e) - ROUND( 4,e,f,g,h,a,b,c,d) - ROUND( 5,d,e,f,g,h,a,b,c) - ROUND( 6,c,d,e,f,g,h,a,b) - ROUND( 7,b,c,d,e,f,g,h,a) - - ROUND( 8,a,b,c,d,e,f,g,h) - ROUND( 9,h,a,b,c,d,e,f,g) - ROUND(10,g,h,a,b,c,d,e,f) - ROUND(11,f,g,h,a,b,c,d,e) - ROUND(12,e,f,g,h,a,b,c,d) - ROUND(13,d,e,f,g,h,a,b,c) - ROUND(14,c,d,e,f,g,h,a,b) - ROUND(15,b,c,d,e,f,g,h,a) - - ROUND(16,a,b,c,d,e,f,g,h) - ROUND(17,h,a,b,c,d,e,f,g) - ROUND(18,g,h,a,b,c,d,e,f) - ROUND(19,f,g,h,a,b,c,d,e) - ROUND(20,e,f,g,h,a,b,c,d) - ROUND(21,d,e,f,g,h,a,b,c) - ROUND(22,c,d,e,f,g,h,a,b) - ROUND(23,b,c,d,e,f,g,h,a) - - ROUND(24,a,b,c,d,e,f,g,h) - ROUND(25,h,a,b,c,d,e,f,g) - ROUND(26,g,h,a,b,c,d,e,f) - ROUND(27,f,g,h,a,b,c,d,e) - ROUND(28,e,f,g,h,a,b,c,d) - ROUND(29,d,e,f,g,h,a,b,c) - ROUND(30,c,d,e,f,g,h,a,b) - ROUND(31,b,c,d,e,f,g,h,a) - - ROUND(32,a,b,c,d,e,f,g,h) - ROUND(33,h,a,b,c,d,e,f,g) - ROUND(34,g,h,a,b,c,d,e,f) - ROUND(35,f,g,h,a,b,c,d,e) - ROUND(36,e,f,g,h,a,b,c,d) - ROUND(37,d,e,f,g,h,a,b,c) - ROUND(38,c,d,e,f,g,h,a,b) - ROUND(39,b,c,d,e,f,g,h,a) - - ROUND(40,a,b,c,d,e,f,g,h) - ROUND(41,h,a,b,c,d,e,f,g) - ROUND(42,g,h,a,b,c,d,e,f) - ROUND(43,f,g,h,a,b,c,d,e) - ROUND(44,e,f,g,h,a,b,c,d) - ROUND(45,d,e,f,g,h,a,b,c) - ROUND(46,c,d,e,f,g,h,a,b) - ROUND(47,b,c,d,e,f,g,h,a) - - ROUND(48,a,b,c,d,e,f,g,h) - ROUND(49,h,a,b,c,d,e,f,g) - ROUND(50,g,h,a,b,c,d,e,f) - ROUND(51,f,g,h,a,b,c,d,e) - ROUND(52,e,f,g,h,a,b,c,d) - ROUND(53,d,e,f,g,h,a,b,c) - ROUND(54,c,d,e,f,g,h,a,b) - ROUND(55,b,c,d,e,f,g,h,a) - - ROUND(56,a,b,c,d,e,f,g,h) - ROUND(57,h,a,b,c,d,e,f,g) - ROUND(58,g,h,a,b,c,d,e,f) - ROUND(59,f,g,h,a,b,c,d,e) - ROUND(60,e,f,g,h,a,b,c,d) - ROUND(61,d,e,f,g,h,a,b,c) - ROUND(62,c,d,e,f,g,h,a,b) - ROUND(63,b,c,d,e,f,g,h,a) -#endif - - H[0] += a; - H[1] += b; - H[2] += c; - H[3] += d; - H[4] += e; - H[5] += f; - H[6] += g; - H[7] += h; - } -#undef ROUND -} - -#undef s0 -#undef s1 -#undef S0 -#undef S1 - -void -SHA256_Update(SHA256Context *ctx, const unsigned char *input, - unsigned int inputLen) -{ - unsigned int inBuf = ctx->sizeLo & 0x3f; - if (!inputLen) - return; - - /* Add inputLen into the count of bytes processed, before processing */ - if ((ctx->sizeLo += inputLen) < inputLen) - ctx->sizeHi++; - - /* if data already in buffer, attemp to fill rest of buffer */ - if (inBuf) { - unsigned int todo = SHA256_BLOCK_LENGTH - inBuf; - if (inputLen < todo) - todo = inputLen; - memcpy(B + inBuf, input, todo); - input += todo; - inputLen -= todo; - if (inBuf + todo == SHA256_BLOCK_LENGTH) - SHA256_Compress(ctx); - } - - /* if enough data to fill one or more whole buffers, process them. */ - while (inputLen >= SHA256_BLOCK_LENGTH) { - memcpy(B, input, SHA256_BLOCK_LENGTH); - input += SHA256_BLOCK_LENGTH; - inputLen -= SHA256_BLOCK_LENGTH; - SHA256_Compress(ctx); - } - /* if data left over, fill it into buffer */ - if (inputLen) - memcpy(B, input, inputLen); -} - -void -SHA256_End(SHA256Context *ctx, unsigned char *digest, - unsigned int *digestLen, unsigned int maxDigestLen) -{ - unsigned int inBuf = ctx->sizeLo & 0x3f; - unsigned int padLen = (inBuf < 56) ? (56 - inBuf) : (56 + 64 - inBuf); - PRUint32 hi, lo; -#ifdef SWAP4MASK - PRUint32 t1; -#endif - - hi = (ctx->sizeHi << 3) | (ctx->sizeLo >> 29); - lo = (ctx->sizeLo << 3); - - SHA256_Update(ctx, pad, padLen); - -#if defined(IS_LITTLE_ENDIAN) - W[14] = SHA_HTONL(hi); - W[15] = SHA_HTONL(lo); -#else - W[14] = hi; - W[15] = lo; -#endif - SHA256_Compress(ctx); - - /* now output the answer */ -#if defined(IS_LITTLE_ENDIAN) - BYTESWAP4(H[0]); - BYTESWAP4(H[1]); - BYTESWAP4(H[2]); - BYTESWAP4(H[3]); - BYTESWAP4(H[4]); - BYTESWAP4(H[5]); - BYTESWAP4(H[6]); - BYTESWAP4(H[7]); -#endif - padLen = PR_MIN(SHA256_LENGTH, maxDigestLen); - memcpy(digest, H, padLen); - if (digestLen) - *digestLen = padLen; -} - -void -SHA256_EndRaw(SHA256Context *ctx, unsigned char *digest, - unsigned int *digestLen, unsigned int maxDigestLen) -{ - PRUint32 h[8]; - unsigned int len; -#ifdef SWAP4MASK - PRUint32 t1; -#endif - - memcpy(h, ctx->h, sizeof(h)); - -#if defined(IS_LITTLE_ENDIAN) - BYTESWAP4(h[0]); - BYTESWAP4(h[1]); - BYTESWAP4(h[2]); - BYTESWAP4(h[3]); - BYTESWAP4(h[4]); - BYTESWAP4(h[5]); - BYTESWAP4(h[6]); - BYTESWAP4(h[7]); -#endif - - len = PR_MIN(SHA256_LENGTH, maxDigestLen); - memcpy(digest, h, len); - if (digestLen) - *digestLen = len; -} - -SECStatus -SHA256_HashBuf(unsigned char *dest, const unsigned char *src, - PRUint32 src_length) -{ - SHA256Context ctx; - unsigned int outLen; - - SHA256_Begin(&ctx); - SHA256_Update(&ctx, src, src_length); - SHA256_End(&ctx, dest, &outLen, SHA256_LENGTH); - memset(&ctx, 0, sizeof ctx); - - return SECSuccess; -} diff --git a/dom/media/gmp/rlz/sha256.h b/dom/media/gmp/rlz/sha256.h deleted file mode 100644 index 6958e382c..000000000 --- a/dom/media/gmp/rlz/sha256.h +++ /dev/null @@ -1,46 +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/. */ - -// Stripped down version of security/nss/lib/freebl/blapi.h -// and related headers. - -#ifndef _SHA256_H_ -#define _SHA256_H_ - -#define SHA256_LENGTH 32 - -#include "prtypes.h" /* for PRUintXX */ -#include "prlong.h" - -#ifdef __cplusplus
-extern "C" {
-#endif - -struct SHA256Context {
- union {
- PRUint32 w[64]; /* message schedule, input buffer, plus 48 words */
- PRUint8 b[256];
- } u;
- PRUint32 h[8]; /* 8 state variables */
- PRUint32 sizeHi,sizeLo; /* 64-bit count of hashed bytes. */
-}; - -typedef struct SHA256Context SHA256Context; - -extern void -SHA256_Begin(SHA256Context *ctx); - -extern void -SHA256_Update(SHA256Context *ctx, const unsigned char *input, - unsigned int inputLen); - -extern void -SHA256_End(SHA256Context *ctx, unsigned char *digest, - unsigned int *digestLen, unsigned int maxDigestLen); - -#ifdef __cplusplus
-} /* extern C */ -#endif - -#endif /* _SHA256_H_ */ diff --git a/dom/media/gmp/rlz/win/lib/machine_id_win.cc b/dom/media/gmp/rlz/win/lib/machine_id_win.cc deleted file mode 100644 index 0a636ebd3..000000000 --- a/dom/media/gmp/rlz/win/lib/machine_id_win.cc +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// Use of this source code is governed by an Apache-style license that can be -// found in the COPYING file. - -#include <windows.h> -#include <sddl.h> // For ConvertSidToStringSidW. -#include <string> -#include <vector> -#include "mozilla/ArrayUtils.h"
- -#include "rlz/lib/assert.h" - -namespace rlz_lib { - -namespace { - -bool GetSystemVolumeSerialNumber(int* number) { - if (!number) - return false; - - *number = 0; - - // Find the system root path (e.g: C:\). - wchar_t system_path[MAX_PATH + 1]; - if (!GetSystemDirectoryW(system_path, MAX_PATH)) - return false; - - wchar_t* first_slash = wcspbrk(system_path, L"\\/"); - if (first_slash != NULL) - *(first_slash + 1) = 0; - - DWORD number_local = 0; - if (!GetVolumeInformationW(system_path, NULL, 0, &number_local, NULL, NULL, - NULL, 0)) - return false; - - *number = (int)number_local; - return true; -} - -bool GetComputerSid(const wchar_t* account_name, SID* sid, DWORD sid_size) { - static const DWORD kStartDomainLength = 128; // reasonable to start with - - std::vector<wchar_t> domain_buffer(kStartDomainLength, 0); - DWORD domain_size = kStartDomainLength; - DWORD sid_dword_size = sid_size; - SID_NAME_USE sid_name_use; - - BOOL success = ::LookupAccountNameW(NULL, account_name, sid, - &sid_dword_size, &domain_buffer.front(), - &domain_size, &sid_name_use); - if (!success && ::GetLastError() == ERROR_INSUFFICIENT_BUFFER) { - // We could have gotten the insufficient buffer error because - // one or both of sid and szDomain was too small. Check for that - // here. - if (sid_dword_size > sid_size) - return false; - - if (domain_size > kStartDomainLength) - domain_buffer.resize(domain_size); - - success = ::LookupAccountNameW(NULL, account_name, sid, &sid_dword_size, - &domain_buffer.front(), &domain_size, - &sid_name_use); - } - - return success != FALSE; -} - -std::vector<uint8_t> ConvertSidToBytes(SID* sid) { - std::wstring sid_string; -#if _WIN32_WINNT >= 0x500 - wchar_t* sid_buffer = NULL; - if (ConvertSidToStringSidW(sid, &sid_buffer)) { - sid_string = sid_buffer; - LocalFree(sid_buffer); - } -#else - SID_IDENTIFIER_AUTHORITY* sia = ::GetSidIdentifierAuthority(sid); - - if(sia->Value[0] || sia->Value[1]) { - base::SStringPrintf( - &sid_string, L"S-%d-0x%02hx%02hx%02hx%02hx%02hx%02hx", - SID_REVISION, (USHORT)sia->Value[0], (USHORT)sia->Value[1], - (USHORT)sia->Value[2], (USHORT)sia->Value[3], (USHORT)sia->Value[4], - (USHORT)sia->Value[5]); - } else { - ULONG authority = 0; - for (int i = 2; i < 6; ++i) { - authority <<= 8; - authority |= sia->Value[i]; - } - base::SStringPrintf(&sid_string, L"S-%d-%lu", SID_REVISION, authority); - } - - int sub_auth_count = *::GetSidSubAuthorityCount(sid); - for(int i = 0; i < sub_auth_count; ++i) - base::StringAppendF(&sid_string, L"-%lu", *::GetSidSubAuthority(sid, i)); -#endif - - // Get the contents of the string as a bunch of bytes. - return std::vector<uint8_t>( - reinterpret_cast<uint8_t*>(&sid_string[0]), - reinterpret_cast<uint8_t*>(&sid_string[sid_string.size()])); -} - -} // namespace - -bool GetRawMachineId(std::vector<uint8_t>* sid_bytes, int* volume_id) { - // Calculate the Windows SID. - - wchar_t computer_name[MAX_COMPUTERNAME_LENGTH + 1] = {0}; - DWORD size = mozilla::ArrayLength(computer_name); - - if (!GetComputerNameW(computer_name, &size)) { - return false; - } - char sid_buffer[SECURITY_MAX_SID_SIZE]; - SID* sid = reinterpret_cast<SID*>(sid_buffer); - if (GetComputerSid(computer_name, sid, SECURITY_MAX_SID_SIZE)) { - *sid_bytes = ConvertSidToBytes(sid); - } - - // Get the system drive volume serial number. - *volume_id = 0; - if (!GetSystemVolumeSerialNumber(volume_id)) { - ASSERT_STRING("GetMachineId: Failed to retrieve volume serial number"); - *volume_id = 0; - } - - return true; -} - -} // namespace rlz_lib diff --git a/dom/media/moz.build b/dom/media/moz.build index 0a8e10177..7771138f7 100644 --- a/dom/media/moz.build +++ b/dom/media/moz.build @@ -9,7 +9,6 @@ with Files('*'): DIRS += [ 'encoder', 'flac', - 'gmp', 'imagecapture', 'ipc', 'mediasink', diff --git a/dom/media/platforms/PDMFactory.cpp b/dom/media/platforms/PDMFactory.cpp index 82bf0f50a..1779b000a 100644 --- a/dom/media/platforms/PDMFactory.cpp +++ b/dom/media/platforms/PDMFactory.cpp @@ -16,7 +16,6 @@ #ifdef MOZ_FFMPEG #include "FFmpegRuntimeLinker.h" #endif -#include "GMPDecoderModule.h" #include "mozilla/ClearOnShutdown.h" #include "mozilla/SharedThreadPool.h" @@ -210,9 +209,6 @@ PDMFactory::CreateDecoder(const CreateDecoderParams& aParams) if (mFFmpegFailedToLoad) { diagnostics->SetFFmpegFailedToLoad(); } - if (mGMPPDMFailedToStartup) { - diagnostics->SetGMPPDMFailedToStartup(); - } } for (auto& current : mCurrentPDMs) { @@ -368,13 +364,6 @@ PDMFactory::CreatePDMs() m = new AgnosticDecoderModule(); StartupPDM(m); - - if (MediaPrefs::PDMGMPEnabled()) { - m = new GMPDecoderModule(); - mGMPPDMFailedToStartup = !StartupPDM(m); - } else { - mGMPPDMFailedToStartup = false; - } } void @@ -407,9 +396,6 @@ PDMFactory::GetDecoder(const TrackInfo& aTrackInfo, if (mFFmpegFailedToLoad) { aDiagnostics->SetFFmpegFailedToLoad(); } - if (mGMPPDMFailedToStartup) { - aDiagnostics->SetGMPPDMFailedToStartup(); - } } RefPtr<PlatformDecoderModule> pdm; diff --git a/dom/media/platforms/PlatformDecoderModule.h b/dom/media/platforms/PlatformDecoderModule.h index 8e1d2f785..54feb13c7 100644 --- a/dom/media/platforms/PlatformDecoderModule.h +++ b/dom/media/platforms/PlatformDecoderModule.h @@ -16,7 +16,6 @@ #include "mozilla/layers/KnowsCompositor.h" #include "nsTArray.h" #include "mozilla/RefPtr.h" -#include "GMPService.h" #include <queue> #include "MediaResult.h" @@ -80,7 +79,6 @@ struct MOZ_STACK_CLASS CreateDecoderParams final { layers::ImageContainer* mImageContainer = nullptr; MediaResult* mError = nullptr; RefPtr<layers::KnowsCompositor> mKnowsCompositor; - RefPtr<GMPCrashHelper> mCrashHelper; bool mUseBlankDecoder = false; private: @@ -89,7 +87,6 @@ private: void Set(DecoderDoctorDiagnostics* aDiagnostics) { mDiagnostics = aDiagnostics; } void Set(layers::ImageContainer* aImageContainer) { mImageContainer = aImageContainer; } void Set(MediaResult* aError) { mError = aError; } - void Set(GMPCrashHelper* aCrashHelper) { mCrashHelper = aCrashHelper; } void Set(bool aUseBlankDecoder) { mUseBlankDecoder = aUseBlankDecoder; } void Set(layers::KnowsCompositor* aKnowsCompositor) { mKnowsCompositor = aKnowsCompositor; } template <typename T1, typename T2, typename... Ts> diff --git a/dom/media/platforms/agnostic/gmp/GMPAudioDecoder.cpp b/dom/media/platforms/agnostic/gmp/GMPAudioDecoder.cpp deleted file mode 100644 index d863d44d4..000000000 --- a/dom/media/platforms/agnostic/gmp/GMPAudioDecoder.cpp +++ /dev/null @@ -1,306 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et cindent: */ -/* 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/. */ - -#include "GMPAudioDecoder.h" -#include "nsServiceManagerUtils.h" -#include "MediaInfo.h" -#include "GMPDecoderModule.h" -#include "nsPrintfCString.h" - -namespace mozilla { - -#if defined(DEBUG) -bool IsOnGMPThread() -{ - nsCOMPtr<mozIGeckoMediaPluginService> mps = do_GetService("@mozilla.org/gecko-media-plugin-service;1"); - MOZ_ASSERT(mps); - - nsCOMPtr<nsIThread> gmpThread; - nsresult rv = mps->GetThread(getter_AddRefs(gmpThread)); - MOZ_ASSERT(NS_SUCCEEDED(rv) && gmpThread); - return NS_GetCurrentThread() == gmpThread; -} -#endif - -void -AudioCallbackAdapter::Decoded(const nsTArray<int16_t>& aPCM, uint64_t aTimeStamp, uint32_t aChannels, uint32_t aRate) -{ - MOZ_ASSERT(IsOnGMPThread()); - - if (aRate == 0 || aChannels == 0) { - mCallback->Error(MediaResult( - NS_ERROR_DOM_MEDIA_FATAL_ERR, - RESULT_DETAIL( - "Invalid rate or num channels returned on GMP audio samples"))); - return; - } - - size_t numFrames = aPCM.Length() / aChannels; - MOZ_ASSERT((aPCM.Length() % aChannels) == 0); - AlignedAudioBuffer audioData(aPCM.Length()); - if (!audioData) { - mCallback->Error( - MediaResult(NS_ERROR_OUT_OF_MEMORY, - RESULT_DETAIL("Unable to allocate audio buffer"))); - return; - } - - for (size_t i = 0; i < aPCM.Length(); ++i) { - audioData[i] = AudioSampleToFloat(aPCM[i]); - } - - if (mMustRecaptureAudioPosition) { - mAudioFrameSum = 0; - auto timestamp = UsecsToFrames(aTimeStamp, aRate); - if (!timestamp.isValid()) { - mCallback->Error(MediaResult(NS_ERROR_DOM_MEDIA_OVERFLOW_ERR, - RESULT_DETAIL("Invalid timestamp"))); - return; - } - mAudioFrameOffset = timestamp.value(); - mMustRecaptureAudioPosition = false; - } - - auto timestamp = FramesToUsecs(mAudioFrameOffset + mAudioFrameSum, aRate); - if (!timestamp.isValid()) { - mCallback->Error( - MediaResult(NS_ERROR_DOM_MEDIA_OVERFLOW_ERR, - RESULT_DETAIL("Invalid timestamp on audio samples"))); - return; - } - mAudioFrameSum += numFrames; - - auto duration = FramesToUsecs(numFrames, aRate); - if (!duration.isValid()) { - mCallback->Error( - MediaResult(NS_ERROR_DOM_MEDIA_OVERFLOW_ERR, - RESULT_DETAIL("Invalid duration on audio samples"))); - return; - } - - RefPtr<AudioData> audio(new AudioData(mLastStreamOffset, - timestamp.value(), - duration.value(), - numFrames, - Move(audioData), - aChannels, - aRate)); - -#ifdef LOG_SAMPLE_DECODE - LOG("Decoded audio sample! timestamp=%lld duration=%lld currentLength=%u", - timestamp, duration, currentLength); -#endif - - mCallback->Output(audio); -} - -void -AudioCallbackAdapter::InputDataExhausted() -{ - MOZ_ASSERT(IsOnGMPThread()); - mCallback->InputExhausted(); -} - -void -AudioCallbackAdapter::DrainComplete() -{ - MOZ_ASSERT(IsOnGMPThread()); - mCallback->DrainComplete(); -} - -void -AudioCallbackAdapter::ResetComplete() -{ - MOZ_ASSERT(IsOnGMPThread()); - mMustRecaptureAudioPosition = true; - mCallback->FlushComplete(); -} - -void -AudioCallbackAdapter::Error(GMPErr aErr) -{ - MOZ_ASSERT(IsOnGMPThread()); - mCallback->Error(MediaResult(aErr == GMPDecodeErr - ? NS_ERROR_DOM_MEDIA_DECODE_ERR - : NS_ERROR_DOM_MEDIA_FATAL_ERR, - RESULT_DETAIL("GMPErr:%x", aErr))); -} - -void -AudioCallbackAdapter::Terminated() -{ - mCallback->Error(MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, - RESULT_DETAIL("Audio GMP decoder terminated."))); -} - -GMPAudioDecoderParams::GMPAudioDecoderParams(const CreateDecoderParams& aParams) - : mConfig(aParams.AudioConfig()) - , mTaskQueue(aParams.mTaskQueue) - , mCallback(nullptr) - , mAdapter(nullptr) - , mCrashHelper(aParams.mCrashHelper) -{} - -GMPAudioDecoderParams& -GMPAudioDecoderParams::WithCallback(MediaDataDecoderProxy* aWrapper) -{ - MOZ_ASSERT(aWrapper); - MOZ_ASSERT(!mCallback); // Should only be called once per instance. - mCallback = aWrapper->Callback(); - mAdapter = nullptr; - return *this; -} - -GMPAudioDecoderParams& -GMPAudioDecoderParams::WithAdapter(AudioCallbackAdapter* aAdapter) -{ - MOZ_ASSERT(aAdapter); - MOZ_ASSERT(!mAdapter); // Should only be called once per instance. - mCallback = aAdapter->Callback(); - mAdapter = aAdapter; - return *this; -} - -GMPAudioDecoder::GMPAudioDecoder(const GMPAudioDecoderParams& aParams) - : mConfig(aParams.mConfig) - , mCallback(aParams.mCallback) - , mGMP(nullptr) - , mAdapter(aParams.mAdapter) - , mCrashHelper(aParams.mCrashHelper) -{ - MOZ_ASSERT(!mAdapter || mCallback == mAdapter->Callback()); - if (!mAdapter) { - mAdapter = new AudioCallbackAdapter(mCallback); - } -} - -void -GMPAudioDecoder::InitTags(nsTArray<nsCString>& aTags) -{ - aTags.AppendElement(NS_LITERAL_CSTRING("aac")); - const Maybe<nsCString> gmp( - GMPDecoderModule::PreferredGMP(NS_LITERAL_CSTRING("audio/mp4a-latm"))); - if (gmp.isSome()) { - aTags.AppendElement(gmp.value()); - } -} - -nsCString -GMPAudioDecoder::GetNodeId() -{ - return SHARED_GMP_DECODING_NODE_ID; -} - -void -GMPAudioDecoder::GMPInitDone(GMPAudioDecoderProxy* aGMP) -{ - MOZ_ASSERT(IsOnGMPThread()); - - if (!aGMP) { - mInitPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__); - return; - } - if (mInitPromise.IsEmpty()) { - // GMP must have been shutdown while we were waiting for Init operation - // to complete. - aGMP->Close(); - return; - } - nsTArray<uint8_t> codecSpecific; - codecSpecific.AppendElements(mConfig.mCodecSpecificConfig->Elements(), - mConfig.mCodecSpecificConfig->Length()); - - nsresult rv = aGMP->InitDecode(kGMPAudioCodecAAC, - mConfig.mChannels, - mConfig.mBitDepth, - mConfig.mRate, - codecSpecific, - mAdapter); - if (NS_FAILED(rv)) { - aGMP->Close(); - mInitPromise.Reject(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__); - return; - } - - mGMP = aGMP; - mInitPromise.Resolve(TrackInfo::kAudioTrack, __func__); -} - -RefPtr<MediaDataDecoder::InitPromise> -GMPAudioDecoder::Init() -{ - MOZ_ASSERT(IsOnGMPThread()); - - mMPS = do_GetService("@mozilla.org/gecko-media-plugin-service;1"); - MOZ_ASSERT(mMPS); - - RefPtr<InitPromise> promise(mInitPromise.Ensure(__func__)); - - nsTArray<nsCString> tags; - InitTags(tags); - UniquePtr<GetGMPAudioDecoderCallback> callback(new GMPInitDoneCallback(this)); - if (NS_FAILED(mMPS->GetGMPAudioDecoder(mCrashHelper, &tags, GetNodeId(), Move(callback)))) { - mInitPromise.Reject(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__); - } - - return promise; -} - -void -GMPAudioDecoder::Input(MediaRawData* aSample) -{ - MOZ_ASSERT(IsOnGMPThread()); - - RefPtr<MediaRawData> sample(aSample); - if (!mGMP) { - mCallback->Error(MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, - RESULT_DETAIL("mGMP not initialized"))); - return; - } - - mAdapter->SetLastStreamOffset(sample->mOffset); - - gmp::GMPAudioSamplesImpl samples(sample, mConfig.mChannels, mConfig.mRate); - nsresult rv = mGMP->Decode(samples); - if (NS_FAILED(rv)) { - mCallback->Error(MediaResult(rv, __func__)); - } -} - -void -GMPAudioDecoder::Flush() -{ - MOZ_ASSERT(IsOnGMPThread()); - - if (!mGMP || NS_FAILED(mGMP->Reset())) { - // Abort the flush. - mCallback->FlushComplete(); - } -} - -void -GMPAudioDecoder::Drain() -{ - MOZ_ASSERT(IsOnGMPThread()); - - if (!mGMP || NS_FAILED(mGMP->Drain())) { - mCallback->DrainComplete(); - } -} - -void -GMPAudioDecoder::Shutdown() -{ - mInitPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__); - if (!mGMP) { - return; - } - // Note this unblocks flush and drain operations waiting for callbacks. - mGMP->Close(); - mGMP = nullptr; -} - -} // namespace mozilla diff --git a/dom/media/platforms/agnostic/gmp/GMPAudioDecoder.h b/dom/media/platforms/agnostic/gmp/GMPAudioDecoder.h deleted file mode 100644 index 90e3ebdb6..000000000 --- a/dom/media/platforms/agnostic/gmp/GMPAudioDecoder.h +++ /dev/null @@ -1,112 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et cindent: */ -/* 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/. */ - -#if !defined(GMPAudioDecoder_h_) -#define GMPAudioDecoder_h_ - -#include "GMPAudioDecoderProxy.h" -#include "MediaDataDecoderProxy.h" -#include "PlatformDecoderModule.h" -#include "mozIGeckoMediaPluginService.h" -#include "nsAutoPtr.h" - -namespace mozilla { - -class AudioCallbackAdapter : public GMPAudioDecoderCallbackProxy { -public: - explicit AudioCallbackAdapter(MediaDataDecoderCallbackProxy* aCallback) - : mCallback(aCallback) - , mLastStreamOffset(0) - , mAudioFrameSum(0) - , mAudioFrameOffset(0) - , mMustRecaptureAudioPosition(true) - {} - - MediaDataDecoderCallbackProxy* Callback() const { return mCallback; } - - // GMPAudioDecoderCallbackProxy - void Decoded(const nsTArray<int16_t>& aPCM, uint64_t aTimeStamp, uint32_t aChannels, uint32_t aRate) override; - void InputDataExhausted() override; - void DrainComplete() override; - void ResetComplete() override; - void Error(GMPErr aErr) override; - void Terminated() override; - - void SetLastStreamOffset(int64_t aStreamOffset) { - mLastStreamOffset = aStreamOffset; - } - -private: - MediaDataDecoderCallbackProxy* mCallback; - int64_t mLastStreamOffset; - - int64_t mAudioFrameSum; - int64_t mAudioFrameOffset; - bool mMustRecaptureAudioPosition; -}; - -struct GMPAudioDecoderParams { - explicit GMPAudioDecoderParams(const CreateDecoderParams& aParams); - GMPAudioDecoderParams& WithCallback(MediaDataDecoderProxy* aWrapper); - GMPAudioDecoderParams& WithAdapter(AudioCallbackAdapter* aAdapter); - - const AudioInfo& mConfig; - TaskQueue* mTaskQueue; - MediaDataDecoderCallbackProxy* mCallback; - AudioCallbackAdapter* mAdapter; - RefPtr<GMPCrashHelper> mCrashHelper; -}; - -class GMPAudioDecoder : public MediaDataDecoder { -public: - explicit GMPAudioDecoder(const GMPAudioDecoderParams& aParams); - - RefPtr<InitPromise> Init() override; - void Input(MediaRawData* aSample) override; - void Flush() override; - void Drain() override; - void Shutdown() override; - const char* GetDescriptionName() const override - { - return "GMP audio decoder"; - } - -protected: - virtual void InitTags(nsTArray<nsCString>& aTags); - virtual nsCString GetNodeId(); - -private: - - class GMPInitDoneCallback : public GetGMPAudioDecoderCallback - { - public: - explicit GMPInitDoneCallback(GMPAudioDecoder* aDecoder) - : mDecoder(aDecoder) - { - } - - void Done(GMPAudioDecoderProxy* aGMP) override - { - mDecoder->GMPInitDone(aGMP); - } - - private: - RefPtr<GMPAudioDecoder> mDecoder; - }; - void GMPInitDone(GMPAudioDecoderProxy* aGMP); - - const AudioInfo mConfig; - MediaDataDecoderCallbackProxy* mCallback; - nsCOMPtr<mozIGeckoMediaPluginService> mMPS; - GMPAudioDecoderProxy* mGMP; - nsAutoPtr<AudioCallbackAdapter> mAdapter; - MozPromiseHolder<InitPromise> mInitPromise; - RefPtr<GMPCrashHelper> mCrashHelper; -}; - -} // namespace mozilla - -#endif // GMPAudioDecoder_h_ diff --git a/dom/media/platforms/agnostic/gmp/GMPDecoderModule.cpp b/dom/media/platforms/agnostic/gmp/GMPDecoderModule.cpp deleted file mode 100644 index 50a5097ac..000000000 --- a/dom/media/platforms/agnostic/gmp/GMPDecoderModule.cpp +++ /dev/null @@ -1,170 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et cindent: */ -/* 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/. */ - -#include "GMPDecoderModule.h" -#include "DecoderDoctorDiagnostics.h" -#include "GMPAudioDecoder.h" -#include "GMPVideoDecoder.h" -#include "GMPUtils.h" -#include "MediaDataDecoderProxy.h" -#include "MediaPrefs.h" -#include "VideoUtils.h" -#include "mozIGeckoMediaPluginService.h" -#include "nsServiceManagerUtils.h" -#include "mozilla/StaticMutex.h" -#include "gmp-audio-decode.h" -#include "gmp-video-decode.h" -#include "MP4Decoder.h" -#include "VPXDecoder.h" -#ifdef XP_WIN -#include "WMFDecoderModule.h" -#endif - -namespace mozilla { - -GMPDecoderModule::GMPDecoderModule() -{ -} - -GMPDecoderModule::~GMPDecoderModule() -{ -} - -static already_AddRefed<MediaDataDecoderProxy> -CreateDecoderWrapper(MediaDataDecoderCallback* aCallback) -{ - RefPtr<gmp::GeckoMediaPluginService> s(gmp::GeckoMediaPluginService::GetGeckoMediaPluginService()); - if (!s) { - return nullptr; - } - RefPtr<AbstractThread> thread(s->GetAbstractGMPThread()); - if (!thread) { - return nullptr; - } - RefPtr<MediaDataDecoderProxy> decoder(new MediaDataDecoderProxy(thread.forget(), aCallback)); - return decoder.forget(); -} - -already_AddRefed<MediaDataDecoder> -GMPDecoderModule::CreateVideoDecoder(const CreateDecoderParams& aParams) -{ - if (!MP4Decoder::IsH264(aParams.mConfig.mMimeType) && - !VPXDecoder::IsVP8(aParams.mConfig.mMimeType) && - !VPXDecoder::IsVP9(aParams.mConfig.mMimeType)) { - return nullptr; - } - - if (aParams.mDiagnostics) { - const Maybe<nsCString> preferredGMP = PreferredGMP(aParams.mConfig.mMimeType); - if (preferredGMP.isSome()) { - aParams.mDiagnostics->SetGMP(preferredGMP.value()); - } - } - - RefPtr<MediaDataDecoderProxy> wrapper = CreateDecoderWrapper(aParams.mCallback); - auto params = GMPVideoDecoderParams(aParams).WithCallback(wrapper); - wrapper->SetProxyTarget(new GMPVideoDecoder(params)); - return wrapper.forget(); -} - -already_AddRefed<MediaDataDecoder> -GMPDecoderModule::CreateAudioDecoder(const CreateDecoderParams& aParams) -{ - if (!aParams.mConfig.mMimeType.EqualsLiteral("audio/mp4a-latm")) { - return nullptr; - } - - if (aParams.mDiagnostics) { - const Maybe<nsCString> preferredGMP = PreferredGMP(aParams.mConfig.mMimeType); - if (preferredGMP.isSome()) { - aParams.mDiagnostics->SetGMP(preferredGMP.value()); - } - } - - RefPtr<MediaDataDecoderProxy> wrapper = CreateDecoderWrapper(aParams.mCallback); - auto params = GMPAudioDecoderParams(aParams).WithCallback(wrapper); - wrapper->SetProxyTarget(new GMPAudioDecoder(params)); - return wrapper.forget(); -} - -PlatformDecoderModule::ConversionRequired -GMPDecoderModule::DecoderNeedsConversion(const TrackInfo& aConfig) const -{ - // GMPVideoCodecType::kGMPVideoCodecH264 specifies that encoded frames must be in AVCC format. - if (aConfig.IsVideo() && MP4Decoder::IsH264(aConfig.mMimeType)) { - return ConversionRequired::kNeedAVCC; - } else { - return ConversionRequired::kNeedNone; - } -} - -/* static */ -const Maybe<nsCString> -GMPDecoderModule::PreferredGMP(const nsACString& aMimeType) -{ - Maybe<nsCString> rv; - if (aMimeType.EqualsLiteral("audio/mp4a-latm")) { - switch (MediaPrefs::GMPAACPreferred()) { - case 1: rv.emplace(kEMEKeySystemClearkey); break; - default: break; - } - } - - if (MP4Decoder::IsH264(aMimeType)) { - switch (MediaPrefs::GMPH264Preferred()) { - case 1: rv.emplace(kEMEKeySystemClearkey); break; - default: break; - } - } - - return rv; -} - -/* static */ -bool -GMPDecoderModule::SupportsMimeType(const nsACString& aMimeType, - const Maybe<nsCString>& aGMP) -{ - if (aGMP.isNothing()) { - return false; - } - - if (MP4Decoder::IsH264(aMimeType)) { - return HaveGMPFor(NS_LITERAL_CSTRING(GMP_API_VIDEO_DECODER), - { NS_LITERAL_CSTRING("h264"), aGMP.value()}); - } - - if (VPXDecoder::IsVP9(aMimeType)) { - return HaveGMPFor(NS_LITERAL_CSTRING(GMP_API_VIDEO_DECODER), - { NS_LITERAL_CSTRING("vp9"), aGMP.value()}); - } - - if (VPXDecoder::IsVP8(aMimeType)) { - return HaveGMPFor(NS_LITERAL_CSTRING(GMP_API_VIDEO_DECODER), - { NS_LITERAL_CSTRING("vp8"), aGMP.value()}); - } - - if (MP4Decoder::IsAAC(aMimeType)) { - return HaveGMPFor(NS_LITERAL_CSTRING(GMP_API_AUDIO_DECODER), - { NS_LITERAL_CSTRING("aac"), aGMP.value()}); - } - - return false; -} - -bool -GMPDecoderModule::SupportsMimeType(const nsACString& aMimeType, - DecoderDoctorDiagnostics* aDiagnostics) const -{ - const Maybe<nsCString> preferredGMP = PreferredGMP(aMimeType); - bool rv = SupportsMimeType(aMimeType, preferredGMP); - if (rv && aDiagnostics && preferredGMP.isSome()) { - aDiagnostics->SetGMP(preferredGMP.value()); - } - return rv; -} - -} // namespace mozilla diff --git a/dom/media/platforms/agnostic/gmp/GMPDecoderModule.h b/dom/media/platforms/agnostic/gmp/GMPDecoderModule.h deleted file mode 100644 index b501ecb54..000000000 --- a/dom/media/platforms/agnostic/gmp/GMPDecoderModule.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et cindent: */ -/* 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/. */ - -#if !defined(GMPDecoderModule_h_) -#define GMPDecoderModule_h_ - -#include "PlatformDecoderModule.h" -#include "mozilla/Maybe.h" - -// The special NodeId we use when doing unencrypted decoding using the GMP's -// decoder. This ensures that each GMP MediaDataDecoder we create doesn't -// require spinning up a new process, but instead we run all instances of -// GMP decoders in the one process, to reduce overhead. -// -// Note: GMP storage is isolated by NodeId, and non persistent for this -// special NodeId, and the only way a GMP can communicate with the outside -// world is through the EME GMP APIs, and we never run EME with this NodeID -// (because NodeIds are random strings which can't contain the '-' character), -// so there's no way a malicious GMP can harvest, store, and then report any -// privacy sensitive data about what users are watching. -#define SHARED_GMP_DECODING_NODE_ID NS_LITERAL_CSTRING("gmp-shared-decoding") - -namespace mozilla { - -class GMPDecoderModule : public PlatformDecoderModule { -public: - GMPDecoderModule(); - - virtual ~GMPDecoderModule(); - - // Decode thread. - already_AddRefed<MediaDataDecoder> - CreateVideoDecoder(const CreateDecoderParams& aParams) override; - - // Decode thread. - already_AddRefed<MediaDataDecoder> - CreateAudioDecoder(const CreateDecoderParams& aParams) override; - - ConversionRequired - DecoderNeedsConversion(const TrackInfo& aConfig) const override; - - bool - SupportsMimeType(const nsACString& aMimeType, - DecoderDoctorDiagnostics* aDiagnostics) const override; - - static const Maybe<nsCString> PreferredGMP(const nsACString& aMimeType); - - static bool SupportsMimeType(const nsACString& aMimeType, - const Maybe<nsCString>& aGMP); -}; - -} // namespace mozilla - -#endif // GMPDecoderModule_h_ diff --git a/dom/media/platforms/agnostic/gmp/GMPVideoDecoder.cpp b/dom/media/platforms/agnostic/gmp/GMPVideoDecoder.cpp deleted file mode 100644 index 26d029da0..000000000 --- a/dom/media/platforms/agnostic/gmp/GMPVideoDecoder.cpp +++ /dev/null @@ -1,388 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et cindent: */ -/* 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/. */ - -#include "GMPVideoDecoder.h" -#include "GMPVideoHost.h" -#include "mozilla/EndianUtils.h" -#include "prsystem.h" -#include "MediaData.h" -#include "GMPDecoderModule.h" -#include "MP4Decoder.h" -#include "VPXDecoder.h" - -namespace mozilla { - -#if defined(DEBUG) -extern bool IsOnGMPThread(); -#endif - -void -VideoCallbackAdapter::Decoded(GMPVideoi420Frame* aDecodedFrame) -{ - GMPUniquePtr<GMPVideoi420Frame> decodedFrame(aDecodedFrame); - - MOZ_ASSERT(IsOnGMPThread()); - - VideoData::YCbCrBuffer b; - for (int i = 0; i < kGMPNumOfPlanes; ++i) { - b.mPlanes[i].mData = decodedFrame->Buffer(GMPPlaneType(i)); - b.mPlanes[i].mStride = decodedFrame->Stride(GMPPlaneType(i)); - if (i == kGMPYPlane) { - b.mPlanes[i].mWidth = decodedFrame->Width(); - b.mPlanes[i].mHeight = decodedFrame->Height(); - } else { - b.mPlanes[i].mWidth = (decodedFrame->Width() + 1) / 2; - b.mPlanes[i].mHeight = (decodedFrame->Height() + 1) / 2; - } - b.mPlanes[i].mOffset = 0; - b.mPlanes[i].mSkip = 0; - } - - gfx::IntRect pictureRegion(0, 0, decodedFrame->Width(), decodedFrame->Height()); - RefPtr<VideoData> v = - VideoData::CreateAndCopyData(mVideoInfo, - mImageContainer, - mLastStreamOffset, - decodedFrame->Timestamp(), - decodedFrame->Duration(), - b, - false, - -1, - pictureRegion); - if (v) { - mCallback->Output(v); - } else { - mCallback->Error(MediaResult(NS_ERROR_OUT_OF_MEMORY, __func__)); - } -} - -void -VideoCallbackAdapter::ReceivedDecodedReferenceFrame(const uint64_t aPictureId) -{ - MOZ_ASSERT(IsOnGMPThread()); -} - -void -VideoCallbackAdapter::ReceivedDecodedFrame(const uint64_t aPictureId) -{ - MOZ_ASSERT(IsOnGMPThread()); -} - -void -VideoCallbackAdapter::InputDataExhausted() -{ - MOZ_ASSERT(IsOnGMPThread()); - mCallback->InputExhausted(); -} - -void -VideoCallbackAdapter::DrainComplete() -{ - MOZ_ASSERT(IsOnGMPThread()); - mCallback->DrainComplete(); -} - -void -VideoCallbackAdapter::ResetComplete() -{ - MOZ_ASSERT(IsOnGMPThread()); - mCallback->FlushComplete(); -} - -void -VideoCallbackAdapter::Error(GMPErr aErr) -{ - MOZ_ASSERT(IsOnGMPThread()); - mCallback->Error(MediaResult(aErr == GMPDecodeErr - ? NS_ERROR_DOM_MEDIA_DECODE_ERR - : NS_ERROR_DOM_MEDIA_FATAL_ERR, - RESULT_DETAIL("GMPErr:%x", aErr))); -} - -void -VideoCallbackAdapter::Terminated() -{ - // Note that this *may* be called from the proxy thread also. - mCallback->Error(MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, - RESULT_DETAIL("Video GMP decoder terminated."))); -} - -GMPVideoDecoderParams::GMPVideoDecoderParams(const CreateDecoderParams& aParams) - : mConfig(aParams.VideoConfig()) - , mTaskQueue(aParams.mTaskQueue) - , mCallback(nullptr) - , mAdapter(nullptr) - , mImageContainer(aParams.mImageContainer) - , mLayersBackend(aParams.GetLayersBackend()) - , mCrashHelper(aParams.mCrashHelper) -{} - -GMPVideoDecoderParams& -GMPVideoDecoderParams::WithCallback(MediaDataDecoderProxy* aWrapper) -{ - MOZ_ASSERT(aWrapper); - MOZ_ASSERT(!mCallback); // Should only be called once per instance. - mCallback = aWrapper->Callback(); - mAdapter = nullptr; - return *this; -} - -GMPVideoDecoderParams& -GMPVideoDecoderParams::WithAdapter(VideoCallbackAdapter* aAdapter) -{ - MOZ_ASSERT(aAdapter); - MOZ_ASSERT(!mAdapter); // Should only be called once per instance. - mCallback = aAdapter->Callback(); - mAdapter = aAdapter; - return *this; -} - -GMPVideoDecoder::GMPVideoDecoder(const GMPVideoDecoderParams& aParams) - : mConfig(aParams.mConfig) - , mCallback(aParams.mCallback) - , mGMP(nullptr) - , mHost(nullptr) - , mAdapter(aParams.mAdapter) - , mConvertNALUnitLengths(false) - , mCrashHelper(aParams.mCrashHelper) -{ - MOZ_ASSERT(!mAdapter || mCallback == mAdapter->Callback()); - if (!mAdapter) { - mAdapter = new VideoCallbackAdapter(mCallback, - VideoInfo(mConfig.mDisplay.width, - mConfig.mDisplay.height), - aParams.mImageContainer); - } -} - -void -GMPVideoDecoder::InitTags(nsTArray<nsCString>& aTags) -{ - if (MP4Decoder::IsH264(mConfig.mMimeType)) { - aTags.AppendElement(NS_LITERAL_CSTRING("h264")); - const Maybe<nsCString> gmp( - GMPDecoderModule::PreferredGMP(NS_LITERAL_CSTRING("video/avc"))); - if (gmp.isSome()) { - aTags.AppendElement(gmp.value()); - } - } else if (VPXDecoder::IsVP8(mConfig.mMimeType)) { - aTags.AppendElement(NS_LITERAL_CSTRING("vp8")); - } else if (VPXDecoder::IsVP9(mConfig.mMimeType)) { - aTags.AppendElement(NS_LITERAL_CSTRING("vp9")); - } -} - -nsCString -GMPVideoDecoder::GetNodeId() -{ - return SHARED_GMP_DECODING_NODE_ID; -} - -GMPUniquePtr<GMPVideoEncodedFrame> -GMPVideoDecoder::CreateFrame(MediaRawData* aSample) -{ - GMPVideoFrame* ftmp = nullptr; - GMPErr err = mHost->CreateFrame(kGMPEncodedVideoFrame, &ftmp); - if (GMP_FAILED(err)) { - mCallback->Error(MediaResult(NS_ERROR_OUT_OF_MEMORY, - RESULT_DETAIL("Host::CreateFrame:%x", err))); - return nullptr; - } - - GMPUniquePtr<GMPVideoEncodedFrame> frame(static_cast<GMPVideoEncodedFrame*>(ftmp)); - err = frame->CreateEmptyFrame(aSample->Size()); - if (GMP_FAILED(err)) { - mCallback->Error(MediaResult(NS_ERROR_OUT_OF_MEMORY, - RESULT_DETAIL("GMPVideoEncodedFrame::CreateEmptyFrame:%x", err))); - return nullptr; - } - - memcpy(frame->Buffer(), aSample->Data(), frame->Size()); - - // Convert 4-byte NAL unit lengths to host-endian 4-byte buffer lengths to - // suit the GMP API. - if (mConvertNALUnitLengths) { - const int kNALLengthSize = 4; - uint8_t* buf = frame->Buffer(); - while (buf < frame->Buffer() + frame->Size() - kNALLengthSize) { - uint32_t length = BigEndian::readUint32(buf) + kNALLengthSize; - *reinterpret_cast<uint32_t *>(buf) = length; - buf += length; - } - } - - frame->SetBufferType(GMP_BufferLength32); - - frame->SetEncodedWidth(mConfig.mDisplay.width); - frame->SetEncodedHeight(mConfig.mDisplay.height); - frame->SetTimeStamp(aSample->mTime); - frame->SetCompleteFrame(true); - frame->SetDuration(aSample->mDuration); - frame->SetFrameType(aSample->mKeyframe ? kGMPKeyFrame : kGMPDeltaFrame); - - return frame; -} - -const VideoInfo& -GMPVideoDecoder::GetConfig() const -{ - return mConfig; -} - -void -GMPVideoDecoder::GMPInitDone(GMPVideoDecoderProxy* aGMP, GMPVideoHost* aHost) -{ - MOZ_ASSERT(IsOnGMPThread()); - - if (!aGMP) { - mInitPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__); - return; - } - MOZ_ASSERT(aHost); - - if (mInitPromise.IsEmpty()) { - // GMP must have been shutdown while we were waiting for Init operation - // to complete. - aGMP->Close(); - return; - } - - GMPVideoCodec codec; - memset(&codec, 0, sizeof(codec)); - - codec.mGMPApiVersion = kGMPVersion33; - nsTArray<uint8_t> codecSpecific; - if (MP4Decoder::IsH264(mConfig.mMimeType)) { - codec.mCodecType = kGMPVideoCodecH264; - codecSpecific.AppendElement(0); // mPacketizationMode. - codecSpecific.AppendElements(mConfig.mExtraData->Elements(), - mConfig.mExtraData->Length()); - } else if (VPXDecoder::IsVP8(mConfig.mMimeType)) { - codec.mCodecType = kGMPVideoCodecVP8; - } else if (VPXDecoder::IsVP9(mConfig.mMimeType)) { - codec.mCodecType = kGMPVideoCodecVP9; - } else { - // Unrecognized mime type - aGMP->Close(); - mInitPromise.Reject(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__); - return; - } - codec.mWidth = mConfig.mImage.width; - codec.mHeight = mConfig.mImage.height; - - nsresult rv = aGMP->InitDecode(codec, - codecSpecific, - mAdapter, - PR_GetNumberOfProcessors()); - if (NS_FAILED(rv)) { - aGMP->Close(); - mInitPromise.Reject(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__); - return; - } - - mGMP = aGMP; - mHost = aHost; - - // GMP implementations have interpreted the meaning of GMP_BufferLength32 - // differently. The OpenH264 GMP expects GMP_BufferLength32 to behave as - // specified in the GMP API, where each buffer is prefixed by a 32-bit - // host-endian buffer length that includes the size of the buffer length - // field. Other existing GMPs currently expect GMP_BufferLength32 (when - // combined with kGMPVideoCodecH264) to mean "like AVCC but restricted to - // 4-byte NAL lengths" (i.e. buffer lengths are specified in big-endian - // and do not include the length of the buffer length field. - mConvertNALUnitLengths = mGMP->GetDisplayName().EqualsLiteral("gmpopenh264"); - - mInitPromise.Resolve(TrackInfo::kVideoTrack, __func__); -} - -RefPtr<MediaDataDecoder::InitPromise> -GMPVideoDecoder::Init() -{ - MOZ_ASSERT(IsOnGMPThread()); - - mMPS = do_GetService("@mozilla.org/gecko-media-plugin-service;1"); - MOZ_ASSERT(mMPS); - - RefPtr<InitPromise> promise(mInitPromise.Ensure(__func__)); - - nsTArray<nsCString> tags; - InitTags(tags); - UniquePtr<GetGMPVideoDecoderCallback> callback(new GMPInitDoneCallback(this)); - if (NS_FAILED(mMPS->GetDecryptingGMPVideoDecoder(mCrashHelper, - &tags, - GetNodeId(), - Move(callback), - DecryptorId()))) { - mInitPromise.Reject(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__); - } - - return promise; -} - -void -GMPVideoDecoder::Input(MediaRawData* aSample) -{ - MOZ_ASSERT(IsOnGMPThread()); - - RefPtr<MediaRawData> sample(aSample); - if (!mGMP) { - mCallback->Error(MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, - RESULT_DETAIL("mGMP not initialized"))); - return; - } - - mAdapter->SetLastStreamOffset(sample->mOffset); - - GMPUniquePtr<GMPVideoEncodedFrame> frame = CreateFrame(sample); - if (!frame) { - mCallback->Error(MediaResult(NS_ERROR_OUT_OF_MEMORY, - RESULT_DETAIL("CreateFrame returned null"))); - return; - } - nsTArray<uint8_t> info; // No codec specific per-frame info to pass. - nsresult rv = mGMP->Decode(Move(frame), false, info, 0); - if (NS_FAILED(rv)) { - mCallback->Error(MediaResult(NS_ERROR_DOM_MEDIA_DECODE_ERR, - RESULT_DETAIL("mGMP->Decode:%x", rv))); - } -} - -void -GMPVideoDecoder::Flush() -{ - MOZ_ASSERT(IsOnGMPThread()); - - if (!mGMP || NS_FAILED(mGMP->Reset())) { - // Abort the flush. - mCallback->FlushComplete(); - } -} - -void -GMPVideoDecoder::Drain() -{ - MOZ_ASSERT(IsOnGMPThread()); - - if (!mGMP || NS_FAILED(mGMP->Drain())) { - mCallback->DrainComplete(); - } -} - -void -GMPVideoDecoder::Shutdown() -{ - mInitPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__); - // Note that this *may* be called from the proxy thread also. - if (!mGMP) { - return; - } - // Note this unblocks flush and drain operations waiting for callbacks. - mGMP->Close(); - mGMP = nullptr; -} - -} // namespace mozilla diff --git a/dom/media/platforms/agnostic/gmp/GMPVideoDecoder.h b/dom/media/platforms/agnostic/gmp/GMPVideoDecoder.h deleted file mode 100644 index 900ef4553..000000000 --- a/dom/media/platforms/agnostic/gmp/GMPVideoDecoder.h +++ /dev/null @@ -1,122 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et cindent: */ -/* 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/. */ - -#if !defined(GMPVideoDecoder_h_) -#define GMPVideoDecoder_h_ - -#include "GMPVideoDecoderProxy.h" -#include "ImageContainer.h" -#include "MediaDataDecoderProxy.h" -#include "PlatformDecoderModule.h" -#include "mozIGeckoMediaPluginService.h" -#include "MediaInfo.h" - -namespace mozilla { - -class VideoCallbackAdapter : public GMPVideoDecoderCallbackProxy { -public: - VideoCallbackAdapter(MediaDataDecoderCallbackProxy* aCallback, - VideoInfo aVideoInfo, - layers::ImageContainer* aImageContainer) - : mCallback(aCallback) - , mLastStreamOffset(0) - , mVideoInfo(aVideoInfo) - , mImageContainer(aImageContainer) - {} - - MediaDataDecoderCallbackProxy* Callback() const { return mCallback; } - - // GMPVideoDecoderCallbackProxy - void Decoded(GMPVideoi420Frame* aDecodedFrame) override; - void ReceivedDecodedReferenceFrame(const uint64_t aPictureId) override; - void ReceivedDecodedFrame(const uint64_t aPictureId) override; - void InputDataExhausted() override; - void DrainComplete() override; - void ResetComplete() override; - void Error(GMPErr aErr) override; - void Terminated() override; - - void SetLastStreamOffset(int64_t aStreamOffset) { - mLastStreamOffset = aStreamOffset; - } - -private: - MediaDataDecoderCallbackProxy* mCallback; - int64_t mLastStreamOffset; - - VideoInfo mVideoInfo; - RefPtr<layers::ImageContainer> mImageContainer; -}; - -struct GMPVideoDecoderParams { - explicit GMPVideoDecoderParams(const CreateDecoderParams& aParams); - GMPVideoDecoderParams& WithCallback(MediaDataDecoderProxy* aWrapper); - GMPVideoDecoderParams& WithAdapter(VideoCallbackAdapter* aAdapter); - - const VideoInfo& mConfig; - TaskQueue* mTaskQueue; - MediaDataDecoderCallbackProxy* mCallback; - VideoCallbackAdapter* mAdapter; - layers::ImageContainer* mImageContainer; - layers::LayersBackend mLayersBackend; - RefPtr<GMPCrashHelper> mCrashHelper; -}; - -class GMPVideoDecoder : public MediaDataDecoder { -public: - explicit GMPVideoDecoder(const GMPVideoDecoderParams& aParams); - - RefPtr<InitPromise> Init() override; - void Input(MediaRawData* aSample) override; - void Flush() override; - void Drain() override; - void Shutdown() override; - const char* GetDescriptionName() const override - { - return "GMP video decoder"; - } - -protected: - virtual void InitTags(nsTArray<nsCString>& aTags); - virtual nsCString GetNodeId(); - virtual uint32_t DecryptorId() const { return 0; } - virtual GMPUniquePtr<GMPVideoEncodedFrame> CreateFrame(MediaRawData* aSample); - virtual const VideoInfo& GetConfig() const; - -private: - - class GMPInitDoneCallback : public GetGMPVideoDecoderCallback - { - public: - explicit GMPInitDoneCallback(GMPVideoDecoder* aDecoder) - : mDecoder(aDecoder) - { - } - - void Done(GMPVideoDecoderProxy* aGMP, GMPVideoHost* aHost) override - { - mDecoder->GMPInitDone(aGMP, aHost); - } - - private: - RefPtr<GMPVideoDecoder> mDecoder; - }; - void GMPInitDone(GMPVideoDecoderProxy* aGMP, GMPVideoHost* aHost); - - const VideoInfo mConfig; - MediaDataDecoderCallbackProxy* mCallback; - nsCOMPtr<mozIGeckoMediaPluginService> mMPS; - GMPVideoDecoderProxy* mGMP; - GMPVideoHost* mHost; - nsAutoPtr<VideoCallbackAdapter> mAdapter; - bool mConvertNALUnitLengths; - MozPromiseHolder<InitPromise> mInitPromise; - RefPtr<GMPCrashHelper> mCrashHelper; -}; - -} // namespace mozilla - -#endif // GMPVideoDecoder_h_ diff --git a/dom/media/platforms/agnostic/gmp/MediaDataDecoderProxy.cpp b/dom/media/platforms/agnostic/gmp/MediaDataDecoderProxy.cpp deleted file mode 100644 index 5a196f8e6..000000000 --- a/dom/media/platforms/agnostic/gmp/MediaDataDecoderProxy.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et cindent: */ -/* 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/. */ - -#include "MediaDataDecoderProxy.h" -#include "MediaData.h" - -namespace mozilla { - -void -MediaDataDecoderCallbackProxy::Error(const MediaResult& aError) -{ - mProxyCallback->Error(aError); -} - -void -MediaDataDecoderCallbackProxy::FlushComplete() -{ - mProxyDecoder->FlushComplete(); -} - -RefPtr<MediaDataDecoder::InitPromise> -MediaDataDecoderProxy::InternalInit() -{ - return mProxyDecoder->Init(); -} - -RefPtr<MediaDataDecoder::InitPromise> -MediaDataDecoderProxy::Init() -{ - MOZ_ASSERT(!mIsShutdown); - - return InvokeAsync(mProxyThread, this, __func__, - &MediaDataDecoderProxy::InternalInit); -} - -void -MediaDataDecoderProxy::Input(MediaRawData* aSample) -{ - MOZ_ASSERT(!IsOnProxyThread()); - MOZ_ASSERT(!mIsShutdown); - - nsCOMPtr<nsIRunnable> task(new InputTask(mProxyDecoder, aSample)); - mProxyThread->Dispatch(task.forget()); -} - -void -MediaDataDecoderProxy::Flush() -{ - MOZ_ASSERT(!IsOnProxyThread()); - MOZ_ASSERT(!mIsShutdown); - - mFlushComplete.Set(false); - - mProxyThread->Dispatch(NewRunnableMethod(mProxyDecoder, &MediaDataDecoder::Flush)); - - mFlushComplete.WaitUntil(true); -} - -void -MediaDataDecoderProxy::Drain() -{ - MOZ_ASSERT(!IsOnProxyThread()); - MOZ_ASSERT(!mIsShutdown); - - mProxyThread->Dispatch(NewRunnableMethod(mProxyDecoder, &MediaDataDecoder::Drain)); -} - -void -MediaDataDecoderProxy::Shutdown() -{ - // Note that this *may* be called from the proxy thread also. - MOZ_ASSERT(!mIsShutdown); -#if defined(DEBUG) - mIsShutdown = true; -#endif - mProxyThread->AsXPCOMThread()->Dispatch(NewRunnableMethod(mProxyDecoder, - &MediaDataDecoder::Shutdown), - NS_DISPATCH_SYNC); -} - -void -MediaDataDecoderProxy::FlushComplete() -{ - mFlushComplete.Set(true); -} - -} // namespace mozilla diff --git a/dom/media/platforms/agnostic/gmp/MediaDataDecoderProxy.h b/dom/media/platforms/agnostic/gmp/MediaDataDecoderProxy.h deleted file mode 100644 index 1e108994d..000000000 --- a/dom/media/platforms/agnostic/gmp/MediaDataDecoderProxy.h +++ /dev/null @@ -1,176 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et cindent: */ -/* 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/. */ - -#if !defined(MediaDataDecoderProxy_h_) -#define MediaDataDecoderProxy_h_ - -#include "PlatformDecoderModule.h" -#include "mozilla/RefPtr.h" -#include "nsThreadUtils.h" -#include "nscore.h" -#include "GMPService.h" - -namespace mozilla { - -class InputTask : public Runnable { -public: - InputTask(MediaDataDecoder* aDecoder, - MediaRawData* aSample) - : mDecoder(aDecoder) - , mSample(aSample) - {} - - NS_IMETHOD Run() override { - mDecoder->Input(mSample); - return NS_OK; - } - -private: - RefPtr<MediaDataDecoder> mDecoder; - RefPtr<MediaRawData> mSample; -}; - -template<typename T> -class Condition { -public: - explicit Condition(T aValue) - : mMonitor("Condition") - , mCondition(aValue) - {} - - void Set(T aValue) { - MonitorAutoLock mon(mMonitor); - mCondition = aValue; - mon.NotifyAll(); - } - - void WaitUntil(T aValue) { - MonitorAutoLock mon(mMonitor); - while (mCondition != aValue) { - mon.Wait(); - } - } - -private: - Monitor mMonitor; - T mCondition; -}; - -class MediaDataDecoderProxy; - -class MediaDataDecoderCallbackProxy : public MediaDataDecoderCallback { -public: - MediaDataDecoderCallbackProxy(MediaDataDecoderProxy* aProxyDecoder, - MediaDataDecoderCallback* aCallback) - : mProxyDecoder(aProxyDecoder) - , mProxyCallback(aCallback) - { - } - - void Output(MediaData* aData) override { - mProxyCallback->Output(aData); - } - - void Error(const MediaResult& aError) override; - - void InputExhausted() override { - mProxyCallback->InputExhausted(); - } - - void DrainComplete() override { - mProxyCallback->DrainComplete(); - } - - void ReleaseMediaResources() override { - mProxyCallback->ReleaseMediaResources(); - } - - void FlushComplete(); - - bool OnReaderTaskQueue() override - { - return mProxyCallback->OnReaderTaskQueue(); - } - -private: - MediaDataDecoderProxy* mProxyDecoder; - MediaDataDecoderCallback* mProxyCallback; -}; - -class MediaDataDecoderProxy : public MediaDataDecoder { -public: - MediaDataDecoderProxy(already_AddRefed<AbstractThread> aProxyThread, - MediaDataDecoderCallback* aCallback) - : mProxyThread(aProxyThread) - , mProxyCallback(this, aCallback) - , mFlushComplete(false) -#if defined(DEBUG) - , mIsShutdown(false) -#endif - { - } - - // Ideally, this would return a regular MediaDataDecoderCallback pointer - // to retain the clean abstraction, but until MediaDataDecoderCallback - // supports the FlushComplete interface, this will have to do. When MDDC - // supports FlushComplete, this, the GMP*Decoders, and the - // *CallbackAdapters can be reverted to accepting a regular - // MediaDataDecoderCallback pointer. - MediaDataDecoderCallbackProxy* Callback() - { - return &mProxyCallback; - } - - void SetProxyTarget(MediaDataDecoder* aProxyDecoder) - { - MOZ_ASSERT(aProxyDecoder); - mProxyDecoder = aProxyDecoder; - } - - // These are called from the decoder thread pool. - // Init and Shutdown run synchronously on the proxy thread, all others are - // asynchronously and responded to via the MediaDataDecoderCallback. - // Note: the nsresults returned by the proxied decoder are lost. - RefPtr<InitPromise> Init() override; - void Input(MediaRawData* aSample) override; - void Flush() override; - void Drain() override; - void Shutdown() override; - - const char* GetDescriptionName() const override - { - return "GMP proxy data decoder"; - } - - // Called by MediaDataDecoderCallbackProxy. - void FlushComplete(); - -private: - RefPtr<InitPromise> InternalInit(); - -#ifdef DEBUG - bool IsOnProxyThread() { - return mProxyThread && mProxyThread->IsCurrentThreadIn(); - } -#endif - - friend class InputTask; - friend class InitTask; - - RefPtr<MediaDataDecoder> mProxyDecoder; - RefPtr<AbstractThread> mProxyThread; - - MediaDataDecoderCallbackProxy mProxyCallback; - - Condition<bool> mFlushComplete; -#if defined(DEBUG) - bool mIsShutdown; -#endif -}; - -} // namespace mozilla - -#endif // MediaDataDecoderProxy_h_ diff --git a/dom/media/platforms/agnostic/gmp/moz.build b/dom/media/platforms/agnostic/gmp/moz.build deleted file mode 100644 index 64e258620..000000000 --- a/dom/media/platforms/agnostic/gmp/moz.build +++ /dev/null @@ -1,23 +0,0 @@ -# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- -# 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/. - -EXPORTS += [ - 'GMPAudioDecoder.h', - 'GMPDecoderModule.h', - 'GMPVideoDecoder.h', - 'MediaDataDecoderProxy.h', -] - -SOURCES += [ - 'GMPAudioDecoder.cpp', - 'GMPDecoderModule.cpp', - 'GMPVideoDecoder.cpp', - 'MediaDataDecoderProxy.cpp', -] - -# GMPVideoEncodedFrameImpl.h needs IPC -include('/ipc/chromium/chromium-config.mozbuild') - -FINAL_LIBRARY = 'xul' diff --git a/dom/media/platforms/moz.build b/dom/media/platforms/moz.build index 5da113e77..b570eb7d9 100644 --- a/dom/media/platforms/moz.build +++ b/dom/media/platforms/moz.build @@ -29,7 +29,6 @@ SOURCES += [ ] DIRS += [ - 'agnostic/gmp', 'omx' ] diff --git a/dom/media/platforms/wmf/WMFVideoMFTManager.cpp b/dom/media/platforms/wmf/WMFVideoMFTManager.cpp index 8cf22c241..bef63ad4c 100644 --- a/dom/media/platforms/wmf/WMFVideoMFTManager.cpp +++ b/dom/media/platforms/wmf/WMFVideoMFTManager.cpp @@ -29,7 +29,6 @@ #include "mozilla/WindowsVersion.h" #include "nsPrintfCString.h" #include "nsIFile.h" -#include "GMPUtils.h" // For SplitAt. TODO: Move SplitAt to a central place. #include "MP4Decoder.h" #include "VPXDecoder.h" #include "mozilla/SyncRunnable.h" @@ -71,6 +70,21 @@ const CLSID CLSID_WebmMfVpxDec = namespace mozilla { +// Utility function only used here. +// XXX: Perhaps make this available globally? +void +SplitAt(const char* aDelims, + const nsACString& aInput, + nsTArray<nsCString>& aOutTokens) +{ + nsAutoCString str(aInput); + char* end = str.BeginWriting(); + const char* start = nullptr; + while (!!(start = NS_strtok(aDelims, &end))) { + aOutTokens.AppendElement(nsCString(start)); + } +} + LayersBackend GetCompositorBackendType(layers::KnowsCompositor* aKnowsCompositor) { diff --git a/dom/media/platforms/wrappers/H264Converter.cpp b/dom/media/platforms/wrappers/H264Converter.cpp index cca03fceb..3d9d2e62f 100644 --- a/dom/media/platforms/wrappers/H264Converter.cpp +++ b/dom/media/platforms/wrappers/H264Converter.cpp @@ -26,7 +26,6 @@ H264Converter::H264Converter(PlatformDecoderModule* aPDM, , mTaskQueue(aParams.mTaskQueue) , mCallback(aParams.mCallback) , mDecoder(nullptr) - , mGMPCrashHelper(aParams.mCrashHelper) , mNeedAVCC(aPDM->DecoderNeedsConversion(aParams.mConfig) == PlatformDecoderModule::ConversionRequired::kNeedAVCC) , mLastError(NS_OK) @@ -202,8 +201,7 @@ H264Converter::CreateDecoder(DecoderDoctorDiagnostics* aDiagnostics) mCallback, aDiagnostics, mImageContainer, - mKnowsCompositor, - mGMPCrashHelper + mKnowsCompositor }); if (!mDecoder) { diff --git a/dom/media/platforms/wrappers/H264Converter.h b/dom/media/platforms/wrappers/H264Converter.h index 6905b1c74..627a56731 100644 --- a/dom/media/platforms/wrappers/H264Converter.h +++ b/dom/media/platforms/wrappers/H264Converter.h @@ -63,7 +63,6 @@ private: MediaDataDecoderCallback* mCallback; RefPtr<MediaDataDecoder> mDecoder; MozPromiseRequestHolder<InitPromise> mInitPromiseRequest; - RefPtr<GMPCrashHelper> mGMPCrashHelper; bool mNeedAVCC; nsresult mLastError; bool mNeedKeyframe = true; diff --git a/dom/media/webaudio/BufferDecoder.cpp b/dom/media/webaudio/BufferDecoder.cpp index ddd9e7d1b..bb1b5c493 100644 --- a/dom/media/webaudio/BufferDecoder.cpp +++ b/dom/media/webaudio/BufferDecoder.cpp @@ -7,15 +7,13 @@ #include "nsISupports.h" #include "MediaResource.h" -#include "GMPService.h" namespace mozilla { NS_IMPL_ISUPPORTS0(BufferDecoder) -BufferDecoder::BufferDecoder(MediaResource* aResource, GMPCrashHelper* aCrashHelper) +BufferDecoder::BufferDecoder(MediaResource* aResource) : mResource(aResource) - , mCrashHelper(aCrashHelper) { MOZ_ASSERT(NS_IsMainThread()); MOZ_COUNT_CTOR(BufferDecoder); @@ -67,10 +65,4 @@ BufferDecoder::GetOwner() const return nullptr; } -already_AddRefed<GMPCrashHelper> -BufferDecoder::GetCrashHelper() -{ - return do_AddRef(mCrashHelper); -} - -} // namespace mozilla +} // namespace mozilla
\ No newline at end of file diff --git a/dom/media/webaudio/BufferDecoder.h b/dom/media/webaudio/BufferDecoder.h index 2c6c49454..ef8a3d9fc 100644 --- a/dom/media/webaudio/BufferDecoder.h +++ b/dom/media/webaudio/BufferDecoder.h @@ -23,7 +23,7 @@ class BufferDecoder final : public AbstractMediaDecoder public: // This class holds a weak pointer to MediaResource. It's the responsibility // of the caller to manage the memory of the MediaResource object. - explicit BufferDecoder(MediaResource* aResource, GMPCrashHelper* aCrashHelper); + explicit BufferDecoder(MediaResource* aResource); NS_DECL_THREADSAFE_ISUPPORTS @@ -39,15 +39,12 @@ public: MediaDecoderOwner* GetOwner() const final override; - already_AddRefed<GMPCrashHelper> GetCrashHelper() override; - private: virtual ~BufferDecoder(); RefPtr<TaskQueue> mTaskQueueIdentity; RefPtr<MediaResource> mResource; - RefPtr<GMPCrashHelper> mCrashHelper; }; } // namespace mozilla -#endif /* BUFFER_DECODER_H_ */ +#endif /* BUFFER_DECODER_H_ */
\ No newline at end of file diff --git a/dom/media/webaudio/MediaBufferDecoder.cpp b/dom/media/webaudio/MediaBufferDecoder.cpp index f590d2f68..aea4fd90e 100644 --- a/dom/media/webaudio/MediaBufferDecoder.cpp +++ b/dom/media/webaudio/MediaBufferDecoder.cpp @@ -25,7 +25,6 @@ #include "WebAudioUtils.h" #include "mozilla/dom/Promise.h" #include "nsPrintfCString.h" -#include "GMPService.h" namespace mozilla { @@ -181,24 +180,6 @@ MediaDecodeTask::Run() return NS_OK; } -class BufferDecoderGMPCrashHelper : public GMPCrashHelper -{ -public: - explicit BufferDecoderGMPCrashHelper(nsPIDOMWindowInner* aParent) - : mParent(do_GetWeakReference(aParent)) - { - MOZ_ASSERT(NS_IsMainThread()); - } - already_AddRefed<nsPIDOMWindowInner> GetPluginCrashedEventTarget() override - { - MOZ_ASSERT(NS_IsMainThread()); - nsCOMPtr<nsPIDOMWindowInner> window = do_QueryReferent(mParent); - return window.forget(); - } -private: - nsWeakPtr mParent; -}; - bool MediaDecodeTask::CreateReader() { @@ -216,8 +197,7 @@ MediaDecodeTask::CreateReader() mLength, principal, mContentType); MOZ_ASSERT(!mBufferDecoder); - mBufferDecoder = new BufferDecoder(resource, - new BufferDecoderGMPCrashHelper(mDecodeJob.mContext->GetParentObject())); + mBufferDecoder = new BufferDecoder(resource); // If you change this list to add support for new decoders, please consider // updating HTMLMediaElement::CreateDecoder as well. @@ -644,4 +624,3 @@ WebAudioDecodeJob::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const } } // namespace mozilla - diff --git a/dom/webidl/PluginCrashedEvent.webidl b/dom/webidl/PluginCrashedEvent.webidl index 8eed7244e..c94315385 100644 --- a/dom/webidl/PluginCrashedEvent.webidl +++ b/dom/webidl/PluginCrashedEvent.webidl @@ -13,7 +13,6 @@ interface PluginCrashedEvent : Event readonly attribute DOMString? browserDumpID; readonly attribute DOMString? pluginFilename; readonly attribute boolean submittedCrashReport; - readonly attribute boolean gmpPlugin; }; dictionary PluginCrashedEventInit : EventInit @@ -24,5 +23,4 @@ dictionary PluginCrashedEventInit : EventInit DOMString? browserDumpID = null; DOMString? pluginFilename = null; boolean submittedCrashReport = false; - boolean gmpPlugin = false; }; diff --git a/ipc/app/moz.build b/ipc/app/moz.build index 41eb8ccff..d6239c5dc 100644 --- a/ipc/app/moz.build +++ b/ipc/app/moz.build @@ -16,15 +16,6 @@ LOCAL_INCLUDES += [ '/xpcom/base', ] -# We link GMPLoader into plugin-container on desktop so that its code is -# covered by the desktop DRM vendor's voucher. -SOURCES += [ - '../../dom/media/gmp/GMPLoader.cpp', -] -USE_LIBS += [ - 'rlz', -] - # DELAYLOAD_DLLS in this block ensures that the DLL blocklist is functional if CONFIG['OS_ARCH'] == 'WINNT': DELAYLOAD_DLLS += [ diff --git a/layout/build/nsLayoutModule.cpp b/layout/build/nsLayoutModule.cpp index 207ce6f2f..29dafb8c2 100644 --- a/layout/build/nsLayoutModule.cpp +++ b/layout/build/nsLayoutModule.cpp @@ -171,8 +171,6 @@ static void Shutdown(); #include "MediaManager.h" -#include "GMPService.h" - #include "nsScriptError.h" #include "mozilla/TextInputProcessor.h" @@ -186,7 +184,6 @@ using mozilla::dom::workers::WorkerDebuggerManager; using mozilla::dom::UDPSocketChild; using mozilla::dom::time::TimeService; using mozilla::net::StreamingProtocolControllerService; -using mozilla::gmp::GeckoMediaPluginService; #define NS_EDITORCOMMANDTABLE_CID \ { 0x4f5e62b8, 0xd659, 0x4156, \ @@ -504,8 +501,6 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsStructuredCloneContainer) NS_GENERIC_FACTORY_CONSTRUCTOR(OSFileConstantsService) NS_GENERIC_FACTORY_CONSTRUCTOR(UDPSocketChild) -NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(GeckoMediaPluginService, GeckoMediaPluginService::GetGeckoMediaPluginService) - NS_GENERIC_FACTORY_CONSTRUCTOR(nsScriptError) #ifdef ACCESSIBILITY @@ -880,7 +875,6 @@ static const mozilla::Module::CIDEntry kLayoutCIDs[] = { { &kNS_POWERMANAGERSERVICE_CID, false, nullptr, nsIPowerManagerServiceConstructor, Module::ALLOW_IN_GPU_PROCESS }, { &kOSFILECONSTANTSSERVICE_CID, true, nullptr, OSFileConstantsServiceConstructor }, { &kUDPSOCKETCHILD_CID, false, nullptr, UDPSocketChildConstructor }, - { &kGECKO_MEDIA_PLUGIN_SERVICE_CID, true, nullptr, GeckoMediaPluginServiceConstructor }, { &kNS_TIMESERVICE_CID, false, nullptr, nsITimeServiceConstructor }, { &kNS_MEDIASTREAMCONTROLLERSERVICE_CID, false, nullptr, nsIStreamingProtocolControllerServiceConstructor }, { &kNS_MEDIAMANAGERSERVICE_CID, false, nullptr, nsIMediaManagerServiceConstructor }, @@ -998,7 +992,6 @@ static const mozilla::Module::ContractIDEntry kLayoutContracts[] = { { "@mozilla.org/accessibilityService;1", &kNS_ACCESSIBILITY_SERVICE_CID }, { "@mozilla.org/accessibleRetrieval;1", &kNS_ACCESSIBILITY_SERVICE_CID }, #endif - { "@mozilla.org/gecko-media-plugin-service;1", &kGECKO_MEDIA_PLUGIN_SERVICE_CID }, { "@mozilla.org/text-input-processor;1", &kTEXT_INPUT_PROCESSOR_CID }, { NS_SCRIPTERROR_CONTRACTID, &kNS_SCRIPTERROR_CID }, { nullptr } diff --git a/system/graphics/layers/ipc/PAPZCTreeManager.ipdl b/system/graphics/layers/ipc/PAPZCTreeManager.ipdl index 21d899f91..134a222ad 100644 --- a/system/graphics/layers/ipc/PAPZCTreeManager.ipdl +++ b/system/graphics/layers/ipc/PAPZCTreeManager.ipdl @@ -8,6 +8,10 @@ include "ipc/nsGUIEventIPC.h"; include protocol PCompositorBridge; +// Workaround to prevent error if PContentChild.cpp & PAPZCTreeManagerChild.cpp +// are put into different UnifiedProtocolsXX.cpp files. +include "mozilla/dom/TabMessageUtils.h"; + using CSSRect from "Units.h"; using LayoutDeviceCoord from "Units.h"; using LayoutDeviceIntPoint from "Units.h"; diff --git a/system/runtime/nsEmbedFunctions.cpp b/system/runtime/nsEmbedFunctions.cpp index 02cd1e39d..def157cf8 100644 --- a/system/runtime/nsEmbedFunctions.cpp +++ b/system/runtime/nsEmbedFunctions.cpp @@ -63,8 +63,6 @@ #include "mozilla/ipc/XPCShellEnvironment.h" #include "mozilla/WindowsDllBlocklist.h" -#include "GMPProcessChild.h" -#include "GMPLoader.h" #include "mozilla/gfx/GPUProcessImpl.h" #include "GeckoProfiler.h" @@ -89,10 +87,6 @@ using mozilla::dom::ContentProcess; using mozilla::dom::ContentParent; using mozilla::dom::ContentChild; -using mozilla::gmp::GMPLoader; -using mozilla::gmp::CreateGMPLoader; -using mozilla::gmp::GMPProcessChild; - using mozilla::ipc::TestShellParent; using mozilla::ipc::TestShellCommandParent; using mozilla::ipc::XPCShellEnvironment; @@ -351,9 +345,6 @@ XRE_InitChildProcess(int aArgc, // Content processes need the XPCOM/chromium frankenventloop uiLoopType = MessageLoop::TYPE_MOZILLA_CHILD; break; - case GeckoProcessType_GMPlugin: - uiLoopType = MessageLoop::TYPE_DEFAULT; - break; default: uiLoopType = MessageLoop::TYPE_UI; break; @@ -415,10 +406,6 @@ XRE_InitChildProcess(int aArgc, #endif break; - case GeckoProcessType_GMPlugin: - process = new gmp::GMPProcessChild(parentPID); - break; - case GeckoProcessType_GPU: process = new gfx::GPUProcessImpl(parentPID); break; |