--- a/dom/media/MediaPrefs.h
+++ b/dom/media/MediaPrefs.h
@@ -96,17 +96,16 @@ private:
DECL_MEDIA_PREF("media.ruin-av-sync.enabled", RuinAvSync, bool, false);
// Encrypted Media Extensions
DECL_MEDIA_PREF("media.clearkey.persistent-license.enabled", ClearKeyPersistentLicenseEnabled, bool, false);
// 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);
#ifdef MOZ_GONK_MEDIACODEC
DECL_MEDIA_PREF("media.gonk.enabled", PDMGonkDecoderEnabled, bool, true);
#endif
#ifdef MOZ_WIDGET_ANDROID
DECL_MEDIA_PREF("media.android-media-codec.enabled", PDMAndroidMediaCodecEnabled, bool, false);
--- a/dom/media/gmp-plugin-openh264/gmp-fake-openh264.cpp
+++ b/dom/media/gmp-plugin-openh264/gmp-fake-openh264.cpp
@@ -407,19 +407,16 @@ extern "C" {
return GMPNoErr;
} else if (!strcmp (aApiName, GMP_API_VIDEO_ENCODER)) {
*aPluginApi = new FakeVideoEncoder (static_cast<GMPVideoHost*> (aHostAPI));
return GMPNoErr;
#if defined(GMP_FAKE_SUPPORT_DECRYPT)
} 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;
}
PUBLIC_FUNC void
GMPShutdown (void) {
g_platform_api = NULL;
--- a/dom/media/gmp-plugin/gmp-fake.cpp
+++ b/dom/media/gmp-plugin/gmp-fake.cpp
@@ -70,19 +70,16 @@ extern "C" {
// Note: Deliberately advertise in our .info file that we support
// video-decode, but we fail the "get" call here to simulate what
// happens when decoder init fails.
return GMPGenericErr;
#if defined(GMP_FAKE_SUPPORT_DECRYPT)
} 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;
}
PUBLIC_FUNC void
GMPShutdown (void) {
g_platform_api = NULL;
--- a/dom/media/gmp-plugin/gmp-test-decryptor.cpp
+++ b/dom/media/gmp-plugin/gmp-test-decryptor.cpp
@@ -568,41 +568,8 @@ FakeDecryptor::UpdateSession(uint32_t aP
std::string voucher((const char*)rawVoucher, (const char*)(rawVoucher + length));
Message("retrieved plugin-voucher: " + voucher);
} else if (task == "retrieve-record-names") {
GMPEnumRecordNames(&RecvGMPRecordIterator, this);
} else if (task == "retrieve-node-id") {
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;
- }
-}
--- a/dom/media/gmp-plugin/gmp-test-decryptor.h
+++ b/dom/media/gmp-plugin/gmp-test-decryptor.h
@@ -2,17 +2,16 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef FAKE_DECRYPTOR_H__
#define FAKE_DECRYPTOR_H__
#include "gmp-decryption.h"
-#include "gmp-async-shutdown.h"
#include <string>
#include "mozilla/Attributes.h"
class FakeDecryptor : public GMPDecryptor {
public:
explicit FakeDecryptor(GMPDecryptorHost* aHost);
@@ -86,20 +85,9 @@ private:
static std::string sNodeId;
void TestStorage();
GMPDecryptorCallback* mCallback;
GMPDecryptorHost* mHost;
};
-class TestAsyncShutdown : public GMPAsyncShutdown {
-public:
- explicit TestAsyncShutdown(GMPAsyncShutdownHost* aHost)
- : mHost(aHost)
- {
- }
- void BeginShutdown() override;
-private:
- GMPAsyncShutdownHost* mHost;
-};
-
#endif
--- a/dom/media/gmp/GMPChild.cpp
+++ b/dom/media/gmp/GMPChild.cpp
@@ -48,18 +48,17 @@ namespace mozilla {
extern LogModule* GetGMPLog();
#define LOG(level, x, ...) MOZ_LOG(GetGMPLog(), (level), (x, ##__VA_ARGS__))
#define LOGD(x, ...) LOG(mozilla::LogLevel::Debug, "GMPChild[pid=%d] " x, (int)base::GetCurrentProcId(), ##__VA_ARGS__)
namespace gmp {
GMPChild::GMPChild()
- : mAsyncShutdown(nullptr)
- , mGMPMessageLoop(MessageLoop::current())
+ : mGMPMessageLoop(MessageLoop::current())
, mGMPLoader(nullptr)
{
LOGD("GMPChild ctor");
nsDebugImpl::SetMultiprocessMode("GMP");
}
GMPChild::~GMPChild()
{
@@ -394,24 +393,16 @@ GMPChild::AnswerStartPlugin(const nsStri
mNodeId.Length(),
platformAPI,
adapter)) {
NS_WARNING("Failed to load GMP");
delete platformAPI;
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();
}
MessageLoop*
GMPChild::GMPMessageLoop()
{
return mGMPMessageLoop;
}
@@ -529,47 +520,24 @@ GMPChild::GetGMPStorage()
mozilla::ipc::IPCResult
GMPChild::RecvCrashPluginNow()
{
MOZ_CRASH();
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()
{
for (uint32_t i = mGMPContentChildren.Length(); i > 0; i--) {
mGMPContentChildren[i - 1]->CloseActive();
}
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)
{
nsAutoString baseName;
GetFileBase(aPluginPath, aOutVoucherFile, baseName);
nsAutoString infoFileName = baseName + NS_LITERAL_STRING(".voucher");
aOutVoucherFile->AppendRelativePath(infoFileName);
--- a/dom/media/gmp/GMPChild.h
+++ b/dom/media/gmp/GMPChild.h
@@ -5,46 +5,41 @@
#ifndef GMPChild_h_
#define GMPChild_h_
#include "mozilla/gmp/PGMPChild.h"
#include "GMPTimerChild.h"
#include "GMPStorageChild.h"
#include "GMPLoader.h"
-#include "gmp-async-shutdown.h"
#include "gmp-entrypoints.h"
#include "prlink.h"
namespace mozilla {
namespace gmp {
class GMPContentChild;
class GMPChild : public PGMPChild
- , public GMPAsyncShutdownHost
{
public:
GMPChild();
virtual ~GMPChild();
bool Init(const nsAString& aPluginPath,
const nsAString& aVoucherPath,
base::ProcessId aParentPid,
MessageLoop* aIOLoop,
IPC::Channel* aChannel);
MessageLoop* GMPMessageLoop();
// Main thread only.
GMPTimerChild* GetGMPTimers();
GMPStorageChild* GetGMPStorage();
- // GMPAsyncShutdownHost
- void ShutdownComplete() override;
-
#if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
bool SetMacSandboxInfo(MacSandboxPluginType aPluginType);
#endif
private:
friend class GMPContentChild;
bool PreLoadPluginVoucher();
@@ -65,27 +60,25 @@ private:
PGMPStorageChild* AllocPGMPStorageChild() override;
bool DeallocPGMPStorageChild(PGMPStorageChild* aActor) override;
PGMPContentChild* AllocPGMPContentChild(Transport* aTransport,
ProcessId aOtherPid) override;
void GMPContentChildActorDestroy(GMPContentChild* aGMPContentChild);
mozilla::ipc::IPCResult RecvCrashPluginNow() override;
- mozilla::ipc::IPCResult RecvBeginAsyncShutdown() override;
mozilla::ipc::IPCResult RecvCloseActive() override;
void ActorDestroy(ActorDestroyReason aWhy) override;
void ProcessingError(Result aCode, const char* aReason) override;
GMPErr GetAPI(const char* aAPIName, void* aHostAPI, void** aPluginAPI, uint32_t aDecryptorId = 0);
nsTArray<UniquePtr<GMPContentChild>> mGMPContentChildren;
- GMPAsyncShutdown* mAsyncShutdown;
RefPtr<GMPTimerChild> mTimerChild;
RefPtr<GMPStorageChild> mStorage;
MessageLoop* mGMPMessageLoop;
nsString mPluginPath;
nsString mSandboxVoucherPath;
nsCString mNodeId;
GMPLoader* mGMPLoader;
--- a/dom/media/gmp/GMPParent.cpp
+++ b/dom/media/gmp/GMPParent.cpp
@@ -63,18 +63,16 @@ namespace gmp {
GMPParent::GMPParent()
: mState(GMPStateNotLoaded)
, mProcess(nullptr)
, mDeleteProcessOnlyOnUnload(false)
, mAbnormalShutdownInProgress(false)
, mIsBlockingDeletion(false)
, mCanDecrypt(false)
, mGMPContentChildCount(0)
- , mAsyncShutdownRequired(false)
- , mAsyncShutdownInProgress(false)
, mChildPid(0)
, mHoldingSelfRef(false)
{
mPluginId = GeckoChildProcessHost::GetUniqueID();
LOGD("GMPParent ctor id=%u", mPluginId);
}
GMPParent::~GMPParent()
@@ -212,225 +210,65 @@ GMPParent::LoadProcess()
// terminate the child process.
MOZ_ASSERT(!mHoldingSelfRef);
mHoldingSelfRef = true;
AddRef();
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();
}
void
GMPParent::CloseIfUnused()
{
MOZ_ASSERT(GMPThread() == NS_GetCurrentThread());
- LOGD("%s: mAsyncShutdownRequired=%d", __FUNCTION__, mAsyncShutdownRequired);
+ LOGD("%s", __FUNCTION__);
if ((mDeleteProcessOnlyOnUnload ||
mState == GMPStateLoaded ||
mState == GMPStateUnloading) &&
!IsUsed()) {
// Ensure all timers are killed.
for (uint32_t i = mTimers.Length(); i > 0; i--) {
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)
{
LOGD("%s: state %d", __FUNCTION__, mState);
MOZ_ASSERT(GMPThread() == NS_GetCurrentThread());
if (aDieWhenUnloaded) {
mDeleteProcessOnlyOnUnload = true; // don't allow this to go back...
}
if (mState == GMPStateLoaded) {
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();
}
}
void
GMPParent::MarkForDeletion()
{
mDeleteProcessOnlyOnUnload = true;
mIsBlockingDeletion = true;
@@ -443,18 +281,16 @@ GMPParent::IsMarkedForDeletion()
}
void
GMPParent::Shutdown()
{
LOGD("%s", __FUNCTION__);
MOZ_ASSERT(GMPThread() == NS_GetCurrentThread());
- MOZ_ASSERT(!mAsyncShutdownTimeout, "Should have canceled shutdown timeout");
-
if (mAbnormalShutdownInProgress) {
return;
}
MOZ_ASSERT(!IsUsed());
if (mState == GMPStateNotLoaded || mState == GMPStateClosing) {
return;
}
@@ -701,26 +537,16 @@ GMPParent::ActorDestroy(ActorDestroyReas
// warn us off trying to close again
mState = GMPStateClosing;
mAbnormalShutdownInProgress = true;
CloseActive(false);
// 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);
DeleteProcess();
// Note: final destruction will be Dispatched to ourself
mService->ReAddOnGMPThread(self);
}
}
@@ -993,29 +819,28 @@ GMPParent::ParseChromiumManifest(const n
mAdapter = NS_LITERAL_STRING("widevine");
return GenericPromise::CreateAndResolve(true, __func__);
}
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
// without a node ID.
!mCanDecrypt;
}
bool
GMPParent::CanBeUsedFrom(const nsACString& aNodeId) const
{
- return !mAsyncShutdownInProgress && mNodeId == aNodeId;
+ return mNodeId == aNodeId;
}
void
GMPParent::SetNodeId(const nsACString& aNodeId)
{
MOZ_ASSERT(!aNodeId.IsEmpty());
mNodeId = aNodeId;
}
@@ -1033,45 +858,16 @@ GMPParent::GetVersion() const
}
uint32_t
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()
{
nsTArray<UniquePtr<MozPromiseHolder<GetGMPContentParentPromise>>> promises;
promises.SwapElements(mGetContentParentPromises);
MOZ_ASSERT(mGetContentParentPromises.IsEmpty());
RefPtr<GMPContentParent::CloseBlocker> blocker(new GMPContentParent::CloseBlocker(mGMPContentParent));
for (auto& holder : promises) {
--- a/dom/media/gmp/GMPParent.h
+++ b/dom/media/gmp/GMPParent.h
@@ -177,32 +177,26 @@ private:
PGMPContentParent* AllocPGMPContentParent(Transport* aTransport,
ProcessId aOtherPid) override;
mozilla::ipc::IPCResult RecvPGMPTimerConstructor(PGMPTimerParent* actor) override;
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()
{
return mGMPContentChildCount > 0 ||
!mGetContentParentPromises.IsEmpty();
}
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
nsCString mDisplayName; // name of plugin displayed to users
nsCString mDescription; // description of plugin for display to users
nsCString mVersion;
#ifdef XP_WIN
nsCString mLibs;
@@ -215,29 +209,25 @@ private:
bool mAbnormalShutdownInProgress;
bool mIsBlockingDeletion;
bool mCanDecrypt;
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;
// This is used for GMP content in the parent, there may be more of these in
// the content processes.
RefPtr<GMPContentParent> mGMPContentParent;
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.
// This ensures that if the GMPService tries to shut us down and drops
// its reference to us, we stay alive long enough for the child process
// to terminate gracefully.
bool mHoldingSelfRef;
};
--- a/dom/media/gmp/GMPService.h
+++ b/dom/media/gmp/GMPService.h
@@ -70,18 +70,16 @@ public:
GetGMPVideoDecoder(GMPCrashHelper* aHelper,
nsTArray<nsCString>* aTags,
const nsACString& aNodeId,
UniquePtr<GetGMPVideoDecoderCallback>&& aCallback) override
{
return GetDecryptingGMPVideoDecoder(aHelper, aTags, aNodeId, Move(aCallback), 0);
}
- int32_t AsyncShutdownTimeoutMs();
-
NS_IMETHOD RunPluginCrashCallbacks(uint32_t aPluginId,
const nsACString& aPluginName) override;
RefPtr<AbstractThread> GetAbstractGMPThread();
void ConnectCrashHelper(uint32_t aPluginId, GMPCrashHelper* aHelper);
void DisconnectCrashHelper(GMPCrashHelper* aHelper);
--- a/dom/media/gmp/GMPServiceParent.cpp
+++ b/dom/media/gmp/GMPServiceParent.cpp
@@ -82,39 +82,29 @@ GeckoMediaPluginServiceParent::GetSingle
NS_IMPL_ISUPPORTS_INHERITED(GeckoMediaPluginServiceParent,
GeckoMediaPluginService,
mozIGeckoMediaPluginChromeService,
nsIAsyncShutdownBlocker)
GeckoMediaPluginServiceParent::GeckoMediaPluginServiceParent()
: mShuttingDown(false)
-#ifdef MOZ_CRASHREPORTER
- , mAsyncShutdownPluginStatesMutex("GeckoMediaPluginService::mAsyncShutdownPluginStatesMutex")
-#endif
, mScannedPluginOnDisk(false)
, mWaitingForPluginsSyncShutdown(false)
, mInitPromiseMonitor("GeckoMediaPluginServiceParent::mInitPromiseMonitor")
, mLoadPluginsFromDiskComplete(false)
, mServiceUserCount(0)
{
MOZ_ASSERT(NS_IsMainThread());
mInitPromise.SetMonitor(&mInitPromiseMonitor);
}
GeckoMediaPluginServiceParent::~GeckoMediaPluginServiceParent()
{
MOZ_ASSERT(mPlugins.IsEmpty());
- MOZ_ASSERT(mAsyncShutdownPlugins.IsEmpty());
-}
-
-int32_t
-GeckoMediaPluginServiceParent::AsyncShutdownTimeoutMs()
-{
- return MediaPrefs::GMPAsyncShutdownTimeout();
}
nsresult
GeckoMediaPluginServiceParent::Init()
{
MOZ_ASSERT(NS_IsMainThread());
nsCOMPtr<nsIObserverService> obsService = mozilla::services::GetObserverService();
@@ -283,131 +273,39 @@ GeckoMediaPluginServiceParent::Observe(n
if (gmpThread) {
gmpThread->Dispatch(WrapRunnable(this,
&GeckoMediaPluginServiceParent::CrashPlugins),
NS_DISPATCH_NORMAL);
}
}
}
} 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;
{
MutexAutoLock lock(mMutex);
MOZ_ASSERT(!mShuttingDown);
mShuttingDown = true;
gmpThread = mGMPThread;
}
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());
mWaitingForPluginsSyncShutdown = false;
}
} else if (!strcmp(NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID, aTopic)) {
MOZ_ASSERT(mShuttingDown);
@@ -515,115 +413,16 @@ GeckoMediaPluginServiceParent::Initializ
[self]() -> void {
MonitorAutoLock lock(self->mInitPromiseMonitor);
self->mLoadPluginsFromDiskComplete = true;
self->mInitPromise.Reject(NS_ERROR_FAILURE, __func__);
});
}
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()
{
MOZ_ASSERT(NS_IsMainThread());
mWaitingForPluginsSyncShutdown = false;
}
bool
GeckoMediaPluginServiceParent::IsShuttingDown()
@@ -633,55 +432,39 @@ GeckoMediaPluginServiceParent::IsShuttin
}
void
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;
{
MutexAutoLock lock(mMutex);
// Move all plugins references to a local array. This way mMutex won't be
// locked when calling CloseActive (to avoid inter-locking).
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);
}
void
GeckoMediaPluginServiceParent::CrashPlugins()
{
@@ -1113,17 +896,16 @@ GeckoMediaPluginServiceParent::RemoveOnG
deadPlugins.AppendElement(gmp);
mPlugins.RemoveElementAt(i);
}
}
{
MutexAutoUnlock unlock(mMutex);
for (auto& gmp : deadPlugins) {
- gmp->AbortAsyncShutdown();
gmp->CloseActive(true);
}
}
if (aDeleteFromDisk && !inUse) {
// Ensure the GMP dir and all files in it are writable, so we have
// permission to delete them.
directory->SetPermissions(0700);
@@ -1557,19 +1339,16 @@ KillPlugins(const nsTArray<RefPtr<GMPPar
if (aFilter(parent)) {
pluginsToKill.AppendElement(parent);
}
}
}
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();
}
}
static nsresult
DeleteDir(nsIFile* aPath)
{
bool exists = false;
nsresult rv = aPath->Exists(&exists);
--- a/dom/media/gmp/GMPServiceParent.h
+++ b/dom/media/gmp/GMPServiceParent.h
@@ -44,23 +44,16 @@ public:
NS_IMETHOD GetNodeId(const nsAString& aOrigin,
const nsAString& aTopLevelOrigin,
const nsAString& aGMPName,
UniquePtr<GetNodeIdCallback>&& aCallback) override;
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);
// GMP thread access only
bool IsShuttingDown();
already_AddRefed<GMPStorage> GetMemoryStorageFor(const nsACString& aNodeId);
nsresult ForgetThisSiteNative(const nsAString& aSite,
@@ -89,26 +82,23 @@ private:
size_t* aOutPluginIndex);
nsresult GetNodeId(const nsAString& aOrigin, const nsAString& aTopLevelOrigin,
const nsAString& aGMPName, nsACString& aOutId);
void UnloadPlugins();
void CrashPlugins();
void NotifySyncShutdownComplete();
- void NotifyAsyncShutdownComplete();
void ProcessPossiblePlugin(nsIFile* aDir);
void RemoveOnGMPThread(const nsAString& aDirectory,
const bool aDeleteFromDisk,
const bool aCanDefer);
- nsresult SetAsyncShutdownTimeout();
-
struct DirectoryFilter {
virtual bool operator()(nsIFile* aPath) = 0;
~DirectoryFilter() {}
};
void ClearNodeIdAndPlugin(DirectoryFilter& aFilter);
void ClearNodeIdAndPlugin(nsIFile* aPluginStorageDir,
DirectoryFilter& aFilter);
void ForgetThisSiteOnGMPThread(const nsACString& aOrigin,
@@ -161,32 +151,16 @@ private:
nsString mPath;
EOperation mOperation;
bool mDefer;
};
// 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.
Atomic<bool> mScannedPluginOnDisk;
template<typename T>
class MainThreadOnly {
public:
--- a/dom/media/gmp/PGMP.ipdl
+++ b/dom/media/gmp/PGMP.ipdl
@@ -23,21 +23,17 @@ intr protocol PGMP
parent:
async PCrashReporter(NativeThreadId tid);
async PGMPTimer();
async PGMPStorage();
async PGMPContentChildDestroyed();
- async AsyncShutdownComplete();
- async AsyncShutdownRequired();
-
child:
- async BeginAsyncShutdown();
async CrashPluginNow();
intr StartPlugin(nsString adapter);
async SetNodeId(nsCString nodeId);
async PreloadLibs(nsCString libs);
async CloseActive();
};
} // namespace gmp
deleted file mode 100644
--- a/dom/media/gmp/gmp-api/gmp-async-shutdown.h
+++ /dev/null
@@ -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_
--- a/dom/media/gmp/moz.build
+++ b/dom/media/gmp/moz.build
@@ -7,17 +7,16 @@
XPIDL_MODULE = 'content_geckomediaplugins'
XPIDL_SOURCES += [
'mozIGeckoMediaPluginChromeService.idl',
'mozIGeckoMediaPluginService.idl',
]
EXPORTS += [
- 'gmp-api/gmp-async-shutdown.h',
'gmp-api/gmp-decryption.h',
'gmp-api/gmp-entrypoints.h',
'gmp-api/gmp-errors.h',
'gmp-api/gmp-platform.h',
'gmp-api/gmp-storage.h',
'gmp-api/gmp-video-codec.h',
'gmp-api/gmp-video-decode.h',
'gmp-api/gmp-video-encode.h',
--- a/dom/media/gtest/TestGMPCrossOrigin.cpp
+++ b/dom/media/gtest/TestGMPCrossOrigin.cpp
@@ -1090,102 +1090,16 @@ class GMPStorageTest : public GMPDecrypt
&GMPStorageTest::SetFinished));
CreateDecryptor(NS_LITERAL_STRING("http://pb1.com"),
NS_LITERAL_STRING("http://pb2.com"),
true,
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();
Expect(NS_LITERAL_CSTRING("OP tests completed"),
NewRunnableMethod(this, &GMPStorageTest::SetFinished));
CreateDecryptor(NS_LITERAL_STRING("http://example15.com"),
@@ -1509,26 +1423,16 @@ TEST(GeckoMediaPlugins, GMPStorageCrossO
runner->DoTest(&GMPStorageTest::TestCrossOriginStorage);
}
TEST(GeckoMediaPlugins, GMPStoragePrivateBrowsing) {
RefPtr<GMPStorageTest> runner = new GMPStorageTest();
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);
}
#if defined(XP_WIN)
TEST(GeckoMediaPlugins, GMPOutputProtection) {
RefPtr<GMPStorageTest> runner = new GMPStorageTest();