Bug 1223734 - AudioChannelService should not be re-initialized after the XPCOM shutdown, r=smaug
authorAndrea Marchesini <amarchesini@mozilla.com>
Mon, 16 Nov 2015 17:34:52 +0000
changeset 306926 b22d1abe0289b6bf6ab30c03015a6553e7aefd1d
parent 306925 1cc8cc0444c0141f85919f37689cb8c1a49a7d0e
child 306927 37ada9330ed67f40c74ef6bdb81c230ca26a2794
push id5513
push userraliiev@mozilla.com
push dateMon, 25 Jan 2016 13:55:34 +0000
treeherdermozilla-beta@5ee97dd05b5c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1223734
milestone45.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1223734 - AudioChannelService should not be re-initialized after the XPCOM shutdown, r=smaug
dom/audiochannel/AudioChannelAgent.cpp
dom/audiochannel/AudioChannelService.cpp
dom/base/nsGlobalWindow.cpp
dom/browser-element/BrowserElementAudioChannel.cpp
dom/ipc/ProcessPriorityManager.cpp
dom/speakermanager/SpeakerManagerService.cpp
dom/system/gonk/AudioChannelManager.cpp
dom/system/gonk/AudioManager.cpp
--- a/dom/audiochannel/AudioChannelAgent.cpp
+++ b/dom/audiochannel/AudioChannelAgent.cpp
@@ -166,17 +166,20 @@ NS_IMETHODIMP AudioChannelAgent::NotifyS
 NS_IMETHODIMP AudioChannelAgent::NotifyStoppedPlaying()
 {
   if (mAudioChannelType == AUDIO_AGENT_CHANNEL_ERROR ||
       !mIsRegToService) {
     return NS_ERROR_FAILURE;
   }
 
   RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
-  service->UnregisterAudioChannelAgent(this, mNotifyPlayback);
+  if (service) {
+    service->UnregisterAudioChannelAgent(this, mNotifyPlayback);
+  }
+
   mIsRegToService = false;
   return NS_OK;
 }
 
 already_AddRefed<nsIAudioChannelAgentCallback>
 AudioChannelAgent::GetCallback()
 {
   nsCOMPtr<nsIAudioChannelAgentCallback> callback = mCallback;
@@ -193,17 +196,19 @@ AudioChannelAgent::WindowVolumeChanged()
   if (!callback) {
     return;
   }
 
   float volume = 1.0;
   bool muted = false;
 
   RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
-  service->GetState(mWindow, mAudioChannelType, &volume, &muted);
+  if (service) {
+    service->GetState(mWindow, mAudioChannelType, &volume, &muted);
+  }
 
   callback->WindowVolumeChanged(volume, muted);
 }
 
 uint64_t
 AudioChannelAgent::WindowID() const
 {
   return mWindow ? mWindow->WindowID() : 0;
--- a/dom/audiochannel/AudioChannelService.cpp
+++ b/dom/audiochannel/AudioChannelService.cpp
@@ -35,16 +35,17 @@
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::hal;
 
 namespace {
 
 // If true, any new AudioChannelAgent will be muted when created.
 bool sAudioChannelMutedByDefault = false;
+bool sXPCOMShuttingDown = false;
 
 class NotifyChannelActiveRunnable final : public nsRunnable
 {
 public:
   NotifyChannelActiveRunnable(uint64_t aWindowID, AudioChannel aAudioChannel,
                               bool aActive)
     : mWindowID(aWindowID)
     , mAudioChannel(aAudioChannel)
@@ -168,22 +169,26 @@ AudioChannelService::CreateServiceIfNeed
   if (!gAudioChannelService) {
     gAudioChannelService = new AudioChannelService();
   }
 }
 
 /* static */ already_AddRefed<AudioChannelService>
 AudioChannelService::GetOrCreate()
 {
+  if (sXPCOMShuttingDown) {
+    return nullptr;
+  }
+
   CreateServiceIfNeeded();
   RefPtr<AudioChannelService> service = gAudioChannelService.get();
   return service.forget();
 }
 
-void
+/* static */ void
 AudioChannelService::Shutdown()
 {
   if (gAudioChannelService) {
     nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
     if (obs) {
       obs->RemoveObserver(gAudioChannelService, "xpcom-shutdown");
       obs->RemoveObserver(gAudioChannelService, "outer-window-destroyed");
 
@@ -192,16 +197,22 @@ AudioChannelService::Shutdown()
 
 #ifdef MOZ_WIDGET_GONK
         // To monitor the volume settings based on audio channel.
         obs->RemoveObserver(gAudioChannelService, "mozsettings-changed");
 #endif
       }
     }
 
+    gAudioChannelService->mWindows.Clear();
+    gAudioChannelService->mPlayingChildren.Clear();
+#ifdef MOZ_WIDGET_GONK
+    gAudioChannelService->mSpeakerManager.Clear();
+#endif
+
     gAudioChannelService = nullptr;
   }
 }
 
 NS_INTERFACE_MAP_BEGIN(AudioChannelService)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIAudioChannelService)
   NS_INTERFACE_MAP_ENTRY(nsIAudioChannelService)
   NS_INTERFACE_MAP_ENTRY(nsIObserver)
