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 179457 dc037e7f4228647e91e91a5d54344a9e6888d580
parent 179456 81db512e365a86035a9c7c9f8da9b9b6744a64aa
child 179458 1f2b13a29a74337aa80c70be3ee2b40c6ecce6f1
push id26624
push userryanvm@gmail.com
push dateMon, 21 Apr 2014 20:17:03 +0000
treeherdermozilla-central@c962bde5ac0b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs992313
milestone31.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 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;