Bug 1247763 - Remove info file parsing from GMP child process. r=gerald
authorChris Pearce <cpearce@mozilla.com>
Wed, 24 Feb 2016 07:21:47 +1300
changeset 285192 c8f8ffd1c0c0c0b502fce43f790cdbbcb90693e4
parent 285191 755b9088813c3553b99b8151b2bf5dac1f95cb4e
child 285193 edb99456bccb2f5e626b48e63a4360d494e4df17
push id72265
push usercpearce@mozilla.com
push dateTue, 23 Feb 2016 18:23:09 +0000
treeherdermozilla-inbound@c8f8ffd1c0c0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgerald
bugs1247763
milestone47.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1247763 - Remove info file parsing from GMP child process. r=gerald The only reason we need to parse the info file in the GMP child process is because we need to read the "Libs:" line so that the child process can preload DLLs on Windows. We already parse the GMP info file in the parent process, so we can remove the need to parse it again if we parse the "Libs" field in the parent, and pass that through to the child.
dom/media/gmp/GMPChild.cpp
dom/media/gmp/GMPChild.h
dom/media/gmp/GMPParent.cpp
dom/media/gmp/GMPParent.h
dom/media/gmp/PGMP.ipdl
--- a/dom/media/gmp/GMPChild.cpp
+++ b/dom/media/gmp/GMPChild.cpp
@@ -132,27 +132,16 @@ static bool
 GetPluginFile(const nsAString& aPluginPath,
               nsCOMPtr<nsIFile>& aLibFile)
 {
   nsCOMPtr<nsIFile> unusedlibDir;
   return GetPluginFile(aPluginPath, unusedlibDir, aLibFile);
 }
 #endif
 
