diff --git a/content/media/gmp/GMPChild.cpp b/content/media/gmp/GMPChild.cpp index f6bb47b19010..6ea09a38933f 100644 --- a/content/media/gmp/GMPChild.cpp +++ b/content/media/gmp/GMPChild.cpp @@ -271,5 +271,12 @@ GMPChild::RecvPGMPDecryptorConstructor(PGMPDecryptorChild* aActor) return true; } +bool +GMPChild::RecvCrashPluginNow() +{ + abort(); + return true; +} + } // namespace gmp } // namespace mozilla diff --git a/content/media/gmp/GMPChild.h b/content/media/gmp/GMPChild.h index 363e3b9008db..5b6a757e6a35 100644 --- a/content/media/gmp/GMPChild.h +++ b/content/media/gmp/GMPChild.h @@ -47,6 +47,8 @@ private: virtual bool DeallocPGMPDecryptorChild(PGMPDecryptorChild* aActor) MOZ_OVERRIDE; virtual bool RecvPGMPDecryptorConstructor(PGMPDecryptorChild* aActor) MOZ_OVERRIDE; + virtual bool RecvCrashPluginNow() MOZ_OVERRIDE; + virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE; virtual void ProcessingError(Result aWhat) MOZ_OVERRIDE; diff --git a/content/media/gmp/GMPParent.cpp b/content/media/gmp/GMPParent.cpp index 783382d6751b..6ebdef655010 100644 --- a/content/media/gmp/GMPParent.cpp +++ b/content/media/gmp/GMPParent.cpp @@ -101,6 +101,14 @@ GMPParent::Init(GeckoMediaPluginService *aService, nsIFile* aPluginDir) return ReadGMPMetaData(); } +void +GMPParent::Crash() +{ + if (mState != GMPStateNotLoaded) { + unused << SendCrashPluginNow(); + } +} + nsresult GMPParent::LoadProcess() { diff --git a/content/media/gmp/GMPParent.h b/content/media/gmp/GMPParent.h index de129c1f85d7..b8e84a8e72cb 100644 --- a/content/media/gmp/GMPParent.h +++ b/content/media/gmp/GMPParent.h @@ -62,6 +62,8 @@ public: nsresult Init(GeckoMediaPluginService *aService, nsIFile* aPluginDir); nsresult CloneFrom(const GMPParent* aOther); + void Crash(); + nsresult LoadProcess(); // Called internally to close this if we don't need it diff --git a/content/media/gmp/GMPService.cpp b/content/media/gmp/GMPService.cpp index 57e1a7481f17..497991959d3e 100644 --- a/content/media/gmp/GMPService.cpp +++ b/content/media/gmp/GMPService.cpp @@ -9,6 +9,7 @@ #include "GMPVideoDecoderParent.h" #include "nsIObserverService.h" #include "GeckoChildProcessHost.h" +#include "mozilla/Preferences.h" #include "mozilla/ClearOnShutdown.h" #include "mozilla/SyncRunnable.h" #include "nsXPCOMPrivate.h" @@ -145,6 +146,11 @@ GeckoMediaPluginService::Init() MOZ_ALWAYS_TRUE(NS_SUCCEEDED(obsService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false))); MOZ_ALWAYS_TRUE(NS_SUCCEEDED(obsService->AddObserver(this, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID, false))); + nsCOMPtr prefs = do_GetService(NS_PREFSERVICE_CONTRACTID); + if (prefs) { + prefs->AddObserver("media.gmp.plugin.crash", this, false); + } + // Kick off scanning for plugins nsCOMPtr thread; unused << GetThread(getter_AddRefs(thread)); @@ -155,7 +161,26 @@ GeckoMediaPluginService::Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aSomeData) { - if (!strcmp(NS_XPCOM_SHUTDOWN_OBSERVER_ID, aTopic)) { + if (!strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) { + nsCOMPtr branch( do_QueryInterface(aSubject) ); + if (branch) { + bool crashNow = false; + if (NS_LITERAL_STRING("media.gmp.plugin.crash").Equals(aSomeData)) { + branch->GetBoolPref("media.gmp.plugin.crash", &crashNow); + } + if (crashNow) { + nsCOMPtr gmpThread; + { + MutexAutoLock lock(mMutex); + gmpThread = mGMPThread; + } + if (gmpThread) { + gmpThread->Dispatch(WrapRunnable(this, &GeckoMediaPluginService::CrashPlugins), + NS_DISPATCH_NORMAL); + } + } + } + } else if (!strcmp(NS_XPCOM_SHUTDOWN_OBSERVER_ID, aTopic)) { nsCOMPtr gmpThread; { MutexAutoLock lock(mMutex); @@ -340,6 +365,17 @@ GeckoMediaPluginService::UnloadPlugins() mPlugins.Clear(); } +void +GeckoMediaPluginService::CrashPlugins() +{ + MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); + + MutexAutoLock lock(mMutex); + for (uint32_t i = 0; i < mPlugins.Length(); i++) { + mPlugins[i]->Crash(); + } +} + void GeckoMediaPluginService::LoadFromEnvironment() { diff --git a/content/media/gmp/GMPService.h b/content/media/gmp/GMPService.h index 424e697b3516..f9dab0be5edf 100644 --- a/content/media/gmp/GMPService.h +++ b/content/media/gmp/GMPService.h @@ -44,6 +44,7 @@ private: const nsTArray& aTags); void UnloadPlugins(); + void CrashPlugins(); void LoadFromEnvironment(); void ProcessPossiblePlugin(nsIFile* aDir); diff --git a/content/media/gmp/PGMP.ipdl b/content/media/gmp/PGMP.ipdl index 23036211326a..49aaff6a3556 100644 --- a/content/media/gmp/PGMP.ipdl +++ b/content/media/gmp/PGMP.ipdl @@ -27,6 +27,8 @@ child: async PGMPDecryptor(); async PGMPVideoDecoder(); async PGMPVideoEncoder(); + + async CrashPluginNow(); }; } // namespace gmp