Backed out changeset 5d60f3e1f6cf (bug 1067216) for breaking the build
authorWes Kocher <wkocher@mozilla.com>
Mon, 13 Oct 2014 14:48:44 -0700
changeset 210237 40394288cb644aee43b7a14af03ab4a5755a1593
parent 210236 04849554535270e21b54ef4aaf4600a06bbba069
child 210238 3d859600949d0aeac0b829acc3facb8083ed69d9
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
bugs1067216
milestone35.0a1
backs out5d60f3e1f6cf2cb5630070916b13b3da1b644818
Backed out changeset 5d60f3e1f6cf (bug 1067216) for breaking the build
content/media/eme/MediaKeys.cpp
content/media/eme/MediaKeys.h
content/media/gmp/GMPService.cpp
content/media/gmp/GMPService.h
content/media/gmp/mozIGeckoMediaPluginService.idl
content/media/test/test_encryptedMediaExtensions.html
media/webrtc/signaling/src/media/VcmSIPCCBinding.cpp
--- a/content/media/eme/MediaKeys.cpp
+++ b/content/media/eme/MediaKeys.cpp
@@ -11,24 +11,19 @@
 #include "mozilla/dom/MediaKeyError.h"
 #include "mozilla/dom/MediaKeySession.h"
 #include "mozilla/dom/DOMException.h"
 #include "mozilla/CDMProxy.h"
 #include "mozilla/EMELog.h"
 #include "nsContentUtils.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "mozilla/Preferences.h"
-#include "nsContentTypeParser.h"
-#include "MP4Decoder.h"
 #ifdef XP_WIN
 #include "mozilla/WindowsVersion.h"
 #endif
