Bug 1209385 - Crash GMPs that don't respond to GMPVideoDecoder::Reset(). r=jwwang

This commit is contained in:
Chris Pearce 2015-09-30 06:56:07 +13:00
parent 3fd903c9df
commit a76b46867d
15 changed files with 117 additions and 9 deletions

View File

@ -606,10 +606,21 @@ GMPChild::GetGMPStorage()
return mStorage; return mStorage;
} }
bool static MOZ_NEVER_INLINE void
GMPChild::RecvCrashPluginNow() CrashForApiTimeout()
{ {
MOZ_CRASH(); // Never inline so that crash reports are distinctive.
MOZ_CRASH("Bug 1209385; GMP API actor failed to respond.");
}
bool
GMPChild::RecvCrashPluginNow(const GMPCrashReason& aReason)
{
if (aReason == kGmpApiTimeout) {
CrashForApiTimeout();
} else {
MOZ_CRASH();
}
return true; return true;
} }

View File

@ -71,7 +71,7 @@ private:
ProcessId aOtherPid) override; ProcessId aOtherPid) override;
void GMPContentChildActorDestroy(GMPContentChild* aGMPContentChild); void GMPContentChildActorDestroy(GMPContentChild* aGMPContentChild);
virtual bool RecvCrashPluginNow() override; virtual bool RecvCrashPluginNow(const GMPCrashReason& aReason) override;
virtual bool RecvBeginAsyncShutdown() override; virtual bool RecvBeginAsyncShutdown() override;
virtual bool RecvCloseActive() override; virtual bool RecvCloseActive() override;

View File

@ -118,6 +118,18 @@ GMPContentParent::DecryptorDestroyed(GMPDecryptorParent* aSession)
CloseIfUnused(); CloseIfUnused();
} }
void
GMPContentParent::CrashPluginNow(GMPCrashReason aReason)
{
if (mParent) {
mParent->Crash(aReason);
} else {
nsRefPtr<GeckoMediaPluginServiceChild> gmp(
GeckoMediaPluginServiceChild::GetSingleton());
gmp->CrashPluginNow(mPluginId, aReason);
}
}
void void
GMPContentParent::CloseIfUnused() GMPContentParent::CloseIfUnused()
{ {

View File

@ -9,6 +9,7 @@
#include "mozilla/gmp/PGMPContentParent.h" #include "mozilla/gmp/PGMPContentParent.h"
#include "GMPSharedMemManager.h" #include "GMPSharedMemManager.h"
#include "nsISupportsImpl.h" #include "nsISupportsImpl.h"
#include "GMPUtils.h"
namespace mozilla { namespace mozilla {
namespace gmp { namespace gmp {
@ -61,6 +62,8 @@ public:
return mPluginId; return mPluginId;
} }
void CrashPluginNow(GMPCrashReason aReason);
private: private:
~GMPContentParent(); ~GMPContentParent();

View File

@ -11,6 +11,8 @@
#include "gmp-audio-codec.h" #include "gmp-audio-codec.h"
#include "gmp-decryption.h" #include "gmp-decryption.h"
#include "GMPUtils.h"
namespace IPC { namespace IPC {
template <> template <>
@ -247,6 +249,13 @@ struct ParamTraits<GMPVideoCodec>
} }
}; };
template <>
struct ParamTraits<mozilla::GMPCrashReason>
: public ContiguousEnumSerializer<mozilla::GMPCrashReason,
mozilla::kPrefChange,
mozilla::kInvalid>
{};
} // namespace IPC } // namespace IPC
#endif // GMPMessageUtils_h_ #endif // GMPMessageUtils_h_

View File

@ -119,10 +119,10 @@ GMPParent::Init(GeckoMediaPluginServiceParent* aService, nsIFile* aPluginDir)
} }
void void
GMPParent::Crash() GMPParent::Crash(GMPCrashReason aReason)
{ {
if (mState != GMPStateNotLoaded) { if (mState != GMPStateNotLoaded) {
unused << SendCrashPluginNow(); unused << SendCrashPluginNow(aReason);
} }
} }

View File

@ -22,6 +22,7 @@
#include "nsTArray.h" #include "nsTArray.h"
#include "nsIFile.h" #include "nsIFile.h"
#include "ThreadSafeRefcountingWithMainThreadDestruction.h" #include "ThreadSafeRefcountingWithMainThreadDestruction.h"
#include "GMPUtils.h"
class nsIThread; class nsIThread;
@ -79,7 +80,7 @@ public:
nsresult Init(GeckoMediaPluginServiceParent* aService, nsIFile* aPluginDir); nsresult Init(GeckoMediaPluginServiceParent* aService, nsIFile* aPluginDir);
nsresult CloneFrom(const GMPParent* aOther); nsresult CloneFrom(const GMPParent* aOther);
void Crash(); void Crash(GMPCrashReason aReason);
nsresult LoadProcess(); nsresult LoadProcess();

