Bug 1162663 - Convert nsHashtable to nsObserverTArray in AudioChannelService. r=alwu, r=ehsan, a=jocheng
--- a/dom/audiochannel/AudioChannelService.cpp
+++ b/dom/audiochannel/AudioChannelService.cpp
@@ -57,17 +57,16 @@ AudioChannelService::GetAudioChannelServ
{
MOZ_ASSERT(NS_IsMainThread());
if (XRE_GetProcessType() != GeckoProcessType_Default) {
return AudioChannelServiceChild::GetAudioChannelService();
}
return gAudioChannelService;
-
}
// static
AudioChannelService*
AudioChannelService::GetOrCreateAudioChannelService()
{
MOZ_ASSERT(NS_IsMainThread());
@@ -131,21 +130,22 @@ void
AudioChannelService::RegisterAudioChannelAgent(AudioChannelAgent* aAgent,
AudioChannel aChannel,
bool aWithVideo)
{
if (mDisabled) {
return;
}
- AudioChannelAgentData* data = new AudioChannelAgentData(aChannel,
- true /* aElementHidden */,
- AUDIO_CHANNEL_STATE_MUTED /* aState */,
- aWithVideo);
- mAgents.Put(aAgent, data);
+ AudioChannelAgentData* data =
+ new AudioChannelAgentData(aAgent, aChannel,
+ true /* aElementHidden */,
+ AUDIO_CHANNEL_STATE_MUTED /* aState */,
+ aWithVideo);
+ mAgents.AppendElement(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,17 +214,26 @@ AudioChannelService::RegisterType(AudioC
void
AudioChannelService::UnregisterAudioChannelAgent(AudioChannelAgent* aAgent)
{
if (mDisabled) {
return;
}
nsAutoPtr<AudioChannelAgentData> data;
- mAgents.RemoveAndForget(aAgent, 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;
+ }
+ }
if (data) {
UnregisterType(data->mChannel, data->mElementHidden,
CONTENT_PROCESS_ID_MAIN, data->mWithVideo);
}
#ifdef MOZ_WIDGET_GONK
bool active = AnyAudioChannelIsActive();
@@ -344,44 +353,45 @@ AudioChannelService::UpdateChannelType(A
mChannelCounters[AUDIO_CHANNEL_INT_CONTENT].IsEmpty()) {
mPlayableHiddenContentChildID = aChildID;
}
}
AudioChannelState
AudioChannelService::GetState(AudioChannelAgent* aAgent, bool aElementHidden)
{
- AudioChannelAgentData* data;
- if (!mAgents.Get(aAgent, &data)) {
+ AudioChannelAgentData* agentData = Find(aAgent);
+ if (!agentData) {
return AUDIO_CHANNEL_STATE_MUTED;
}
- bool oldElementHidden = data->mElementHidden;
+ bool oldElementHidden = agentData->mElementHidden;
// Update visibility.
- data->mElementHidden = aElementHidden;
+ agentData->mElementHidden = aElementHidden;
- data->mState = GetStateInternal(data->mChannel, CONTENT_PROCESS_ID_MAIN,
- aElementHidden, oldElementHidden);
+ agentData->mState = GetStateInternal(agentData->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 data->mState;
+ return agentData->mState;
}
AudioChannelState
AudioChannelService::GetStateInternal(AudioChannel aChannel, uint64_t aChildID,
bool aElementHidden,
bool aElementWasHidden)
{
UpdateChannelType(aChannel, aChildID, aElementHidden, aElementWasHidden);
@@ -665,25 +675,16 @@ 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()
@@ -711,17 +712,21 @@ AudioChannelService::SendNotification()
void
AudioChannelService::Notify()
{
MOZ_ASSERT(NS_IsMainThread());
mRunnable = nullptr;
// Notify any agent for the main process.
- mAgents.EnumerateRead(NotifyEnumerator, nullptr);
+ nsTObserverArray<nsAutoPtr<AudioChannelAgentData>>::ForwardIterator iter(mAgents);
+ while (iter.HasMore()) {
+ AudioChannelAgentData* data = iter.GetNext();
+ data->mAgent->NotifyAudioChannelStateChanged();
+ }
// Notify for the child processes.
nsTArray<ContentParent*> children;
ContentParent::GetAll(children);
for (uint32_t i = 0; i < children.Length(); i++) {
unused << children[i]->SendAudioChannelNotify();
}
}
@@ -761,38 +766,16 @@ 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")) {
@@ -884,17 +867,34 @@ 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;
}
- mAgents.Enumerate(WindowDestroyedEnumerator, &innerID);
+ 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.RemoveElement(data);
+ }
#ifdef MOZ_WIDGET_GONK
bool active = AnyAudioChannelIsActive();
for (uint32_t i = 0; i < mSpeakerManager.Length(); i++) {
mSpeakerManager[i]->SetAudioChannelActive(active);
}
#endif
}
@@ -944,89 +944,47 @@ 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)
{
- 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)
- {}
+ nsTObserverArray<nsAutoPtr<AudioChannelAgentData>>::ForwardIterator iter(mAgents);
+ while (iter.HasMore()) {
+ AudioChannelAgentData* data = iter.GetNext();
- nsIDOMWindow* mWindow;
- uint32_t mCount;
-};
+ nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(data->mAgent->Window());
+ if (window && !window->IsInnerWindow()) {
+ window = window->GetCurrentInnerWindow();
+ }
-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;
+ if (window == aWindow) {
+ data->mAgent->WindowVolumeChanged();
+ }
}
-
- return PL_DHASH_NEXT;
}
uint32_t
AudioChannelService::CountWindow(nsIDOMWindow* aWindow)
{
- CountWindowData data(aWindow);
- mAgents.EnumerateRead(CountWindowEnumerator, &data);
- return data.mCount;
+ 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;
}
/* static */ const nsAttrValue::EnumTable*
AudioChannelService::GetAudioChannelTable()
{
return kMozAudioChannelAttributeTable;
}
@@ -1120,8 +1078,22 @@ 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 "nsClassHashtable.h"
+#include "nsTObserverArray.h"
#include "mozilla/dom/AudioChannelBinding.h"
class nsIRunnable;
class nsPIDOMWindow;
namespace mozilla {
namespace dom {
#ifdef MOZ_WIDGET_GONK
@@ -184,57 +184,48 @@ protected:
bool ChannelsActiveWithHigherPriorityThan(AudioChannelInternalType aType);
bool CheckVolumeFadedCondition(AudioChannelInternalType aType,
bool aElementHidden);
AudioChannelInternalType GetInternalType(AudioChannel aChannel,
bool aElementHidden);
- class AudioChannelAgentData {
+ class AudioChannelAgentData
+ {
public:
- AudioChannelAgentData(AudioChannel aChannel,
+ AudioChannelAgentData(AudioChannelAgent* aAgent,
+ AudioChannel aChannel,
bool aElementHidden,
AudioChannelState aState,
bool aWithVideo)
- : mChannel(aChannel)
+ : mAgent(aAgent)
+ , 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;
};
- 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);
+ AudioChannelAgentData* Find(AudioChannelAgent* aAgent);
// This returns the number of agents from this aWindow.
uint32_t CountWindow(nsIDOMWindow* aWindow);
- nsClassHashtable< nsPtrHashKey<AudioChannelAgent>, AudioChannelAgentData > mAgents;
+ nsTObserverArray<nsAutoPtr<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;
- if (!mAgents.Get(aAgent, &data)) {
+ AudioChannelAgentData* data = Find(aAgent);
+ if (!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;
- if (!mAgents.Get(aAgent, &pData)) {
+ AudioChannelAgentData* pData = Find(aAgent);
+ if (!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,9 +54,8 @@ protected:
AudioChannelServiceChild();
virtual ~AudioChannelServiceChild();
};
} // namespace dom
} // namespace mozilla
#endif
-