Bug 1368583 - Add deprecation warning for MediaKeySystemConfiguration properties no longer supported by the EME spec. r?bz
As per
Bug 1355252, the EME spec requires our
navigator.requestMediaKeySystemAccess() function to reject request for
configurations which don't contain at least one MediaKeySystemCapabilities
(audioCapabilities or videoCapabilities).
That's step 15 of this algorithm:
https://w3c.github.io/encrypted-media/#get-supported-configuration-and-consent
We also shouldn't be assuming that WebM and MP4 normatively implies a specific
set of codecs and codec constraints, as that violates step 10 of the "Get
Supported Capabilities for Audio/Video Type" algorithm.
https://w3c.github.io/encrypted-media/#get-supported-capabilities-for-audio-video-type
Making this change has the effect of causing us to reject configurations with
MediaKeySystemCapabilities where those capabilities don't specify a codec
string.
This patch adds a deprecation warning to encourage authors to make their sites
spec compliant.
MozReview-Commit-ID: 6kM9LATDfy6
--- a/dom/locales/en-US/chrome/dom/dom.properties
+++ b/dom/locales/en-US/chrome/dom/dom.properties
@@ -142,16 +142,20 @@ MediaCannotInitializePulseAudio=Unable t
# LOCALIZATION NOTE: Do not translate "MediaRecorder".
MediaRecorderMultiTracksNotSupported=MediaRecorder does not support recording multiple tracks of the same type at this time.
# LOCALIZATION NOTE: %S is the ID of the MediaStreamTrack passed to MediaStream.addTrack(). Do not translate "MediaStreamTrack" and "AudioChannel".
MediaStreamAddTrackDifferentAudioChannel=MediaStreamTrack %S could not be added since it belongs to a different AudioChannel.
# LOCALIZATION NOTE: Do not translate "MediaStream", "stop()" and "MediaStreamTrack"
MediaStreamStopDeprecatedWarning=MediaStream.stop() is deprecated and will soon be removed. Use MediaStreamTrack.stop() instead.
# LOCALIZATION NOTE: %S is the URL of the web page which is not served on HTTPS and thus is not encrypted and considered insecure.
MediaEMEInsecureContextDeprecatedWarning=Using Encrypted Media Extensions at %S on an insecure (i.e. non-HTTPS) context is deprecated and will soon be removed. You should consider switching to a secure origin such as HTTPS.
+# LOCALIZATION NOTE: %S is the URL of the web page which is not served on HTTPS and thus is not encrypted and considered insecure.
+MediaEMENoCapabilitiesDeprecatedWarning=Calling navigator.requestMediaKeySystemAccess() (at %S) without passing a candidate MediaKeySystemConfiguration containing audioCapabilities or videoCapabilities is deprecated and will soon become unsupported.
+# LOCALIZATION NOTE: %S is the URL of the web page which is not served on HTTPS and thus is not encrypted and considered insecure.
+MediaEMENoCodecsDeprecatedWarning=Calling navigator.requestMediaKeySystemAccess() (at %S) without passing a candidate MediaKeySystemConfiguration containing audioCapabilities or videoCapabilities without a contentType with a "codecs" string is deprecated and will soon become unsupported.
# LOCALIZATION NOTE: Do not translate "DOMException", "code" and "name"
DOMExceptionCodeWarning=Use of DOMException’s code attribute is deprecated. Use name instead.
# LOCALIZATION NOTE: Do not translate "__exposedProps__"
NoExposedPropsWarning=Exposing chrome JS objects to content without __exposedProps__ is insecure and deprecated. See https://developer.mozilla.org/en/XPConnect_wrappers for more information.
# LOCALIZATION NOTE: Do not translate "Mutation Event" and "MutationObserver"
MutationEventWarning=Use of Mutation Events is deprecated. Use MutationObserver instead.
# LOCALIZATION NOTE: Do not translate "Components"
ComponentsWarning=The Components object is deprecated. It will soon be removed.
--- a/dom/media/eme/MediaKeySystemAccess.cpp
+++ b/dom/media/eme/MediaKeySystemAccess.cpp
@@ -32,16 +32,17 @@
#include "WebMDecoder.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/ClearOnShutdown.h"
#include "nsUnicharUtils.h"
#include "mozilla/dom/MediaSource.h"
#ifdef MOZ_WIDGET_ANDROID
#include "FennecJNIWrappers.h"
#endif
+#include <functional>
namespace mozilla {
namespace dom {
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(MediaKeySystemAccess,
mParent)
NS_IMPL_CYCLE_COLLECTING_ADDREF(MediaKeySystemAccess)
NS_IMPL_CYCLE_COLLECTING_RELEASE(MediaKeySystemAccess)
@@ -538,21 +539,23 @@ IsParameterUnrecognized(const nsAString&
return true;
}
}
return false;
}
// 3.1.2.3 Get Supported Capabilities for Audio/Video Type
static Sequence<MediaKeySystemMediaCapability>
-GetSupportedCapabilities(const CodecType aCodecType,
- const nsTArray<MediaKeySystemMediaCapability>& aRequestedCapabilities,
- const MediaKeySystemConfiguration& aPartialConfig,
- const KeySystemConfig& aKeySystem,
- DecoderDoctorDiagnostics* aDiagnostics)
+GetSupportedCapabilities(
+ const CodecType aCodecType,
+ const nsTArray<MediaKeySystemMediaCapability>& aRequestedCapabilities,
+ const MediaKeySystemConfiguration& aPartialConfig,
+ const KeySystemConfig& aKeySystem,
+ DecoderDoctorDiagnostics* aDiagnostics,
+ const std::function<void(const char*)>& aDeprecationLogFn)
{
// Let local accumulated configuration be a local copy of partial configuration.
// (Note: It's not necessary for us to maintain a local copy, as we don't need
// to test whether capabilites from previous calls to this algorithm work with
// the capabilities currently being considered in this call. )
// Let supported media capabilities be an empty sequence of
// MediaKeySystemMediaCapability dictionaries.
@@ -655,16 +658,19 @@ GetSupportedCapabilities(const CodecType
// Let media types be the set of codecs and codec constraints specified by
// parameters. The case-sensitivity of string comparisons is determined by
// the appropriate RFC or other specification.
// (Note: codecs array is 'parameter').
// If media types is empty:
if (codecs.IsEmpty()) {
+ // Log deprecation warning to encourage authors to not do this!
+ aDeprecationLogFn("MediaEMENoCodecsDeprecatedWarning");
+ // TODO: Remove this once we're sure it doesn't break the web.
// If container normatively implies a specific set of codecs and codec constraints:
// Let parameters be that set.
if (isMP4) {
if (aCodecType == Audio) {
codecs.AppendElement(EME_CODEC_AAC);
} else if (aCodecType == Video) {
codecs.AppendElement(EME_CODEC_H264);
}
@@ -829,17 +835,18 @@ UnboxSessionTypes(const Optional<Sequenc
return sessionTypes;
}
// 3.1.2.2 Get Supported Configuration and Consent
static bool
GetSupportedConfig(const KeySystemConfig& aKeySystem,
const MediaKeySystemConfiguration& aCandidate,
MediaKeySystemConfiguration& aOutConfig,
- DecoderDoctorDiagnostics* aDiagnostics)
+ DecoderDoctorDiagnostics* aDiagnostics,
+ const std::function<void(const char*)>& aDeprecationLogFn)
{
// Let accumulated configuration be a new MediaKeySystemConfiguration dictionary.
MediaKeySystemConfiguration config;
// Set the label member of accumulated configuration to equal the label member of
// candidate configuration.
config.mLabel = aCandidate.mLabel;
// If the initDataTypes member of candidate configuration is non-empty, run the
// following steps:
@@ -936,29 +943,32 @@ GetSupportedConfig(const KeySystemConfig
}
// Set the sessionTypes member of accumulated configuration to session types.
config.mSessionTypes.Construct(Move(sessionTypes));
// If the videoCapabilities and audioCapabilities members in candidate
// configuration are both empty, return NotSupported.
// TODO: Most sites using EME still don't pass capabilities, so we
// can't reject on it yet without breaking them. So add this later.
+ // Log deprecation warning to encourage authors to not do this!
+ aDeprecationLogFn("MediaEMENoCapabilitiesDeprecatedWarning");
// If the videoCapabilities member in candidate configuration is non-empty:
if (!aCandidate.mVideoCapabilities.IsEmpty()) {
// Let video capabilities be the result of executing the Get Supported
// Capabilities for Audio/Video Type algorithm on Video, candidate
// configuration's videoCapabilities member, accumulated configuration,
// and restrictions.
Sequence<MediaKeySystemMediaCapability> caps =
GetSupportedCapabilities(Video,
aCandidate.mVideoCapabilities,
config,
aKeySystem,
- aDiagnostics);
+ aDiagnostics,
+ aDeprecationLogFn);
// If video capabilities is null, return NotSupported.
if (caps.IsEmpty()) {
EME_LOG("MediaKeySystemConfiguration (label='%s') rejected; "
"no supported video capabilities.",
NS_ConvertUTF16toUTF8(aCandidate.mLabel).get());
return false;
}
// Set the videoCapabilities member of accumulated configuration to video capabilities.
@@ -973,17 +983,18 @@ GetSupportedConfig(const KeySystemConfig
// Let audio capabilities be the result of executing the Get Supported Capabilities
// for Audio/Video Type algorithm on Audio, candidate configuration's audioCapabilities
// member, accumulated configuration, and restrictions.
Sequence<MediaKeySystemMediaCapability> caps =
GetSupportedCapabilities(Audio,
aCandidate.mAudioCapabilities,
config,
aKeySystem,
- aDiagnostics);
+ aDiagnostics,
+ aDeprecationLogFn);
// If audio capabilities is null, return NotSupported.
if (caps.IsEmpty()) {
EME_LOG("MediaKeySystemConfiguration (label='%s') rejected; "
"no supported audio capabilities.",
NS_ConvertUTF16toUTF8(aCandidate.mLabel).get());
return false;
}
// Set the audioCapabilities member of accumulated configuration to audio capabilities.
@@ -1047,30 +1058,33 @@ GetSupportedConfig(const KeySystemConfig
// Return accumulated configuration.
aOutConfig = config;
return true;
}
/* static */
bool
-MediaKeySystemAccess::GetSupportedConfig(const nsAString& aKeySystem,
- const Sequence<MediaKeySystemConfiguration>& aConfigs,
- MediaKeySystemConfiguration& aOutConfig,
- DecoderDoctorDiagnostics* aDiagnostics)
+MediaKeySystemAccess::GetSupportedConfig(
+ const nsAString& aKeySystem,
+ const Sequence<MediaKeySystemConfiguration>& aConfigs,
+ MediaKeySystemConfiguration& aOutConfig,
+ DecoderDoctorDiagnostics* aDiagnostics,
+ const std::function<void(const char*)>& aDeprecationLogFn)
{
KeySystemConfig implementation;
if (!GetKeySystemConfig(aKeySystem, implementation)) {
return false;
}
for (const MediaKeySystemConfiguration& candidate : aConfigs) {
if (mozilla::dom::GetSupportedConfig(implementation,
candidate,
aOutConfig,
- aDiagnostics)) {
+ aDiagnostics,
+ aDeprecationLogFn)) {
return true;
}
}
return false;
}
--- a/dom/media/eme/MediaKeySystemAccessManager.cpp
+++ b/dom/media/eme/MediaKeySystemAccessManager.cpp
@@ -13,16 +13,18 @@
#include "mozilla/DetailedPromise.h"
#ifdef XP_WIN
#include "mozilla/WindowsVersion.h"
#endif
#ifdef XP_MACOSX
#include "nsCocoaFeatures.h"
#endif
#include "nsPrintfCString.h"
+#include "nsContentUtils.h"
+#include "nsIScriptError.h"
namespace mozilla {
namespace dom {
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MediaKeySystemAccessManager)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_ENTRY(nsIObserver)
NS_INTERFACE_MAP_END
@@ -160,18 +162,36 @@ MediaKeySystemAccessManager::Request(Det
// Failed due to user disabling something, send a notification to
// chrome, so we can show some UI to explain how the user can rectify
// the situation.
MediaKeySystemAccess::NotifyObservers(mWindow, aKeySystem, status);
aPromise->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR, message);
return;
}
+ nsCOMPtr<nsIDocument> doc = mWindow->GetExtantDoc();
+ std::function<void(const char*)> deprecationWarningLogFn =
+ [doc](const char* aMsgName) {
+ EME_LOG("Logging deprecation warning '%s' to WebConsole.", aMsgName);
+ nsString uri;
+ if (doc) {
+ Unused << doc->GetDocumentURI(uri);
+ }
+ const char16_t* params[] = { uri.get() };
+ nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
+ NS_LITERAL_CSTRING("Media"),
+ doc,
+ nsContentUtils::eDOM_PROPERTIES,
+ aMsgName,
+ params,
+ ArrayLength(params));
+ };
MediaKeySystemConfiguration config;
- if (MediaKeySystemAccess::GetSupportedConfig(aKeySystem, aConfigs, config, &diagnostics)) {
+ if (MediaKeySystemAccess::GetSupportedConfig(
+ aKeySystem, aConfigs, config, &diagnostics, deprecationWarningLogFn)) {
RefPtr<MediaKeySystemAccess> access(
new MediaKeySystemAccess(mWindow, aKeySystem, config));
aPromise->MaybeResolve(access);
diagnostics.StoreMediaKeySystemAccess(mWindow->GetExtantDoc(),
aKeySystem, true, __func__);
return;
}
// Not to inform user, because nothing to do if the corresponding keySystem