View File

@ -215,6 +215,38 @@ GeckoMediaPluginServiceChild::UpdateTrialCreateState(const nsAString& aKeySystem
return NS_OK; return NS_OK;
} }
void
GeckoMediaPluginServiceChild::CrashPluginNow(uint32_t aPluginId, GMPCrashReason aReason)
{
if (NS_GetCurrentThread() != mGMPThread) {
mGMPThread->Dispatch(NS_NewRunnableMethodWithArgs<uint32_t, GMPCrashReason>(
this, &GeckoMediaPluginServiceChild::CrashPluginNow,
aPluginId, aReason), NS_DISPATCH_NORMAL);
return;
}
class Callback : public GetServiceChildCallback
{
public:
Callback(uint32_t aPluginId, GMPCrashReason aReason)
: mPluginId(aPluginId)
, mReason(aReason)
{ }
virtual void Done(GMPServiceChild* aService) override
{
aService->SendCrashPluginNow(mPluginId, mReason);
}
private:
uint32_t mPluginId;
GMPCrashReason mReason;
};
UniquePtr<GetServiceChildCallback> callback(new Callback(aPluginId, aReason));
GetServiceChild(Move(callback));
}
NS_IMETHODIMP NS_IMETHODIMP
GeckoMediaPluginServiceChild::Observe(nsISupports* aSubject, GeckoMediaPluginServiceChild::Observe(nsISupports* aSubject,
const char* aTopic, const char* aTopic,

View File

@ -11,6 +11,7 @@
#include "mozilla/ipc/Transport.h" #include "mozilla/ipc/Transport.h"
#include "mozilla/gmp/PGMPServiceChild.h" #include "mozilla/gmp/PGMPServiceChild.h"
#include "nsRefPtrHashtable.h" #include "nsRefPtrHashtable.h"
#include "GMPUtils.h"
namespace mozilla { namespace mozilla {
namespace gmp { namespace gmp {
@ -52,6 +53,8 @@ public:
NS_IMETHOD UpdateTrialCreateState(const nsAString& aKeySystem, NS_IMETHOD UpdateTrialCreateState(const nsAString& aKeySystem,
uint32_t aState) override; uint32_t aState) override;
void CrashPluginNow(uint32_t aPluginId, GMPCrashReason aReason);
NS_DECL_NSIOBSERVER NS_DECL_NSIOBSERVER
void SetServiceChild(UniquePtr<GMPServiceChild>&& aServiceChild); void SetServiceChild(UniquePtr<GMPServiceChild>&& aServiceChild);

View File

@ -511,7 +511,7 @@ GeckoMediaPluginServiceParent::CrashPlugins()
MutexAutoLock lock(mMutex); MutexAutoLock lock(mMutex);
for (size_t i = 0; i < mPlugins.Length(); i++) { for (size_t i = 0; i < mPlugins.Length(); i++) {
mPlugins[i]->Crash(); mPlugins[i]->Crash(kPrefChange);
} }
} }
@ -1221,6 +1221,19 @@ GeckoMediaPluginServiceParent::UpdateTrialCreateState(const nsAString& aKeySyste
#endif #endif
} }
void
GeckoMediaPluginServiceParent::CrashPluginNow(uint32_t aPluginId, GMPCrashReason aReason)
{
MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
MutexAutoLock lock(mMutex);
LOGD(("%s::%s(%u, %u)", __CLASS__, __FUNCTION__, aPluginId, aReason));
for (const auto& plugin : mPlugins) {
if (plugin->GetPluginId() == aPluginId) {
plugin->Crash(aReason);
}
}
}
static bool static bool
ExtractHostName(const nsACString& aOrigin, nsACString& aOutData) ExtractHostName(const nsACString& aOrigin, nsACString& aOutData)
{ {
@ -1555,6 +1568,14 @@ GMPServiceParent::~GMPServiceParent()
new DeleteTask<Transport>(GetTransport())); new DeleteTask<Transport>(GetTransport()));
} }
bool
GMPServiceParent::RecvCrashPluginNow(const uint32_t& aPluginId,
const GMPCrashReason& aReason)
{
mService->CrashPluginNow(aPluginId, aReason);
return true;
}
bool bool
GMPServiceParent::RecvLoadGMP(const nsCString& aNodeId, GMPServiceParent::RecvLoadGMP(const nsCString& aNodeId,
const nsCString& aAPI, const nsCString& aAPI,

View File

@ -13,6 +13,7 @@
#include "nsDataHashtable.h" #include "nsDataHashtable.h"
#include "mozilla/Atomics.h" #include "mozilla/Atomics.h"
#include "nsThreadUtils.h" #include "nsThreadUtils.h"
#include "GMPUtils.h"
template <class> struct already_AddRefed; template <class> struct already_AddRefed;
@ -57,6 +58,8 @@ public:
void SetAsyncShutdownPluginState(GMPParent* aGMPParent, char aId, const nsCString& aState); void SetAsyncShutdownPluginState(GMPParent* aGMPParent, char aId, const nsCString& aState);
#endif // MOZ_CRASHREPORTER #endif // MOZ_CRASHREPORTER
void CrashPluginNow(uint32_t aPluginId, GMPCrashReason aReason);
private: private:
friend class GMPServiceParent; friend class GMPServiceParent;
@ -223,6 +226,8 @@ public:
nsCString* aVersion); nsCString* aVersion);
virtual bool RecvUpdateGMPTrialCreateState(const nsString& aKeySystem, virtual bool RecvUpdateGMPTrialCreateState(const nsString& aKeySystem,
const uint32_t& aState) override; const uint32_t& aState) override;
virtual bool RecvCrashPluginNow(const uint32_t& aPluginId,
const GMPCrashReason& aReason) override;
virtual void ActorDestroy(ActorDestroyReason aWhy) override; virtual void ActorDestroy(ActorDestroyReason aWhy) override;

View File

@ -37,6 +37,12 @@ SplitAt(const char* aDelims,
nsCString nsCString
ToBase64(const nsTArray<uint8_t>& aBytes); ToBase64(const nsTArray<uint8_t>& aBytes);
enum GMPCrashReason {
kPrefChange, // media.gmp.plugin.crash has been toggled.
kGmpApiTimeout, // Some API did not respond.
kInvalid,
};
} // namespace mozilla } // namespace mozilla
#endif #endif

View File

@ -188,6 +188,7 @@ GMPVideoDecoderParent::Reset()
LOGD(("GMPVideoDecoderParent[%p]::ResetCompleteTimeout() timed out waiting for ResetComplete", self.get())); LOGD(("GMPVideoDecoderParent[%p]::ResetCompleteTimeout() timed out waiting for ResetComplete", self.get()));
self->mResetCompleteTimeout = nullptr; self->mResetCompleteTimeout = nullptr;
LogToBrowserConsole(NS_LITERAL_STRING("GMPVideoDecoderParent timed out waiting for ResetComplete()")); LogToBrowserConsole(NS_LITERAL_STRING("GMPVideoDecoderParent timed out waiting for ResetComplete()"));
self->mPlugin->CrashPluginNow(kGmpApiTimeout);
}); });
CancelResetCompleteTimeout(); CancelResetCompleteTimeout();
mResetCompleteTimeout = SimpleTimer::Create(task, 5000, mPlugin->GMPThread()); mResetCompleteTimeout = SimpleTimer::Create(task, 5000, mPlugin->GMPThread());

