Bug 1035653 - Proxy GMPParent creation to main thread to avoid assert in IToplevelProtocol ctor. r=jesup
--- 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)