Backed out changeset bf3531db0d54 (bug 1162663) for test_mozaudiochannel.html crashes.
authorRyan VanderMeulen <ryanvm@gmail.com>
Mon, 15 Jun 2015 12:47:38 -0400
changeset 238639 8045028bf400f3e7e605c69e5c11dfa5baa90453
parent 238638 6dd1b4a1f8b89a003538915776e8bb066500b14d
child 238640 74510e64899477179b9cc9a5557c621cf916adfe
push id699
push userryanvm@gmail.com
push dateMon, 15 Jun 2015 16:47:39 +0000
treeherdermozilla-b2g37_v2_2@8045028bf400 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1162663
milestone37.0
backs outbf3531db0d545c1950c7889539bd7ea31d7eb189
Backed out changeset bf3531db0d54 (bug 1162663) for test_mozaudiochannel.html crashes.
dom/audiochannel/AudioChannelService.cpp
dom/audiochannel/AudioChannelService.h
dom/audiochannel/AudioChannelServiceChild.cpp
dom/audiochannel/AudioChannelServiceChild.h
--- 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
+