Bug 1419144 - Part 7: Move WindowDestroyedEvent into its own file, r=smaug
authorNika Layzell <nika@thelayzells.com>
Fri, 17 Nov 2017 16:40:04 -0500
changeset 393441 5d92f87daafa47a7c6e15a4f52e141bf476eadc6
parent 393440 53bc343fcf1bc043be4ec9fab8a15bf0aabcb23b
child 393442 752c1ff4c3a44f3697b873c9b8329f5d2398d337
push id32960
push usertoros@mozilla.com
push dateThu, 23 Nov 2017 22:29:10 +0000
treeherdermozilla-central@3f5d48c08903 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1419144
milestone59.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 1419144 - Part 7: Move WindowDestroyedEvent into its own file, r=smaug MozReview-Commit-ID: HZDX84ktgiy
dom/base/WindowDestroyedEvent.cpp
dom/base/WindowDestroyedEvent.h
dom/base/moz.build
dom/base/nsGlobalWindow.cpp
new file mode 100644
--- /dev/null
+++ b/dom/base/WindowDestroyedEvent.cpp
@@ -0,0 +1,138 @@
+#include "WindowDestroyedEvent.h"
+
+#include "nsJSUtils.h"
+#include "jsapi.h"              // for JSAutoRequest
+#include "jswrapper.h"
+#include "nsIPrincipal.h"
+#include "nsISupportsPrimitives.h"
+#include "nsIAppStartup.h"
+#include "nsToolkitCompsCID.h"
+#include "nsCOMPtr.h"
+
+namespace mozilla {
+
+// Try to match compartments that are not web content by matching compartments
+// with principals that are either the system principal or an expanded principal.
+// This may not return true for all non-web-content compartments.
+struct BrowserCompartmentMatcher : public js::CompartmentFilter {
+  bool match(JSCompartment* aC) const override
+  {
+    nsCOMPtr<nsIPrincipal> pc = nsJSPrincipals::get(JS_GetCompartmentPrincipals(aC));
+    return nsContentUtils::IsSystemOrExpandedPrincipal(pc);
+  }
+};
+
+WindowDestroyedEvent::WindowDestroyedEvent(nsGlobalWindowInner* aWindow,
+                                           uint64_t aID, const char* aTopic)
+  : mozilla::Runnable("WindowDestroyedEvent")
+  , mID(aID)
+  , mPhase(Phase::Destroying)
+  , mTopic(aTopic)
+  , mIsInnerWindow(true)
+{
+  mWindow = do_GetWeakReference(aWindow);
+}
+
+WindowDestroyedEvent::WindowDestroyedEvent(nsGlobalWindowOuter* aWindow,
+                                           uint64_t aID, const char* aTopic)
+  : mozilla::Runnable("WindowDestroyedEvent")
+  , mID(aID)
+  , mPhase(Phase::Destroying)
+  , mTopic(aTopic)
+  , mIsInnerWindow(false)
+{
+  mWindow = do_GetWeakReference(aWindow);
+}
+
+NS_IMETHODIMP
+WindowDestroyedEvent::Run()
+{
+  AUTO_PROFILER_LABEL("WindowDestroyedEvent::Run", OTHER);
+
+  nsCOMPtr<nsIObserverService> observerService =
+    services::GetObserverService();
+  if (!observerService) {
+    return NS_OK;
+  }
+
+  nsCOMPtr<nsISupportsPRUint64> wrapper =
+    do_CreateInstance(NS_SUPPORTS_PRUINT64_CONTRACTID);
+  if (wrapper) {
+    wrapper->SetData(mID);
+    observerService->NotifyObservers(wrapper, mTopic.get(), nullptr);
+  }
+
+  switch (mPhase) {
+    case Phase::Destroying:
+    {
+      bool skipNukeCrossCompartment = false;
+#ifndef DEBUG
+      nsCOMPtr<nsIAppStartup> appStartup =
+        do_GetService(NS_APPSTARTUP_CONTRACTID);
+
+      if (appStartup) {
+        appStartup->GetShuttingDown(&skipNukeCrossCompartment);
+      }
+#endif
+
+      if (!skipNukeCrossCompartment) {
+        // The compartment nuking phase might be too expensive, so do that
+        // part off of idle dispatch.
+
+        // For the compartment nuking phase, we dispatch either an
+        // inner-window-nuked or an outer-window-nuked notification.
+        // This will allow tests to wait for compartment nuking to happen.
+        if (mTopic.EqualsLiteral("inner-window-destroyed")) {
+          mTopic.AssignLiteral("inner-window-nuked");
+        } else if (mTopic.EqualsLiteral("outer-window-destroyed")) {
+          mTopic.AssignLiteral("outer-window-nuked");
+        }
+        mPhase = Phase::Nuking;
+
+        nsCOMPtr<nsIRunnable> copy(this);
+        NS_IdleDispatchToCurrentThread(copy.forget(), 1000);
+      }
+    }
+    break;
+
+    case Phase::Nuking:
+    {
+      nsCOMPtr<nsISupports> window = do_QueryReferent(mWindow);
+      if (window) {
+        nsGlobalWindowInner* currentInner;
+        if (mIsInnerWindow) {
+          currentInner = nsGlobalWindowInner::FromSupports(window);
+        } else {
+          nsGlobalWindowOuter* outer = nsGlobalWindowOuter::FromSupports(window);
+          currentInner = outer->GetCurrentInnerWindowInternal();
+        }
+        NS_ENSURE_TRUE(currentInner, NS_OK);
+
+        AutoSafeJSContext cx;
+        JS::Rooted<JSObject*> obj(cx, currentInner->FastGetGlobalJSObject());
+        if (obj && !js::IsSystemCompartment(js::GetObjectCompartment(obj))) {
+          JSCompartment* cpt = js::GetObjectCompartment(obj);
+          nsCOMPtr<nsIPrincipal> pc = nsJSPrincipals::get(JS_GetCompartmentPrincipals(cpt));
+
+          if (BasePrincipal::Cast(pc)->AddonPolicy()) {
+            // We want to nuke all references to the add-on compartment.
+            xpc::NukeAllWrappersForCompartment(cx, cpt,
+                                               mIsInnerWindow ? js::DontNukeWindowReferences
+                                                              : js::NukeWindowReferences);
+          } else {
+            // We only want to nuke wrappers for the chrome->content case
+            js::NukeCrossCompartmentWrappers(cx, BrowserCompartmentMatcher(), cpt,
+                                             mIsInnerWindow ? js::DontNukeWindowReferences
+                                                            : js::NukeWindowReferences,
+                                             js::NukeIncomingReferences);
+          }
+        }
+      }
+    }
+    break;
+  }
+
+  return NS_OK;
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/base/WindowDestroyedEvent.h
@@ -0,0 +1,43 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef WindowDestroyedEvent_h
+#define WindowDestroyedEvent_h
+
+#include "nsGlobalWindow.h"
+#include "nsThreadUtils.h"
+#include "nsWeakPtr.h"
+#include "nsString.h"
+
+namespace mozilla {
+
+class WindowDestroyedEvent final : public Runnable
+{
+public:
+  WindowDestroyedEvent(nsGlobalWindowInner* aWindow,
+                       uint64_t aID, const char* aTopic);
+  WindowDestroyedEvent(nsGlobalWindowOuter* aWindow,
+                       uint64_t aID, const char* aTopic);
+
+  enum class Phase
+  {
+    Destroying,
+    Nuking
+  };
+
+  NS_IMETHOD Run() override;
+
+private:
+  uint64_t mID;
+  Phase mPhase;
+  nsCString mTopic;
+  nsWeakPtr mWindow;
+  bool mIsInnerWindow;
+};
+
+} // namespace mozilla
+
+#endif // defined(WindowDestroyedEvent_h)
--- a/dom/base/moz.build
+++ b/dom/base/moz.build
@@ -358,16 +358,17 @@ UNIFIED_SOURCES += [
     'ThirdPartyUtil.cpp',
     'Timeout.cpp',
     'TimeoutBudgetManager.cpp',
     'TimeoutExecutor.cpp',
     'TimeoutHandler.cpp',
     'TimeoutManager.cpp',
     'TreeWalker.cpp',
     'WebKitCSSMatrix.cpp',
+    'WindowDestroyedEvent.cpp',
     'WindowNamedPropertiesHandler.cpp',
     'WindowOrientationObserver.cpp',
     'XPathGenerator.cpp',
 ]
 
 if CONFIG['MOZ_WEBRTC']:
     UNIFIED_SOURCES += [
         'nsDOMDataChannel.cpp',
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -54,16 +54,17 @@
 #include "nsWindowMemoryReporter.h"
 #include "nsWindowSizes.h"
 #include "WindowNamedPropertiesHandler.h"
 #include "nsFrameSelection.h"
 #include "nsNetUtil.h"
 #include "nsVariant.h"
 #include "nsPrintfCString.h"
 #include "mozilla/intl/LocaleService.h"
+#include "WindowDestroyedEvent.h"
 
 // Helper Classes
 #include "nsJSUtils.h"
 #include "jsapi.h"              // for JSAutoRequest
 #include "jswrapper.h"
 #include "nsCharSeparatedTokenizer.h"
 #include "nsReadableUtils.h"
 #include "nsDOMClassInfo.h"
@@ -568,153 +569,16 @@ nsPIDOMWindow<T>::MaybeCreateDoc()
     // Note that |document| here is the same thing as our mDoc, but we
     // don't have to explicitly set the member variable because the docshell
     // has already called SetNewDocument().
     nsCOMPtr<nsIDocument> document = docShell->GetDocument();
     Unused << document;
   }
 }
 
-// Try to match compartments that are not web content by matching compartments
-// with principals that are either the system principal or an expanded principal.
-// This may not return true for all non-web-content compartments.
-struct BrowserCompartmentMatcher : public js::CompartmentFilter {
-  bool match(JSCompartment* aC) const override
-    {
-      nsCOMPtr<nsIPrincipal> pc = nsJSPrincipals::get(JS_GetCompartmentPrincipals(aC));
-      return nsContentUtils::IsSystemOrExpandedPrincipal(pc);
-    }
-};
-
-class WindowDestroyedEvent final : public Runnable
-{
-public:
-  WindowDestroyedEvent(nsGlobalWindowInner* aWindow, uint64_t aID, const char* aTopic)
-    : mozilla::Runnable("WindowDestroyedEvent")
-    , mID(aID)
-    , mPhase(Phase::Destroying)
-    , mTopic(aTopic)
-    , mIsInnerWindow(true)
-  {
-    mWindow = do_GetWeakReference(aWindow);
-  }
-  WindowDestroyedEvent(nsGlobalWindowOuter* aWindow, uint64_t aID, const char* aTopic)
-    : mozilla::Runnable("WindowDestroyedEvent")
-    , mID(aID)
-    , mPhase(Phase::Destroying)
-    , mTopic(aTopic)
-    , mIsInnerWindow(false)
-  {
-    mWindow = do_GetWeakReference(aWindow);
-  }
-
-  enum class Phase
-  {
-    Destroying,
-    Nuking
-  };
-
-  NS_IMETHOD Run() override
-  {
-    AUTO_PROFILER_LABEL("WindowDestroyedEvent::Run", OTHER);
-
-    nsCOMPtr<nsIObserverService> observerService =
-      services::GetObserverService();
-    if (!observerService) {
-      return NS_OK;
-    }
-
-    nsCOMPtr<nsISupportsPRUint64> wrapper =
-      do_CreateInstance(NS_SUPPORTS_PRUINT64_CONTRACTID);
-    if (wrapper) {
-      wrapper->SetData(mID);
-      observerService->NotifyObservers(wrapper, mTopic.get(), nullptr);
-    }
-
-    switch (mPhase) {
-      case Phase::Destroying:
-      {
-        bool skipNukeCrossCompartment = false;
-#ifndef DEBUG
-        nsCOMPtr<nsIAppStartup> appStartup =
-          do_GetService(NS_APPSTARTUP_CONTRACTID);
-
-        if (appStartup) {
-          appStartup->GetShuttingDown(&skipNukeCrossCompartment);
-        }
-#endif
-
-        if (!skipNukeCrossCompartment) {
-          // The compartment nuking phase might be too expensive, so do that
-          // part off of idle dispatch.
-
-          // For the compartment nuking phase, we dispatch either an
-          // inner-window-nuked or an outer-window-nuked notification.
-          // This will allow tests to wait for compartment nuking to happen.
-          if (mTopic.EqualsLiteral("inner-window-destroyed")) {
-            mTopic.AssignLiteral("inner-window-nuked");
-          } else if (mTopic.EqualsLiteral("outer-window-destroyed")) {
-            mTopic.AssignLiteral("outer-window-nuked");
-          }
-          mPhase = Phase::Nuking;
-
-          nsCOMPtr<nsIRunnable> copy(this);
-          NS_IdleDispatchToCurrentThread(copy.forget(), 1000);
-        }
-      }
-      break;
-
-      case Phase::Nuking:
-      {
-        nsCOMPtr<nsISupports> window = do_QueryReferent(mWindow);
-        if (window) {
-          nsGlobalWindowInner* currentInner;
-          if (mIsInnerWindow) {
-            currentInner = nsGlobalWindowInner::FromSupports(window);
-          } else {
-            nsGlobalWindowOuter* outer = nsGlobalWindowOuter::FromSupports(window);
-            currentInner = outer->GetCurrentInnerWindowInternal();
-          }
-          NS_ENSURE_TRUE(currentInner, NS_OK);
-
-          AutoSafeJSContext cx;
-          JS::Rooted<JSObject*> obj(cx, currentInner->FastGetGlobalJSObject());
-          if (obj && !js::IsSystemCompartment(js::GetObjectCompartment(obj))) {
-            JSCompartment* cpt = js::GetObjectCompartment(obj);
-            nsCOMPtr<nsIPrincipal> pc = nsJSPrincipals::get(JS_GetCompartmentPrincipals(cpt));
-
-            if (BasePrincipal::Cast(pc)->AddonPolicy()) {
-              // We want to nuke all references to the add-on compartment.
-              xpc::NukeAllWrappersForCompartment(cx, cpt,
-                                                 mIsInnerWindow ? js::DontNukeWindowReferences
-                                                                : js::NukeWindowReferences);
-            } else {
-              // We only want to nuke wrappers for the chrome->content case
-              js::NukeCrossCompartmentWrappers(cx, BrowserCompartmentMatcher(), cpt,
-                                               mIsInnerWindow ? js::DontNukeWindowReferences
-                                                              : js::NukeWindowReferences,
-                                               js::NukeIncomingReferences);
-            }
-          }
-        }
-      }
-      break;
-    }
-
-    return NS_OK;
-  }
-
-private:
-  uint64_t mID;
-  Phase mPhase;
-  nsCString mTopic;
-  nsWeakPtr mWindow;
-  bool mIsInnerWindow;
-};
-
 template<typename T>
 mozilla::dom::DocGroup*
 nsPIDOMWindow<T>::GetDocGroup() const
 {
   nsIDocument* doc = GetExtantDoc();
   if (doc) {
     return doc->GetDocGroup();
   }