mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 03:45:46 +00:00
Bug 1331829 - Remove async shutdown GMP API. r=gerald
Now that we're not supporting Adobe EME anymore, we don't need to provide a mechanism for GMPs to block browser shutdown. MozReview-Commit-ID: KUC94IBQiod --HG-- extra : rebase_source : ed521f28e272de11b2d0c4546b98baf6bd7c6e72
This commit is contained in:
parent
2b4c7c9921
commit
abf5ab3771
@ -101,7 +101,6 @@ private:
|
||||
// PlatformDecoderModule
|
||||
DECL_MEDIA_PREF("media.apple.forcevda", AppleForceVDA, bool, false);
|
||||
DECL_MEDIA_PREF("media.gmp.insecure.allow", GMPAllowInsecure, bool, false);
|
||||
DECL_MEDIA_PREF("media.gmp.async-shutdown-timeout", GMPAsyncShutdownTimeout, uint32_t, GMP_DEFAULT_ASYNC_SHUTDOWN_TIMEOUT);
|
||||
DECL_MEDIA_PREF("media.eme.enabled", EMEEnabled, bool, false);
|
||||
DECL_MEDIA_PREF("media.use-blank-decoder", PDMUseBlankDecoder, bool, false);
|
||||
DECL_MEDIA_PREF("media.gpu-process-decoder", PDMUseGPUDecoder, bool, false);
|
||||
|
@ -412,9 +412,6 @@ extern "C" {
|
||||
} else if (!strcmp (aApiName, GMP_API_DECRYPTOR)) {
|
||||
*aPluginApi = new FakeDecryptor(static_cast<GMPDecryptorHost*> (aHostAPI));
|
||||
return GMPNoErr;
|
||||
} else if (!strcmp (aApiName, GMP_API_ASYNC_SHUTDOWN)) {
|
||||
*aPluginApi = new TestAsyncShutdown(static_cast<GMPAsyncShutdownHost*> (aHostAPI));
|
||||
return GMPNoErr;
|
||||
#endif
|
||||
}
|
||||
return GMPGenericErr;
|
||||
|
@ -75,9 +75,6 @@ extern "C" {
|
||||
} else if (!strcmp (aApiName, GMP_API_DECRYPTOR)) {
|
||||
*aPluginApi = new FakeDecryptor(static_cast<GMPDecryptorHost*> (aHostAPI));
|
||||
return GMPNoErr;
|
||||
} else if (!strcmp (aApiName, GMP_API_ASYNC_SHUTDOWN)) {
|
||||
*aPluginApi = new TestAsyncShutdown(static_cast<GMPAsyncShutdownHost*> (aHostAPI));
|
||||
return GMPNoErr;
|
||||
#endif
|
||||
}
|
||||
return GMPGenericErr;
|
||||
|
@ -573,36 +573,3 @@ FakeDecryptor::UpdateSession(uint32_t aPromiseId,
|
||||
Message("node-id " + sNodeId);
|
||||
}
|
||||
}
|
||||
|
||||
class CompleteShutdownTask : public GMPTask {
|
||||
public:
|
||||
explicit CompleteShutdownTask(GMPAsyncShutdownHost* aHost)
|
||||
: mHost(aHost)
|
||||
{
|
||||
}
|
||||
void Run() override {
|
||||
mHost->ShutdownComplete();
|
||||
}
|
||||
void Destroy() override { delete this; }
|
||||
GMPAsyncShutdownHost* mHost;
|
||||
};
|
||||
|
||||
void
|
||||
TestAsyncShutdown::BeginShutdown() {
|
||||
switch (sShutdownMode) {
|
||||
case ShutdownNormal:
|
||||
mHost->ShutdownComplete();
|
||||
break;
|
||||
case ShutdownTimeout:
|
||||
// Don't do anything; wait for timeout, Gecko should kill
|
||||
// the plugin and recover.
|
||||
break;
|
||||
case ShutdownStoreToken:
|
||||
// Store message, then shutdown.
|
||||
WriteRecord("shutdown-token",
|
||||
sShutdownToken,
|
||||
new CompleteShutdownTask(mHost),
|
||||
new SendMessageTask("FAIL writing shutdown-token."));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,6 @@
|
||||
#define FAKE_DECRYPTOR_H__
|
||||
|
||||
#include "gmp-decryption.h"
|
||||
#include "gmp-async-shutdown.h"
|
||||
#include <string>
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
@ -91,15 +90,4 @@ private:
|
||||
GMPDecryptorHost* mHost;
|
||||
};
|
||||
|
||||
class TestAsyncShutdown : public GMPAsyncShutdown {
|
||||
public:
|
||||
explicit TestAsyncShutdown(GMPAsyncShutdownHost* aHost)
|
||||
: mHost(aHost)
|
||||
{
|
||||
}
|
||||
void BeginShutdown() override;
|
||||
private:
|
||||
GMPAsyncShutdownHost* mHost;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -53,8 +53,7 @@ extern LogModule* GetGMPLog();
|
||||
namespace gmp {
|
||||
|
||||
GMPChild::GMPChild()
|
||||
: mAsyncShutdown(nullptr)
|
||||
, mGMPMessageLoop(MessageLoop::current())
|
||||
: mGMPMessageLoop(MessageLoop::current())
|
||||
, mGMPLoader(nullptr)
|
||||
{
|
||||
LOGD("GMPChild ctor");
|
||||
@ -399,14 +398,6 @@ GMPChild::AnswerStartPlugin(const nsString& aAdapter)
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
|
||||
void* sh = nullptr;
|
||||
GMPAsyncShutdownHost* host = static_cast<GMPAsyncShutdownHost*>(this);
|
||||
GMPErr err = GetAPI(GMP_API_ASYNC_SHUTDOWN, host, &sh);
|
||||
if (err == GMPNoErr && sh) {
|
||||
mAsyncShutdown = reinterpret_cast<GMPAsyncShutdown*>(sh);
|
||||
SendAsyncShutdownRequired();
|
||||
}
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
@ -533,20 +524,6 @@ GMPChild::RecvCrashPluginNow()
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
GMPChild::RecvBeginAsyncShutdown()
|
||||
{
|
||||
LOGD("%s AsyncShutdown=%d", __FUNCTION__, mAsyncShutdown!=nullptr);
|
||||
|
||||
MOZ_ASSERT(mGMPMessageLoop == MessageLoop::current());
|
||||
if (mAsyncShutdown) {
|
||||
mAsyncShutdown->BeginShutdown();
|
||||
} else {
|
||||
ShutdownComplete();
|
||||
}
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
GMPChild::RecvCloseActive()
|
||||
{
|
||||
@ -556,15 +533,6 @@ GMPChild::RecvCloseActive()
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
void
|
||||
GMPChild::ShutdownComplete()
|
||||
{
|
||||
LOGD("%s", __FUNCTION__);
|
||||
MOZ_ASSERT(mGMPMessageLoop == MessageLoop::current());
|
||||
mAsyncShutdown = nullptr;
|
||||
SendAsyncShutdownComplete();
|
||||
}
|
||||
|
||||
static void
|
||||
GetPluginVoucherFile(const nsAString& aPluginPath,
|
||||
nsCOMPtr<nsIFile>& aOutVoucherFile)
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include "GMPTimerChild.h"
|
||||
#include "GMPStorageChild.h"
|
||||
#include "GMPLoader.h"
|
||||
#include "gmp-async-shutdown.h"
|
||||
#include "gmp-entrypoints.h"
|
||||
#include "prlink.h"
|
||||
|
||||
@ -20,7 +19,6 @@ namespace gmp {
|
||||
class GMPContentChild;
|
||||
|
||||
class GMPChild : public PGMPChild
|
||||
, public GMPAsyncShutdownHost
|
||||
{
|
||||
public:
|
||||
GMPChild();
|
||||
@ -37,9 +35,6 @@ public:
|
||||
GMPTimerChild* GetGMPTimers();
|
||||
GMPStorageChild* GetGMPStorage();
|
||||
|
||||
// GMPAsyncShutdownHost
|
||||
void ShutdownComplete() override;
|
||||
|
||||
#if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
|
||||
bool SetMacSandboxInfo(MacSandboxPluginType aPluginType);
|
||||
#endif
|
||||
@ -70,7 +65,6 @@ private:
|
||||
void GMPContentChildActorDestroy(GMPContentChild* aGMPContentChild);
|
||||
|
||||
mozilla::ipc::IPCResult RecvCrashPluginNow() override;
|
||||
mozilla::ipc::IPCResult RecvBeginAsyncShutdown() override;
|
||||
mozilla::ipc::IPCResult RecvCloseActive() override;
|
||||
|
||||
void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
@ -80,7 +74,6 @@ private:
|
||||
|
||||
nsTArray<UniquePtr<GMPContentChild>> mGMPContentChildren;
|
||||
|
||||
GMPAsyncShutdown* mAsyncShutdown;
|
||||
RefPtr<GMPTimerChild> mTimerChild;
|
||||
RefPtr<GMPStorageChild> mStorage;
|
||||
|
||||
|
@ -68,8 +68,6 @@ GMPParent::GMPParent()
|
||||
, mIsBlockingDeletion(false)
|
||||
, mCanDecrypt(false)
|
||||
, mGMPContentChildCount(0)
|
||||
, mAsyncShutdownRequired(false)
|
||||
, mAsyncShutdownInProgress(false)
|
||||
, mChildPid(0)
|
||||
, mHoldingSelfRef(false)
|
||||
{
|
||||
@ -217,75 +215,13 @@ GMPParent::LoadProcess()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
GMPParent::AbortWaitingForGMPAsyncShutdown(nsITimer* aTimer, void* aClosure)
|
||||
{
|
||||
NS_WARNING("Timed out waiting for GMP async shutdown!");
|
||||
GMPParent* parent = reinterpret_cast<GMPParent*>(aClosure);
|
||||
MOZ_ASSERT(parent->mService);
|
||||
#if defined(MOZ_CRASHREPORTER)
|
||||
parent->mService->SetAsyncShutdownPluginState(parent, 'G',
|
||||
NS_LITERAL_CSTRING("Timed out waiting for async shutdown"));
|
||||
#endif
|
||||
parent->mService->AsyncShutdownComplete(parent);
|
||||
}
|
||||
|
||||
nsresult
|
||||
GMPParent::EnsureAsyncShutdownTimeoutSet()
|
||||
{
|
||||
MOZ_ASSERT(mAsyncShutdownRequired);
|
||||
if (mAsyncShutdownTimeout) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
mAsyncShutdownTimeout = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Set timer to abort waiting for plugin to shutdown if it takes
|
||||
// too long.
|
||||
rv = mAsyncShutdownTimeout->SetTarget(mGMPThread);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
int32_t timeout = MediaPrefs::GMPAsyncShutdownTimeout();
|
||||
RefPtr<GeckoMediaPluginServiceParent> service =
|
||||
GeckoMediaPluginServiceParent::GetSingleton();
|
||||
if (service) {
|
||||
timeout = service->AsyncShutdownTimeoutMs();
|
||||
}
|
||||
rv = mAsyncShutdownTimeout->InitWithFuncCallback(
|
||||
&AbortWaitingForGMPAsyncShutdown, this, timeout,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
Unused << NS_WARN_IF(NS_FAILED(rv));
|
||||
return rv;
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
GMPParent::RecvPGMPContentChildDestroyed()
|
||||
{
|
||||
--mGMPContentChildCount;
|
||||
if (!IsUsed()) {
|
||||
#if defined(MOZ_CRASHREPORTER)
|
||||
if (mService) {
|
||||
mService->SetAsyncShutdownPluginState(this, 'E',
|
||||
NS_LITERAL_CSTRING("Last content child destroyed"));
|
||||
}
|
||||
#endif
|
||||
CloseIfUnused();
|
||||
}
|
||||
#if defined(MOZ_CRASHREPORTER)
|
||||
else {
|
||||
if (mService) {
|
||||
mService->SetAsyncShutdownPluginState(this, 'F',
|
||||
nsPrintfCString("Content child destroyed, remaining: %u", mGMPContentChildCount));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
@ -293,7 +229,7 @@ void
|
||||
GMPParent::CloseIfUnused()
|
||||
{
|
||||
MOZ_ASSERT(GMPThread() == NS_GetCurrentThread());
|
||||
LOGD("%s: mAsyncShutdownRequired=%d", __FUNCTION__, mAsyncShutdownRequired);
|
||||
LOGD("%s", __FUNCTION__);
|
||||
|
||||
if ((mDeleteProcessOnlyOnUnload ||
|
||||
mState == GMPStateLoaded ||
|
||||
@ -304,74 +240,15 @@ GMPParent::CloseIfUnused()
|
||||
mTimers[i - 1]->Shutdown();
|
||||
}
|
||||
|
||||
if (mAsyncShutdownRequired) {
|
||||
if (!mAsyncShutdownInProgress) {
|
||||
LOGD("%s: sending async shutdown notification", __FUNCTION__);
|
||||
#if defined(MOZ_CRASHREPORTER)
|
||||
if (mService) {
|
||||
mService->SetAsyncShutdownPluginState(this, 'H',
|
||||
NS_LITERAL_CSTRING("Sent BeginAsyncShutdown"));
|
||||
}
|
||||
#endif
|
||||
mAsyncShutdownInProgress = true;
|
||||
if (!SendBeginAsyncShutdown()) {
|
||||
#if defined(MOZ_CRASHREPORTER)
|
||||
if (mService) {
|
||||
mService->SetAsyncShutdownPluginState(this, 'I',
|
||||
NS_LITERAL_CSTRING("Could not send BeginAsyncShutdown - Aborting async shutdown"));
|
||||
}
|
||||
#endif
|
||||
AbortAsyncShutdown();
|
||||
} else if (NS_FAILED(EnsureAsyncShutdownTimeoutSet())) {
|
||||
#if defined(MOZ_CRASHREPORTER)
|
||||
if (mService) {
|
||||
mService->SetAsyncShutdownPluginState(this, 'J',
|
||||
NS_LITERAL_CSTRING("Could not start timer after sending BeginAsyncShutdown - Aborting async shutdown"));
|
||||
}
|
||||
#endif
|
||||
AbortAsyncShutdown();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
#if defined(MOZ_CRASHREPORTER)
|
||||
if (mService) {
|
||||
mService->SetAsyncShutdownPluginState(this, 'K',
|
||||
NS_LITERAL_CSTRING("No (more) async-shutdown required"));
|
||||
}
|
||||
#endif
|
||||
// No async-shutdown, kill async-shutdown timer started in CloseActive().
|
||||
AbortAsyncShutdown();
|
||||
// Any async shutdown must be complete. Shutdown GMPStorage.
|
||||
for (size_t i = mStorage.Length(); i > 0; i--) {
|
||||
mStorage[i - 1]->Shutdown();
|
||||
}
|
||||
Shutdown();
|
||||
// Shutdown GMPStorage. Given that all protocol actors must be shutdown
|
||||
// (!Used() is true), all storage operations should be complete.
|
||||
for (size_t i = mStorage.Length(); i > 0; i--) {
|
||||
mStorage[i - 1]->Shutdown();
|
||||
}
|
||||
Shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GMPParent::AbortAsyncShutdown()
|
||||
{
|
||||
MOZ_ASSERT(GMPThread() == NS_GetCurrentThread());
|
||||
LOGD("%s", __FUNCTION__);
|
||||
|
||||
if (mAsyncShutdownTimeout) {
|
||||
mAsyncShutdownTimeout->Cancel();
|
||||
mAsyncShutdownTimeout = nullptr;
|
||||
}
|
||||
|
||||
if (!mAsyncShutdownRequired || !mAsyncShutdownInProgress) {
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<GMPParent> kungFuDeathGrip(this);
|
||||
mService->AsyncShutdownComplete(this);
|
||||
mAsyncShutdownRequired = false;
|
||||
mAsyncShutdownInProgress = false;
|
||||
CloseIfUnused();
|
||||
}
|
||||
|
||||
void
|
||||
GMPParent::CloseActive(bool aDieWhenUnloaded)
|
||||
{
|
||||
@ -385,47 +262,8 @@ GMPParent::CloseActive(bool aDieWhenUnloaded)
|
||||
mState = GMPStateUnloading;
|
||||
}
|
||||
if (mState != GMPStateNotLoaded && IsUsed()) {
|
||||
#if defined(MOZ_CRASHREPORTER)
|
||||
if (mService) {
|
||||
mService->SetAsyncShutdownPluginState(this, 'A',
|
||||
nsPrintfCString("Sent CloseActive, content children to close: %u", mGMPContentChildCount));
|
||||
}
|
||||
#endif
|
||||
if (!SendCloseActive()) {
|
||||
#if defined(MOZ_CRASHREPORTER)
|
||||
if (mService) {
|
||||
mService->SetAsyncShutdownPluginState(this, 'B',
|
||||
NS_LITERAL_CSTRING("Could not send CloseActive - Aborting async shutdown"));
|
||||
}
|
||||
#endif
|
||||
AbortAsyncShutdown();
|
||||
} else if (IsUsed()) {
|
||||
// We're expecting RecvPGMPContentChildDestroyed's -> Start async-shutdown timer now if needed.
|
||||
if (mAsyncShutdownRequired && NS_FAILED(EnsureAsyncShutdownTimeoutSet())) {
|
||||
#if defined(MOZ_CRASHREPORTER)
|
||||
if (mService) {
|
||||
mService->SetAsyncShutdownPluginState(this, 'C',
|
||||
NS_LITERAL_CSTRING("Could not start timer after sending CloseActive - Aborting async shutdown"));
|
||||
}
|
||||
#endif
|
||||
AbortAsyncShutdown();
|
||||
}
|
||||
} else {
|
||||
// We're not expecting any RecvPGMPContentChildDestroyed
|
||||
// -> Call CloseIfUnused() now, to run async shutdown if necessary.
|
||||
// Note that CloseIfUnused() may have already been called from a prior
|
||||
// RecvPGMPContentChildDestroyed(), however depending on the state at
|
||||
// that time, it might not have proceeded with shutdown; And calling it
|
||||
// again after shutdown is fine because after the first one we'll be in
|
||||
// GMPStateNotLoaded.
|
||||
#if defined(MOZ_CRASHREPORTER)
|
||||
if (mService) {
|
||||
mService->SetAsyncShutdownPluginState(this, 'D',
|
||||
NS_LITERAL_CSTRING("Content children already destroyed"));
|
||||
}
|
||||
#endif
|
||||
CloseIfUnused();
|
||||
}
|
||||
Unused << SendCloseActive();
|
||||
CloseIfUnused();
|
||||
}
|
||||
}
|
||||
|
||||
@ -448,8 +286,6 @@ GMPParent::Shutdown()
|
||||
LOGD("%s", __FUNCTION__);
|
||||
MOZ_ASSERT(GMPThread() == NS_GetCurrentThread());
|
||||
|
||||
MOZ_ASSERT(!mAsyncShutdownTimeout, "Should have canceled shutdown timeout");
|
||||
|
||||
if (mAbnormalShutdownInProgress) {
|
||||
return;
|
||||
}
|
||||
@ -706,16 +542,6 @@ GMPParent::ActorDestroy(ActorDestroyReason aWhy)
|
||||
// Normal Shutdown() will delete the process on unwind.
|
||||
if (AbnormalShutdown == aWhy) {
|
||||
RefPtr<GMPParent> self(this);
|
||||
if (mAsyncShutdownRequired) {
|
||||
#if defined(MOZ_CRASHREPORTER)
|
||||
if (mService) {
|
||||
mService->SetAsyncShutdownPluginState(this, 'M',
|
||||
NS_LITERAL_CSTRING("Actor destroyed"));
|
||||
}
|
||||
#endif
|
||||
mService->AsyncShutdownComplete(this);
|
||||
mAsyncShutdownRequired = false;
|
||||
}
|
||||
// Must not call Close() again in DeleteProcess(), as we'll recurse
|
||||
// infinitely if we do.
|
||||
MOZ_ASSERT(mState == GMPStateClosing);
|
||||
@ -998,8 +824,7 @@ GMPParent::ParseChromiumManifest(const nsAString& aJSON)
|
||||
bool
|
||||
GMPParent::CanBeSharedCrossNodeIds() const
|
||||
{
|
||||
return !mAsyncShutdownInProgress &&
|
||||
mNodeId.IsEmpty() &&
|
||||
return mNodeId.IsEmpty() &&
|
||||
// XXX bug 1159300 hack -- maybe remove after openh264 1.4
|
||||
// We don't want to use CDM decoders for non-encrypted playback
|
||||
// just yet; especially not for WebRTC. Don't allow CDMs to be used
|
||||
@ -1010,7 +835,7 @@ GMPParent::CanBeSharedCrossNodeIds() const
|
||||
bool
|
||||
GMPParent::CanBeUsedFrom(const nsACString& aNodeId) const
|
||||
{
|
||||
return !mAsyncShutdownInProgress && mNodeId == aNodeId;
|
||||
return mNodeId == aNodeId;
|
||||
}
|
||||
|
||||
void
|
||||
@ -1038,35 +863,6 @@ GMPParent::GetPluginId() const
|
||||
return mPluginId;
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
GMPParent::RecvAsyncShutdownRequired()
|
||||
{
|
||||
LOGD("%s", __FUNCTION__);
|
||||
if (mAsyncShutdownRequired) {
|
||||
NS_WARNING("Received AsyncShutdownRequired message more than once!");
|
||||
return IPC_OK();
|
||||
}
|
||||
mAsyncShutdownRequired = true;
|
||||
mService->AsyncShutdownNeeded(this);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
GMPParent::RecvAsyncShutdownComplete()
|
||||
{
|
||||
LOGD("%s", __FUNCTION__);
|
||||
|
||||
MOZ_ASSERT(mAsyncShutdownRequired);
|
||||
#if defined(MOZ_CRASHREPORTER)
|
||||
if (mService) {
|
||||
mService->SetAsyncShutdownPluginState(this, 'L',
|
||||
NS_LITERAL_CSTRING("Received AsyncShutdownComplete"));
|
||||
}
|
||||
#endif
|
||||
AbortAsyncShutdown();
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
void
|
||||
GMPParent::ResolveGetContentParentPromises()
|
||||
{
|
||||
|
@ -182,9 +182,6 @@ private:
|
||||
PGMPTimerParent* AllocPGMPTimerParent() override;
|
||||
bool DeallocPGMPTimerParent(PGMPTimerParent* aActor) override;
|
||||
|
||||
mozilla::ipc::IPCResult RecvAsyncShutdownComplete() override;
|
||||
mozilla::ipc::IPCResult RecvAsyncShutdownRequired() override;
|
||||
|
||||
mozilla::ipc::IPCResult RecvPGMPContentChildDestroyed() override;
|
||||
bool IsUsed()
|
||||
{
|
||||
@ -195,9 +192,6 @@ private:
|
||||
void ResolveGetContentParentPromises();
|
||||
void RejectGetContentParentPromises();
|
||||
|
||||
static void AbortWaitingForGMPAsyncShutdown(nsITimer* aTimer, void* aClosure);
|
||||
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
|
||||
@ -220,7 +214,6 @@ private:
|
||||
nsTArray<RefPtr<GMPTimerParent>> mTimers;
|
||||
nsTArray<RefPtr<GMPStorageParent>> mStorage;
|
||||
nsCOMPtr<nsIThread> mGMPThread;
|
||||
nsCOMPtr<nsITimer> mAsyncShutdownTimeout; // GMP Thread only.
|
||||
// NodeId the plugin is assigned to, or empty if the the plugin is not
|
||||
// assigned to a NodeId.
|
||||
nsCString mNodeId;
|
||||
@ -230,9 +223,6 @@ private:
|
||||
nsTArray<UniquePtr<MozPromiseHolder<GetGMPContentParentPromise>>> mGetContentParentPromises;
|
||||
uint32_t mGMPContentChildCount;
|
||||
|
||||
bool mAsyncShutdownRequired;
|
||||
bool mAsyncShutdownInProgress;
|
||||
|
||||
int mChildPid;
|
||||
|
||||
// We hold a self reference to ourself while the child process is alive.
|
||||
|
@ -75,8 +75,6 @@ public:
|
||||
return GetDecryptingGMPVideoDecoder(aHelper, aTags, aNodeId, Move(aCallback), 0);
|
||||
}
|
||||
|
||||
int32_t AsyncShutdownTimeoutMs();
|
||||
|
||||
NS_IMETHOD RunPluginCrashCallbacks(uint32_t aPluginId,
|
||||
const nsACString& aPluginName) override;
|
||||
|
||||
|
@ -87,9 +87,6 @@ NS_IMPL_ISUPPORTS_INHERITED(GeckoMediaPluginServiceParent,
|
||||
|
||||
GeckoMediaPluginServiceParent::GeckoMediaPluginServiceParent()
|
||||
: mShuttingDown(false)
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
, mAsyncShutdownPluginStatesMutex("GeckoMediaPluginService::mAsyncShutdownPluginStatesMutex")
|
||||
#endif
|
||||
, mScannedPluginOnDisk(false)
|
||||
, mWaitingForPluginsSyncShutdown(false)
|
||||
, mInitPromiseMonitor("GeckoMediaPluginServiceParent::mInitPromiseMonitor")
|
||||
@ -103,13 +100,6 @@ GeckoMediaPluginServiceParent::GeckoMediaPluginServiceParent()
|
||||
GeckoMediaPluginServiceParent::~GeckoMediaPluginServiceParent()
|
||||
{
|
||||
MOZ_ASSERT(mPlugins.IsEmpty());
|
||||
MOZ_ASSERT(mAsyncShutdownPlugins.IsEmpty());
|
||||
}
|
||||
|
||||
int32_t
|
||||
GeckoMediaPluginServiceParent::AsyncShutdownTimeoutMs()
|
||||
{
|
||||
return MediaPrefs::GMPAsyncShutdownTimeout();
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -288,48 +278,6 @@ GeckoMediaPluginServiceParent::Observe(nsISupports* aSubject,
|
||||
}
|
||||
}
|
||||
} else if (!strcmp("profile-change-teardown", aTopic)) {
|
||||
|
||||
// How shutdown works:
|
||||
//
|
||||
// Some GMPs require time to do bookkeeping upon shutdown. These GMPs
|
||||
// need to be given time to access storage during shutdown. To signal
|
||||
// that time to shutdown is required, those GMPs implement the
|
||||
// GMPAsyncShutdown interface.
|
||||
//
|
||||
// When we startup the child process, we query the GMP for the
|
||||
// GMPAsyncShutdown interface, and if it's present, we send a message
|
||||
// back to the GMPParent, which then registers the GMPParent by calling
|
||||
// GMPService::AsyncShutdownNeeded().
|
||||
//
|
||||
// On shutdown, we set mWaitingForPluginsSyncShutdown to true, and then
|
||||
// call UnloadPlugins on the GMPThread, and process events on the main
|
||||
// thread until 1. An event sets mWaitingForPluginsSyncShutdown=false on
|
||||
// the main thread; then 2. All async-shutdown plugins have indicated
|
||||
// they have completed shutdown.
|
||||
//
|
||||
// UnloadPlugins() sends close messages for all plugins' API objects to
|
||||
// the GMP interfaces in the child process, and then sends the async
|
||||
// shutdown notifications to child GMPs. When a GMP has completed its
|
||||
// shutdown, it calls GMPAsyncShutdownHost::ShutdownComplete(), which
|
||||
// sends a message back to the parent, which calls
|
||||
// GMPService::AsyncShutdownComplete(). If all plugins requiring async
|
||||
// shutdown have called AsyncShutdownComplete() we stick a dummy event on
|
||||
// the main thread, where the list of pending plugins is checked. We must
|
||||
// use an event to do this, as we must ensure the main thread processes an
|
||||
// event to run its loop. This will unblock the main thread, and shutdown
|
||||
// of other components will proceed.
|
||||
//
|
||||
// During shutdown, each GMPParent starts a timer, and pretends shutdown
|
||||
// is complete if it is taking too long.
|
||||
//
|
||||
// We shutdown in "profile-change-teardown", as the profile dir is
|
||||
// still writable then, and it's required for GMPStorage. We block the
|
||||
// shutdown process by spinning the main thread event loop until all GMPs
|
||||
// have shutdown, or timeout has occurred.
|
||||
//
|
||||
// GMPStorage needs to work up until the shutdown-complete notification
|
||||
// arrives from the GMP process.
|
||||
|
||||
mWaitingForPluginsSyncShutdown = true;
|
||||
|
||||
nsCOMPtr<nsIThread> gmpThread;
|
||||
@ -341,68 +289,18 @@ GeckoMediaPluginServiceParent::Observe(nsISupports* aSubject,
|
||||
}
|
||||
|
||||
if (gmpThread) {
|
||||
LOGD(("%s::%s Starting to unload plugins, waiting for first sync shutdown..."
|
||||
LOGD(("%s::%s Starting to unload plugins, waiting for sync shutdown..."
|
||||
, __CLASS__, __FUNCTION__));
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
SetAsyncShutdownPluginState(nullptr, '0',
|
||||
NS_LITERAL_CSTRING("Dispatching UnloadPlugins"));
|
||||
#endif
|
||||
gmpThread->Dispatch(
|
||||
NewRunnableMethod(this,
|
||||
&GeckoMediaPluginServiceParent::UnloadPlugins),
|
||||
NS_DISPATCH_NORMAL);
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
SetAsyncShutdownPluginState(nullptr, '1',
|
||||
NS_LITERAL_CSTRING("Waiting for sync shutdown"));
|
||||
#endif
|
||||
// Wait for UnloadPlugins() to do initial sync shutdown...
|
||||
// Wait for UnloadPlugins() to do sync shutdown...
|
||||
while (mWaitingForPluginsSyncShutdown) {
|
||||
NS_ProcessNextEvent(NS_GetCurrentThread(), true);
|
||||
}
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
SetAsyncShutdownPluginState(nullptr, '4',
|
||||
NS_LITERAL_CSTRING("Waiting for async shutdown"));
|
||||
#endif
|
||||
// Wait for other plugins (if any) to do async shutdown...
|
||||
auto syncShutdownPluginsRemaining =
|
||||
std::numeric_limits<decltype(mAsyncShutdownPlugins.Length())>::max();
|
||||
for (;;) {
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
if (mAsyncShutdownPlugins.IsEmpty()) {
|
||||
LOGD(("%s::%s Finished unloading all plugins"
|
||||
, __CLASS__, __FUNCTION__));
|
||||
#if defined(MOZ_CRASHREPORTER)
|
||||
CrashReporter::RemoveCrashReportAnnotation(
|
||||
NS_LITERAL_CSTRING("AsyncPluginShutdown"));
|
||||
#endif
|
||||
break;
|
||||
} else if (mAsyncShutdownPlugins.Length() < syncShutdownPluginsRemaining) {
|
||||
// First time here, or number of pending plugins has decreased.
|
||||
// -> Update list of pending plugins in crash report.
|
||||
syncShutdownPluginsRemaining = mAsyncShutdownPlugins.Length();
|
||||
LOGD(("%s::%s Still waiting for %d plugins to shutdown..."
|
||||
, __CLASS__, __FUNCTION__, (int)syncShutdownPluginsRemaining));
|
||||
#if defined(MOZ_CRASHREPORTER)
|
||||
nsAutoCString names;
|
||||
for (const auto& plugin : mAsyncShutdownPlugins) {
|
||||
if (!names.IsEmpty()) { names.Append(NS_LITERAL_CSTRING(", ")); }
|
||||
names.Append(plugin->GetDisplayName());
|
||||
}
|
||||
CrashReporter::AnnotateCrashReport(
|
||||
NS_LITERAL_CSTRING("AsyncPluginShutdown"),
|
||||
names);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
NS_ProcessNextEvent(NS_GetCurrentThread(), true);
|
||||
}
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
SetAsyncShutdownPluginState(nullptr, '5',
|
||||
NS_LITERAL_CSTRING("Async shutdown complete"));
|
||||
#endif
|
||||
} else {
|
||||
// GMP thread has already shutdown.
|
||||
MOZ_ASSERT(mPlugins.IsEmpty());
|
||||
@ -519,105 +417,6 @@ GeckoMediaPluginServiceParent::InitializePlugins(
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
GeckoMediaPluginServiceParent::AsyncShutdownNeeded(GMPParent* aParent)
|
||||
{
|
||||
LOGD(("%s::%s %p", __CLASS__, __FUNCTION__, aParent));
|
||||
MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
|
||||
|
||||
MutexAutoLock lock(mMutex);
|
||||
MOZ_ASSERT(!mAsyncShutdownPlugins.Contains(aParent));
|
||||
mAsyncShutdownPlugins.AppendElement(aParent);
|
||||
}
|
||||
|
||||
void
|
||||
GeckoMediaPluginServiceParent::AsyncShutdownComplete(GMPParent* aParent)
|
||||
{
|
||||
LOGD(("%s::%s %p '%s'", __CLASS__, __FUNCTION__,
|
||||
aParent, aParent->GetDisplayName().get()));
|
||||
MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
|
||||
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
mAsyncShutdownPlugins.RemoveElement(aParent);
|
||||
}
|
||||
|
||||
if (mShuttingDownOnGMPThread) {
|
||||
// The main thread may be waiting for async shutdown of plugins,
|
||||
// one of which has completed. Wake up the main thread by sending a task.
|
||||
nsCOMPtr<nsIRunnable> task(NewRunnableMethod(
|
||||
this, &GeckoMediaPluginServiceParent::NotifyAsyncShutdownComplete));
|
||||
NS_DispatchToMainThread(task);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
void
|
||||
GeckoMediaPluginServiceParent::SetAsyncShutdownPluginState(GMPParent* aGMPParent,
|
||||
char aId,
|
||||
const nsCString& aState)
|
||||
{
|
||||
MutexAutoLock lock(mAsyncShutdownPluginStatesMutex);
|
||||
if (!aGMPParent) {
|
||||
mAsyncShutdownPluginStates.Update(NS_LITERAL_CSTRING("-"),
|
||||
NS_LITERAL_CSTRING("-"),
|
||||
aId,
|
||||
aState);
|
||||
return;
|
||||
}
|
||||
mAsyncShutdownPluginStates.Update(aGMPParent->GetDisplayName(),
|
||||
nsPrintfCString("%p", aGMPParent),
|
||||
aId,
|
||||
aState);
|
||||
}
|
||||
|
||||
void
|
||||
GeckoMediaPluginServiceParent::AsyncShutdownPluginStates::Update(const nsCString& aPlugin,
|
||||
const nsCString& aInstance,
|
||||
char aId,
|
||||
const nsCString& aState)
|
||||
{
|
||||
nsCString note;
|
||||
StatesByInstance* instances = mStates.LookupOrAdd(aPlugin);
|
||||
if (!instances) { return; }
|
||||
State* state = instances->LookupOrAdd(aInstance);
|
||||
if (!state) { return; }
|
||||
state->mStateSequence += aId;
|
||||
state->mLastStateDescription = aState;
|
||||
note += '{';
|
||||
bool firstPlugin = true;
|
||||
for (auto pluginIt = mStates.ConstIter(); !pluginIt.Done(); pluginIt.Next()) {
|
||||
if (!firstPlugin) { note += ','; } else { firstPlugin = false; }
|
||||
note += pluginIt.Key();
|
||||
note += ":{";
|
||||
bool firstInstance = true;
|
||||
for (auto instanceIt = pluginIt.UserData()->ConstIter(); !instanceIt.Done(); instanceIt.Next()) {
|
||||
if (!firstInstance) { note += ','; } else { firstInstance = false; }
|
||||
note += instanceIt.Key();
|
||||
note += ":\"";
|
||||
note += instanceIt.UserData()->mStateSequence;
|
||||
note += '=';
|
||||
note += instanceIt.UserData()->mLastStateDescription;
|
||||
note += '"';
|
||||
}
|
||||
note += '}';
|
||||
}
|
||||
note += '}';
|
||||
LOGD(("%s::%s states[%s][%s]='%c'/'%s' -> %s", __CLASS__, __FUNCTION__,
|
||||
aPlugin.get(), aInstance.get(), aId, aState.get(), note.get()));
|
||||
CrashReporter::AnnotateCrashReport(
|
||||
NS_LITERAL_CSTRING("AsyncPluginShutdownStates"),
|
||||
note);
|
||||
}
|
||||
#endif // MOZ_CRASHREPORTER
|
||||
|
||||
void
|
||||
GeckoMediaPluginServiceParent::NotifyAsyncShutdownComplete()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
// Nothing to do, this task is just used to wake up the event loop in Observe().
|
||||
}
|
||||
|
||||
void
|
||||
GeckoMediaPluginServiceParent::NotifySyncShutdownComplete()
|
||||
{
|
||||
@ -638,10 +437,6 @@ GeckoMediaPluginServiceParent::UnloadPlugins()
|
||||
MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
|
||||
MOZ_ASSERT(!mShuttingDownOnGMPThread);
|
||||
mShuttingDownOnGMPThread = true;
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
SetAsyncShutdownPluginState(nullptr, '2',
|
||||
NS_LITERAL_CSTRING("Starting to unload plugins"));
|
||||
#endif
|
||||
|
||||
nsTArray<RefPtr<GMPParent>> plugins;
|
||||
{
|
||||
@ -651,32 +446,20 @@ GeckoMediaPluginServiceParent::UnloadPlugins()
|
||||
Swap(plugins, mPlugins);
|
||||
}
|
||||
|
||||
LOGD(("%s::%s plugins:%u including async:%u", __CLASS__, __FUNCTION__,
|
||||
plugins.Length(), mAsyncShutdownPlugins.Length()));
|
||||
LOGD(("%s::%s plugins:%u", __CLASS__, __FUNCTION__,
|
||||
plugins.Length()));
|
||||
#ifdef DEBUG
|
||||
for (const auto& plugin : plugins) {
|
||||
LOGD(("%s::%s plugin: '%s'", __CLASS__, __FUNCTION__,
|
||||
plugin->GetDisplayName().get()));
|
||||
}
|
||||
for (const auto& plugin : mAsyncShutdownPlugins) {
|
||||
LOGD(("%s::%s async plugin: '%s'", __CLASS__, __FUNCTION__,
|
||||
plugin->GetDisplayName().get()));
|
||||
}
|
||||
#endif
|
||||
// Note: CloseActive may be async; it could actually finish
|
||||
// shutting down when all the plugins have unloaded.
|
||||
for (const auto& plugin : plugins) {
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
SetAsyncShutdownPluginState(plugin, 'S',
|
||||
NS_LITERAL_CSTRING("CloseActive"));
|
||||
#endif
|
||||
plugin->CloseActive(true);
|
||||
}
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
SetAsyncShutdownPluginState(nullptr, '3',
|
||||
NS_LITERAL_CSTRING("Dispatching sync-shutdown-complete"));
|
||||
#endif
|
||||
nsCOMPtr<nsIRunnable> task(NewRunnableMethod(
|
||||
this, &GeckoMediaPluginServiceParent::NotifySyncShutdownComplete));
|
||||
NS_DispatchToMainThread(task);
|
||||
@ -1118,7 +901,6 @@ GeckoMediaPluginServiceParent::RemoveOnGMPThread(const nsAString& aDirectory,
|
||||
{
|
||||
MutexAutoUnlock unlock(mMutex);
|
||||
for (auto& gmp : deadPlugins) {
|
||||
gmp->AbortAsyncShutdown();
|
||||
gmp->CloseActive(true);
|
||||
}
|
||||
}
|
||||
@ -1562,9 +1344,6 @@ KillPlugins(const nsTArray<RefPtr<GMPParent>>& aPlugins,
|
||||
|
||||
for (size_t i = 0; i < pluginsToKill.Length(); i++) {
|
||||
pluginsToKill[i]->CloseActive(false);
|
||||
// Abort async shutdown because we're going to wipe the plugin's storage,
|
||||
// so we don't want it writing more data in its async shutdown path.
|
||||
pluginsToKill[i]->AbortAsyncShutdown();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,13 +49,6 @@ public:
|
||||
NS_DECL_MOZIGECKOMEDIAPLUGINCHROMESERVICE
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
void AsyncShutdownNeeded(GMPParent* aParent);
|
||||
void AsyncShutdownComplete(GMPParent* aParent);
|
||||
|
||||
int32_t AsyncShutdownTimeoutMs();
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
void SetAsyncShutdownPluginState(GMPParent* aGMPParent, char aId, const nsCString& aState);
|
||||
#endif // MOZ_CRASHREPORTER
|
||||
RefPtr<GenericPromise> EnsureInitialized();
|
||||
RefPtr<GenericPromise> AsyncAddPluginDirectory(const nsAString& aDirectory);
|
||||
|
||||
@ -94,7 +87,6 @@ private:
|
||||
void UnloadPlugins();
|
||||
void CrashPlugins();
|
||||
void NotifySyncShutdownComplete();
|
||||
void NotifyAsyncShutdownComplete();
|
||||
|
||||
void ProcessPossiblePlugin(nsIFile* aDir);
|
||||
|
||||
@ -102,8 +94,6 @@ private:
|
||||
const bool aDeleteFromDisk,
|
||||
const bool aCanDefer);
|
||||
|
||||
nsresult SetAsyncShutdownTimeout();
|
||||
|
||||
struct DirectoryFilter {
|
||||
virtual bool operator()(nsIFile* aPath) = 0;
|
||||
~DirectoryFilter() {}
|
||||
@ -166,22 +156,6 @@ private:
|
||||
// Protected by mMutex from the base class.
|
||||
nsTArray<RefPtr<GMPParent>> mPlugins;
|
||||
bool mShuttingDown;
|
||||
nsTArray<RefPtr<GMPParent>> mAsyncShutdownPlugins;
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
Mutex mAsyncShutdownPluginStatesMutex; // Protects mAsyncShutdownPluginStates.
|
||||
class AsyncShutdownPluginStates
|
||||
{
|
||||
public:
|
||||
void Update(const nsCString& aPlugin, const nsCString& aInstance,
|
||||
char aId, const nsCString& aState);
|
||||
private:
|
||||
struct State { nsCString mStateSequence; nsCString mLastStateDescription; };
|
||||
typedef nsClassHashtable<nsCStringHashKey, State> StatesByInstance;
|
||||
typedef nsClassHashtable<nsCStringHashKey, StatesByInstance> StateInstancesByPlugin;
|
||||
StateInstancesByPlugin mStates;
|
||||
} mAsyncShutdownPluginStates;
|
||||
#endif // MOZ_CRASHREPORTER
|
||||
|
||||
// True if we've inspected MOZ_GMP_PATH on the GMP thread and loaded any
|
||||
// plugins found there into mPlugins.
|
||||
|
@ -28,11 +28,7 @@ parent:
|
||||
|
||||
async PGMPContentChildDestroyed();
|
||||
|
||||
async AsyncShutdownComplete();
|
||||
async AsyncShutdownRequired();
|
||||
|
||||
child:
|
||||
async BeginAsyncShutdown();
|
||||
async CrashPluginNow();
|
||||
intr StartPlugin(nsString adapter);
|
||||
async SetNodeId(nsCString nodeId);
|
||||
|
@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013, Mozilla Foundation and contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef GMP_ASYNC_SHUTDOWN_H_
|
||||
#define GMP_ASYNC_SHUTDOWN_H_
|
||||
|
||||
#define GMP_API_ASYNC_SHUTDOWN "async-shutdown"
|
||||
|
||||
// API exposed by the plugin library to manage asynchronous shutdown.
|
||||
// Some plugins require special cleanup which may need to make calls
|
||||
// to host services and wait for async responses.
|
||||
//
|
||||
// To enable a plugins to block shutdown until its async shutdown is
|
||||
// complete, implement the GMPAsyncShutdown interface and return it when
|
||||
// your plugin's GMPGetAPI function is called with "async-shutdown".
|
||||
// When your GMPAsyncShutdown's BeginShutdown() implementation is called
|
||||
// by the GMP host, you should initate your async shutdown process.
|
||||
// Once you have completed shutdown, call the ShutdownComplete() function
|
||||
// of the GMPAsyncShutdownHost that is passed as the host argument to the
|
||||
// GMPGetAPI() call.
|
||||
//
|
||||
// Note: Your GMP's GMPShutdown function will still be called after your
|
||||
// call to ShutdownComplete().
|
||||
//
|
||||
// API name macro: GMP_API_ASYNC_SHUTDOWN
|
||||
// Host API: GMPAsyncShutdownHost
|
||||
class GMPAsyncShutdown {
|
||||
public:
|
||||
virtual ~GMPAsyncShutdown() {}
|
||||
|
||||
virtual void BeginShutdown() = 0;
|
||||
};
|
||||
|
||||
class GMPAsyncShutdownHost {
|
||||
public:
|
||||
virtual ~GMPAsyncShutdownHost() {}
|
||||
|
||||
virtual void ShutdownComplete() = 0;
|
||||
};
|
||||
|
||||
#endif // GMP_ASYNC_SHUTDOWN_H_
|
@ -12,7 +12,6 @@ XPIDL_SOURCES += [
|
||||
]
|
||||
|
||||
EXPORTS += [
|
||||
'gmp-api/gmp-async-shutdown.h',
|
||||
'gmp-api/gmp-decryption.h',
|
||||
'gmp-api/gmp-entrypoints.h',
|
||||
'gmp-api/gmp-errors.h',
|
||||
|
@ -1095,92 +1095,6 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
|
||||
NS_LITERAL_CSTRING("retrieve pbdata"));
|
||||
}
|
||||
|
||||
void NextAsyncShutdownTimeoutTest(nsIRunnable* aContinuation)
|
||||
{
|
||||
if (mDecryptor) {
|
||||
Update(NS_LITERAL_CSTRING("shutdown-mode timeout"));
|
||||
Shutdown();
|
||||
}
|
||||
nsCOMPtr<nsIThread> thread(GetGMPThread());
|
||||
thread->Dispatch(aContinuation, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
void CreateAsyncShutdownTimeoutGMP(const nsAString& aOrigin1,
|
||||
const nsAString& aOrigin2,
|
||||
void (GMPStorageTest::*aCallback)()) {
|
||||
nsCOMPtr<nsIRunnable> continuation(
|
||||
NewRunnableMethod<nsCOMPtr<nsIRunnable>>(
|
||||
this,
|
||||
&GMPStorageTest::NextAsyncShutdownTimeoutTest,
|
||||
NewRunnableMethod(this, aCallback)));
|
||||
|
||||
CreateDecryptor(GetNodeId(aOrigin1, aOrigin2, false), continuation);
|
||||
}
|
||||
|
||||
void TestAsyncShutdownTimeout() {
|
||||
// Create decryptors that timeout in their async shutdown.
|
||||
// If the gtest hangs on shutdown, test fails!
|
||||
CreateAsyncShutdownTimeoutGMP(NS_LITERAL_STRING("http://example7.com"),
|
||||
NS_LITERAL_STRING("http://example8.com"),
|
||||
&GMPStorageTest::TestAsyncShutdownTimeout2);
|
||||
};
|
||||
|
||||
void TestAsyncShutdownTimeout2() {
|
||||
CreateAsyncShutdownTimeoutGMP(NS_LITERAL_STRING("http://example9.com"),
|
||||
NS_LITERAL_STRING("http://example10.com"),
|
||||
&GMPStorageTest::TestAsyncShutdownTimeout3);
|
||||
};
|
||||
|
||||
void TestAsyncShutdownTimeout3() {
|
||||
CreateAsyncShutdownTimeoutGMP(NS_LITERAL_STRING("http://example11.com"),
|
||||
NS_LITERAL_STRING("http://example12.com"),
|
||||
&GMPStorageTest::SetFinished);
|
||||
};
|
||||
|
||||
void TestAsyncShutdownStorage() {
|
||||
// Instruct the GMP to write a token (the current timestamp, so it's
|
||||
// unique) during async shutdown, then shutdown the plugin, re-create
|
||||
// it, and check that the token was successfully stored.
|
||||
auto t = time(0);
|
||||
nsCString update("shutdown-mode token ");
|
||||
nsCString token;
|
||||
token.AppendInt((int64_t)t);
|
||||
update.Append(token);
|
||||
|
||||
// Wait for a response from the GMP, so we know it's had time to receive
|
||||
// the token.
|
||||
nsCString response("shutdown-token received ");
|
||||
response.Append(token);
|
||||
Expect(response, NewRunnableMethod<nsCString>(this,
|
||||
&GMPStorageTest::TestAsyncShutdownStorage_ReceivedShutdownToken, token));
|
||||
|
||||
// Test that a GMP can write to storage during shutdown, and retrieve
|
||||
// that written data in a subsequent session.
|
||||
CreateDecryptor(NS_LITERAL_STRING("http://example13.com"),
|
||||
NS_LITERAL_STRING("http://example14.com"),
|
||||
false,
|
||||
update);
|
||||
}
|
||||
|
||||
void TestAsyncShutdownStorage_ReceivedShutdownToken(const nsCString& aToken) {
|
||||
ShutdownThen(NewRunnableMethod<nsCString>(this,
|
||||
&GMPStorageTest::TestAsyncShutdownStorage_AsyncShutdownComplete, aToken));
|
||||
}
|
||||
|
||||
void TestAsyncShutdownStorage_AsyncShutdownComplete(const nsCString& aToken) {
|
||||
// Create a new instance of the plugin, retrieve the token written
|
||||
// during shutdown and verify it is correct.
|
||||
nsCString response("retrieved shutdown-token ");
|
||||
response.Append(aToken);
|
||||
Expect(response,
|
||||
NewRunnableMethod(this, &GMPStorageTest::SetFinished));
|
||||
|
||||
CreateDecryptor(NS_LITERAL_STRING("http://example13.com"),
|
||||
NS_LITERAL_STRING("http://example14.com"),
|
||||
false,
|
||||
NS_LITERAL_CSTRING("retrieve-shutdown-token"));
|
||||
}
|
||||
|
||||
#if defined(XP_WIN)
|
||||
void TestOutputProtection() {
|
||||
Shutdown();
|
||||
@ -1514,16 +1428,6 @@ TEST(GeckoMediaPlugins, GMPStoragePrivateBrowsing) {
|
||||
runner->DoTest(&GMPStorageTest::TestPBStorage);
|
||||
}
|
||||
|
||||
TEST(GeckoMediaPlugins, GMPStorageAsyncShutdownTimeout) {
|
||||
RefPtr<GMPStorageTest> runner = new GMPStorageTest();
|
||||
runner->DoTest(&GMPStorageTest::TestAsyncShutdownTimeout);
|
||||
}
|
||||
|
||||
TEST(GeckoMediaPlugins, GMPStorageAsyncShutdownStorage) {
|
||||
RefPtr<GMPStorageTest> runner = new GMPStorageTest();
|
||||
runner->DoTest(&GMPStorageTest::TestAsyncShutdownStorage);
|
||||
}
|
||||
|
||||
TEST(GeckoMediaPlugins, GMPPluginVoucher) {
|
||||
RefPtr<GMPStorageTest> runner = new GMPStorageTest();
|
||||
runner->DoTest(&GMPStorageTest::TestPluginVoucher);
|
||||
|
Loading…
Reference in New Issue
Block a user