@@ -463,17 +474,17 @@ AudioChannelService::AnyAudioChannelIsAc
   return false;
 }
 
 NS_IMETHODIMP
 AudioChannelService::Observe(nsISupports* aSubject, const char* aTopic,
                              const char16_t* aData)
 {
   if (!strcmp(aTopic, "xpcom-shutdown")) {
-    mWindows.Clear();
+    sXPCOMShuttingDown = true;
     Shutdown();
   } else if (!strcmp(aTopic, "outer-window-destroyed")) {
     nsCOMPtr<nsISupportsPRUint64> wrapper = do_QueryInterface(aSubject);
     NS_ENSURE_TRUE(wrapper, NS_ERROR_FAILURE);
 
     uint64_t outerID;
     nsresult rv = wrapper->GetData(&outerID);
     if (NS_WARN_IF(NS_FAILED(rv))) {
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -3698,17 +3698,19 @@ nsPIDOMWindow::SetAudioVolume(float aVol
   RefreshMediaElements();
   return NS_OK;
 }
 
 void
 nsPIDOMWindow::RefreshMediaElements()
 {
   RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
-  service->RefreshAgentsVolume(GetOuterWindow());
+  if (service) {
+    service->RefreshAgentsVolume(GetOuterWindow());
+  }
 }
 
 bool
 nsPIDOMWindow::GetAudioCaptured() const
 {
   MOZ_ASSERT(IsInnerWindow());
   return mAudioCaptured;
 }
@@ -3716,17 +3718,19 @@ nsPIDOMWindow::GetAudioCaptured() const
 nsresult
 nsPIDOMWindow::SetAudioCapture(bool aCapture)
 {
   MOZ_ASSERT(IsInnerWindow());
 
   mAudioCaptured = aCapture;
 
   RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
-  service->RefreshAgentsCapture(GetOuterWindow(), mWindowID);
+  if (service) {
+    service->RefreshAgentsCapture(GetOuterWindow(), mWindowID);
+  }
 
   return NS_OK;
 }
 
 // nsISpeechSynthesisGetter
 
 #ifdef MOZ_WEBSPEECH
 SpeechSynthesis*
--- a/dom/browser-element/BrowserElementAudioChannel.cpp
+++ b/dom/browser-element/BrowserElementAudioChannel.cpp
@@ -194,17 +194,19 @@ public:
     , mFrameWindow(aFrameWindow)
     , mRequest(aRequest)
     , mAudioChannel(aAudioChannel)
   {}
 
   NS_IMETHODIMP Run() override
   {
     RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
-    MOZ_ASSERT(service);
+    if (!service) {
+      return NS_OK;
+    }
 
     AutoJSAPI jsapi;
     if (!jsapi.Init(mParentWindow)) {
       mRequest->FireError(NS_ERROR_FAILURE);
       return NS_OK;
     }
 
     DoWork(service, jsapi.cx());
@@ -391,19 +393,19 @@ BrowserElementAudioChannel::SetVolume(fl
     if (NS_WARN_IF(aRv.Failed())) {
       return nullptr;
     }
 
     return request.forget().downcast<DOMRequest>();
   }
 
   RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
-  MOZ_ASSERT(service);
-
-  service->SetAudioChannelVolume(mFrameWindow, mAudioChannel, aVolume);
+  if (service) {
+    service->SetAudioChannelVolume(mFrameWindow, mAudioChannel, aVolume);
+  }
 
   RefPtr<DOMRequest> domRequest = new DOMRequest(GetOwner());
   nsCOMPtr<nsIRunnable> runnable = new FireSuccessRunnable(GetOwner(),
                                                            mFrameWindow,
                                                            domRequest,
                                                            mAudioChannel);
   NS_DispatchToMainThread(runnable);
 
@@ -450,19 +452,19 @@ BrowserElementAudioChannel::SetMuted(boo
     if (NS_WARN_IF(aRv.Failed())) {
       return nullptr;
     }
 
     return request.forget().downcast<DOMRequest>();
   }
 
   RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
-  MOZ_ASSERT(service);
-
-  service->SetAudioChannelMuted(mFrameWindow, mAudioChannel, aMuted);
+  if (service) {
+    service->SetAudioChannelMuted(mFrameWindow, mAudioChannel, aMuted);
+  }
 
   RefPtr<DOMRequest> domRequest = new DOMRequest(GetOwner());
   nsCOMPtr<nsIRunnable> runnable = new FireSuccessRunnable(GetOwner(),
                                                            mFrameWindow,
                                                            domRequest,
                                                            mAudioChannel);
   NS_DispatchToMainThread(runnable);
 
--- a/dom/ipc/ProcessPriorityManager.cpp
+++ b/dom/ipc/ProcessPriorityManager.cpp
@@ -1103,17 +1103,17 @@ ParticularProcessPriorityManager::Comput
   }
 
   if ((mHoldsCPUWakeLock || mHoldsHighPriorityWakeLock) &&
       IsExpectingSystemMessage()) {
     return PROCESS_PRIORITY_BACKGROUND_PERCEIVABLE;
   }
 
   RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
-  if (service->ProcessContentOrNormalChannelIsActive(ChildID())) {
+  if (service && service->ProcessContentOrNormalChannelIsActive(ChildID())) {
     return PROCESS_PRIORITY_BACKGROUND_PERCEIVABLE;
   }
 
   return mIsActivityOpener ? PROCESS_PRIORITY_BACKGROUND_PERCEIVABLE
                            : PROCESS_PRIORITY_BACKGROUND;
 }
 
 void
--- a/dom/speakermanager/SpeakerManagerService.cpp
+++ b/dom/speakermanager/SpeakerManagerService.cpp
@@ -179,17 +179,19 @@ SpeakerManagerService::Observe(nsISuppor
     } else {
       NS_WARNING("ipc:content-shutdown message without childID property");
     }
   } else if (!strcmp(aTopic, "xpcom-will-shutdown")) {
     // Note that we need to do this before xpcom-shutdown, since the
     // AudioChannelService cannot be used past that point.
     RefPtr<AudioChannelService> audioChannelService =
       AudioChannelService::GetOrCreate();
-    audioChannelService->UnregisterSpeakerManager(this);
+    if (audioChannelService) {
+      audioChannelService->UnregisterSpeakerManager(this);
+    }
 
     nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
     if (obs) {
       obs->RemoveObserver(this, "ipc:content-shutdown");
       obs->RemoveObserver(this, "xpcom-will-shutdown");
     }
 
     Shutdown();
@@ -206,15 +208,17 @@ SpeakerManagerService::SpeakerManagerSer
     nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
     if (obs) {
       obs->AddObserver(this, "ipc:content-shutdown", false);
       obs->AddObserver(this, "xpcom-will-shutdown", false);
     }
   }
   RefPtr<AudioChannelService> audioChannelService =
     AudioChannelService::GetOrCreate();
-  audioChannelService->RegisterSpeakerManager(this);
+  if (audioChannelService) {
+    audioChannelService->RegisterSpeakerManager(this);
+  }
 }
 
 SpeakerManagerService::~SpeakerManagerService()
 {
   MOZ_COUNT_DTOR(SpeakerManagerService);
 }
--- a/dom/system/gonk/AudioChannelManager.cpp
+++ b/dom/system/gonk/AudioChannelManager.cpp
@@ -126,16 +126,20 @@ AudioChannelManager::NotifyVolumeControl
 {
   nsCOMPtr<nsIDocShell> docshell = do_GetInterface(GetOwner());
   NS_ENSURE_TRUE_VOID(docshell);
 
   bool isActive = false;
   docshell->GetIsActive(&isActive);
 
   RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
+  if (!service) {
+    return;
+  }
+
   if (isActive) {
     service->SetDefaultVolumeControlChannel(mVolumeChannel, isActive);
   } else {
     service->SetDefaultVolumeControlChannel(-1, isActive);
   }
 }
 
 NS_IMETHODIMP
--- a/dom/system/gonk/AudioManager.cpp
+++ b/dom/system/gonk/AudioManager.cpp
@@ -546,19 +546,17 @@ AudioManager::HandleAudioChannelProcessC
   // PHONE_STATE_IN_COMMUNICATION audio state.
 
   if ((mPhoneState == PHONE_STATE_IN_CALL) ||
       (mPhoneState == PHONE_STATE_RINGTONE)) {
     return;
   }
 
   RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
-  MOZ_ASSERT(service);
-
-  bool telephonyChannelIsActive = service->TelephonyChannelIsActive();
+  bool telephonyChannelIsActive = service && service->TelephonyChannelIsActive();
   telephonyChannelIsActive ? SetPhoneState(PHONE_STATE_IN_COMMUNICATION) :
                              SetPhoneState(PHONE_STATE_NORMAL);
 }
 
 nsresult
 AudioManager::Observe(nsISupports* aSubject,
                       const char* aTopic,
                       const char16_t* aData)