Bug 1035653 - Proxy GMPParent creation to main thread to avoid assert in IToplevelProtocol ctor. r=jesup
☠☠ backed out by 70f3b01cb736 ☠ ☠
authorChris Pearce <cpearce@mozilla.com>
Fri, 11 Jul 2014 12:21:33 +1200
changeset 193511 412b654e5cd2ad309055f2081b62ac9679478111
parent 193510 01ba0892af2942d53a2061f4d2d778deff3e04f6
child 193512 d988238c67d80db0e1f770399523b313a0eacef9
push id27123
push userryanvm@gmail.com
push dateFri, 11 Jul 2014 20:35:05 +0000
treeherdermozilla-central@84bd8d9f4256 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjesup
bugs1035653
milestone33.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 1035653 - Proxy GMPParent creation to main thread to avoid assert in IToplevelProtocol ctor. r=jesup
content/media/gmp/GMPParent.h
content/media/gmp/GMPService.cpp
--- a/content/media/gmp/GMPParent.h
+++ b/content/media/gmp/GMPParent.h
@@ -11,16 +11,17 @@
 #include "GMPVideoEncoderParent.h"
 #include "mozilla/gmp/PGMPParent.h"
 #include "nsCOMPtr.h"
 #include "nscore.h"
 #include "nsISupports.h"
 #include "nsString.h"
 #include "nsTArray.h"
 #include "nsIFile.h"
+#include "ThreadSafeRefcountingWithMainThreadDestruction.h"
 
 class nsILineInputStream;
 class nsIThread;
 
 namespace mozilla {
 namespace gmp {
 
 class GMPCapability
@@ -33,17 +34,17 @@ public:
 enum GMPState {
   GMPStateNotLoaded,
   GMPStateLoaded
 };
 
 class GMPParent MOZ_FINAL : public PGMPParent
 {
 public:
-  NS_INLINE_DECL_REFCOUNTING(GMPParent)
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(GMPParent)
 
   GMPParent();
 
   nsresult Init(nsIFile* aPluginDir);
   nsresult LoadProcess();
   void MaybeUnloadProcess();
   void UnloadProcess();
   bool SupportsAPI(const nsCString& aAPI, const nsCString& aTag);
--- a/content/media/gmp/GMPService.cpp
+++ b/content/media/gmp/GMPService.cpp
@@ -359,31 +359,51 @@ GeckoMediaPluginService::SelectPluginFor
         gmp->SetOrigin(aOrigin);
       }
       return gmp;
     }
   }
   return nullptr;
 }
 
+class CreateGMPParentTask : public nsRunnable {
+public:
+  NS_IMETHOD Run() {
+    MOZ_ASSERT(NS_IsMainThread());
+    mParent = new GMPParent();
+    return NS_OK;
+  }
+  already_AddRefed<GMPParent> GetParent() {
+    return mParent.forget();
+  }
+private:
+  nsRefPtr<GMPParent> mParent;
+};
 
 void
 GeckoMediaPluginService::AddOnGMPThread(const nsAString& aDirectory)
 {
   MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
 
   nsCOMPtr<nsIFile> directory;
   nsresult rv = NS_NewLocalFile(aDirectory, false, getter_AddRefs(directory));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return;
   }
 
-  nsRefPtr<GMPParent> gmp = new GMPParent();
+  // The GMPParent inherits from IToplevelProtocol, which must be created
+  // on the main thread to be threadsafe. See Bug 1035653.
+  nsRefPtr<CreateGMPParentTask> task(new CreateGMPParentTask());
+  nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
+  MOZ_ASSERT(mainThread);
+  mozilla::SyncRunnable::DispatchToThread(mainThread, task);
+  nsRefPtr<GMPParent> gmp = task->GetParent();
   rv = gmp->Init(directory);
   if (NS_FAILED(rv)) {
+    NS_WARNING("Can't Create GMPParent");
     return;
   }
 
   mPlugins.AppendElement(gmp);
 }
 
 void
 GeckoMediaPluginService::RemoveOnGMPThread(const nsAString& aDirectory)