Backed out changeset bf3531db0d54 (
bug 1162663) for test_mozaudiochannel.html crashes.
--- a/dom/audiochannel/AudioChannelService.cpp
+++ b/dom/audiochannel/AudioChannelService.cpp
@@ -57,16 +57,17 @@ AudioChannelService::GetAudioChannelServ
{
MOZ_ASSERT(NS_IsMainThread());
if (XRE_GetProcessType() != GeckoProcessType_Default) {
return AudioChannelServiceChild::GetAudioChannelService();
}
return gAudioChannelService;
+
}
// static
AudioChannelService*
AudioChannelService::GetOrCreateAudioChannelService()
{
MOZ_ASSERT(NS_IsMainThread());
@@ -130,22 +131,21 @@ void
AudioChannelService::RegisterAudioChannelAgent(AudioChannelAgent* aAgent,
AudioChannel aChannel,
bool aWithVideo)
{
if (mDisabled) {
return;
}
- AudioChannelAgentData* data =
- new AudioChannelAgentData(aAgent, aChannel,
- true /* aElementHidden */,
- AUDIO_CHANNEL_STATE_MUTED /* aState */,
- aWithVideo);
- mAgents.AppendElement(data);
+ AudioChannelAgentData* data = new AudioChannelAgentData(aChannel,
+ true /* aElementHidden */,
+ AUDIO_CHANNEL_STATE_MUTED /* aState */,
+ aWithVideo);
+ mAgents.Put(aAgent, data);
RegisterType(aChannel, CONTENT_PROCESS_ID_MAIN, aWithVideo);
// If this is the first agent for this window, we must notify the observers.
uint32_t count = CountWindow(aAgent->Window());
if (count == 1) {
nsCOMPtr<nsIObserverService> observerService =
services::GetObserverService();
if (observerService) {
@@ -214,26 +214,17 @@ AudioChannelService::RegisterType(AudioC
void
AudioChannelService::UnregisterAudioChannelAgent(AudioChannelAgent* aAgent)
{
if (mDisabled) {
return;
}
nsAutoPtr<AudioChannelAgentData> data;
- nsTObserverArray<nsAutoPtr<AudioChannelAgentData>>::ForwardIterator iter(mAgents);
- while (iter.HasMore()) {
- nsAutoPtr<AudioChannelAgentData>& pData = iter.GetNext();
- if (pData->mAgent == aAgent) {
- uint32_t pos = mAgents.IndexOf(pData);
- data = pData.forget();
- mAgents.RemoveElementAt(pos);
- break;
- }
- }
+ mAgents.RemoveAndForget(aAgent, data);
if (data) {
UnregisterType(data->mChannel, data->mElementHidden,
CONTENT_PROCESS_ID_MAIN, data->mWithVideo);
}
#ifdef MOZ_WIDGET_GONK
bool active = AnyAudioChannelIsActive();
@@ -353,45 +344,44 @@ AudioChannelService::UpdateChannelType(A
mChannelCounters[AUDIO_CHANNEL_INT_CONTENT].IsEmpty()) {
mPlayableHiddenContentChildID = aChildID;
}
}
AudioChannelState
AudioChannelService::GetState(AudioChannelAgent* aAgent, bool aElementHidden)
{
- AudioChannelAgentData* agentData = Find(aAgent);
- if (!agentData) {
+ AudioChannelAgentData* data;
+ if (!mAgents.Get(aAgent, &data)) {
return AUDIO_CHANNEL_STATE_MUTED;
}
- bool oldElementHidden = agentData->mElementHidden;
+ bool oldElementHidden = data->mElementHidden;
// Update visibility.
- agentData->mElementHidden = aElementHidden;
+ data->mElementHidden = aElementHidden;
- agentData->mState = GetStateInternal(agentData->mChannel,
- CONTENT_PROCESS_ID_MAIN,
- aElementHidden, oldElementHidden);
+ data->mState = GetStateInternal(data->mChannel, CONTENT_PROCESS_ID_MAIN,
+ aElementHidden, oldElementHidden);
#ifdef MOZ_WIDGET_GONK
/** Only modify the speaker status when
* (1) apps in the foreground.
* (2) apps in the backgrund and inactive.
* Notice : check the state when the visible status is stable, because there
* has lantency in passing the visibility events.
**/
bool active = AnyAudioChannelIsActive();
if (aElementHidden == oldElementHidden &&
(!aElementHidden || (aElementHidden && !active))) {
for (uint32_t i = 0; i < mSpeakerManager.Length(); i++) {
mSpeakerManager[i]->SetAudioChannelActive(active);
}
}
#endif
- return agentData->mState;
+ return data->mState;
}
AudioChannelState
AudioChannelService::GetStateInternal(AudioChannel aChannel, uint64_t aChildID,
bool aElementHidden,
bool aElementWasHidden)
{
UpdateChannelType(aChannel, aChildID, aElementHidden, aElementWasHidden);
@@ -675,16 +665,25 @@ AudioChannelService::SendAudioChannelCha
}
if (obs) {
obs->NotifyObservers(nullptr, "visible-audio-channel-changed", channelName.get());
}
}
}
+PLDHashOperator
+AudioChannelService::NotifyEnumerator(AudioChannelAgent* aAgent,
+ AudioChannelAgentData* aData, void* aUnused)
+{
+ MOZ_ASSERT(aAgent);
+ aAgent->NotifyAudioChannelStateChanged();
+ return PL_DHASH_NEXT;
+}
+
class NotifyRunnable : public nsRunnable
{
public:
explicit NotifyRunnable(AudioChannelService* aService)
: mService(aService)
{}
NS_IMETHOD Run()
@@ -712,21 +711,17 @@ AudioChannelService::SendNotification()
void
AudioChannelService::Notify()
{
MOZ_ASSERT(NS_IsMainThread());
mRunnable = nullptr;
// Notify any agent for the main process.
- nsTObserverArray<nsAutoPtr<AudioChannelAgentData>>::ForwardIterator iter(mAgents);
- while (iter.HasMore()) {
- AudioChannelAgentData* data = iter.GetNext();
- data->mAgent->NotifyAudioChannelStateChanged();
- }
+ mAgents.EnumerateRead(NotifyEnumerator, nullptr);
// Notify for the child processes.
nsTArray<ContentParent*> children;
ContentParent::GetAll(children);
for (uint32_t i = 0; i < children.Length(); i++) {
unused << children[i]->SendAudioChannelNotify();
}
}
@@ -766,16 +761,38 @@ AudioChannelService::ChannelsActiveWithH
if (!mChannelCounters[i].IsEmpty()) {
return true;
}
}
return false;
}
+PLDHashOperator
+AudioChannelService::WindowDestroyedEnumerator(AudioChannelAgent* aAgent,
+ nsAutoPtr<AudioChannelAgentData>& aData,
+ void* aPtr)
+{
+ uint64_t* innerID = static_cast<uint64_t*>(aPtr);
+ MOZ_ASSERT(innerID);
+
+ nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aAgent->Window());
+ if (!window || window->WindowID() != *innerID) {
+ return PL_DHASH_NEXT;
+ }
+
+ AudioChannelService* service = AudioChannelService::GetAudioChannelService();
+ MOZ_ASSERT(service);
+
+ service->UnregisterType(aData->mChannel, aData->mElementHidden,
+ CONTENT_PROCESS_ID_MAIN, aData->mWithVideo);
+
+ return PL_DHASH_REMOVE;
+}
+
NS_IMETHODIMP
AudioChannelService::Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData)
{
if (!strcmp(aTopic, "xpcom-shutdown")) {
mDisabled = true;
}
if (!strcmp(aTopic, "ipc:content-shutdown")) {
@@ -867,32 +884,17 @@ AudioChannelService::Observe(nsISupports
NS_ENSURE_TRUE(wrapper, NS_ERROR_FAILURE);
uint64_t innerID;
nsresult rv = wrapper->GetData(&innerID);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
- nsTObserverArray<nsAutoPtr<AudioChannelAgentData>>::ForwardIterator iter(mAgents);
- while (iter.HasMore()) {
- AudioChannelAgentData* data = iter.GetNext();
-
- nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(data->mAgent->Window());
- if (window && !window->IsInnerWindow()) {
- window = window->GetCurrentInnerWindow();
- }
-
- if (!window || window->WindowID() != innerID) {
- continue;
- }
-
- UnregisterType(data->mChannel, data->mElementHidden,
- CONTENT_PROCESS_ID_MAIN, data->mWithVideo);
- }
+ mAgents.Enumerate(WindowDestroyedEnumerator, &innerID);
#ifdef MOZ_WIDGET_GONK
bool active = AnyAudioChannelIsActive();
for (uint32_t i = 0; i < mSpeakerManager.Length(); i++) {
mSpeakerManager[i]->SetAudioChannelActive(active);
}
#endif
}
@@ -942,47 +944,89 @@ AudioChannelService::GetInternalType(Aud
default:
break;
}
MOZ_CRASH("unexpected audio channel");
}
+struct RefreshAgentsVolumeData
+{
+ explicit RefreshAgentsVolumeData(nsPIDOMWindow* aWindow)
+ : mWindow(aWindow)
+ {}
+
+ nsPIDOMWindow* mWindow;
+ nsTArray<nsRefPtr<AudioChannelAgent>> mAgents;
+};
+
+PLDHashOperator
+AudioChannelService::RefreshAgentsVolumeEnumerator(AudioChannelAgent* aAgent,
+ AudioChannelAgentData* aUnused,
+ void* aPtr)
+{
+ MOZ_ASSERT(aAgent);
+ RefreshAgentsVolumeData* data = static_cast<RefreshAgentsVolumeData*>(aPtr);
+ MOZ_ASSERT(data);
+
+ nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aAgent->Window());
+ if (window && !window->IsInnerWindow()) {
+ window = window->GetCurrentInnerWindow();
+ }
+
+ if (window == data->mWindow) {
+ data->mAgents.AppendElement(aAgent);
+ }
+
+ return PL_DHASH_NEXT;
+}
void
AudioChannelService::RefreshAgentsVolume(nsPIDOMWindow* aWindow)
{
- nsTObserverArray<nsAutoPtr<AudioChannelAgentData>>::ForwardIterator iter(mAgents);
- while (iter.HasMore()) {
- AudioChannelAgentData* data = iter.GetNext();
+ RefreshAgentsVolumeData data(aWindow);
+ mAgents.EnumerateRead(RefreshAgentsVolumeEnumerator, &data);
+
+ for (uint32_t i = 0; i < data.mAgents.Length(); ++i) {
+ data.mAgents[i]->WindowVolumeChanged();
+ }
+}
+
+struct CountWindowData
+{
+ explicit CountWindowData(nsIDOMWindow* aWindow)
+ : mWindow(aWindow)
+ , mCount(0)
+ {}
- nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(data->mAgent->Window());
- if (window && !window->IsInnerWindow()) {
- window = window->GetCurrentInnerWindow();
- }
+ nsIDOMWindow* mWindow;
+ uint32_t mCount;
+};
- if (window == aWindow) {
- data->mAgent->WindowVolumeChanged();
- }
+PLDHashOperator
+AudioChannelService::CountWindowEnumerator(AudioChannelAgent* aAgent,
+ AudioChannelAgentData* aUnused,
+ void* aPtr)
+{
+ CountWindowData* data = static_cast<CountWindowData*>(aPtr);
+ MOZ_ASSERT(aAgent);
+
+ if (aAgent->Window() == data->mWindow) {
+ ++data->mCount;
}
+
+ return PL_DHASH_NEXT;
}
uint32_t
AudioChannelService::CountWindow(nsIDOMWindow* aWindow)
{
- uint32_t count = 0;
- nsTObserverArray<nsAutoPtr<AudioChannelAgentData>>::ForwardIterator iter(mAgents);
- while (iter.HasMore()) {
- AudioChannelAgentData* data = iter.GetNext();
- if (data->mAgent->Window() == aWindow) {
- ++count;
- }
- }
-
- return count;
+ CountWindowData data(aWindow);
+ mAgents.EnumerateRead(CountWindowEnumerator, &data);
+ return data.mCount;
}
/* static */ const nsAttrValue::EnumTable*
AudioChannelService::GetAudioChannelTable()
{
return kMozAudioChannelAttributeTable;
}
@@ -1076,22 +1120,8 @@ AudioChannelService::UnregisterTelephony
}
return;
}
}
MOZ_ASSERT(false, "This should not happen.");
}
-
-AudioChannelService::AudioChannelAgentData*
-AudioChannelService::Find(AudioChannelAgent* aAgent)
-{
- nsTObserverArray<nsAutoPtr<AudioChannelAgentData>>::ForwardIterator iter(mAgents);
- while (iter.HasMore()) {
- AudioChannelAgentData* data = iter.GetNext();
- if (data->mAgent == aAgent) {
- return data;
- }
- }
-
- return nullptr;
-}
--- a/dom/audiochannel/AudioChannelService.h
+++ b/dom/audiochannel/AudioChannelService.h
@@ -10,17 +10,17 @@
#include "nsAutoPtr.h"
#include "nsIObserver.h"
#include "nsTArray.h"
#include "nsITimer.h"
#include "AudioChannelCommon.h"
#include "AudioChannelAgent.h"
#include "nsAttrValue.h"
-#include "nsTObserverArray.h"
+#include "nsClassHashtable.h"
#include "mozilla/dom/AudioChannelBinding.h"
class nsIRunnable;
class nsPIDOMWindow;
namespace mozilla {
namespace dom {
#ifdef MOZ_WIDGET_GONK
@@ -184,48 +184,57 @@ protected:
bool ChannelsActiveWithHigherPriorityThan(AudioChannelInternalType aType);
bool CheckVolumeFadedCondition(AudioChannelInternalType aType,
bool aElementHidden);
AudioChannelInternalType GetInternalType(AudioChannel aChannel,
bool aElementHidden);
- class AudioChannelAgentData
- {
+ class AudioChannelAgentData {
public:
- AudioChannelAgentData(AudioChannelAgent* aAgent,
- AudioChannel aChannel,
+ AudioChannelAgentData(AudioChannel aChannel,
bool aElementHidden,
AudioChannelState aState,
bool aWithVideo)
- : mAgent(aAgent)
- , mChannel(aChannel)
+ : mChannel(aChannel)
, mElementHidden(aElementHidden)
, mState(aState)
, mWithVideo(aWithVideo)
- {
- MOZ_ASSERT(mAgent);
- }
+ {}
- // AudioChannelAgent will unregister itself in the DTOR.
- AudioChannelAgent* mAgent;
AudioChannel mChannel;
bool mElementHidden;
AudioChannelState mState;
const bool mWithVideo;
};
- AudioChannelAgentData* Find(AudioChannelAgent* aAgent);
+ static PLDHashOperator
+ NotifyEnumerator(AudioChannelAgent* aAgent,
+ AudioChannelAgentData* aData, void *aUnused);
+
+ static PLDHashOperator
+ RefreshAgentsVolumeEnumerator(AudioChannelAgent* aAgent,
+ AudioChannelAgentData* aUnused,
+ void *aPtr);
+
+ static PLDHashOperator
+ CountWindowEnumerator(AudioChannelAgent* aAgent,
+ AudioChannelAgentData* aUnused,
+ void *aPtr);
+
+ static PLDHashOperator
+ WindowDestroyedEnumerator(AudioChannelAgent* aAgent,
+ nsAutoPtr<AudioChannelAgentData>& aData,
+ void *aPtr);
// This returns the number of agents from this aWindow.
uint32_t CountWindow(nsIDOMWindow* aWindow);
- nsTObserverArray<nsAutoPtr<AudioChannelAgentData>> mAgents;
-
+ nsClassHashtable< nsPtrHashKey<AudioChannelAgent>, AudioChannelAgentData > mAgents;
#ifdef MOZ_WIDGET_GONK
nsTArray<SpeakerManagerService*> mSpeakerManager;
#endif
nsTArray<uint64_t> mChannelCounters[AUDIO_CHANNEL_INT_LAST];
int32_t mCurrentHigherChannel;
int32_t mCurrentVisibleHigherChannel;
--- a/dom/audiochannel/AudioChannelServiceChild.cpp
+++ b/dom/audiochannel/AudioChannelServiceChild.cpp
@@ -69,18 +69,18 @@ AudioChannelServiceChild::AudioChannelSe
AudioChannelServiceChild::~AudioChannelServiceChild()
{
}
AudioChannelState
AudioChannelServiceChild::GetState(AudioChannelAgent* aAgent, bool aElementHidden)
{
- AudioChannelAgentData* data = Find(aAgent);
- if (!data) {
+ AudioChannelAgentData* data;
+ if (!mAgents.Get(aAgent, &data)) {
return AUDIO_CHANNEL_STATE_MUTED;
}
AudioChannelState state = AUDIO_CHANNEL_STATE_MUTED;
bool oldElementHidden = data->mElementHidden;
UpdateChannelType(data->mChannel, CONTENT_PROCESS_ID_MAIN, aElementHidden,
oldElementHidden);
@@ -126,18 +126,18 @@ AudioChannelServiceChild::RegisterAudioC
if (obs) {
obs->NotifyObservers(nullptr, "audio-channel-agent-changed", nullptr);
}
}
void
AudioChannelServiceChild::UnregisterAudioChannelAgent(AudioChannelAgent* aAgent)
{
- AudioChannelAgentData* pData = Find(aAgent);
- if (!pData) {
+ AudioChannelAgentData *pData;
+ if (!mAgents.Get(aAgent, &pData)) {
return;
}
// We need to keep a copy because unregister will remove the
// AudioChannelAgentData object from the hashtable.
AudioChannelAgentData data(*pData);
AudioChannelService::UnregisterAudioChannelAgent(aAgent);
--- a/dom/audiochannel/AudioChannelServiceChild.h
+++ b/dom/audiochannel/AudioChannelServiceChild.h
@@ -54,8 +54,9 @@ protected:
AudioChannelServiceChild();
virtual ~AudioChannelServiceChild();
};
} // namespace dom
} // namespace mozilla
#endif
+