Bug 1346678 - Label runnables in dom/media/gmp/GMPParent.cpp and its friends. r?cpearce
MozReview-Commit-ID: DWYx30T7gCJ
--- a/dom/media/gmp/GMPCrashHelper.cpp
+++ b/dom/media/gmp/GMPCrashHelper.cpp
@@ -14,13 +14,15 @@ NS_IMPL_RELEASE_WITH_DESTROY(GMPCrashHel
void
GMPCrashHelper::Destroy()
{
if (NS_IsMainThread()) {
delete this;
} else {
// Don't addref, as then we'd end up releasing after the detele runs!
- NS_DispatchToMainThread(mozilla::NewNonOwningRunnableMethod(this, &GMPCrashHelper::Destroy));
+ SystemGroup::Dispatch(
+ "GMPCrashHelper::Destroy", TaskCategory::Other,
+ NewNonOwningRunnableMethod(this, &GMPCrashHelper::Destroy));
}
}
} // namespace mozilla
--- a/dom/media/gmp/GMPParent.cpp
+++ b/dom/media/gmp/GMPParent.cpp
@@ -55,26 +55,27 @@ extern LogModule* GetGMPLog();
#ifdef __CLASS__
#undef __CLASS__
#endif
#define __CLASS__ "GMPParent"
namespace gmp {
-GMPParent::GMPParent()
+GMPParent::GMPParent(AbstractThread* aMainThread)
: mState(GMPStateNotLoaded)
, mProcess(nullptr)
, mDeleteProcessOnlyOnUnload(false)
, mAbnormalShutdownInProgress(false)
, mIsBlockingDeletion(false)
, mCanDecrypt(false)
, mGMPContentChildCount(0)
, mChildPid(0)
, mHoldingSelfRef(false)
+ , mMainThread(aMainThread)
{
mPluginId = GeckoChildProcessHost::GetUniqueID();
LOGD("GMPParent ctor id=%u", mPluginId);
}
GMPParent::~GMPParent()
{
LOGD("GMPParent dtor id=%u", mPluginId);
@@ -297,17 +298,18 @@ GMPParent::Shutdown()
mService->ReAddOnGMPThread(self);
} // else we've been asked to die and stay dead
MOZ_ASSERT(mState == GMPStateNotLoaded);
}
class NotifyGMPShutdownTask : public Runnable {
public:
explicit NotifyGMPShutdownTask(const nsAString& aNodeId)
- : mNodeId(aNodeId)
+ : Runnable("NotifyGMPShutdownTask")
+ , mNodeId(aNodeId)
{
}
NS_IMETHOD Run() override {
MOZ_ASSERT(NS_IsMainThread());
nsCOMPtr<nsIObserverService> obsService = mozilla::services::GetObserverService();
MOZ_ASSERT(obsService);
if (obsService) {
obsService->NotifyObservers(nullptr, "gmp-shutdown", mNodeId.get());
@@ -349,19 +351,19 @@ GMPParent::DeleteProcess()
mState = GMPStateClosing;
Close();
}
mProcess->Delete(NewRunnableMethod(this, &GMPParent::ChildTerminated));
LOGD("%s: Shut down process", __FUNCTION__);
mProcess = nullptr;
mState = GMPStateNotLoaded;
- NS_DispatchToMainThread(
- new NotifyGMPShutdownTask(NS_ConvertUTF8toUTF16(mNodeId)),
- NS_DISPATCH_NORMAL);
+ nsCOMPtr<nsIRunnable> r
+ = new NotifyGMPShutdownTask(NS_ConvertUTF8toUTF16(mNodeId));
+ mMainThread->Dispatch(r.forget());
if (mHoldingSelfRef) {
Release();
mHoldingSelfRef = false;
}
}
GMPState
@@ -512,19 +514,19 @@ GMPParent::ActorDestroy(ActorDestroyReas
if (!GetCrashID(dumpID)) {
NS_WARNING("GMP crash without crash report");
dumpID = mName;
dumpID += '-';
AppendUTF8toUTF16(mVersion, dumpID);
}
// NotifyObservers is mainthread-only
- NS_DispatchToMainThread(WrapRunnableNM(&GMPNotifyObservers,
- mPluginId, mDisplayName, dumpID),
- NS_DISPATCH_NORMAL);
+ nsCOMPtr<nsIRunnable> r = WrapRunnableNM(
+ &GMPNotifyObservers, mPluginId, mDisplayName, dumpID);
+ mMainThread->Dispatch(r.forget());
}
#endif
// warn us off trying to close again
mState = GMPStateClosing;
mAbnormalShutdownInProgress = true;
CloseActive(false);
// Normal Shutdown() will delete the process on unwind.
@@ -723,18 +725,17 @@ GMPParent::ReadChromiumManifestFile(nsIF
{
nsAutoCString json;
if (!ReadIntoString(aFile, json, 5 * 1024)) {
return GenericPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
}
// DOM JSON parsing needs to run on the main thread.
return InvokeAsync<nsString&&>(
- // Non DocGroup-version of AbstractThread::MainThread for the task in parent.
- AbstractThread::MainThread(), this, __func__,
+ mMainThread, this, __func__,
&GMPParent::ParseChromiumManifest, NS_ConvertUTF8toUTF16(json));
}
RefPtr<GenericPromise>
GMPParent::ParseChromiumManifest(const nsAString& aJSON)
{
LOGD("%s: for '%s'", __FUNCTION__, NS_LossyConvertUTF16toASCII(aJSON).get());
--- a/dom/media/gmp/GMPParent.h
+++ b/dom/media/gmp/GMPParent.h
@@ -68,17 +68,17 @@ enum GMPState {
class GMPContentParent;
class GMPParent final : public PGMPParent
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GMPParent)
- GMPParent();
+ explicit GMPParent(AbstractThread* aMainThread);
RefPtr<GenericPromise> Init(GeckoMediaPluginServiceParent* aService, nsIFile* aPluginDir);
nsresult CloneFrom(const GMPParent* aOther);
void Crash();
nsresult LoadProcess();
@@ -223,14 +223,16 @@ private:
// 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;
#ifdef MOZ_CRASHREPORTER
UniquePtr<ipc::CrashReporterHost> mCrashReporter;
#endif
+
+ const RefPtr<AbstractThread> mMainThread;
};
} // namespace gmp
} // namespace mozilla
#endif // GMPParent_h_
--- a/dom/media/gmp/GMPService.cpp
+++ b/dom/media/gmp/GMPService.cpp
@@ -74,31 +74,31 @@ public:
static already_AddRefed<GeckoMediaPluginService>
GetOrCreate()
{
RefPtr<GeckoMediaPluginService> service;
if (NS_IsMainThread()) {
service = GetOrCreateOnMainThread();
} else {
- nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
- MOZ_ASSERT(mainThread);
-
RefPtr<GMPServiceCreateHelper> createHelper = new GMPServiceCreateHelper();
- mozilla::SyncRunnable::DispatchToThread(mainThread, createHelper, true);
+ mozilla::SyncRunnable::DispatchToThread(
+ SystemGroup::EventTargetFor(mozilla::TaskCategory::Other),
+ createHelper, true);
service = createHelper->mService.forget();
}
return service.forget();
}
private:
GMPServiceCreateHelper()
+ : Runnable("GMPServiceCreateHelper")
{
}
~GMPServiceCreateHelper()
{
MOZ_ASSERT(!mService);
}
--- a/dom/media/gmp/GMPServiceChild.cpp
+++ b/dom/media/gmp/GMPServiceChild.cpp
@@ -300,18 +300,19 @@ GeckoMediaPluginServiceChild::GetService
if (!mServiceChild) {
dom::ContentChild* contentChild = dom::ContentChild::GetSingleton();
if (!contentChild) {
return GetServiceChildPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
}
MozPromiseHolder<GetServiceChildPromise>* holder = mGetServiceChildPromises.AppendElement();
RefPtr<GetServiceChildPromise> promise = holder->Ensure(__func__);
if (mGetServiceChildPromises.Length() == 1) {
- NS_DispatchToMainThread(WrapRunnable(contentChild,
- &dom::ContentChild::SendCreateGMPService));
+ nsCOMPtr<nsIRunnable> r = WrapRunnable(
+ contentChild, &dom::ContentChild::SendCreateGMPService);
+ SystemGroup::Dispatch("SendCreateGMPService", TaskCategory::Other, r.forget());
}
return promise;
}
return GetServiceChildPromise::CreateAndResolve(mServiceChild.get(), __func__);
}
void
GeckoMediaPluginServiceChild::SetServiceChild(UniquePtr<GMPServiceChild>&& aServiceChild)
--- a/dom/media/gmp/GMPServiceParent.cpp
+++ b/dom/media/gmp/GMPServiceParent.cpp
@@ -89,16 +89,17 @@ NS_IMPL_ISUPPORTS_INHERITED(GeckoMediaPl
GeckoMediaPluginServiceParent::GeckoMediaPluginServiceParent()
: mShuttingDown(false)
, mScannedPluginOnDisk(false)
, mWaitingForPluginsSyncShutdown(false)
, mInitPromiseMonitor("GeckoMediaPluginServiceParent::mInitPromiseMonitor")
, mLoadPluginsFromDiskComplete(false)
, mServiceUserCount(0)
+ , mMainThread(SystemGroup::AbstractMainThreadFor(TaskCategory::Other))
{
MOZ_ASSERT(NS_IsMainThread());
mInitPromise.SetMonitor(&mInitPromiseMonitor);
}
GeckoMediaPluginServiceParent::~GeckoMediaPluginServiceParent()
{
MOZ_ASSERT(mPlugins.IsEmpty());
@@ -457,19 +458,20 @@ GeckoMediaPluginServiceParent::UnloadPlu
}
#endif
// Note: CloseActive may be async; it could actually finish
// shutting down when all the plugins have unloaded.
for (const auto& plugin : plugins) {
plugin->CloseActive(true);
}
- nsCOMPtr<nsIRunnable> task(NewRunnableMethod(
- this, &GeckoMediaPluginServiceParent::NotifySyncShutdownComplete));
- NS_DispatchToMainThread(task);
+ nsCOMPtr<nsIRunnable> task = NewRunnableMethod(
+ "GeckoMediaPluginServiceParent::NotifySyncShutdownComplete",
+ this, &GeckoMediaPluginServiceParent::NotifySyncShutdownComplete);
+ mMainThread->Dispatch(task.forget());
}
void
GeckoMediaPluginServiceParent::CrashPlugins()
{
LOGD(("%s::%s", __CLASS__, __FUNCTION__));
MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
@@ -515,17 +517,18 @@ GeckoMediaPluginServiceParent::LoadFromE
mScannedPluginOnDisk = true;
return GenericPromise::All(thread, promises);
}
class NotifyObserversTask final : public mozilla::Runnable {
public:
explicit NotifyObserversTask(const char* aTopic, nsString aData = EmptyString())
- : mTopic(aTopic)
+ : Runnable(aTopic)
+ , mTopic(aTopic)
, mData(aData)
{}
NS_IMETHOD Run() override {
MOZ_ASSERT(NS_IsMainThread());
nsCOMPtr<nsIObserverService> obsService = mozilla::services::GetObserverService();
MOZ_ASSERT(obsService);
if (obsService) {
obsService->NotifyObservers(nullptr, mTopic, mData.get());
@@ -548,19 +551,20 @@ GeckoMediaPluginServiceParent::PathRunna
mService->UpdateContentProcessGMPCapabilities();
return NS_OK;
}
void
GeckoMediaPluginServiceParent::UpdateContentProcessGMPCapabilities()
{
if (!NS_IsMainThread()) {
- nsCOMPtr<nsIRunnable> task =
- NewRunnableMethod(this, &GeckoMediaPluginServiceParent::UpdateContentProcessGMPCapabilities);
- NS_DispatchToMainThread(task);
+ nsCOMPtr<nsIRunnable> task = NewRunnableMethod(
+ "GeckoMediaPluginServiceParent::UpdateContentProcessGMPCapabilities",
+ this, &GeckoMediaPluginServiceParent::UpdateContentProcessGMPCapabilities);
+ mMainThread->Dispatch(task.forget());
return;
}
typedef mozilla::dom::GMPCapabilityData GMPCapabilityData;
typedef mozilla::dom::GMPAPITags GMPAPITags;
typedef mozilla::dom::ContentParent ContentParent;
nsTArray<GMPCapabilityData> caps;
@@ -612,17 +616,17 @@ GeckoMediaPluginServiceParent::AsyncAddP
}
nsString dir(aDirectory);
RefPtr<GeckoMediaPluginServiceParent> self = this;
return InvokeAsync<nsString&&>(
thread, this, __func__,
&GeckoMediaPluginServiceParent::AddOnGMPThread, dir)
->Then(
- AbstractThread::MainThread(), // Non DocGroup-version for the task in parent.
+ mMainThread,
__func__,
[dir, self]() -> void {
LOGD(("GeckoMediaPluginServiceParent::AsyncAddPluginDirectory %s succeeded",
NS_ConvertUTF16toUTF8(dir).get()));
MOZ_ASSERT(NS_IsMainThread());
self->UpdateContentProcessGMPCapabilities();
},
[dir]() -> void {
@@ -774,36 +778,36 @@ GeckoMediaPluginServiceParent::SelectPlu
}
return clone.forget();
}
return nullptr;
}
RefPtr<GMPParent>
-CreateGMPParent()
+CreateGMPParent(AbstractThread* aMainThread)
{
#if defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX)
if (!SandboxInfo::Get().CanSandboxMedia()) {
if (!MediaPrefs::GMPAllowInsecure()) {
NS_WARNING("Denying media plugin load due to lack of sandboxing.");
return nullptr;
}
NS_WARNING("Loading media plugin despite lack of sandboxing.");
}
#endif
- return new GMPParent();
+ return new GMPParent(aMainThread);
}
already_AddRefed<GMPParent>
GeckoMediaPluginServiceParent::ClonePlugin(const GMPParent* aOriginal)
{
MOZ_ASSERT(aOriginal);
- RefPtr<GMPParent> gmp = CreateGMPParent();
+ RefPtr<GMPParent> gmp = CreateGMPParent(mMainThread);
nsresult rv = gmp ? gmp->CloneFrom(aOriginal) : NS_ERROR_NOT_AVAILABLE;
if (NS_FAILED(rv)) {
NS_WARNING("Can't Create GMPParent");
return nullptr;
}
return gmp.forget();
@@ -832,17 +836,17 @@ GeckoMediaPluginServiceParent::AddOnGMPT
nsCOMPtr<nsIFile> directory;
nsresult rv = NS_NewLocalFile(aDirectory, false, getter_AddRefs(directory));
if (NS_WARN_IF(NS_FAILED(rv))) {
LOGD(("%s::%s: failed to create nsIFile for dir=%s rv=%" PRIx32,
__CLASS__, __FUNCTION__, dir.get(), static_cast<uint32_t>(rv)));
return GenericPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
}
- RefPtr<GMPParent> gmp = CreateGMPParent();
+ RefPtr<GMPParent> gmp = CreateGMPParent(mMainThread);
if (!gmp) {
NS_WARNING("Can't Create GMPParent");
return GenericPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
}
RefPtr<GeckoMediaPluginServiceParent> self(this);
return gmp->Init(this, directory)->Then(thread, __func__,
[gmp, self, dir]() -> void {
@@ -915,19 +919,19 @@ GeckoMediaPluginServiceParent::RemoveOnG
// permission to delete them.
directory->SetPermissions(0700);
DirectoryEnumerator iter(directory, DirectoryEnumerator::FilesAndDirs);
for (nsCOMPtr<nsIFile> dirEntry; (dirEntry = iter.Next()) != nullptr;) {
dirEntry->SetPermissions(0700);
}
if (NS_SUCCEEDED(directory->Remove(true))) {
mPluginsWaitingForDeletion.RemoveElement(aDirectory);
- NS_DispatchToMainThread(new NotifyObserversTask("gmp-directory-deleted",
- nsString(aDirectory)),
- NS_DISPATCH_NORMAL);
+ nsCOMPtr<nsIRunnable> task = new NotifyObserversTask(
+ "gmp-directory-deleted", nsString(aDirectory));
+ mMainThread->Dispatch(task.forget());
}
}
}
// May remove when Bug 1043671 is fixed
static void Dummy(RefPtr<GMPParent>& aOnDeathsDoor)
{
// exists solely to do nothing and let the Runnable kill the GMPParent
@@ -1532,17 +1536,19 @@ GeckoMediaPluginServiceParent::ClearRece
return NS_SUCCEEDED(temp->AppendNative(salt)) && IsModifiedAfter(temp);
}
private:
const PRTime mSince;
} filter(aSince);
ClearNodeIdAndPlugin(filter);
- NS_DispatchToMainThread(new NotifyObserversTask("gmp-clear-storage-complete"), NS_DISPATCH_NORMAL);
+ nsCOMPtr<nsIRunnable> task
+ = new NotifyObserversTask("gmp-clear-storage-complete");
+ mMainThread->Dispatch(task.forget());
}
NS_IMETHODIMP
GeckoMediaPluginServiceParent::ForgetThisSite(const nsAString& aSite,
const nsAString& aPattern)
{
MOZ_ASSERT(NS_IsMainThread());
@@ -1642,36 +1648,39 @@ GeckoMediaPluginServiceParent::ClearStor
if (NS_FAILED(DeleteDir(path))) {
NS_WARNING("Failed to delete GMP storage directory");
}
// Clear private-browsing storage.
mTempGMPStorage.Clear();
- NS_DispatchToMainThread(new NotifyObserversTask("gmp-clear-storage-complete"), NS_DISPATCH_NORMAL);
+ nsCOMPtr<nsIRunnable> task
+ = new NotifyObserversTask("gmp-clear-storage-complete");
+ mMainThread->Dispatch(task.forget());
}
already_AddRefed<GMPParent>
GeckoMediaPluginServiceParent::GetById(uint32_t aPluginId)
{
MutexAutoLock lock(mMutex);
for (const RefPtr<GMPParent>& gmp : mPlugins) {
if (gmp->GetPluginId() == aPluginId) {
return do_AddRef(gmp);
}
}
return nullptr;
}
GMPServiceParent::~GMPServiceParent()
{
- NS_DispatchToMainThread(
- NewRunnableMethod(mService.get(),
- &GeckoMediaPluginServiceParent::ServiceUserDestroyed));
+ nsCOMPtr<nsIRunnable> task = NewRunnableMethod(
+ "GeckoMediaPluginServiceParent::ServiceUserDestroyed",
+ mService.get(), &GeckoMediaPluginServiceParent::ServiceUserDestroyed);
+ mService->MainThread()->Dispatch(task.forget());
}
mozilla::ipc::IPCResult
GMPServiceParent::RecvLaunchGMP(const nsCString& aNodeId,
const nsCString& aAPI,
nsTArray<nsCString>&& aTags,
nsTArray<ProcessId>&& aAlreadyBridgedTo,
uint32_t* aOutPluginId,
--- a/dom/media/gmp/GMPServiceParent.h
+++ b/dom/media/gmp/GMPServiceParent.h
@@ -60,16 +60,18 @@ public:
const mozilla::OriginAttributesPattern& aPattern);
// Notifies that some user of this class is created/destroyed.
void ServiceUserCreated();
void ServiceUserDestroyed();
void UpdateContentProcessGMPCapabilities();
+ AbstractThread* MainThread() const { return mMainThread; }
+
private:
friend class GMPServiceParent;
virtual ~GeckoMediaPluginServiceParent();
void ClearStorage();
already_AddRefed<GMPParent> SelectPluginForAPI(const nsACString& aNodeId,
@@ -197,16 +199,18 @@ private:
bool mLoadPluginsFromDiskComplete;
// Hashes nodeId to the hashtable of storage for that nodeId.
nsRefPtrHashtable<nsCStringHashKey, GMPStorage> mTempGMPStorage;
// Tracks how many users are running (on the GMP thread). Only when this count
// drops to 0 can we safely shut down the thread.
MainThreadOnly<int32_t> mServiceUserCount;
+
+ const RefPtr<AbstractThread> mMainThread;
};
nsresult ReadSalt(nsIFile* aPath, nsACString& aOutData);
bool MatchOrigin(nsIFile* aPath,
const nsACString& aSite,
const mozilla::OriginAttributesPattern& aPattern);
class GMPServiceParent final : public PGMPServiceParent