Bug 992313 - Keep track of registered idle observers so we don't call into a freed pointer. r=roc
authorReuben Morais <reuben.morais@gmail.com>
Mon, 21 Apr 2014 14:18:53 -0300
changeset 179863 dc037e7f4228647e91e91a5d54344a9e6888d580
parent 179862 81db512e365a86035a9c7c9f8da9b9b6744a64aa
child 179864 1f2b13a29a74337aa80c70be3ee2b40c6ecce6f1
push id272
push userpvanderbeken@mozilla.com
push dateMon, 05 May 2014 16:31:18 +0000
reviewersroc
bugs992313
milestone31.0a1
Bug 992313 - Keep track of registered idle observers so we don't call into a freed pointer. r=roc
dom/ipc/ContentChild.cpp
dom/ipc/ContentChild.h
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -46,17 +46,16 @@
 
 #include "nsIConsoleListener.h"
 #include "nsIIPCBackgroundChildCreateCallback.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIMemoryReporter.h"
 #include "nsIMemoryInfoDumper.h"
 #include "nsIMutable.h"
 #include "nsIObserverService.h"
-#include "nsIObserver.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsServiceManagerUtils.h"
 #include "nsStyleSheetService.h"
 #include "nsXULAppAPI.h"
 #include "nsIScriptError.h"
 #include "nsIConsoleService.h"
 #include "nsJSEnvironment.h"
 #include "SandboxHal.h"
@@ -1277,16 +1276,18 @@ ContentChild::ActorDestroy(ActorDestroyR
 #endif
 
     if (sFirstIdleTask) {
         sFirstIdleTask->Cancel();
     }
 
     mAlertObservers.Clear();
 
+    mIdleObservers.Clear();
+
     nsCOMPtr<nsIConsoleService> svc(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
     if (svc) {
         svc->UnregisterListener(mConsoleListener);
         mConsoleListener->mChild = nullptr;
     }
 
     XRE_ShutdownChildProcess();
 }
@@ -1655,33 +1656,39 @@ ContentChild::RecvNotifyPhoneStateChange
 
 void
 ContentChild::AddIdleObserver(nsIObserver* aObserver, uint32_t aIdleTimeInS)
 {
   MOZ_ASSERT(aObserver, "null idle observer");
   // Make sure aObserver isn't released while we wait for the parent
   aObserver->AddRef();
   SendAddIdleObserver(reinterpret_cast<uint64_t>(aObserver), aIdleTimeInS);
+  mIdleObservers.PutEntry(aObserver);
 }
 
 void
 ContentChild::RemoveIdleObserver(nsIObserver* aObserver, uint32_t aIdleTimeInS)
 {
   MOZ_ASSERT(aObserver, "null idle observer");
   SendRemoveIdleObserver(reinterpret_cast<uint64_t>(aObserver), aIdleTimeInS);
   aObserver->Release();
+  mIdleObservers.RemoveEntry(aObserver);
 }
 
 bool
 ContentChild::RecvNotifyIdleObserver(const uint64_t& aObserver,
                                      const nsCString& aTopic,
                                      const nsString& aTimeStr)
 {
   nsIObserver* observer = reinterpret_cast<nsIObserver*>(aObserver);
-  observer->Observe(nullptr, aTopic.get(), aTimeStr.get());
+  if (mIdleObservers.Contains(observer)) {
+    observer->Observe(nullptr, aTopic.get(), aTimeStr.get());
+  } else {
+    NS_WARNING("Received notification for an idle observer that was removed.");
+  }
   return true;
 }
 
 bool
 ContentChild::RecvLoadAndRegisterSheet(const URIParams& aURI, const uint32_t& aType)
 {
     nsCOMPtr<nsIURI> uri = DeserializeURI(aURI);
     if (!uri) {
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -5,18 +5,23 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_ContentChild_h
 #define mozilla_dom_ContentChild_h
 
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/PContentChild.h"
 #include "mozilla/dom/ipc/Blob.h"
+#include "nsHashKeys.h"
+#include "nsIObserver.h"
+#include "nsTHashtable.h"
+
 #include "nsWeakPtr.h"
 
+
 struct ChromePackage;
 class nsIDOMBlob;
 class nsIObserver;
 struct ResourceMapping;
 struct OverrideMapping;
 
 namespace mozilla {
 
@@ -293,16 +298,18 @@ private:
      * Exit *now*.  Do not shut down XPCOM, do not pass Go, do not run
      * static destructors, do not collect $200.
      */
     MOZ_NORETURN void QuickExit();
 
     InfallibleTArray<nsAutoPtr<AlertObserver> > mAlertObservers;
     nsRefPtr<ConsoleListener> mConsoleListener;
 
+    nsTHashtable<nsPtrHashKey<nsIObserver>> mIdleObservers;
+
     /**
      * An ID unique to the process containing our corresponding
      * content parent.
      *
      * We expect our content parent to set this ID immediately after opening a
      * channel to us.
      */
     uint64_t mID;