Bug 1245789 - Parse Chrome CDM manifest in GMPService.addPluginDir. r=gerald,a=ritu
authorChris Pearce <cpearce@mozilla.com>
Tue, 12 Apr 2016 16:12:21 +1200
changeset 325938 b03196c1e2dad1dc6efdc1b22f91cc93d13fb355
parent 325937 772542e1bddcbc6099f0ff14b92de3a6c5f87628
child 325939 ab2a0c597daf60f87bd4ef4a3064a77009c36d85
push id1128
push userjlund@mozilla.com
push dateWed, 01 Jun 2016 01:31:59 +0000
treeherdermozilla-release@fe0d30de989d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgerald, ritu
bugs1245789
milestone47.0a2
Bug 1245789 - Parse Chrome CDM manifest in GMPService.addPluginDir. r=gerald,a=ritu This has to happen on the main thread, as WebIDL parsing only happens there. So it has to be async. MozReview-Commit-ID: AfAoSkQAhl3
dom/media/gmp/GMPParent.cpp
dom/media/gmp/GMPParent.h
dom/media/gmp/GMPUtils.cpp
dom/media/gmp/GMPUtils.h
--- a/dom/media/gmp/GMPParent.cpp
+++ b/dom/media/gmp/GMPParent.cpp
@@ -17,28 +17,30 @@
 #include "mozilla/unused.h"
 #include "nsIObserverService.h"
 #include "GMPTimerParent.h"
 #include "runnable_utils.h"
 #if defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX)
 #include "mozilla/SandboxInfo.h"
 #endif
 #include "GMPContentParent.h"
+#include "widevine-adapter/WidevineAdapter.h"
 
 #include "mozilla/dom/CrashReporterParent.h"
 using mozilla::dom::CrashReporterParent;
 using mozilla::ipc::GeckoChildProcessHost;
 
 #ifdef MOZ_CRASHREPORTER
 #include "nsPrintfCString.h"
 using CrashReporter::AnnotationTable;
 using CrashReporter::GetIDFromMinidump;
 #endif
 
 #include "mozilla/Telemetry.h"
+#include "mozilla/dom/WidevineCDMManifestBinding.h"
 
 namespace mozilla {
 
 #undef LOG
 #undef LOGD
 
 extern LogModule* GetGMPLog();
 #define LOG(level, x, ...) MOZ_LOG(GetGMPLog(), (level), (x, ##__VA_ARGS__))
@@ -777,17 +779,24 @@ GMPParent::ReadGMPMetaData()
     return InitPromise::CreateAndReject(rv, __func__);
   }
   infoFile->AppendRelativePath(mName + NS_LITERAL_STRING(".info"));
 
   if (FileExists(infoFile)) {
     return ReadGMPInfoFile(infoFile);
   }
 
