Bug 915507 - Modify class Agent to inherit nsSupportsWeakReference then circular reference between Agent & AudioChannelAgent can be released. r=baku, a=test-only
authorMarco Chen <mchen@mozilla.com>
Tue, 15 Oct 2013 16:55:37 +0800
changeset 161649 ab9457c487435f7a342f50d7550169aceb2b7898
parent 161648 ef0f77bda0be84a1ca353507666b104ccd0fefe4
child 161650 778f774dbde2c641c46e4dca04130e5b77e6fd11
push id407
push userlsblakk@mozilla.com
push dateTue, 03 Dec 2013 03:32:50 +0000
treeherdermozilla-release@babf8c9ebc52 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbaku, test-only
bugs915507
milestone26.0a2
Bug 915507 - Modify class Agent to inherit nsSupportsWeakReference then circular reference between Agent & AudioChannelAgent can be released. r=baku, a=test-only
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;
 }