mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1044514 - AudioDestinationNode should not be kept alive by the event listener, r=ehsan
This commit is contained in:
parent
715a091a96
commit
a83b79a685
@ -96,9 +96,10 @@ AudioContext::AudioContext(nsPIDOMWindow* aWindow,
|
||||
// bound to the window.
|
||||
mDestination = new AudioDestinationNode(this, aIsOffline, aChannel,
|
||||
aNumberOfChannels, aLength, aSampleRate);
|
||||
// We skip calling SetIsOnlyNodeForContext during mDestination's constructor,
|
||||
// because we can only call SetIsOnlyNodeForContext after mDestination has
|
||||
// been set up.
|
||||
// We skip calling SetIsOnlyNodeForContext and the creation of the
|
||||
// audioChannelAgent during mDestination's constructor, because we can only
|
||||
// call them after mDestination has been set up.
|
||||
mDestination->CreateAudioChannelAgent();
|
||||
mDestination->SetIsOnlyNodeForContext(true);
|
||||
}
|
||||
|
||||
|
@ -258,8 +258,40 @@ static bool UseAudioChannelService()
|
||||
return Preferences::GetBool("media.useAudioChannelService");
|
||||
}
|
||||
|
||||
class EventProxyHandler MOZ_FINAL : public nsIDOMEventListener
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
explicit EventProxyHandler(nsIDOMEventListener* aNode)
|
||||
{
|
||||
MOZ_ASSERT(aNode);
|
||||
mWeakNode = do_GetWeakReference(aNode);
|
||||
}
|
||||
|
||||
// nsIDOMEventListener
|
||||
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent) MOZ_OVERRIDE
|
||||
{
|
||||
nsCOMPtr<nsIDOMEventListener> listener = do_QueryReferent(mWeakNode);
|
||||
if (!listener) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
auto node = static_cast<AudioDestinationNode*>(listener.get());
|
||||
return node->HandleEvent(aEvent);
|
||||
}
|
||||
|
||||
private:
|
||||
~EventProxyHandler()
|
||||
{ }
|
||||
|
||||
nsWeakPtr mWeakNode;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(EventProxyHandler, nsIDOMEventListener)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(AudioDestinationNode, AudioNode,
|
||||
mAudioChannelAgent)
|
||||
mAudioChannelAgent, mEventProxyHelper)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(AudioDestinationNode)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
|
||||
@ -305,17 +337,6 @@ AudioDestinationNode::AudioDestinationNode(AudioContext* aContext,
|
||||
ErrorResult rv;
|
||||
SetMozAudioChannelType(aChannel, rv);
|
||||
}
|
||||
|
||||
if (!aIsOffline && UseAudioChannelService()) {
|
||||
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(GetOwner());
|
||||
if (target) {
|
||||
target->AddSystemEventListener(NS_LITERAL_STRING("visibilitychange"), this,
|
||||
/* useCapture = */ true,
|
||||
/* wantsUntrusted = */ false);
|
||||
}
|
||||
|
||||
CreateAudioChannelAgent();
|
||||
}
|
||||
}
|
||||
|
||||
AudioDestinationNode::~AudioDestinationNode()
|
||||
@ -347,7 +368,8 @@ AudioDestinationNode::DestroyMediaStream()
|
||||
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(GetOwner());
|
||||
NS_ENSURE_TRUE_VOID(target);
|
||||
|
||||
target->RemoveSystemEventListener(NS_LITERAL_STRING("visibilitychange"), this,
|
||||
target->RemoveSystemEventListener(NS_LITERAL_STRING("visibilitychange"),
|
||||
mEventProxyHelper,
|
||||
/* useCapture = */ true);
|
||||
}
|
||||
|
||||
@ -565,6 +587,24 @@ AudioDestinationNode::CheckAudioChannelPermissions(AudioChannel aValue)
|
||||
void
|
||||
AudioDestinationNode::CreateAudioChannelAgent()
|
||||
{
|
||||
if (mIsOffline || !UseAudioChannelService()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mEventProxyHelper) {
|
||||
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(GetOwner());
|
||||
if (target) {
|
||||
// We use a proxy because otherwise the event listerner would hold a
|
||||
// reference of the destination node, and by extension, everything
|
||||
// connected to it.
|
||||
mEventProxyHelper = new EventProxyHandler(this);
|
||||
target->AddSystemEventListener(NS_LITERAL_STRING("visibilitychange"),
|
||||
mEventProxyHelper,
|
||||
/* useCapture = */ true,
|
||||
/* wantsUntrusted = */ false);
|
||||
}
|
||||
}
|
||||
|
||||
if (mAudioChannelAgent) {
|
||||
mAudioChannelAgent->StopPlaying();
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class AudioContext;
|
||||
class EventProxyHandler;
|
||||
|
||||
class AudioDestinationNode : public AudioNode
|
||||
, public nsIDOMEventListener
|
||||
@ -57,7 +58,7 @@ public:
|
||||
|
||||
void OfflineShutdown();
|
||||
|
||||
// nsIDOMEventListener
|
||||
// nsIDOMEventListener - by proxy
|
||||
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
|
||||
|
||||
AudioChannel MozAudioChannelType() const;
|
||||
@ -73,6 +74,8 @@ public:
|
||||
// When aIsOnlyNode is true, this is the only node for the AudioContext.
|
||||
void SetIsOnlyNodeForContext(bool aIsOnlyNode);
|
||||
|
||||
void CreateAudioChannelAgent();
|
||||
|
||||
virtual const char* NodeType() const
|
||||
{
|
||||
return "AudioDestinationNode";
|
||||
@ -88,7 +91,6 @@ protected:
|
||||
|
||||
private:
|
||||
bool CheckAudioChannelPermissions(AudioChannel aValue);
|
||||
void CreateAudioChannelAgent();
|
||||
|
||||
void SetCanPlay(bool aCanPlay);
|
||||
|
||||
@ -100,6 +102,8 @@ private:
|
||||
|
||||
nsCOMPtr<nsIAudioChannelAgent> mAudioChannelAgent;
|
||||
|
||||
nsRefPtr<EventProxyHandler> mEventProxyHelper;
|
||||
|
||||
// Audio Channel Type.
|
||||
AudioChannel mAudioChannel;
|
||||
bool mIsOffline;
|
||||
|
Loading…
Reference in New Issue
Block a user