-static bool
-GetInfoFile(const nsAString& aPluginPath,
-            nsCOMPtr<nsIFile>& aInfoFile)
-{
-  nsAutoString baseName;
-  GetFileBase(aPluginPath, aInfoFile, baseName);
-  nsAutoString infoFileName = baseName + NS_LITERAL_STRING(".info");
-  aInfoFile->AppendRelativePath(infoFileName);
-  return true;
-}
-
 #if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
 static nsCString
 GetNativeTarget(nsIFile* aFile)
 {
   bool isLink;
   nsCString path;
   aFile->IsSymlink(&isLink);
   if (isLink) {
@@ -263,24 +252,16 @@ GMPChild::Init(const nsAString& aPluginP
 
 #ifdef MOZ_CRASHREPORTER
   SendPCrashReporterConstructor(CrashReporter::CurrentThreadId());
 #endif
 
   mPluginPath = aPluginPath;
   mSandboxVoucherPath = aVoucherPath;
 
-  nsCOMPtr<nsIFile> infoFile;
-  if (!GetInfoFile(mPluginPath, infoFile) || !infoFile) {
-    return false;
-  }
-  if (!mInfoParser.Init(infoFile)) {
-    return false;
-  }
-
   return true;
 }
 
 bool
 GMPChild::RecvSetNodeId(const nsCString& aNodeId)
 {
   LOGD("%s nodeId=%s", __FUNCTION__, aNodeId.Data());
 
@@ -295,54 +276,49 @@ GMPErr
 GMPChild::GetAPI(const char* aAPIName, void* aHostAPI, void** aPluginAPI)
 {
   if (!mGMPLoader) {
     return GMPGenericErr;
   }
   return mGMPLoader->GetAPI(aAPIName, aHostAPI, aPluginAPI);
 }
 
+bool
+GMPChild::RecvPreloadLibs(const nsCString& aLibs)
+{
 #ifdef XP_WIN
-// Pre-load DLLs that need to be used by the EME plugin but that can't be
-// loaded after the sandbox has started
-bool
-GMPChild::PreLoadLibraries()
-{
+  // Pre-load DLLs that need to be used by the EME plugin but that can't be
+  // loaded after the sandbox has started
   // Items in this must be lowercase!
   static const char* whitelist[] = {
     "d3d9.dll", // Create an `IDirect3D9` to get adapter information
     "dxva2.dll", // Get monitor information
     "evr.dll", // MFGetStrideForBitmapInfoHeader
     "mfh264dec.dll", // H.264 decoder (on Windows Vista)
     "mfheaacdec.dll", // AAC decoder (on Windows Vista)
     "mfplat.dll", // MFCreateSample, MFCreateAlignedMemoryBuffer, MFCreateMediaType
     "msauddecmft.dll", // AAC decoder (on Windows 8)
     "msmpeg2adec.dll", // AAC decoder (on Windows 7)
     "msmpeg2vdec.dll", // H.264 decoder
   };
 
-  if (!mInfoParser.Contains(NS_LITERAL_CSTRING("libraries"))) {
-    return false;
-  }
-
   nsTArray<nsCString> libs;
-  SplitAt(", ", mInfoParser.Get(NS_LITERAL_CSTRING("libraries")), libs);
+  SplitAt(", ", aLibs, libs);
   for (nsCString lib : libs) {
     ToLowerCase(lib);
     for (const char* whiteListedLib : whitelist) {
       if (lib.EqualsASCII(whiteListedLib)) {
         LoadLibraryA(lib.get());
         break;
       }
     }
   }
-
+#endif
   return true;
 }
-#endif
 
 bool
 GMPChild::GetUTF8LibPath(nsACString& aOutLibPath)
 {
 #if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
   nsAutoCString pluginDirectoryPath, pluginFilePath;
   if (!GetPluginPaths(mPluginPath, pluginDirectoryPath, pluginFilePath)) {
     MOZ_CRASH("Error scanning plugin path");
@@ -368,19 +344,16 @@ GMPChild::GetUTF8LibPath(nsACString& aOu
 #endif
 }
 
 bool
 GMPChild::AnswerStartPlugin()
 {
   LOGD("%s", __FUNCTION__);
 
-#if defined(XP_WIN)
-  PreLoadLibraries();
-#endif
   if (!PreLoadPluginVoucher()) {
     NS_WARNING("Plugin voucher failed to load!");
     return false;
   }
   PreLoadSandboxVoucher();
 
   nsCString libPath;
   if (!GetUTF8LibPath(libPath)) {
--- a/dom/media/gmp/GMPChild.h
+++ b/dom/media/gmp/GMPChild.h
@@ -8,17 +8,16 @@
 
 #include "mozilla/gmp/PGMPChild.h"
 #include "GMPTimerChild.h"
 #include "GMPStorageChild.h"
 #include "GMPLoader.h"
 #include "gmp-async-shutdown.h"
 #include "gmp-entrypoints.h"
 #include "prlink.h"
-#include "GMPUtils.h"
 
 namespace mozilla {
 namespace gmp {
 
 class GMPContentChild;
 
 class GMPChild : public PGMPChild
                , public GMPAsyncShutdownHost
@@ -27,19 +26,16 @@ public:
   GMPChild();
   virtual ~GMPChild();
 
   bool Init(const nsAString& aPluginPath,
             const nsAString& aVoucherPath,
             base::ProcessId aParentPid,
             MessageLoop* aIOLoop,
             IPC::Channel* aChannel);
-#ifdef XP_WIN
-  bool PreLoadLibraries();
-#endif
   MessageLoop* GMPMessageLoop();
 
   // Main thread only.
   GMPTimerChild* GetGMPTimers();
   GMPStorageChild* GetGMPStorage();
 
   // GMPAsyncShutdownHost
   void ShutdownComplete() override;
@@ -53,16 +49,17 @@ private:
 
   bool PreLoadPluginVoucher();
   void PreLoadSandboxVoucher();
 
   bool GetUTF8LibPath(nsACString& aOutLibPath);
 
   bool RecvSetNodeId(const nsCString& aNodeId) override;
   bool AnswerStartPlugin() override;
+  bool RecvPreloadLibs(const nsCString& aLibs) override;
 
   PCrashReporterChild* AllocPCrashReporterChild(const NativeThreadId& aThread) override;
   bool DeallocPCrashReporterChild(PCrashReporterChild*) override;
 
   PGMPTimerChild* AllocPGMPTimerChild() override;
   bool DeallocPGMPTimerChild(PGMPTimerChild* aActor) override;
 
   PGMPStorageChild* AllocPGMPStorageChild() override;
@@ -89,15 +86,14 @@ private:
 
   MessageLoop* mGMPMessageLoop;
   nsString mPluginPath;
   nsString mSandboxVoucherPath;
   nsCString mNodeId;
   GMPLoader* mGMPLoader;
   nsTArray<uint8_t> mPluginVoucher;
   nsTArray<uint8_t> mSandboxVoucher;
-  GMPInfoFileParser mInfoParser;
 };
 
 } // namespace gmp
 } // namespace mozilla
 
 #endif // GMPChild_h_
--- a/dom/media/gmp/GMPParent.cpp
+++ b/dom/media/gmp/GMPParent.cpp
@@ -157,16 +157,27 @@ GMPParent::LoadProcess()
 
     bool ok = SendSetNodeId(mNodeId);
     if (!ok) {
       LOGD("%s: Failed to send node id to child process", __FUNCTION__);
       return NS_ERROR_FAILURE;
     }
     LOGD("%s: Sent node id to child process", __FUNCTION__);
 
+#ifdef XP_WIN
+    if (!mLibs.IsEmpty()) {
+      bool ok = SendPreloadLibs(mLibs);
+      if (!ok) {
+        LOGD("%s: Failed to send preload-libs to child process", __FUNCTION__);
+        return NS_ERROR_FAILURE;
+      }
+      LOGD("%s: Sent preload-libs ('%s') to child process", __FUNCTION__, mLibs.get());
+    }
+#endif
+
     // Intr call to block initialization on plugin load.
     ok = CallStartPlugin();
     if (!ok) {
       LOGD("%s: Failed to send start to child process", __FUNCTION__);
       return NS_ERROR_FAILURE;
     }
     LOGD("%s: Sent StartPlugin to child process", __FUNCTION__);
   }
@@ -726,17 +737,17 @@ GMPParent::DeallocPGMPTimerParent(PGMPTi
 {
   GMPTimerParent* p = static_cast<GMPTimerParent*>(aActor);
   p->Shutdown();
   mTimers.RemoveElement(p);
   return true;
 }
 
 bool
-ReadRequiredField(GMPInfoFileParser& aParser, const nsCString& aKey, nsACString& aOutValue)
+ReadInfoField(GMPInfoFileParser& aParser, const nsCString& aKey, nsACString& aOutValue)
 {
   if (!aParser.Contains(aKey) || aParser.Get(aKey).IsEmpty()) {
     return false;
   }
   aOutValue = aParser.Get(aKey);
   return true;
 }
 
@@ -754,23 +765,28 @@ GMPParent::ReadGMPMetaData()
   infoFile->AppendRelativePath(mName + NS_LITERAL_STRING(".info"));
 
   GMPInfoFileParser parser;
   if (!parser.Init(infoFile)) {
     return NS_ERROR_FAILURE;
   }
 
   nsAutoCString apis;
-  if (!ReadRequiredField(parser, NS_LITERAL_CSTRING("name"), mDisplayName) ||
-      !ReadRequiredField(parser, NS_LITERAL_CSTRING("description"), mDescription) ||
-      !ReadRequiredField(parser, NS_LITERAL_CSTRING("version"), mVersion) ||
-      !ReadRequiredField(parser, NS_LITERAL_CSTRING("apis"), apis)) {
+  if (!ReadInfoField(parser, NS_LITERAL_CSTRING("name"), mDisplayName) ||
+      !ReadInfoField(parser, NS_LITERAL_CSTRING("description"), mDescription) ||
+      !ReadInfoField(parser, NS_LITERAL_CSTRING("version"), mVersion) ||
+      !ReadInfoField(parser, NS_LITERAL_CSTRING("apis"), apis)) {
     return NS_ERROR_FAILURE;
   }
 
+#ifdef XP_WIN
+  // "Libraries" field is optional.
+  ReadInfoField(parser, NS_LITERAL_CSTRING("libraries"), mLibs);
+#endif
+
   nsTArray<nsCString> apiTokens;
   SplitAt(", ", apis, apiTokens);
   for (nsCString api : apiTokens) {
     int32_t tagsStart = api.FindChar('[');
     if (tagsStart == 0) {
       // Not allowed to be the first character.
       // API name must be at least one character.
       continue;
--- a/dom/media/gmp/GMPParent.h
+++ b/dom/media/gmp/GMPParent.h
@@ -188,16 +188,19 @@ private:
   nsresult EnsureAsyncShutdownTimeoutSet();
 
   GMPState mState;
   nsCOMPtr<nsIFile> mDirectory; // plugin directory on disk
   nsString mName; // base name of plugin on disk, UTF-16 because used for paths
   nsCString mDisplayName; // name of plugin displayed to users
   nsCString mDescription; // description of plugin for display to users
   nsCString mVersion;
+#ifdef XP_WIN
+  nsCString mLibs;
+#endif
   uint32_t mPluginId;
   nsTArray<nsAutoPtr<GMPCapability>> mCapabilities;
   GMPProcessParent* mProcess;
   bool mDeleteProcessOnlyOnUnload;
   bool mAbnormalShutdownInProgress;
   bool mIsBlockingDeletion;
 
   bool mCanDecrypt;
--- a/dom/media/gmp/PGMP.ipdl
+++ b/dom/media/gmp/PGMP.ipdl
@@ -31,13 +31,14 @@ parent:
   async AsyncShutdownComplete();
   async AsyncShutdownRequired();
 
 child:
   async BeginAsyncShutdown();
   async CrashPluginNow();
   intr StartPlugin();
   async SetNodeId(nsCString nodeId);
+  async PreloadLibs(nsCString libs);
   async CloseActive();
 };
 
 } // namespace gmp
 } // namespace mozilla