Bug 923247 - patch 1 - window in the AudioChannelAgent, r=mchen
authorAndrea Marchesini <amarchesini@mozilla.com>
Tue, 11 Mar 2014 10:46:04 +0000
changeset 191161 798346050542c3a44758ad6487936d4c0ffa083e
parent 191160 571356679b106c24370605bfcd47aeb82600430e
child 191162 71d145853be84028380a701ec20bb03a6afcb0d5
push id474
push userasasaki@mozilla.com
push dateMon, 02 Jun 2014 21:01:02 +0000
treeherdermozilla-release@967f4cf1b31c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmchen
bugs923247
milestone30.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 923247 - patch 1 - window in the AudioChannelAgent, r=mchen
content/html/content/src/HTMLAudioElement.cpp
content/html/content/src/HTMLMediaElement.cpp
content/media/webaudio/AudioDestinationNode.cpp
dom/audiochannel/AudioChannelAgent.cpp
dom/audiochannel/AudioChannelAgent.h
dom/audiochannel/nsIAudioChannelAgent.idl
dom/audiochannel/tests/TestAudioChannelService.cpp
dom/camera/DOMCameraControl.cpp
dom/fmradio/FMRadio.cpp
dom/system/gonk/AudioManager.cpp
--- a/content/html/content/src/HTMLAudioElement.cpp
+++ b/content/html/content/src/HTMLAudioElement.cpp
@@ -269,17 +269,18 @@ HTMLAudioElement::UpdateAudioChannelPlay
 
     if (!mAudioChannelAgent) {
       nsresult rv;
       mAudioChannelAgent = do_CreateInstance("@mozilla.org/audiochannelagent;1", &rv);
       if (!mAudioChannelAgent) {
         return;
       }
       // Use a weak ref so the audio channel agent can't leak |this|.
-      mAudioChannelAgent->InitWithWeakCallback(mAudioChannelType, this);
+      mAudioChannelAgent->InitWithWeakCallback(OwnerDoc()->GetWindow(),
+                                               mAudioChannelType, this);
 
       mAudioChannelAgent->SetVisibilityState(!OwnerDoc()->Hidden());
     }
 
     if (mPlayingThroughTheAudioChannel) {
       int32_t canPlay;
       mAudioChannelAgent->StartPlaying(&canPlay);
       CanPlayChanged(canPlay);
--- a/content/html/content/src/HTMLMediaElement.cpp
+++ b/content/html/content/src/HTMLMediaElement.cpp
@@ -3874,19 +3874,21 @@ void HTMLMediaElement::UpdateAudioChanne
       nsresult rv;
       mAudioChannelAgent = do_CreateInstance("@mozilla.org/audiochannelagent;1", &rv);
       if (!mAudioChannelAgent) {
         return;
       }
       nsCOMPtr<nsIDOMHTMLVideoElement> video = do_QueryObject(this);
       // Use a weak ref so the audio channel agent can't leak |this|.
       if (AUDIO_CHANNEL_NORMAL == mAudioChannelType && video) {
-        mAudioChannelAgent->InitWithVideo(mAudioChannelType, this, true);
+        mAudioChannelAgent->InitWithVideo(OwnerDoc()->GetWindow(),
+                                          mAudioChannelType, this, true);
       } else {
-        mAudioChannelAgent->InitWithWeakCallback(mAudioChannelType, this);
+        mAudioChannelAgent->InitWithWeakCallback(OwnerDoc()->GetWindow(),
+                                                 mAudioChannelType, this);
       }
       mAudioChannelAgent->SetVisibilityState(!OwnerDoc()->Hidden());
     }
 
     if (mPlayingThroughTheAudioChannel) {
       int32_t canPlay;
       mAudioChannelAgent->StartPlaying(&canPlay);
       CanPlayChanged(canPlay);
--- a/content/media/webaudio/AudioDestinationNode.cpp
+++ b/content/media/webaudio/AudioDestinationNode.cpp
@@ -473,17 +473,17 @@ AudioDestinationNode::CreateAudioChannel
 
     case AudioChannel::Publicnotification:
       type = AUDIO_CHANNEL_PUBLICNOTIFICATION;
       break;
 
   }
 
   mAudioChannelAgent = new AudioChannelAgent();
