Bug 1189196 - Process MediaKeySystemConfiguration in navigator.requestMediaKeySystemAccess. r=jwwang,a=lizzard
authorChris Pearce <cpearce@mozilla.com>
Tue, 27 Oct 2015 14:10:51 +1300
changeset 296701 0c3338032dc3
parent 296700 0851006030fe
child 296702 83b2962d6861
push id5296
push usercpearce@mozilla.com
push date2015-11-12 01:32 +0000
treeherdermozilla-beta@ba6b7797e925 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjwwang, lizzard
bugs1189196
milestone43.0
Bug 1189196 - Process MediaKeySystemConfiguration in navigator.requestMediaKeySystemAccess. r=jwwang,a=lizzard
dom/media/eme/MediaKeySystemAccess.cpp
dom/media/eme/MediaKeySystemAccess.h
dom/media/eme/MediaKeySystemAccessManager.cpp
--- a/dom/media/eme/MediaKeySystemAccess.cpp
+++ b/dom/media/eme/MediaKeySystemAccess.cpp
@@ -377,40 +377,119 @@ GMPDecryptsAndGeckoDecodesAAC(mozIGeckoM
     // Clearkey on Windows XP can't decode, but advertises that it can
     // in its GMP info file.
     || (aKeySystem.EqualsLiteral("org.w3.clearkey") && !IsVistaOrLater())
 #endif
     ) && MP4Decoder::CanHandleMediaType(aContentType);
 }
 
 static bool
+IsSupportedAudio(mozIGeckoMediaPluginService* aGMPService,
+                 const nsAString& aKeySystem,
+                 const nsAString& aAudioType)
+{
+  return IsAACContentType(aAudioType) &&
+         (GMPDecryptsAndDecodesAAC(aGMPService, aKeySystem) ||
+          GMPDecryptsAndGeckoDecodesAAC(aGMPService, aKeySystem, aAudioType));
+}
+
+static bool
+IsSupportedVideo(mozIGeckoMediaPluginService* aGMPService,
+                 const nsAString& aKeySystem,
+                 const nsAString& aVideoType)
+{
+  return IsH264ContentType(aVideoType) &&
+         (GMPDecryptsAndDecodesH264(aGMPService, aKeySystem) ||
+          GMPDecryptsAndGeckoDecodesH264(aGMPService, aKeySystem, aVideoType));
+}
+
+static bool
 IsSupported(mozIGeckoMediaPluginService* aGMPService,
             const nsAString& aKeySystem,
             const MediaKeySystemConfiguration& aConfig)
 {
+  if (aConfig.mInitDataType.IsEmpty() &&
+      aConfig.mAudioType.IsEmpty() &&
+      aConfig.mVideoType.IsEmpty()) {
+    // Not an old-style request.
+    return false;
+  }
+
   // Backwards compatibility with legacy MediaKeySystemConfiguration method.
   if (!aConfig.mInitDataType.IsEmpty() &&
       !aConfig.mInitDataType.EqualsLiteral("cenc")) {
     return false;
   }
   if (!aConfig.mAudioType.IsEmpty() &&
-      (!IsAACContentType(aConfig.mAudioType) ||
-       (!GMPDecryptsAndDecodesAAC(aGMPService, aKeySystem) &&
-        !GMPDecryptsAndGeckoDecodesAAC(aGMPService, aKeySystem, aConfig.mAudioType)))) {
+      !IsSupportedAudio(aGMPService, aKeySystem, aConfig.mAudioType)) {
     return false;
   }
   if (!aConfig.mVideoType.IsEmpty() &&
-      (!IsH264ContentType(aConfig.mVideoType) ||
-       (!GMPDecryptsAndDecodesH264(aGMPService, aKeySystem) &&
-        !GMPDecryptsAndGeckoDecodesH264(aGMPService, aKeySystem, aConfig.mVideoType)))) {
+      !IsSupportedVideo(aGMPService, aKeySystem, aConfig.mVideoType)) {
     return false;
   }
+
   return true;
 }
 