-  return InitPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
+  // Maybe this is the Widevine adapted plugin?
+  nsCOMPtr<nsIFile> manifestFile;
+  rv = mDirectory->Clone(getter_AddRefs(manifestFile));
+  if (NS_FAILED(rv)) {
+    return InitPromise::CreateAndReject(rv, __func__);
+  }
+  manifestFile->AppendRelativePath(NS_LITERAL_STRING("manifest.json"));
+  return ReadChromiumManifestFile(manifestFile);
 }
 
 RefPtr<GMPParent::InitPromise>
 GMPParent::ReadGMPInfoFile(nsIFile* aFile)
 {
   GMPInfoFileParser parser;
   if (!parser.Init(aFile)) {
     return InitPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
@@ -877,16 +886,73 @@ GMPParent::ReadGMPInfoFile(nsIFile* aFil
 
   if (mCapabilities.IsEmpty()) {
     return InitPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
   }
 
   return InitPromise::CreateAndResolve(NS_OK, __func__);
 }
 
+RefPtr<GMPParent::InitPromise>
+GMPParent::ReadChromiumManifestFile(nsIFile* aFile)
+{
+  nsAutoCString json;
+  if (!ReadIntoString(aFile, json, 5 * 1024)) {
+    return InitPromise::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<GMPParent::InitPromise>
+GMPParent::ParseChromiumManifest(nsString aJSON)
+{
+  LOGD("%s: for '%s'", __FUNCTION__, NS_LossyConvertUTF16toASCII(aJSON).get());
+
+  MOZ_ASSERT(NS_IsMainThread());
+  mozilla::dom::WidevineCDMManifest m;
+  if (!m.Init(aJSON)) {
+    return InitPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
+  }
+
+  nsresult ignored; // Note: ToInteger returns 0 on failure.
+  if (!WidevineAdapter::Supports(m.mX_cdm_module_versions.ToInteger(&ignored),
+                                 m.mX_cdm_interface_versions.ToInteger(&ignored),
+                                 m.mX_cdm_host_versions.ToInteger(&ignored))) {
+    return InitPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
+  }
+
+  mDisplayName = NS_ConvertUTF16toUTF8(m.mName);
+  mDescription = NS_ConvertUTF16toUTF8(m.mDescription);
+  mVersion = NS_ConvertUTF16toUTF8(m.mVersion);
+
+  GMPCapability audio(NS_LITERAL_CSTRING(GMP_API_AUDIO_DECODER));
+  audio.mAPITags.AppendElement(NS_LITERAL_CSTRING("aac"));
+  audio.mAPITags.AppendElement(NS_LITERAL_CSTRING("com.widevine.alpha"));
+  mCapabilities.AppendElement(Move(audio));
+
+  GMPCapability video(NS_LITERAL_CSTRING(GMP_API_VIDEO_DECODER));
+  video.mAPITags.AppendElement(NS_LITERAL_CSTRING("h264"));
+  video.mAPITags.AppendElement(NS_LITERAL_CSTRING("com.widevine.alpha"));
+  mCapabilities.AppendElement(Move(video));
+
+  GMPCapability decrypt(NS_LITERAL_CSTRING(GMP_API_DECRYPTOR));
+  decrypt.mAPITags.AppendElement(NS_LITERAL_CSTRING("com.widevine.alpha"));
+  mCapabilities.AppendElement(Move(decrypt));
+
+  MOZ_ASSERT(mName.EqualsLiteral("widevinecdm"));
+#ifdef XP_WIN
+  mLibs = NS_LITERAL_CSTRING("dxva2.dll");
+#endif
+
+  return InitPromise::CreateAndResolve(NS_OK, __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
--- a/dom/media/gmp/GMPParent.h
+++ b/dom/media/gmp/GMPParent.h
@@ -159,20 +159,23 @@ public:
   already_AddRefed<GMPContentParent> ForgetGMPContentParent();
 
   bool EnsureProcessLoaded(base::ProcessId* aID);
 
   bool Bridge(GMPServiceParent* aGMPServiceParent);
 
 private:
   ~GMPParent();
+
   RefPtr<GeckoMediaPluginServiceParent> mService;
   bool EnsureProcessLoaded();
   RefPtr<InitPromise> ReadGMPMetaData();
   RefPtr<InitPromise> ReadGMPInfoFile(nsIFile* aFile);
+  RefPtr<InitPromise> ReadChromiumManifestFile(nsIFile* aFile);
+  RefPtr<InitPromise> ParseChromiumManifest(nsString aJSON); // Main thread.
 #ifdef MOZ_CRASHREPORTER
   void WriteExtraDataForMinidump(CrashReporter::AnnotationTable& notes);
   void GetCrashID(nsString& aResult);
 #endif
   void ActorDestroy(ActorDestroyReason aWhy) override;
 
   PCrashReporterParent* AllocPCrashReporterParent(const NativeThreadId& aThread) override;
   bool DeallocPCrashReporterParent(PCrashReporterParent* aCrashReporter) override;
--- a/dom/media/gmp/GMPUtils.cpp
+++ b/dom/media/gmp/GMPUtils.cpp
@@ -133,17 +133,17 @@ ReadIntoArray(nsIFile* aFile,
     return false;
   }
   aOutDst.SetLength(length);
   int32_t bytesRead = PR_Read(fd, aOutDst.Elements(), length);
   PR_Close(fd);
   return (bytesRead == length);
 }
 
-static bool
+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.
--- a/dom/media/gmp/GMPUtils.h
+++ b/dom/media/gmp/GMPUtils.h
@@ -70,11 +70,16 @@ 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);
+
 } // namespace mozilla
 
 #endif