-  mAudioChannelAgent->InitWithWeakCallback(type, this);
+  mAudioChannelAgent->InitWithWeakCallback(GetOwner(), type, this);
 
   nsCOMPtr<nsIDocShell> docshell = do_GetInterface(GetOwner());
   if (docshell) {
     bool isActive = false;
     docshell->GetIsActive(&isActive);
     mAudioChannelAgent->SetVisibilityState(isActive);
   }
 
--- a/dom/audiochannel/AudioChannelAgent.cpp
+++ b/dom/audiochannel/AudioChannelAgent.cpp
@@ -1,19 +1,21 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "AudioChannelAgent.h"
 #include "AudioChannelCommon.h"
 #include "AudioChannelService.h"
+#include "nsIDOMWindow.h"
+#include "nsXULAppAPI.h"
 
 using namespace mozilla::dom;
 
-NS_IMPL_CYCLE_COLLECTION_1(AudioChannelAgent, mCallback)
+NS_IMPL_CYCLE_COLLECTION_2(AudioChannelAgent, mWindow, mCallback)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AudioChannelAgent)
   NS_INTERFACE_MAP_ENTRY(nsIAudioChannelAgent)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(AudioChannelAgent)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(AudioChannelAgent)
@@ -35,44 +37,56 @@ AudioChannelAgent::~AudioChannelAgent()
 
 /* readonly attribute long audioChannelType; */
 NS_IMETHODIMP AudioChannelAgent::GetAudioChannelType(int32_t *aAudioChannelType)
 {
   *aAudioChannelType = mAudioChannelType;
   return NS_OK;
 }
 
-/* boolean init (in long channelType, in nsIAudioChannelAgentCallback callback); */
-NS_IMETHODIMP AudioChannelAgent::Init(int32_t channelType, nsIAudioChannelAgentCallback *callback)
+/* boolean init (in nsIDOMWindow window, in long channelType,
+ *               in nsIAudioChannelAgentCallback callback); */
+NS_IMETHODIMP
+AudioChannelAgent::Init(nsIDOMWindow* aWindow, int32_t aChannelType,
+                        nsIAudioChannelAgentCallback *aCallback)
 {
-  return InitInternal(channelType, callback, /* useWeakRef = */ false);
+  return InitInternal(aWindow, aChannelType, aCallback,
+                      /* useWeakRef = */ false);
 }
 
-/* boolean initWithWeakCallback (in long channelType,
+/* boolean initWithWeakCallback (in nsIDOMWindow window, in long channelType,
  *                               in nsIAudioChannelAgentCallback callback); */
 NS_IMETHODIMP
-AudioChannelAgent::InitWithWeakCallback(int32_t channelType,
-                                        nsIAudioChannelAgentCallback *callback)
+AudioChannelAgent::InitWithWeakCallback(nsIDOMWindow* aWindow,
+                                        int32_t aChannelType,
+                                        nsIAudioChannelAgentCallback *aCallback)
 {
-  return InitInternal(channelType, callback, /* useWeakRef = */ true);
+  return InitInternal(aWindow, aChannelType, aCallback,
+                      /* useWeakRef = */ true);
 }
 
+/* void initWithVideo(in nsIDOMWindow window, in long channelType,
+ *                    in nsIAudioChannelAgentCallback callback, in boolean weak); */
 NS_IMETHODIMP
