Bug 915507 - Modify class Agent to inherit nsSupportsWeakReference then circular reference between Agent & AudioChannelAgent can be released. r=baku
authorMarco Chen <mchen@mozilla.com>
Tue, 15 Oct 2013 16:55:37 +0800
changeset 164591 c338eea00f79cbfbb2e87989f61b73ba061edd64
parent 164590 44a0355a4ead7966b6fa1dcd49e39427030e143c
child 164592 597eac1e1988b27ace6e27aef16cfdc8ae94b7a9
push id3066
push userakeybl@mozilla.com
push dateMon, 09 Dec 2013 19:58:46 +0000
treeherdermozilla-beta@a31a0dce83aa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbaku
bugs915507
milestone27.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 915507 - Modify class Agent to inherit nsSupportsWeakReference then circular reference between Agent & AudioChannelAgent can be released. r=baku
dom/audiochannel/tests/TestAudioChannelService.cpp
--- a/dom/audiochannel/tests/TestAudioChannelService.cpp
+++ b/dom/audiochannel/tests/TestAudioChannelService.cpp
@@ -4,64 +4,67 @@
 #ifdef XP_WIN
 #include <windows.h>
 #else
 #include <unistd.h>
 #endif
 
 #include "TestHarness.h"
 
-// Work around the fact that the nsWeakPtr, used by AudioChannelService.h, is
-// not exposed to consumers outside the internal API.
-#include "nsIWeakReference.h"
-typedef nsCOMPtr<nsIWeakReference> nsWeakPtr;
-
+#include "nsWeakReference.h"
 #include "AudioChannelService.h"
 #include "AudioChannelAgent.h"
 
 #define TEST_ENSURE_BASE(_test, _msg)       \
   PR_BEGIN_MACRO                            \
-    if (!(_test)) {                           \
+    if (!(_test)) {                         \
       fail(_msg);                           \
       return NS_ERROR_FAILURE;              \
     } else {                                \
       passed(_msg);                         \
     }                                       \
   PR_END_MACRO
 
 using namespace mozilla::dom;
 
-class Agent : public nsIAudioChannelAgentCallback
+class Agent : public nsIAudioChannelAgentCallback,
+              public nsSupportsWeakReference
 {
 public:
   NS_DECL_ISUPPORTS
 
   Agent(AudioChannelType aType)
   : mType(aType)
   , mWaitCallback(false)
   , mRegistered(false)
   , mCanPlay(AUDIO_CHANNEL_STATE_MUTED)
   {
     mAgent = do_CreateInstance("@mozilla.org/audiochannelagent;1");
   }
 
-  virtual ~Agent() {}
+  virtual ~Agent()
+  {
+    if (mRegistered) {
+      StopPlaying();
+    }
+  }
 
   nsresult Init()
   {
-    nsresult rv = mAgent->Init(mType, this);
+    nsresult rv = mAgent->InitWithWeakCallback(mType, this);
     NS_ENSURE_SUCCESS(rv, rv);
 
     return mAgent->SetVisibilityState(false);
   }
 
   nsresult StartPlaying(AudioChannelState *_ret)
   {
-    if (mRegistered)
+    if (mRegistered) {
       StopPlaying();
+    }
 
     nsresult rv = mAgent->StartPlaying((int32_t *)_ret);
     mRegistered = true;
     return rv;
   }
 
   nsresult StopPlaying()
   {
@@ -107,49 +110,49 @@ public:
       if (loop++ == 5) {
         TEST_ENSURE_BASE(false, "GetCanPlay timeout");
       }
     }
     *_ret = mCanPlay;
     return NS_OK;
   }
 
-  nsCOMPtr<AudioChannelAgent> mAgent;
+  nsRefPtr<AudioChannelAgent> mAgent;
   AudioChannelType mType;
   bool mWaitCallback;
   bool mRegistered;
   AudioChannelState mCanPlay;
 };
 
