Bug 1368583 - Add deprecation warning for MediaKeySystemConfiguration properties no longer supported by the EME spec. r?gerald draft
authorChris Pearce <cpearce@mozilla.com>
Tue, 30 May 2017 11:50:50 +1200
changeset 586240 4436cba19f9b732c5b0b0b038542bb4b8404cf8d
parent 586213 8f1c4b1bac37df93eaeff4c6407d414ed7459f3f
child 630930 3dc2dce449a122b2d3b87b18f1e720e3bfaa2188
push id61339
push userbmo:cpearce@mozilla.com
push dateTue, 30 May 2017 01:24:51 +0000
reviewersgerald
bugs1368583, 1355252
milestone55.0a1
Bug 1368583 - Add deprecation warning for MediaKeySystemConfiguration properties no longer supported by the EME spec. r?gerald 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
dom/locales/en-US/chrome/dom/dom.properties
dom/media/eme/MediaKeySystemAccess.cpp
dom/media/eme/MediaKeySystemAccessManager.cpp
--- 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 calling web APIs without passing data (either an audioCapabilities or a videoCapabilities) that will soon be required.
+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 calling web APIs without passing data (a "codecs" string in the "contentType") that will soon be required.
+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,19 @@
 #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"
+#include "mozilla/Unused.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 +163,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