Bug 965860 - patch 5 - Console inner-window-destroyed observer, r=khuey
authorAndrea Marchesini <amarchesini@mozilla.com>
Thu, 27 Feb 2014 23:39:17 +0000
changeset 171461 200b26e5e847bd6af20b7e6a98bd03abbc3c68eb
parent 171460 39be88a5ce66f4e806515f607cc9b13352ad3870
child 171462 4d27a920dbf9a44dd3e011bb129a8707c1eceaf2
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
reviewerskhuey
bugs965860
milestone30.0a1
Bug 965860 - patch 5 - Console inner-window-destroyed observer, r=khuey
dom/base/Console.cpp
dom/base/Console.h
dom/base/ConsoleAPIStorage.js
--- a/dom/base/Console.cpp
+++ b/dom/base/Console.cpp
@@ -128,42 +128,86 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(Con
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(Console)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(Console)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Console)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
-  NS_INTERFACE_MAP_ENTRY(nsISupports)
+  NS_INTERFACE_MAP_ENTRY(nsIObserver)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsITimerCallback)
 NS_INTERFACE_MAP_END
 
 Console::Console(nsPIDOMWindow* aWindow)
   : mWindow(aWindow)
   , mOuterID(0)
   , mInnerID(0)
 {
   if (mWindow) {
     MOZ_ASSERT(mWindow->IsInnerWindow());
     mInnerID = mWindow->WindowID();
 
     nsPIDOMWindow* outerWindow = mWindow->GetOuterWindow();
     MOZ_ASSERT(outerWindow);
     mOuterID = outerWindow->WindowID();
   }
 
+  if (NS_IsMainThread()) {
+    nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
+    if (obs) {
+      obs->AddObserver(this, "inner-window-destroyed", false);
+    }
+  }
+
   SetIsDOMBinding();
   mozilla::HoldJSObjects(this);
 }
 
 Console::~Console()
 {
   mozilla::DropJSObjects(this);
 }
 
+NS_IMETHODIMP
+Console::Observe(nsISupports* aSubject, const char* aTopic,
+                 const char16_t* aData)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  if (strcmp(aTopic, "inner-window-destroyed")) {
+    return NS_OK;
+  }
+
+  nsCOMPtr<nsISupportsPRUint64> wrapper = do_QueryInterface(aSubject);
+  NS_ENSURE_TRUE(wrapper, NS_ERROR_FAILURE);
+
+  uint64_t innerID;
+  nsresult rv = wrapper->GetData(&innerID);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  if (innerID == mInnerID) {
+    nsCOMPtr<nsIObserverService> obs =
+      do_GetService("@mozilla.org/observer-service;1");
+    if (obs) {
+      obs->RemoveObserver(this, "inner-window-destroyed");
+    }
+
+    mQueuedCalls.Clear();
+    mTimerRegistry.Clear();
+
+    if (mTimer) {
+      mTimer->Cancel();
+      mTimer = nullptr;
+    }
+  }
+
+  return NS_OK;
+}
+
 JSObject*
 Console::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
 {
   return ConsoleBinding::Wrap(aCx, aScope, this);
 }
 
 #define METHOD(name, string)                                          \
   void                                                                \
--- a/dom/base/Console.h
+++ b/dom/base/Console.h
@@ -7,33 +7,37 @@
 #define mozilla_dom_Console_h
 
 #include "mozilla/dom/BindingDeclarations.h"
 #include "mozilla/dom/UnionConversions.h"
 #include "mozilla/ErrorResult.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsDataHashtable.h"
 #include "nsHashKeys.h"
+#include "nsIObserver.h"
 #include "nsITimer.h"
 #include "nsWrapperCache.h"
 
 class nsIConsoleAPIStorage;
 
 namespace mozilla {
 namespace dom {
 
 class ConsoleCallData;
 
 class Console MOZ_FINAL : public nsITimerCallback
+                        , public nsIObserver
                         , public nsWrapperCache
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Console)
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(Console,
+                                                         nsITimerCallback)
   NS_DECL_NSITIMERCALLBACK
+  NS_DECL_NSIOBSERVER
 
   Console(nsPIDOMWindow* aWindow);
   ~Console();
 
   // WebIDL methods
   nsISupports* GetParentObject() const
   {
     return mWindow;
--- a/dom/base/ConsoleAPIStorage.js
+++ b/dom/base/ConsoleAPIStorage.js
@@ -57,17 +57,17 @@ ConsoleAPIStorageService.prototype = {
   {
     if (aTopic == "xpcom-shutdown") {
       Services.obs.removeObserver(this, "xpcom-shutdown");
       Services.obs.removeObserver(this, "inner-window-destroyed");
       Services.obs.removeObserver(this, "memory-pressure");
     }
     else if (aTopic == "inner-window-destroyed") {
       let innerWindowID = aSubject.QueryInterface(Ci.nsISupportsPRUint64).data;
-      this.clearEvents(innerWindowID);
+      this.clearEvents(innerWindowID + "");
     }
     else if (aTopic == "memory-pressure") {
       this.clearEvents();
     }
   },
 
   /** @private */
   init: function CS_init()