Bug 1241763: Don't fire dom-window-destroyed on outer windows. r=bz
authorKyle Huey <khuey@kylehuey.com>
Fri, 22 Jan 2016 10:27:54 -0800
changeset 281273 29690442872da3f5955e94b3889958ccb865257a
parent 281272 451f93ef9c141062b7d9ca3e080c1aec47de2bdf
child 281274 682d034c8978e15ee6238ac302a6a80613d99003
push id70731
push userkhuey@mozilla.com
push dateFri, 22 Jan 2016 18:39:03 +0000
treeherdermozilla-inbound@682d034c8978 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs1241763
milestone46.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 1241763: Don't fire dom-window-destroyed on outer windows. r=bz
dom/base/nsGlobalWindow.cpp
dom/base/nsPIDOMWindow.h
dom/base/nsWindowMemoryReporter.cpp
dom/base/nsWindowMemoryReporter.h
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -1617,16 +1617,19 @@ void
 nsGlobalWindow::FreeInnerObjects()
 {
   NS_ASSERTION(IsInnerWindow(), "Don't free inner objects on an outer window");
 
   // Make sure that this is called before we null out the document and
   // other members that the window destroyed observers could
   // re-create.
   NotifyDOMWindowDestroyed(this);
+  if (auto* reporter = nsWindowMemoryReporter::Get()) {
+    reporter->ObserveDOMWindowDetached(this);
+  }
 
   mInnerObjectsFreed = true;
 
   // Kill all of the workers for this window.
   mozilla::dom::workers::CancelWorkersForWindow(this);
 
   ClearAllTimeouts();
 
@@ -2927,18 +2930,19 @@ nsGlobalWindow::DetachFromDocShell()
   for (RefPtr<nsGlobalWindow> inner = (nsGlobalWindow *)PR_LIST_HEAD(this);
        inner != this;
        inner = (nsGlobalWindow*)PR_NEXT_LINK(inner)) {
     NS_ASSERTION(!inner->mOuterWindow || inner->mOuterWindow == this,
                  "bad outer window pointer");
     inner->FreeInnerObjects();
   }
 
-  // Make sure that this is called before we null out the document.
-  NotifyDOMWindowDestroyed(this);
+  if (auto* reporter = nsWindowMemoryReporter::Get()) {
+    reporter->ObserveDOMWindowDetached(this);
+  }
 
   NotifyWindowIDDestroyed("outer-window-destroyed");
 
   nsGlobalWindow *currentInner = GetCurrentInnerWindowInternal();
 
   if (currentInner) {
     NS_ASSERTION(mDoc, "Must have doc!");
 
--- a/dom/base/nsPIDOMWindow.h
+++ b/dom/base/nsPIDOMWindow.h
@@ -12,16 +12,17 @@
 
 #include "nsCOMPtr.h"
 #include "nsAutoPtr.h"
 #include "nsTArray.h"
 #include "mozilla/dom/EventTarget.h"
 #include "js/TypeDecls.h"
 #include "nsRefPtrHashtable.h"
 
+// Only fired for inner windows.
 #define DOM_WINDOW_DESTROYED_TOPIC "dom-window-destroyed"
 #define DOM_WINDOW_FROZEN_TOPIC "dom-window-frozen"
 #define DOM_WINDOW_THAWED_TOPIC "dom-window-thawed"
 
 class nsIArray;
 class nsIContent;
 class nsICSSDeclaration;
 class nsIDocShell;
--- a/dom/base/nsWindowMemoryReporter.cpp
+++ b/dom/base/nsWindowMemoryReporter.cpp
@@ -106,32 +106,34 @@ nsWindowMemoryReporter::Init()
   MOZ_ASSERT(!sWindowReporter);
   sWindowReporter = new nsWindowMemoryReporter();
   ClearOnShutdown(&sWindowReporter);
   RegisterStrongMemoryReporter(sWindowReporter);
   RegisterNonJSSizeOfTab(NonJSSizeOfTab);
 
   nsCOMPtr<nsIObserverService> os = services::GetObserverService();
   if (os) {
-    // DOM_WINDOW_DESTROYED_TOPIC announces what we call window "detachment",
-    // when a window's docshell is set to nullptr.
-    os->AddObserver(sWindowReporter, DOM_WINDOW_DESTROYED_TOPIC,
-                    /* weakRef = */ true);
     os->AddObserver(sWindowReporter, "after-minimize-memory-usage",
                     /* weakRef = */ true);
     os->AddObserver(sWindowReporter, "cycle-collector-begin",
                     /* weakRef = */ true);
     os->AddObserver(sWindowReporter, "cycle-collector-end",
                     /* weakRef = */ true);
   }
 
   RegisterStrongMemoryReporter(new GhostWindowsReporter());
   RegisterGhostWindowsDistinguishedAmount(GhostWindowsReporter::DistinguishedAmount);
 }
 
+/* static */ nsWindowMemoryReporter*
+nsWindowMemoryReporter::Get()
+{
+  return sWindowReporter;
+}
+
 static already_AddRefed<nsIURI>
 GetWindowURI(nsIDOMWindow *aWindow)
 {
   nsCOMPtr<nsPIDOMWindow> pWindow = do_QueryInterface(aWindow);
   NS_ENSURE_TRUE(pWindow, nullptr);
 
   nsCOMPtr<nsIDocument> doc = pWindow->GetExtantDoc();
   nsCOMPtr<nsIURI> uri;
@@ -609,19 +611,17 @@ nsWindowMemoryReporter::GetGhostTimeout(
 {
   return Preferences::GetUint("memory.ghost_window_timeout_seconds", 60);
 }
 
 NS_IMETHODIMP
 nsWindowMemoryReporter::Observe(nsISupports *aSubject, const char *aTopic,
                                 const char16_t *aData)
 {
-  if (!strcmp(aTopic, DOM_WINDOW_DESTROYED_TOPIC)) {
-    ObserveDOMWindowDetached(aSubject);
-  } else if (!strcmp(aTopic, "after-minimize-memory-usage")) {
+  if (!strcmp(aTopic, "after-minimize-memory-usage")) {
     ObserveAfterMinimizeMemoryUsage();
   } else if (!strcmp(aTopic, "cycle-collector-begin")) {
     if (mCheckTimer) {
       mCheckTimerWaitingForCCEnd = true;
       KillCheckTimer();
     }
     mCycleCollectorIsRunning = true;
   } else if (!strcmp(aTopic, "cycle-collector-end")) {
@@ -633,19 +633,19 @@ nsWindowMemoryReporter::Observe(nsISuppo
   } else {
     MOZ_ASSERT(false);
   }
 
   return NS_OK;
 }
 
 void
-nsWindowMemoryReporter::ObserveDOMWindowDetached(nsISupports* aWindow)
+nsWindowMemoryReporter::ObserveDOMWindowDetached(nsGlobalWindow* aWindow)
 {
-  nsWeakPtr weakWindow = do_GetWeakReference(aWindow);
+  nsWeakPtr weakWindow = do_GetWeakReference(static_cast<nsIDOMEventTarget*>(aWindow));
   if (!weakWindow) {
     NS_WARNING("Couldn't take weak reference to a window?");
     return;
   }
 
   mDetachedWindows.Put(weakWindow, TimeStamp());
 
   AsyncCheckForGhostWindows();
--- a/dom/base/nsWindowMemoryReporter.h
+++ b/dom/base/nsWindowMemoryReporter.h
@@ -153,16 +153,19 @@ public:
 #ifdef DEBUG
   /**
    * Unlink all known ghost windows, to enable investigating what caused them
    * to become ghost windows in the first place.
    */
   static void UnlinkGhostWindows();
 #endif
 
+  static nsWindowMemoryReporter* Get();
+  void ObserveDOMWindowDetached(nsGlobalWindow* aWindow);
+
 private:
   ~nsWindowMemoryReporter();
 
   /**
    * nsGhostWindowReporter generates the "ghost-windows" report, which counts
    * the number of ghost windows present.
    */
   class GhostWindowsReporter final : public nsIMemoryReporter
@@ -194,17 +197,16 @@ private:
   nsWindowMemoryReporter();
 
   /**
    * Get the number of seconds for which a window must satisfy ghost criteria
    * (1) and (2) before we deem that it satisfies criterion (3).
    */
   uint32_t GetGhostTimeout();
 
-  void ObserveDOMWindowDetached(nsISupports* aWindow);
   void ObserveAfterMinimizeMemoryUsage();
 
   /**
    * Iterate over all weak window pointers in mDetachedWindows and update our
    * accounting of which windows meet ghost criterion (2).
    *
    * This method also cleans up mDetachedWindows, removing entries for windows
    * which have been destroyed or are no longer detached.