Bug 1656349 - Refactor the IPC lifetimes for the PGamepadEventChannel object r=daoshengmu

Change the GamepadEventChannel so it is fully-initialized by the IPC
constuctor and needs no separate "init" message, and so its completely
destroyed by the ActorDestroy() message so it needs no "cleanup" message.

This simplifies the object lifetime, as well as unifies the IPC error vs
clean shutdown paths.

Differential Revision: https://phabricator.services.mozilla.com/D85481
This commit is contained in:
Chris Martin 2020-08-04 21:27:53 +00:00
parent cb4022c808
commit c946e6eaf9
8 changed files with 41 additions and 59 deletions

View File

@ -113,7 +113,7 @@ GamepadManager::Observe(nsISupports* aSubject, const char* aTopic,
void GamepadManager::StopMonitoring() {
for (uint32_t i = 0; i < mChannelChildren.Length(); ++i) {
mChannelChildren[i]->SendGamepadListenerRemoved();
PGamepadEventChannelChild::Send__delete__(mChannelChildren[i]);
}
if (gfx::VRManagerChild::IsCreated()) {
gfx::VRManagerChild* vm = gfx::VRManagerChild::Get();
@ -155,7 +155,6 @@ void GamepadManager::AddListener(nsGlobalWindowInner* aWindow) {
}
MOZ_ASSERT(initedChild == child);
child->SendGamepadListenerAdded();
mChannelChildren.AppendElement(child);
if (gfx::VRManagerChild::IsCreated()) {

View File

@ -261,12 +261,7 @@ bool GamepadPlatformService::HasGamepadListeners() {
// We use mutex here to prevent race condition with monitor thread
MutexAutoLock autoLock(mMutex);
for (uint32_t i = 0; i < mChannelParents.Length(); i++) {
if (mChannelParents[i]->HasGamepadListener()) {
return true;
}
}
return false;
return !mChannelParents.IsEmpty();
}
void GamepadPlatformService::MaybeShutdown() {

View File

@ -15,6 +15,7 @@ class GamepadEventChannelChild final : public PGamepadEventChannelChild {
public:
GamepadEventChannelChild() = default;
~GamepadEventChannelChild() = default;
mozilla::ipc::IPCResult RecvGamepadUpdate(
const GamepadChangeEvent& aGamepadEvent);
mozilla::ipc::IPCResult RecvReplyGamepadPromise(const uint32_t& aPromiseID);

View File

@ -24,50 +24,45 @@ class SendGamepadUpdateRunnable final : public Runnable {
public:
SendGamepadUpdateRunnable(GamepadEventChannelParent* aParent,
GamepadChangeEvent aEvent)
: Runnable("dom::SendGamepadUpdateRunnable"), mEvent(aEvent) {
MOZ_ASSERT(aParent);
mParent = aParent;
: Runnable("dom::SendGamepadUpdateRunnable"),
mParent(aParent),
mEvent(aEvent) {
MOZ_ASSERT(mParent);
}
NS_IMETHOD Run() override {
AssertIsOnBackgroundThread();
if (mParent->HasGamepadListener()) {
Unused << mParent->SendGamepadUpdate(mEvent);
}
Unused << mParent->SendGamepadUpdate(mEvent);
return NS_OK;
}
};
} // namespace
GamepadEventChannelParent::GamepadEventChannelParent()
: mHasGamepadListener(false) {
bool GamepadEventChannelParent::Init() {
AssertIsOnBackgroundThread();
mBackgroundEventTarget = GetCurrentEventTarget();
RefPtr<GamepadPlatformService> service =
GamepadPlatformService::GetParentService();
MOZ_ASSERT(service);
mBackgroundEventTarget = GetCurrentEventTarget();
service->AddChannelParent(this);
}
mozilla::ipc::IPCResult GamepadEventChannelParent::RecvGamepadListenerAdded() {
AssertIsOnBackgroundThread();
MOZ_ASSERT(!mHasGamepadListener);
mHasGamepadListener = true;
StartGamepadMonitoring();
return IPC_OK();
return true;
}
mozilla::ipc::IPCResult
GamepadEventChannelParent::RecvGamepadListenerRemoved() {
void GamepadEventChannelParent::ActorDestroy(ActorDestroyReason aWhy) {
AssertIsOnBackgroundThread();
MOZ_ASSERT(mHasGamepadListener);
mHasGamepadListener = false;
RefPtr<GamepadPlatformService> service =
GamepadPlatformService::GetParentService();
MOZ_ASSERT(service);
service->RemoveChannelParent(this);
Unused << Send__delete__(this);
return IPC_OK();
MaybeStopGamepadMonitoring();
}
mozilla::ipc::IPCResult GamepadEventChannelParent::RecvVibrateHaptic(
@ -93,12 +88,8 @@ mozilla::ipc::IPCResult GamepadEventChannelParent::RecvLightIndicatorColor(
const uint32_t& aControllerIdx, const uint32_t& aLightColorIndex,
const uint8_t& aRed, const uint8_t& aGreen, const uint8_t& aBlue,
const uint32_t& aPromiseID) {
// It may be called because IPDL child side crashed, we'll
// not receive RecvGamepadListenerRemoved in that case
if (mHasGamepadListener) {
SetGamepadLightIndicatorColor(aControllerIdx, aLightColorIndex, aRed,
aGreen, aBlue);
}
SetGamepadLightIndicatorColor(aControllerIdx, aLightColorIndex, aRed, aGreen,
aBlue);
if (SendReplyGamepadPromise(aPromiseID)) {
return IPC_OK();
@ -107,21 +98,6 @@ mozilla::ipc::IPCResult GamepadEventChannelParent::RecvLightIndicatorColor(
return IPC_FAIL(this, "SendReplyGamepadPromise fail.");
}
void GamepadEventChannelParent::ActorDestroy(ActorDestroyReason aWhy) {
AssertIsOnBackgroundThread();
// It may be called because IPDL child side crashed, we'll
// not receive RecvGamepadListenerRemoved in that case
if (mHasGamepadListener) {
mHasGamepadListener = false;
RefPtr<GamepadPlatformService> service =
GamepadPlatformService::GetParentService();
MOZ_ASSERT(service);
service->RemoveChannelParent(this);
}
MaybeStopGamepadMonitoring();
}
void GamepadEventChannelParent::DispatchUpdateEvent(
const GamepadChangeEvent& aEvent) {
mBackgroundEventTarget->Dispatch(new SendGamepadUpdateRunnable(this, aEvent),

View File

@ -14,10 +14,11 @@ namespace dom {
class GamepadEventChannelParent final : public PGamepadEventChannelParent {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GamepadEventChannelParent)
GamepadEventChannelParent();
virtual void ActorDestroy(ActorDestroyReason aWhy) override;
mozilla::ipc::IPCResult RecvGamepadListenerAdded();
mozilla::ipc::IPCResult RecvGamepadListenerRemoved();
GamepadEventChannelParent() = default;
bool Init();
void ActorDestroy(ActorDestroyReason aWhy) override;
mozilla::ipc::IPCResult RecvVibrateHaptic(const uint32_t& aControllerIdx,
const uint32_t& aHapticIndex,
const double& aIntensity,
@ -29,11 +30,9 @@ class GamepadEventChannelParent final : public PGamepadEventChannelParent {
const uint8_t& aRed, const uint8_t& aGreen, const uint8_t& aBlue,
const uint32_t& aPromiseID);
void DispatchUpdateEvent(const GamepadChangeEvent& aEvent);
bool HasGamepadListener() const { return mHasGamepadListener; }
private:
~GamepadEventChannelParent() = default;
bool mHasGamepadListener;
nsCOMPtr<nsIEventTarget> mBackgroundEventTarget;
};

View File

@ -10,8 +10,8 @@ namespace dom {
async protocol PGamepadEventChannel {
manager PBackground;
parent:
async GamepadListenerAdded();
async GamepadListenerRemoved();
async __delete__();
async VibrateHaptic(uint32_t aControllerIdx, uint32_t aHapticIndex,
double aIntensity, double aDuration, uint32_t aPromiseID);
async StopVibrateHaptic(uint32_t aControllerIdx);
@ -19,7 +19,6 @@ async protocol PGamepadEventChannel {
uint8_t aRed, uint8_t aGreen, uint8_t aBlue, uint32_t aPromiseID);
child:
async __delete__();
async GamepadUpdate(GamepadChangeEvent aGamepadEvent);
async ReplyGamepadPromise(uint32_t aPromiseID);
};

View File

@ -1102,6 +1102,16 @@ bool BackgroundParentImpl::DeallocPGamepadEventChannelParent(
return true;
}
mozilla::ipc::IPCResult
BackgroundParentImpl::RecvPGamepadEventChannelConstructor(
PGamepadEventChannelParent* aActor) {
MOZ_ASSERT(aActor);
if (!static_cast<dom::GamepadEventChannelParent*>(aActor)->Init()) {
return IPC_FAIL_NO_REASON(this);
}
return IPC_OK();
}
dom::PGamepadTestChannelParent*
BackgroundParentImpl::AllocPGamepadTestChannelParent() {
RefPtr<dom::GamepadTestChannelParent> parent =

View File

@ -329,6 +329,9 @@ class BackgroundParentImpl : public PBackgroundParent,
virtual bool DeallocPGamepadEventChannelParent(
PGamepadEventChannelParent* aActor) override;
virtual mozilla::ipc::IPCResult RecvPGamepadEventChannelConstructor(
PGamepadEventChannelParent* aActor) override;
virtual PGamepadTestChannelParent* AllocPGamepadTestChannelParent() override;
virtual bool DeallocPGamepadTestChannelParent(