+static bool
+GetSupportedConfig(mozIGeckoMediaPluginService* aGMPService,
+                   const nsAString& aKeySystem,
+                   const MediaKeySystemConfiguration& aCandidate,
+                   MediaKeySystemConfiguration& aOutConfig)
+{
+  MediaKeySystemConfiguration config;
+  config.mLabel = aCandidate.mLabel;
+  if (aCandidate.mInitDataTypes.WasPassed()) {
+    nsTArray<nsString> initDataTypes;
+    for (const nsString& candidate : aCandidate.mInitDataTypes.Value()) {
+      if (candidate.EqualsLiteral("cenc")) {
+        initDataTypes.AppendElement(candidate);
+      }
+    }
+    if (initDataTypes.IsEmpty()) {
+      return false;
+    }
+    config.mInitDataTypes.Construct();
+    config.mInitDataTypes.Value().Assign(initDataTypes);
+  }
+  if (aCandidate.mAudioCapabilities.WasPassed()) {
+    nsTArray<MediaKeySystemMediaCapability> caps;
+    for (const MediaKeySystemMediaCapability& cap : aCandidate.mAudioCapabilities.Value()) {
+      if (IsSupportedAudio(aGMPService, aKeySystem, cap.mContentType)) {
+        caps.AppendElement(cap);
+      }
+    }
+    if (caps.IsEmpty()) {
+      return false;
+    }
+    config.mAudioCapabilities.Construct();
+    config.mAudioCapabilities.Value().Assign(caps);
+  }
+  if (aCandidate.mVideoCapabilities.WasPassed()) {
+    nsTArray<MediaKeySystemMediaCapability> caps;
+    for (const MediaKeySystemMediaCapability& cap : aCandidate.mVideoCapabilities.Value()) {
+      if (IsSupportedVideo(aGMPService, aKeySystem, cap.mContentType)) {
+        caps.AppendElement(cap);
+      }
+    }
+    if (caps.IsEmpty()) {
+      return false;
+    }
+    config.mVideoCapabilities.Construct();
+    config.mVideoCapabilities.Value().Assign(caps);
+  }
+
+  aOutConfig = config;
+
+  return true;
+}
+
+// Backwards compatibility with legacy requestMediaKeySystemAccess with fields
+// from old MediaKeySystemOptions dictionary.
 /* static */
 bool
 MediaKeySystemAccess::IsSupported(const nsAString& aKeySystem,
                                   const Sequence<MediaKeySystemConfiguration>& aConfigs)
 {
   nsCOMPtr<mozIGeckoMediaPluginService> mps =
     do_GetService("@mozilla.org/gecko-media-plugin-service;1");
   if (NS_WARN_IF(!mps)) {
@@ -427,16 +506,44 @@ MediaKeySystemAccess::IsSupported(const 
     if (mozilla::dom::IsSupported(mps, aKeySystem, config)) {
       return true;
     }
   }
   return false;
 }
 
 /* static */
+bool
+MediaKeySystemAccess::GetSupportedConfig(const nsAString& aKeySystem,
+                                         const Sequence<MediaKeySystemConfiguration>& aConfigs,
+                                         MediaKeySystemConfiguration& aOutConfig)
+{
+  nsCOMPtr<mozIGeckoMediaPluginService> mps =
+    do_GetService("@mozilla.org/gecko-media-plugin-service;1");
+  if (NS_WARN_IF(!mps)) {
+    return false;
+  }
+
+  if (!HaveGMPFor(mps,
+                  NS_ConvertUTF16toUTF8(aKeySystem),
+                  NS_LITERAL_CSTRING(GMP_API_DECRYPTOR))) {
+    return false;
+  }
+
+  for (const MediaKeySystemConfiguration& config : aConfigs) {
+    if (mozilla::dom::GetSupportedConfig(mps, aKeySystem, config, aOutConfig)) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
+
+/* static */
 void
 MediaKeySystemAccess::NotifyObservers(nsIDOMWindow* aWindow,
                                       const nsAString& aKeySystem,
                                       MediaKeySystemStatus aStatus)
 {
   RequestMediaKeySystemAccessNotification data;
   data.mKeySystem = aKeySystem;
   data.mStatus = aStatus;
--- a/dom/media/eme/MediaKeySystemAccess.h
+++ b/dom/media/eme/MediaKeySystemAccess.h
@@ -40,17 +40,17 @@ protected:
 public:
   nsPIDOMWindow* GetParentObject() const;
 
   virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   void GetKeySystem(nsString& aRetVal) const;
 
   void GetConfiguration(MediaKeySystemConfiguration& aConfig);
-  
+
   already_AddRefed<Promise> CreateMediaKeys(ErrorResult& aRv);
 
 
 
   static MediaKeySystemStatus GetKeySystemStatus(const nsAString& aKeySystem,
                                                  int32_t aMinCdmVersion,
                                                  nsACString& aOutExceptionMessage,
                                                  nsACString& aOutCdmVersion);
@@ -61,16 +61,20 @@ public:
   static void NotifyObservers(nsIDOMWindow* aWindow,
                               const nsAString& aKeySystem,
                               MediaKeySystemStatus aStatus);
 
   static bool IsGMPPresentOnDisk(const nsAString& aKeySystem,
                                  const nsACString& aVersion,
                                  nsACString& aOutMessage);
 
+  static bool GetSupportedConfig(const nsAString& aKeySystem,
+                                 const Sequence<MediaKeySystemConfiguration>& aConfigs,
+                                 MediaKeySystemConfiguration& aOutConfig);
+
 private:
   nsCOMPtr<nsPIDOMWindow> mParent;
   const nsString mKeySystem;
   const nsString mCDMVersion;
   const MediaKeySystemConfiguration mConfig;
 };
 
 } // namespace dom
--- a/dom/media/eme/MediaKeySystemAccessManager.cpp
+++ b/dom/media/eme/MediaKeySystemAccessManager.cpp
@@ -170,17 +170,19 @@ MediaKeySystemAccessManager::Request(Det
       return;
     }
     aPromise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR,
                           NS_LITERAL_CSTRING("GetKeySystemAccess failed"));
     return;
   }
 
   MediaKeySystemConfiguration config;
-  if (aConfigs.IsEmpty() ||
+  // TODO: Remove IsSupported() check here once we remove backwards
+  // compatibility with initial implementation...
+  if (MediaKeySystemAccess::GetSupportedConfig(keySystem, aConfigs, config) ||
       MediaKeySystemAccess::IsSupported(keySystem, aConfigs)) {
     nsRefPtr<MediaKeySystemAccess> access(
       new MediaKeySystemAccess(mWindow, keySystem, NS_ConvertUTF8toUTF16(cdmVersion), config));
     if (ShouldTrialCreateGMP(keySystem)) {
       // Ensure we have tried creating a GMPVideoDecoder for this
       // keySystem, and that we can use it to decode. This ensures that we only
       // report that we support this keySystem when the CDM us usable.
       mTrialCreator->MaybeAwaitTrialCreate(keySystem, access, aPromise, mWindow);