-AudioChannelAgent::InitWithVideo(int32_t channelType,
-                                 nsIAudioChannelAgentCallback *callback,
+AudioChannelAgent::InitWithVideo(nsIDOMWindow* aWindow, int32_t aChannelType,
+                                 nsIAudioChannelAgentCallback *aCallback,
                                  bool aUseWeakRef)
 {
-  return InitInternal(channelType, callback, aUseWeakRef, true);
+  return InitInternal(aWindow, aChannelType, aCallback, aUseWeakRef,
+                      /* withVideo = */ true);
 }
 
 nsresult
-AudioChannelAgent::InitInternal(int32_t aChannelType,
+AudioChannelAgent::InitInternal(nsIDOMWindow* aWindow, int32_t aChannelType,
                                 nsIAudioChannelAgentCallback *aCallback,
                                 bool aUseWeakRef, bool aWithVideo)
 {
+  // We need the window only for IPC.
+  MOZ_ASSERT(aWindow || XRE_GetProcessType() == GeckoProcessType_Default);
+
   // We syncd the enum of channel type between nsIAudioChannelAgent.idl and
   // AudioChannelCommon.h the same.
   static_assert(static_cast<AudioChannelType>(AUDIO_AGENT_CHANNEL_NORMAL) ==
                 AUDIO_CHANNEL_NORMAL &&
                 static_cast<AudioChannelType>(AUDIO_AGENT_CHANNEL_CONTENT) ==
                 AUDIO_CHANNEL_CONTENT &&
                 static_cast<AudioChannelType>(AUDIO_AGENT_CHANNEL_NOTIFICATION) ==
                 AUDIO_CHANNEL_NOTIFICATION &&
@@ -87,16 +101,17 @@ AudioChannelAgent::InitInternal(int32_t 
                 "Enum of channel on nsIAudioChannelAgent.idl should be the same with AudioChannelCommon.h");
 
   if (mAudioChannelType != AUDIO_AGENT_CHANNEL_ERROR ||
       aChannelType > AUDIO_AGENT_CHANNEL_PUBLICNOTIFICATION ||
       aChannelType < AUDIO_AGENT_CHANNEL_NORMAL) {
     return NS_ERROR_FAILURE;
   }
 
+  mWindow = aWindow;
   mAudioChannelType = aChannelType;
 
   if (aUseWeakRef) {
     mWeakCallback = do_GetWeakReference(aCallback);
   } else {
     mCallback = aCallback;
   }
 
--- a/dom/audiochannel/AudioChannelAgent.h
+++ b/dom/audiochannel/AudioChannelAgent.h
@@ -12,16 +12,18 @@
 #include "nsCOMPtr.h"
 #include "nsWeakPtr.h"
 
 #define NS_AUDIOCHANNELAGENT_CONTRACTID "@mozilla.org/audiochannelagent;1"
 // f27688e2-3dd7-11e2-904e-10bf48d64bd4
 #define NS_AUDIOCHANNELAGENT_CID {0xf27688e2, 0x3dd7, 0x11e2, \
       {0x90, 0x4e, 0x10, 0xbf, 0x48, 0xd6, 0x4b, 0xd4}}
 
+class nsIDOMWindow;
+
 namespace mozilla {
 namespace dom {
 
 /* Header file */
 class AudioChannelAgent : public nsIAudioChannelAgent
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
@@ -34,20 +36,21 @@ public:
 
 private:
   virtual ~AudioChannelAgent();
 
   // Returns mCallback if that's non-null, or otherwise tries to get an
   // nsIAudioChannelAgentCallback out of mWeakCallback.
   already_AddRefed<nsIAudioChannelAgentCallback> GetCallback();
 
-  nsresult InitInternal(int32_t aAudioAgentType,
+  nsresult InitInternal(nsIDOMWindow* aWindow, int32_t aAudioAgentType,
                         nsIAudioChannelAgentCallback* aCallback,
                         bool aUseWeakRef, bool aWithVideo=false);
 
+  nsCOMPtr<nsIDOMWindow> mWindow;
   nsCOMPtr<nsIAudioChannelAgentCallback> mCallback;
   nsWeakPtr mWeakCallback;
   int32_t mAudioChannelType;
   bool mIsRegToService;
   bool mVisible;
   bool mWithVideo;
 };
 
--- a/dom/audiochannel/nsIAudioChannelAgent.idl
+++ b/dom/audiochannel/nsIAudioChannelAgent.idl
@@ -1,15 +1,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
-[function, scriptable, uuid(c7227506-5f8e-11e2-8bb3-10bf48d64bd4)]
+interface nsIDOMWindow;
+
+[function, scriptable, uuid(86975108-cd78-4796-8fc8-6cd777cd6eba)]
 interface nsIAudioChannelAgentCallback : nsISupports
 {
   /**
    * Notified when the playable status of channel is changed.
    *
    * @param canPlay
    *        Callback from agent to notify component of the playable status
    *        of the channel. If canPlay is muted state, component SHOULD stop
@@ -17,21 +19,22 @@ interface nsIAudioChannelAgentCallback :
    *        it is faded state then the volume of media should be reduced.
    */
   void canPlayChanged(in long canPlay);
 };
 
 /**
  * This interface provides an agent for gecko components to participate
  * in the audio channel service. Gecko components are responsible for
- *   1. Indicating what channel type they are using (via the init() member function).
+ *   1. Indicating what channel type they are using (via the init() member
+ *      function).
  *   2. Before playing, checking the playable status of the channel.
  *   3. Notifying the agent when they start/stop using this channel.
  *   4. Notifying the agent of changes to the visibility of the component using
- *       this channel.
+ *      this channel.
  *
  * The agent will invoke a callback to notify Gecko components of
  *   1. Changes to the playable status of this channel.
  */
 
 [scriptable, uuid(86ef883d-9cec-4c04-994f-5de198286e7c)]
 interface nsIAudioChannelAgent : nsISupports
 {
@@ -53,43 +56,50 @@ interface nsIAudioChannelAgent : nsISupp
    * Before init() is called, this returns AUDIO_AGENT_CHANNEL_ERROR.
    */
   readonly attribute long audioChannelType;
 
   /**
    * Initialize the agent with a channel type.
    * Note: This function should only be called once.
    *
+   * @param window
+   *    The window
    * @param channelType
    *    Audio Channel Type listed as above
    * @param callback
-   *    1. Once the playable status changes, agent uses this callback function to notify
-   *       Gecko component.
-   *    2. The callback is allowed to be null. Ex: telephony doesn't need to listen change
-   *       of the playable status.
-   *    3. The AudioChannelAgent keeps a strong reference to the callback object.
+   *    1. Once the playable status changes, agent uses this callback function
+   *       to notify Gecko component.
+   *    2. The callback is allowed to be null. Ex: telephony doesn't need to
+   *       listen change of the playable status.
+   *    3. The AudioChannelAgent keeps a strong reference to the callback
+   *       object.
    */
-  void init(in long channelType, in nsIAudioChannelAgentCallback callback);
+  void init(in nsIDOMWindow window, in long channelType,
+            in nsIAudioChannelAgentCallback callback);
 
   /**
    * This method is just like init(), except the audio channel agent keeps a
    * weak reference to the callback object.
    *
    * In order for this to work, |callback| must implement
    * nsISupportsWeakReference.
    */
-  void initWithWeakCallback(in long channelType, in nsIAudioChannelAgentCallback callback);
+  void initWithWeakCallback(in nsIDOMWindow window, in long channelType,
+                            in nsIAudioChannelAgentCallback callback);
 
   /**
-   * This method is just like init(), and specify the channel is associated with video.
+   * This method is just like init(), and specify the channel is associated
+   * with video.
    *
    * @param weak
    *    true if weak reference should be hold.
    */
-  void initWithVideo(in long channelType, in nsIAudioChannelAgentCallback callback, in boolean weak);
+  void initWithVideo(in nsIDOMWindow window, in long channelType,
+                     in nsIAudioChannelAgentCallback callback, in boolean weak);
 
   /**
    * Notify the agent that we want to start playing.
    * Note: Gecko component SHOULD call this function first then start to
    *          play audio stream only when return value is true.
    *
    *
    * @return
--- a/dom/audiochannel/tests/TestAudioChannelService.cpp
+++ b/dom/audiochannel/tests/TestAudioChannelService.cpp
@@ -46,20 +46,20 @@ public:
       StopPlaying();
     }
   }
 
   nsresult Init(bool video=false)
   {
     nsresult rv = NS_OK;
     if (video) {
-      rv = mAgent->InitWithVideo(mType, this, true);
+      rv = mAgent->InitWithVideo(nullptr, mType, this, true);
     }
     else {
-      rv = mAgent->InitWithWeakCallback(mType, this);
+      rv = mAgent->InitWithWeakCallback(nullptr, mType, this);
     }
     NS_ENSURE_SUCCESS(rv, rv);
 
     return mAgent->SetVisibilityState(false);
   }
 
   nsresult StartPlaying(AudioChannelState *_ret)
   {
--- a/dom/camera/DOMCameraControl.cpp
+++ b/dom/camera/DOMCameraControl.cpp
@@ -694,17 +694,17 @@ nsDOMCameraControl::StartRecording(const
 
   NotifyRecordingStatusChange(NS_LITERAL_STRING("starting"));
 
 #ifdef MOZ_B2G
   if (!mAudioChannelAgent) {
     mAudioChannelAgent = do_CreateInstance("@mozilla.org/audiochannelagent;1");
     if (mAudioChannelAgent) {
       // Camera app will stop recording when it falls to the background, so no callback is necessary.
-      mAudioChannelAgent->Init(AUDIO_CHANNEL_CONTENT, nullptr);
+      mAudioChannelAgent->Init(mWindow, AUDIO_CHANNEL_CONTENT, nullptr);
       // Video recording doesn't output any sound, so it's not necessary to check canPlay.
       int32_t canPlay;
       mAudioChannelAgent->StartPlaying(&canPlay);
     }
   }
 #endif
 
   nsCOMPtr<nsIDOMDOMRequest> request;
--- a/dom/fmradio/FMRadio.cpp
+++ b/dom/fmradio/FMRadio.cpp
@@ -145,16 +145,17 @@ FMRadio::Init(nsPIDOMWindow *aWindow)
   // if preferences doesn't enable AudioChannelService.
   NS_ENSURE_TRUE_VOID(Preferences::GetBool("media.useAudioChannelService"));
 
   nsCOMPtr<nsIAudioChannelAgent> audioChannelAgent =
     do_CreateInstance("@mozilla.org/audiochannelagent;1");
   NS_ENSURE_TRUE_VOID(audioChannelAgent);
 
   audioChannelAgent->InitWithWeakCallback(
+    GetOwner(),
     nsIAudioChannelAgent::AUDIO_AGENT_CHANNEL_CONTENT,
     this);
 
   nsCOMPtr<nsIDocShell> docshell = do_GetInterface(GetOwner());
   NS_ENSURE_TRUE_VOID(docshell);
 
   bool isActive = false;
   docshell->GetIsActive(&isActive);
--- a/dom/system/gonk/AudioManager.cpp
+++ b/dom/system/gonk/AudioManager.cpp
@@ -526,19 +526,19 @@ AudioManager::SetPhoneState(int32_t aSta
     mPhoneAudioAgent = nullptr;
   }
 
   if (aState == PHONE_STATE_IN_CALL || aState == PHONE_STATE_RINGTONE) {
     mPhoneAudioAgent = do_CreateInstance("@mozilla.org/audiochannelagent;1");
     MOZ_ASSERT(mPhoneAudioAgent);
     if (aState == PHONE_STATE_IN_CALL) {
       // Telephony doesn't be paused by any other channels.
-      mPhoneAudioAgent->Init(AUDIO_CHANNEL_TELEPHONY, nullptr);
+      mPhoneAudioAgent->Init(nullptr, AUDIO_CHANNEL_TELEPHONY, nullptr);
     } else {
-      mPhoneAudioAgent->Init(AUDIO_CHANNEL_RINGER, nullptr);
+      mPhoneAudioAgent->Init(nullptr, AUDIO_CHANNEL_RINGER, nullptr);
     }
 
     // Telephony can always play.
     int32_t canPlay;
     mPhoneAudioAgent->StartPlaying(&canPlay);
   }
 
   return NS_OK;