View File

@ -9,6 +9,7 @@ include protocol PGMPTimer;
include protocol PGMPStorage; include protocol PGMPStorage;
using mozilla::dom::NativeThreadId from "mozilla/dom/TabMessageUtils.h"; using mozilla::dom::NativeThreadId from "mozilla/dom/TabMessageUtils.h";
using mozilla::GMPCrashReason from "GMPUtils.h";
namespace mozilla { namespace mozilla {
namespace gmp { namespace gmp {
@ -33,7 +34,7 @@ parent:
child: child:
async BeginAsyncShutdown(); async BeginAsyncShutdown();
async CrashPluginNow(); async CrashPluginNow(GMPCrashReason aReason);
intr StartPlugin(); intr StartPlugin();
async SetNodeId(nsCString nodeId); async SetNodeId(nsCString nodeId);
async CloseActive(); async CloseActive();

View File

@ -6,6 +6,7 @@
include protocol PGMP; include protocol PGMP;
using base::ProcessId from "base/process.h"; using base::ProcessId from "base/process.h";
using mozilla::GMPCrashReason from "GMPUtils.h";
namespace mozilla { namespace mozilla {
namespace gmp { namespace gmp {
@ -23,6 +24,8 @@ parent:
returns (nsCString id); returns (nsCString id);
async UpdateGMPTrialCreateState(nsString keySystem, uint32_t status); async UpdateGMPTrialCreateState(nsString keySystem, uint32_t status);
async CrashPluginNow(uint32_t pluginId, GMPCrashReason aReason);
}; };
} // namespace gmp } // namespace gmp