-NS_IMPL_ISUPPORTS1(Agent, nsIAudioChannelAgentCallback)
+NS_IMPL_ISUPPORTS2(Agent, nsIAudioChannelAgentCallback,
+                   nsISupportsWeakReference)
 
 nsresult
 TestDoubleStartPlaying()
 {
-  nsCOMPtr<Agent> agent = new Agent(AUDIO_CHANNEL_NORMAL);
+  nsRefPtr<Agent> agent = new Agent(AUDIO_CHANNEL_NORMAL);
 
   nsresult rv = agent->Init();
   NS_ENSURE_SUCCESS(rv, rv);
 
   AudioChannelState playable;
   rv = agent->mAgent->StartPlaying((int32_t *)&playable);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = agent->mAgent->StartPlaying((int32_t *)&playable);
   TEST_ENSURE_BASE(NS_FAILED(rv),
     "Test0: StartPlaying calling twice must return error");
 
-  agent->mAgent->StopPlaying();
   return NS_OK;
 }
 
 nsresult
 TestOneNormalChannel()
 {
-  nsCOMPtr<Agent> agent = new Agent(AUDIO_CHANNEL_NORMAL);
+  nsRefPtr<Agent> agent = new Agent(AUDIO_CHANNEL_NORMAL);
   nsresult rv = agent->Init();
   NS_ENSURE_SUCCESS(rv, rv);
 
   AudioChannelState playable;
   rv = agent->StartPlaying(&playable);
   NS_ENSURE_SUCCESS(rv, rv);
   TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_MUTED,
     "Test1: A normal channel unvisible agent must be muted");
@@ -157,28 +160,27 @@ TestOneNormalChannel()
   rv = agent->SetVisibilityState(true);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = agent->GetCanPlay(&playable);
   NS_ENSURE_SUCCESS(rv, rv);
   TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_NORMAL,
     "Test1: A normal channel visible agent must be playable");
 
-  agent->StopPlaying();
   return rv;
 }
 
 nsresult
 TestTwoNormalChannels()
 {
-  nsCOMPtr<Agent> agent1 = new Agent(AUDIO_CHANNEL_NORMAL);
+  nsRefPtr<Agent> agent1 = new Agent(AUDIO_CHANNEL_NORMAL);
   nsresult rv = agent1->Init();
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsCOMPtr<Agent> agent2 = new Agent(AUDIO_CHANNEL_NORMAL);
+  nsRefPtr<Agent> agent2 = new Agent(AUDIO_CHANNEL_NORMAL);
   rv = agent2->Init();
   NS_ENSURE_SUCCESS(rv, rv);
 
   AudioChannelState playable;
   rv = agent1->StartPlaying(&playable);
   NS_ENSURE_SUCCESS(rv, rv);
   TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_MUTED,
     "Test2: A normal channel unvisible agent1 must be muted");
@@ -199,29 +201,27 @@ TestTwoNormalChannels()
   TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_NORMAL,
     "Test2: A normal channel visible agent1 must be playable");
 
   rv = agent2->GetCanPlay(&playable);
   NS_ENSURE_SUCCESS(rv, rv);
   TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_NORMAL,
     "Test2: A normal channel visible agent2 must be playable");
 
-  agent1->StopPlaying();
-  agent2->StopPlaying();
   return rv;
 }
 
 nsresult
 TestContentChannels()
 {
-  nsCOMPtr<Agent> agent1 = new Agent(AUDIO_CHANNEL_CONTENT);
+  nsRefPtr<Agent> agent1 = new Agent(AUDIO_CHANNEL_CONTENT);
   nsresult rv = agent1->Init();
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsCOMPtr<Agent> agent2 = new Agent(AUDIO_CHANNEL_CONTENT);
+  nsRefPtr<Agent> agent2 = new Agent(AUDIO_CHANNEL_CONTENT);
   rv = agent2->Init();
   NS_ENSURE_SUCCESS(rv, rv);
 
   // All content channels in the foreground can be allowed to play
   rv = agent1->SetVisibilityState(true);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = agent2->SetVisibilityState(true);
@@ -286,33 +286,31 @@ TestContentChannels()
     "from background state");
 
   rv = agent2->StartPlaying(&playable);
   NS_ENSURE_SUCCESS(rv, rv);
   TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_NORMAL,
     "Test3: A content channel unvisible agent2 must be playable "
     "from background state");
 
-  agent1->StopPlaying();
-  agent2->StopPlaying();
   return rv;
 }
 
 nsresult
 TestFadedState()
 {
-  nsCOMPtr<Agent> normalAgent = new Agent(AUDIO_CHANNEL_NORMAL);
+  nsRefPtr<Agent> normalAgent = new Agent(AUDIO_CHANNEL_NORMAL);
   nsresult rv = normalAgent->Init();
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsCOMPtr<Agent> contentAgent = new Agent(AUDIO_CHANNEL_CONTENT);
+  nsRefPtr<Agent> contentAgent = new Agent(AUDIO_CHANNEL_CONTENT);
   rv = contentAgent->Init();
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsCOMPtr<Agent> notificationAgent = new Agent(AUDIO_CHANNEL_NOTIFICATION);
+  nsRefPtr<Agent> notificationAgent = new Agent(AUDIO_CHANNEL_NOTIFICATION);
   rv = notificationAgent->Init();
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = normalAgent->SetVisibilityState(true);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = contentAgent->SetVisibilityState(true);
   NS_ENSURE_SUCCESS(rv, rv);
@@ -367,49 +365,47 @@ TestFadedState()
   NS_ENSURE_SUCCESS(rv, rv);
   TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_NORMAL,
     "Test4: A content channel unvisible agent must be playable "
     "because of notification channel is stopped");
 
   rv = contentAgent->SetVisibilityState(true);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  normalAgent->StopPlaying();
