Bug 635552 - Avoid leaking nsAlertsIconObserver objects by using a weak reference. r=karlt
authorJosh Matthews <josh@joshmatthews.net>
Mon, 21 Feb 2011 01:50:57 -0500
changeset 64443 a3b18039e32fe7ca4b662f73fd6d2e6a5cd9823b
parent 64442 4ede7b9b55bca99cb1bed7948c44dcb2f195e4f0
child 64444 db8e95fbcd39b56b7ae7ad0877e774f9e046949b
push idunknown
push userunknown
push dateunknown
reviewerskarlt
bugs635552
milestone2.2a1pre
Bug 635552 - Avoid leaking nsAlertsIconObserver objects by using a weak reference. r=karlt
toolkit/system/gnome/nsAlertsIconListener.cpp
toolkit/system/gnome/nsAlertsIconListener.h
--- a/toolkit/system/gnome/nsAlertsIconListener.cpp
+++ b/toolkit/system/gnome/nsAlertsIconListener.cpp
@@ -70,42 +70,29 @@ static void notify_closed_marshal(GClosu
   NS_ABORT_IF_FALSE(n_param_values >= 1, "No object in params");
 
   nsAlertsIconListener* alert =
     static_cast<nsAlertsIconListener*>(closure->data);
   alert->SendClosed();
   NS_RELEASE(alert);
 }
 
-NS_IMPL_ISUPPORTS3(nsAlertsIconListener, imgIContainerObserver, imgIDecoderObserver, nsIObserver)
+NS_IMPL_ISUPPORTS4(nsAlertsIconListener, imgIContainerObserver,
+                   imgIDecoderObserver, nsIObserver, nsISupportsWeakReference)
 
 nsAlertsIconListener::nsAlertsIconListener()
 : mLoadedFrame(PR_FALSE),
-  mHasQuit(PR_FALSE),
   mNotification(NULL)
 {
-  MOZ_COUNT_CTOR(nsAlertsIconListener);
-
-  nsCOMPtr<nsIObserverService> obsServ =
-      do_GetService("@mozilla.org/observer-service;1");
-  obsServ->AddObserver(this, "quit-application", PR_FALSE);
 }
 
 nsAlertsIconListener::~nsAlertsIconListener()
 {
-  MOZ_COUNT_DTOR(nsAlertsIconListener);
-
   if (mIconRequest)
     mIconRequest->CancelAndForgetObserver(NS_BINDING_ABORTED);
-
-  if (!mHasQuit) {
-    nsCOMPtr<nsIObserverService> obsServ =
-        do_GetService("@mozilla.org/observer-service;1");
-    obsServ->RemoveObserver(this, "quit-application");
-  }
 }
 
 NS_IMETHODIMP
 nsAlertsIconListener::OnStartRequest(imgIRequest* aRequest)
 {
   return NS_OK;
 }
 
@@ -302,17 +289,16 @@ NS_IMETHODIMP
 nsAlertsIconListener::Observe(nsISupports *aSubject, const char *aTopic,
                               const PRUnichar *aData) {
   // We need to close any open notifications upon application exit, otherwise
   // we will leak since libnotify holds a ref for us.
   if (!nsCRT::strcmp(aTopic, "quit-application") && mNotification) {
     g_signal_handler_disconnect(mNotification, mClosureHandler);
     g_object_unref(mNotification);
     mNotification = NULL;
-    mHasQuit = PR_TRUE;
     Release(); // equivalent to NS_RELEASE(this)
   }
   return NS_OK;
 }
 
 nsresult
 nsAlertsIconListener::InitAlertAsync(const nsAString & aImageUrl,
                                      const nsAString & aAlertTitle, 
@@ -359,16 +345,21 @@ nsAlertsIconListener::InitAlertAsync(con
       g_list_foreach(server_caps, (GFunc)g_free, NULL);
       g_list_free(server_caps);
     }
   }
 
   if (!gHasActions && aAlertTextClickable)
     return NS_ERROR_FAILURE; // No good, fallback to XUL
 
+  nsCOMPtr<nsIObserverService> obsServ =
+      do_GetService("@mozilla.org/observer-service;1");
+  if (obsServ)
+    obsServ->AddObserver(this, "quit-application", PR_TRUE);
+
   // Workaround for a libnotify bug - blank titles aren't dealt with
   // properly so we use a space
   if (aAlertTitle.IsEmpty()) {
     mAlertTitle = NS_LITERAL_CSTRING(" ");
   } else {
     mAlertTitle = NS_ConvertUTF16toUTF8(aAlertTitle);
   }
 
--- a/toolkit/system/gnome/nsAlertsIconListener.h
+++ b/toolkit/system/gnome/nsAlertsIconListener.h
@@ -37,24 +37,26 @@
 
 #ifndef nsAlertsIconListener_h__
 #define nsAlertsIconListener_h__
 
 #include "nsCOMPtr.h"
 #include "imgIDecoderObserver.h"
 #include "nsStringAPI.h"
 #include "nsIObserver.h"
+#include "nsWeakReference.h"
 
 #include <gdk-pixbuf/gdk-pixbuf.h>
 #include <libnotify/notify.h>
 
 class imgIRequest;
 
 class nsAlertsIconListener : public imgIDecoderObserver,
-                             public nsIObserver
+                             public nsIObserver,
+                             public nsSupportsWeakReference
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_IMGICONTAINEROBSERVER
   NS_DECL_IMGIDECODEROBSERVER
   NS_DECL_NSIOBSERVER
 
   nsAlertsIconListener();
@@ -75,17 +77,16 @@ protected:
   nsCString mAlertTitle;
   nsCString mAlertText;
 
   nsCOMPtr<nsIObserver> mAlertListener;
   nsString mAlertCookie;
 
   PRPackedBool mLoadedFrame;
   PRPackedBool mAlertHasAction;
-  PRPackedBool mHasQuit;
 
   NotifyNotification* mNotification;
   gulong mClosureHandler;
 
   nsresult StartRequest(const nsAString & aImageUrl);
   nsresult ShowAlert(GdkPixbuf* aPixbuf);
 };