Bug 612551 - Clear appshell observers on xpcom-shutdown. r=blassey a=blocking-fennec
authorJosh Matthews <josh@joshmatthews.net>
Tue, 21 Dec 2010 13:28:45 -0800
changeset 60299 e28ce34157f14821034ca8157fbbd2ad67c27ee0
parent 60298 7a5beb46743f7f0811e5551d93c7a49c1ca739b5
child 60300 a36ba194fd7cdde6c86edceb205f9a67fa704f51
push idunknown
push userunknown
push dateunknown
reviewersblassey, blocking-fennec
bugs612551
milestone2.0b10pre
Bug 612551 - Clear appshell observers on xpcom-shutdown. r=blassey a=blocking-fennec
widget/src/android/nsAppShell.cpp
widget/src/android/nsAppShell.h
--- a/widget/src/android/nsAppShell.cpp
+++ b/widget/src/android/nsAppShell.cpp
@@ -70,16 +70,18 @@ using namespace mozilla;
 PRLogModuleInfo *gWidgetLog = nsnull;
 #endif
 
 nsAccelerometerSystem *gAccel = nsnull;
 nsIGeolocationUpdate *gLocationCallback = nsnull;
 
 nsAppShell *nsAppShell::gAppShell = nsnull;
 
+NS_IMPL_ISUPPORTS_INHERITED1(nsAppShell, nsBaseAppShell, nsIObserver)
+
 nsAppShell::nsAppShell()
     : mQueueLock(nsnull),
       mCondLock(nsnull),
       mQueueCond(nsnull),
       mNumDraws(0)
 {
     gAppShell = this;
 }
@@ -109,19 +111,37 @@ nsAppShell::Init()
     mCondLock = PR_NewLock();
     mQueueCond = PR_NewCondVar(mCondLock);
 
     mObserversHash.Init();
 
     nsresult rv = nsBaseAppShell::Init();
     if (AndroidBridge::Bridge())
         AndroidBridge::Bridge()->NotifyAppShellReady();
+
+    nsCOMPtr<nsIObserverService> obsServ =
+            mozilla::services::GetObserverService();
+    if (obsServ) {
+        obsServ->AddObserver(this, "xpcom-shutdown", PR_FALSE);
+    }
     return rv;
 }
 
+NS_IMETHODIMP
+nsAppShell::Observe(nsISupports* aSubject,
+                    const char* aTopic,
+                    const PRUnichar* aData)
+{
+    if (!strcmp(aTopic, "xpcom-shutdown")) {
+        // We need to ensure no observers stick around after XPCOM shuts down
+        // or we'll see crashes, as the app shell outlives XPConnect.
+        mObserversHash.Clear();
+    }
+    return nsBaseAppShell::Observe(aSubject, aTopic, aData);
+}
 
 void
 nsAppShell::ScheduleNativeEventCallback()
 {
     EVLOG("nsAppShell::ScheduleNativeEventCallback pth: %p thread: %p main: %d", (void*) pthread_self(), (void*) NS_GetCurrentThread(), NS_IsMainThread());
 
     // this is valid to be called from any thread, so do so.
     PostEvent(new AndroidGeckoEvent(AndroidGeckoEvent::NATIVE_POKE));
--- a/widget/src/android/nsAppShell.h
+++ b/widget/src/android/nsAppShell.h
@@ -56,16 +56,19 @@ class nsAppShell :
     public nsBaseAppShell
 {
 public:
     static nsAppShell *gAppShell;
     static mozilla::AndroidGeckoEvent *gEarlyEvent;
 
     nsAppShell();
 
+    NS_DECL_ISUPPORTS_INHERITED
+    NS_DECL_NSIOBSERVER
+
     nsresult Init();
 
     void NotifyNativeEvent();
 
     virtual PRBool ProcessNextNativeEvent(PRBool mayWait);
 
     void PostEvent(mozilla::AndroidGeckoEvent *event);
     void RemoveNextEvent();