-  contentAgent->StopPlaying();
   return rv;
 }
 
 nsresult
 TestPriorities()
 {
-  nsCOMPtr<Agent> normalAgent = new Agent(AUDIO_CHANNEL_NORMAL);
+  nsRefPtr<Agent> normalAgent = new Agent(AUDIO_CHANNEL_NORMAL);
   nsresult rv = normalAgent->Init();
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsCOMPtr<Agent> contentAgent = new Agent(AUDIO_CHANNEL_CONTENT);
+  nsRefPtr<Agent> contentAgent = new Agent(AUDIO_CHANNEL_CONTENT);
   rv = contentAgent->Init();
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsCOMPtr<Agent> notificationAgent = new Agent(AUDIO_CHANNEL_NOTIFICATION);
+  nsRefPtr<Agent> notificationAgent = new Agent(AUDIO_CHANNEL_NOTIFICATION);
   rv = notificationAgent->Init();
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsCOMPtr<Agent> alarmAgent = new Agent(AUDIO_CHANNEL_ALARM);
+  nsRefPtr<Agent> alarmAgent = new Agent(AUDIO_CHANNEL_ALARM);
   rv = alarmAgent->Init();
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsCOMPtr<Agent> telephonyAgent = new Agent(AUDIO_CHANNEL_TELEPHONY);
+  nsRefPtr<Agent> telephonyAgent = new Agent(AUDIO_CHANNEL_TELEPHONY);
   rv = telephonyAgent->Init();
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsCOMPtr<Agent> ringerAgent = new Agent(AUDIO_CHANNEL_RINGER);
+  nsRefPtr<Agent> ringerAgent = new Agent(AUDIO_CHANNEL_RINGER);
   rv = ringerAgent->Init();
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsCOMPtr<Agent> pNotificationAgent =
+  nsRefPtr<Agent> pNotificationAgent =
     new Agent(AUDIO_CHANNEL_PUBLICNOTIFICATION);
   rv = pNotificationAgent->Init();
   NS_ENSURE_SUCCESS(rv, rv);
 
   AudioChannelState playable;
 
   rv = normalAgent->StartPlaying(&playable);
   NS_ENSURE_SUCCESS(rv, rv);
@@ -526,44 +522,45 @@ TestPriorities()
   rv = pNotificationAgent->SetVisibilityState(true);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = pNotificationAgent->GetCanPlay(&playable);
   NS_ENSURE_SUCCESS(rv, rv);
   TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_NORMAL,
     "Test5: A pNotification channel visible agent must be playable");
 
-  normalAgent->StopPlaying();
-  contentAgent->StopPlaying();
-  alarmAgent->StopPlaying();
-  telephonyAgent->StopPlaying();
-  ringerAgent->StopPlaying();
-  pNotificationAgent->StopPlaying();
   return rv;
 }
 
 int main(int argc, char** argv)
 {
   ScopedXPCOM xpcom("AudioChannelService");
-  if (xpcom.failed())
+  if (xpcom.failed()) {
     return 1;
+  }
 
-  if (NS_FAILED(TestDoubleStartPlaying()))
+  if (NS_FAILED(TestDoubleStartPlaying())) {
     return 1;
+  }
 
-  if (NS_FAILED(TestOneNormalChannel()))
+  if (NS_FAILED(TestOneNormalChannel())) {
     return 1;
+  }
 
-  if (NS_FAILED(TestTwoNormalChannels()))
+  if (NS_FAILED(TestTwoNormalChannels())) {
     return 1;
+  }
 
-  if (NS_FAILED(TestContentChannels()))
+  if (NS_FAILED(TestContentChannels())) {
     return 1;
+  }
 
-  if (NS_FAILED(TestFadedState()))
+  if (NS_FAILED(TestFadedState())) {
     return 1;
+  }
 
-  if (NS_FAILED(TestPriorities()))
+  if (NS_FAILED(TestPriorities())) {
     return 1;
+  }
 
   return 0;
 }