-#include "nsContentCID.h"
-#include "nsServiceManagerUtils.h"
-#include "mozIGeckoMediaPluginService.h"
 
 namespace mozilla {
 
 namespace dom {
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(MediaKeys,
                                       mElement,
                                       mParent,
@@ -107,114 +102,39 @@ MediaKeys::SetServerCertificate(const Ar
     return promise.forget();
   }
 
   mProxy->SetServerCertificate(StorePromise(promise), data);
   return promise.forget();
 }
 
 static bool
-HaveGMPFor(const nsCString& aKeySystem,
-           const nsCString& aAPI,
-           const nsCString& aTag = EmptyCString())
-{
-  nsCOMPtr<mozIGeckoMediaPluginService> mps =
-    do_GetService("@mozilla.org/gecko-media-plugin-service;1");
-  if (NS_WARN_IF(!mps)) {
-    return false;
-  }
-
-  nsTArray<nsCString> tags;
-  tags.AppendElement(aKeySystem);
-  if (!aTag.IsEmpty()) {
-    tags.AppendElement(aTag);
-  }
-  // Note: EME plugins need a non-null nodeId here, as they must
-  // not be shared across origins.
-  bool hasPlugin = false;
-  if (NS_FAILED(mps->HasPluginForAPI(aAPI,
-                                     &tags,
-                                     &hasPlugin))) {
-    return false;
-  }
-  return hasPlugin;
-}
-
-static bool
-IsPlayableMP4Type(const nsAString& aContentType)
+IsSupportedKeySystem(const nsAString& aKeySystem)
 {
-  nsContentTypeParser parser(aContentType);
-  nsAutoString mimeType;
-  nsresult rv = parser.GetType(mimeType);
-  if (NS_FAILED(rv)) {
-    return false;
-  }
-  nsAutoString codecs;
-  parser.GetParameter("codecs", codecs);
-
-  NS_ConvertUTF16toUTF8 mimeTypeUTF8(mimeType);
-  return MP4Decoder::CanHandleMediaType(mimeTypeUTF8, codecs);
-}
-
-bool
-MediaKeys::IsTypeSupported(const nsAString& aKeySystem,
-                           const Optional<nsAString>& aInitDataType,
-                           const Optional<nsAString>& aContentType)
-{
-  if (aKeySystem.EqualsLiteral("org.w3.clearkey") &&
-      (!aInitDataType.WasPassed() || aInitDataType.Value().EqualsLiteral("cenc")) &&
-      (!aContentType.WasPassed() || IsPlayableMP4Type(aContentType.Value())) &&
-      HaveGMPFor(NS_LITERAL_CSTRING("org.w3.clearkey"),
-                 NS_LITERAL_CSTRING("eme-decrypt"))) {
-    return true;
-  }
-
+  return aKeySystem.EqualsASCII("org.w3.clearkey") ||
 #ifdef XP_WIN
-  // Note: Adobe Access's GMP uses WMF to decode, so anything our MP4Reader
-  // thinks it can play on Windows, the Access GMP should be able to play.
-  if (aKeySystem.EqualsLiteral("com.adobe.access") &&
-      Preferences::GetBool("media.eme.adobe-access.enabled", false) &&
-      IsVistaOrLater() && // Win Vista and later only.
-      (!aInitDataType.WasPassed() || aInitDataType.Value().EqualsLiteral("cenc")) &&
-      (!aContentType.WasPassed() || IsPlayableMP4Type(aContentType.Value())) &&
-      HaveGMPFor(NS_LITERAL_CSTRING("com.adobe.access"),
-                 NS_LITERAL_CSTRING("eme-decrypt")) &&
-      HaveGMPFor(NS_LITERAL_CSTRING("com.adobe.access"),
-                 NS_LITERAL_CSTRING("decode-video"),
-                 NS_LITERAL_CSTRING("h264")) &&
-      HaveGMPFor(NS_LITERAL_CSTRING("com.adobe.access"),
-                 NS_LITERAL_CSTRING("decode-audio"),
-                 NS_LITERAL_CSTRING("aac"))) {
-      return true;
-  }
+         (aKeySystem.EqualsASCII("com.adobe.access") &&
+          IsVistaOrLater() &&
+          Preferences::GetBool("media.eme.adobe-access.enabled", false)) ||
 #endif
-
-  return false;
+         false;
 }
 
 /* static */
 IsTypeSupportedResult
 MediaKeys::IsTypeSupported(const GlobalObject& aGlobal,
                            const nsAString& aKeySystem,
                            const Optional<nsAString>& aInitDataType,
                            const Optional<nsAString>& aContentType,
                            const Optional<nsAString>& aCapability)
 {
   // TODO: Should really get spec changed to this is async, so we can wait
   //       for user to consent to running plugin.
-  bool supported = IsTypeSupported(aKeySystem, aInitDataType, aContentType);
-
-  EME_LOG("MediaKeys::IsTypeSupported keySystem='%s' initDataType='%s' contentType='%s' supported=%d",
-          NS_ConvertUTF16toUTF8(aKeySystem).get(),
-          (aInitDataType.WasPassed() ? NS_ConvertUTF16toUTF8(aInitDataType.Value()).get() : ""),
-          (aContentType.WasPassed() ? NS_ConvertUTF16toUTF8(aContentType.Value()).get() : ""),
-          supported);
-
-  return supported ? IsTypeSupportedResult::Probably
-                   : IsTypeSupportedResult::_empty;
+  return IsSupportedKeySystem(aKeySystem) ? IsTypeSupportedResult::Maybe
+                                          : IsTypeSupportedResult::_empty;
 }
 
 already_AddRefed<Promise>
 MediaKeys::MakePromise(ErrorResult& aRv)
 {
   nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject());
   if (!global) {
     NS_WARNING("Passed non-global to MediaKeys ctor!");
@@ -317,17 +237,17 @@ MediaKeys::Create(const GlobalObject& aG
 already_AddRefed<Promise>
 MediaKeys::Init(ErrorResult& aRv)
 {
   nsRefPtr<Promise> promise(MakePromise(aRv));
   if (aRv.Failed()) {
     return nullptr;
   }
 
-  if (!IsTypeSupported(mKeySystem)) {
+  if (!IsSupportedKeySystem(mKeySystem)) {
     promise->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
     return promise.forget();
   }
 
   mProxy = new CDMProxy(this, mKeySystem);
 
   // Determine principal (at creation time) of the MediaKeys object.
   nsCOMPtr<nsIScriptObjectPrincipal> sop = do_QueryInterface(GetParentObject());
@@ -346,17 +266,17 @@ MediaKeys::Init(ErrorResult& aRv)
   }
   nsCOMPtr<nsIDOMWindow> topWindow;
   window->GetTop(getter_AddRefs(topWindow));
   nsCOMPtr<nsPIDOMWindow> top = do_QueryInterface(topWindow);
   if (!top || !top->GetExtantDoc()) {
     promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
     return promise.forget();
   }
-
+  
   mTopLevelPrincipal = top->GetExtantDoc()->NodePrincipal();
 
   if (!mPrincipal || !mTopLevelPrincipal) {
     NS_WARNING("Failed to get principals when creating MediaKeys");
     promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
     return promise.forget();
   }
 
--- a/content/media/eme/MediaKeys.h
+++ b/content/media/eme/MediaKeys.h
@@ -119,20 +119,16 @@ public:
   bool IsBoundToMediaElement() const;
 
   // Return NS_OK if the principals are the same as when the MediaKeys
   // was created, failure otherwise.
   nsresult CheckPrincipals();
 
 private:
 
-  static bool IsTypeSupported(const nsAString& aKeySystem,
-                              const Optional<nsAString>& aInitDataType = Optional<nsAString>(),
-                              const Optional<nsAString>& aContentType = Optional<nsAString>());
-
   bool IsInPrivateBrowsing();
   already_AddRefed<Promise> Init(ErrorResult& aRv);
 
   // Removes promise from mPromises, and returns it.
   already_AddRefed<Promise> RetrievePromise(PromiseId aId);
 
   // Owning ref to proxy. The proxy has a weak reference back to the MediaKeys,
   // and the MediaKeys destructor clears the proxy's reference to the MediaKeys.
--- a/content/media/gmp/GMPService.cpp
+++ b/content/media/gmp/GMPService.cpp
@@ -138,17 +138,16 @@ NS_IMPL_ISUPPORTS(GeckoMediaPluginServic
 
 #define GMP_DEFAULT_ASYNC_SHUTDONW_TIMEOUT 3000
 static int32_t sMaxAsyncShutdownWaitMs = 0;
 
 GeckoMediaPluginService::GeckoMediaPluginService()
   : mMutex("GeckoMediaPluginService::mMutex")
   , mShuttingDown(false)
   , mShuttingDownOnGMPThread(false)
-  , mScannedPluginOnDisk(false)
   , mWaitingForPluginsAsyncShutdown(false)
 {
   MOZ_ASSERT(NS_IsMainThread());
   static bool setTimeoutPrefCache = false;
   if (!setTimeoutPrefCache) {
     setTimeoutPrefCache = true;
     Preferences::AddIntVarCache(&sMaxAsyncShutdownWaitMs,
                                 "media.gmp.async-shutdown-timeout",
@@ -648,18 +647,16 @@ GeckoMediaPluginService::LoadFromEnviron
     if (next == -1) {
       AddOnGMPThread(nsDependentSubstring(allpaths, pos));
       break;
     } else {
       AddOnGMPThread(nsDependentSubstring(allpaths, pos, next - pos));
       pos = next + 1;
     }
   }
-
-  mScannedPluginOnDisk = true;
 }
 
 NS_IMETHODIMP
 GeckoMediaPluginService::PathRunnable::Run()
 {
   if (mAdd) {
     mService->AddOnGMPThread(mPath);
   } else {
@@ -691,119 +688,76 @@ GeckoMediaPluginService::RemovePluginDir
   if (NS_FAILED(rv)) {
     return rv;
   }
   nsCOMPtr<nsIRunnable> r = new PathRunnable(this, aDirectory, false);
   thread->Dispatch(r, NS_DISPATCH_NORMAL);
   return NS_OK;
 }
 
-class DummyRunnable : public nsRunnable {
-public:
-  NS_IMETHOD Run() { return NS_OK; }
-};
-
 NS_IMETHODIMP
-GeckoMediaPluginService::HasPluginForAPI(const nsACString& aAPI,
+GeckoMediaPluginService::HasPluginForAPI(const nsACString& aNodeId,
+                                         const nsACString& aAPI,
                                          nsTArray<nsCString>* aTags,
                                          bool* aResult)
 {
   NS_ENSURE_ARG(aTags && aTags->Length() > 0);
   NS_ENSURE_ARG(aResult);
 
-  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.
-    nsCOMPtr<nsIThread> thread;
-    nsresult rv = GetThread(getter_AddRefs(thread));
-    if (NS_FAILED(rv)) {
-      return rv;
-    }
-    thread->Dispatch(new DummyRunnable(), NS_DISPATCH_SYNC);
-    MOZ_ASSERT(mScannedPluginOnDisk, "Should have scanned MOZ_GMP_PATH by now");
-  }
-
-  {
-    MutexAutoLock lock(mMutex);
-    nsCString api(aAPI);
-    GMPParent* gmp = FindPluginForAPIFrom(0, api, *aTags, nullptr);
-    *aResult = (gmp != nullptr);
-  }
+  nsCString temp(aAPI);
+  GMPParent *parent = SelectPluginForAPI(aNodeId, temp, *aTags, false);
+  *aResult = !!parent;
 
   return NS_OK;
 }
 
 GMPParent*
-GeckoMediaPluginService::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++) {
-    GMPParent* gmp = mPlugins[i];
-    bool supportsAllTags = true;
-    for (uint32_t t = 0; t < aTags.Length(); t++) {
-      const nsCString& tag = aTags.ElementAt(t);
-      if (!gmp->SupportsAPI(aAPI, tag)) {
-        supportsAllTags = false;
-        break;
-      }
-    }
-    if (!supportsAllTags) {
-      continue;
-    }
-    if (aOutPluginIndex) {
-      *aOutPluginIndex = i;
-    }
-    return gmp;
-  }
-  return nullptr;
-}
-
-GMPParent*
 GeckoMediaPluginService::SelectPluginForAPI(const nsACString& aNodeId,
                                             const nsCString& aAPI,
-                                            const nsTArray<nsCString>& aTags)
+                                            const nsTArray<nsCString>& aTags,
+                                            bool aCloneCrossNodeIds)
 {
-  MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread,
+  MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread || !aCloneCrossNodeIds,
              "Can't clone GMP plugins on non-GMP threads.");
 
   GMPParent* gmpToClone = nullptr;
   {
     MutexAutoLock lock(mMutex);
-    size_t index = 0;
-    GMPParent* gmp = nullptr;
-    while ((gmp = FindPluginForAPIFrom(index, aAPI, aTags, &index))) {
+    for (uint32_t i = 0; i < mPlugins.Length(); i++) {
+      GMPParent* gmp = mPlugins[i];
+      bool supportsAllTags = true;
+      for (uint32_t t = 0; t < aTags.Length(); t++) {
+        const nsCString& tag = aTags[t];
+        if (!gmp->SupportsAPI(aAPI, tag)) {
+          supportsAllTags = false;
+          break;
+        }
+      }
+      if (!supportsAllTags) {
+        continue;
+      }
       if (aNodeId.IsEmpty()) {
         if (gmp->CanBeSharedCrossNodeIds()) {
           return gmp;
         }
       } else if (gmp->CanBeUsedFrom(aNodeId)) {
         MOZ_ASSERT(!aNodeId.IsEmpty());
         gmp->SetNodeId(aNodeId);
         return gmp;
       }
 
-      // This GMP has the correct type but has the wrong nodeId; hold on to it
+      // This GMP has the correct type but has the wrong origin; hold on to it
       // in case we need to clone it.
       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) {
+  if (aCloneCrossNodeIds && gmpToClone) {
     GMPParent* clone = ClonePlugin(gmpToClone);
     if (!aNodeId.IsEmpty()) {
       clone->SetNodeId(aNodeId);
     }
     return clone;
   }
 
   return nullptr;
--- a/content/media/gmp/GMPService.h
+++ b/content/media/gmp/GMPService.h
@@ -14,17 +14,16 @@
 #include "mozilla/Monitor.h"
 #include "nsString.h"
 #include "nsCOMPtr.h"
 #include "nsIThread.h"
 #include "nsThreadUtils.h"
 #include "nsITimer.h"
 #include "nsClassHashtable.h"
 #include "nsDataHashtable.h"
-#include "mozilla/Atomics.h"
 
 template <class> struct already_AddRefed;
 
 namespace mozilla {
 namespace gmp {
 
 class GMPParent;
 
@@ -45,21 +44,18 @@ public:
   void AsyncShutdownComplete(GMPParent* aParent);
   void AbortAsyncShutdown();
 
 private:
   ~GeckoMediaPluginService();
 
   GMPParent* SelectPluginForAPI(const nsACString& aNodeId,
                                 const nsCString& aAPI,
-                                const nsTArray<nsCString>& aTags);
-  GMPParent* FindPluginForAPIFrom(size_t aSearchStartIndex,
-                                  const nsCString& aAPI,
-                                  const nsTArray<nsCString>& aTags,
-                                  size_t* aOutPluginIndex);
+                                const nsTArray<nsCString>& aTags,
+                                bool aCloneCrossNodeIds = true);
 
   void UnloadPlugins();
   void CrashPlugins();
   void SetAsyncShutdownComplete();
 
   void LoadFromEnvironment();
   void ProcessPossiblePlugin(nsIFile* aDir);
 
@@ -93,20 +89,16 @@ private:
   };
 
   Mutex mMutex; // Protects mGMPThread and mShuttingDown and mPlugins
   nsTArray<nsRefPtr<GMPParent>> mPlugins;
   nsCOMPtr<nsIThread> mGMPThread;
   bool mShuttingDown;
   bool mShuttingDownOnGMPThread;
 
-  // 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());
--- a/content/media/gmp/mozIGeckoMediaPluginService.idl
+++ b/content/media/gmp/mozIGeckoMediaPluginService.idl
@@ -21,31 +21,33 @@ class GMPVideoHost;
 [ptr] native GMPVideoDecoderProxy(GMPVideoDecoderProxy);
 [ptr] native GMPVideoEncoderProxy(GMPVideoEncoderProxy);
 [ptr] native GMPVideoHost(GMPVideoHost);
 [ptr] native MessageLoop(MessageLoop);
 [ptr] native TagArray(nsTArray<nsCString>);
 [ptr] native GMPDecryptorProxy(GMPDecryptorProxy);
 [ptr] native GMPAudioDecoderProxy(GMPAudioDecoderProxy);
 
-[scriptable, uuid(657443a4-6b5d-4181-98b0-56997b35bd57)]
+[scriptable, uuid(b350d3b6-00c9-4602-bdfe-84c2be8d1e7a)]
 interface mozIGeckoMediaPluginService : nsISupports
 {
 
   /**
    * The GMP thread. Callable from any thread.
    */
   readonly attribute nsIThread thread;
 
   /**
    * Get a plugin that supports the specified tags.
    * Callable on any thread
    */
   [noscript]
-  boolean hasPluginForAPI(in ACString api, in TagArray tags);
+  boolean hasPluginForAPI([optional] in ACString nodeId,
+                          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.
    */
   [noscript]
--- a/content/media/test/test_encryptedMediaExtensions.html
+++ b/content/media/test/test_encryptedMediaExtensions.html
@@ -115,19 +115,16 @@ function startTest(test, token)
        "MediaKeys should support this keysystem");
 
     MediaKeys.create(KEYSYSTEM_TYPE).then(function(mediaKeys) {
       info("created MediaKeys object ok");
       return v.setMediaKeys(mediaKeys);
     }, bail("failed to create MediaKeys object")).then(function() {
       info("set MediaKeys on <video> element ok");
 
-      ok(MediaKeys.isTypeSupported(KEYSYSTEM_TYPE, ev.initDataType, test.type),
-         "MediaKeys should still support keysystem after CDM created...");
-
       var session = v.mediaKeys.createSession(test.sessionType);
       session.addEventListener("message", UpdateSessionFunc(test));
       session.generateRequest(ev.initDataType, ev.initData).then(function() {
       }, bail("Failed to initialise MediaKeySession"));
 
     }, bail("Failed to set MediaKeys on <video> element"));
   });
 
@@ -137,33 +134,17 @@ function startTest(test, token)
   });
 
   v.addEventListener("error", bail("got error event"));
 
   v.src = test.name;
   v.play();
 }
 
-function testIsTypeSupported()
-{
-  var t = MediaKeys.isTypeSupported;
-  const clearkey = "org.w3.clearkey";
-  ok(!t("bogus", "bogon", "video/bogus"), "Invalid type.");
-  ok(t(clearkey), "ClearKey supported.");
-  ok(!t(clearkey, "bogus"), "ClearKey bogus initDataType not supported.");
-  ok(t(clearkey, "cenc"), "ClearKey/cenc should be supported.");
-  ok(!t(clearkey, "cenc", "bogus"), "ClearKey/cenc bogus content type should be supported.");
-  ok(t(clearkey, "cenc", 'video/mp4'), "ClearKey/cenc video/mp4 supported.");
-  ok(t(clearkey, "cenc", 'video/mp4; codecs="avc1.4d4015,mp4a.40.2"'), "ClearKey/cenc H.264/AAC supported.");
-  ok(t(clearkey, "cenc", 'audio/mp4'), "ClearKey/cenc audio/mp4 supported.");
-  ok(t(clearkey, "cenc", 'audio/mp4; codecs="mp4a.40.2"'), "ClearKey/cenc AAC LC supported.");
-}
-
 function beginTest() {
-  testIsTypeSupported();
   manager.runTests(gEMETests, startTest);
 }
 
 var prefs = [ ];
 
 if (/Linux/.test(navigator.userAgent) ||
     !document.createElement('video').canPlayType("video/mp4")) {
   // XXX remove once we have mp4 PlatformDecoderModules on all platforms.
--- a/media/webrtc/signaling/src/media/VcmSIPCCBinding.cpp
+++ b/media/webrtc/signaling/src/media/VcmSIPCCBinding.cpp
@@ -198,24 +198,26 @@ int VcmSIPCCBinding::getVideoCodecsGmp()
   // XXX I'd prefer if this was all known ahead of time...
 
   nsTArray<nsCString> tags;
   tags.AppendElement(NS_LITERAL_CSTRING("h264"));
 
   // H.264 only for now
   bool has_gmp;
   nsresult rv;
-  rv = gSelf->mGMPService->HasPluginForAPI(NS_LITERAL_CSTRING("encode-video"),
+  rv = gSelf->mGMPService->HasPluginForAPI(NS_LITERAL_CSTRING(""),
+                                           NS_LITERAL_CSTRING("encode-video"),
                                            &tags,
                                            &has_gmp);
   if (NS_FAILED(rv) || !has_gmp) {
     return 0;
   }
 
-  rv = gSelf->mGMPService->HasPluginForAPI(NS_LITERAL_CSTRING("decode-video"),
+  rv = gSelf->mGMPService->HasPluginForAPI(NS_LITERAL_CSTRING(""),
+                                           NS_LITERAL_CSTRING("decode-video"),
                                            &tags,
                                            &has_gmp);
   if (NS_FAILED(rv) || !has_gmp) {
     return 0;
   }
 
   return VCM_CODEC_RESOURCE_H264;
 }