Bug 932309 - Don't null out mDoc in nsGlobalWindow::FreeInnerObjects. r=smaug.
☠☠ backed out by 2137bf09cdc1 ☠ ☠
authorPeter Van der Beken <peterv@propagandism.org>
Wed, 16 Oct 2013 18:11:24 +0200
changeset 153017 a6878c4ee086c844e6b86bb7c2b69a2881c8bc13
parent 153016 989403e34775fbd3258022856609ce019c7ca464
child 153018 e790b3c30e1a62e05079cd99c5caa002218d87b6
push id25566
push userryanvm@gmail.com
push dateFri, 01 Nov 2013 18:40:05 +0000
treeherdermozilla-central@5bb07c1ae9f5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs932309
milestone28.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 932309 - Don't null out mDoc in nsGlobalWindow::FreeInnerObjects. r=smaug.
dom/base/nsGlobalWindow.cpp
dom/base/nsPIDOMWindow.h
dom/gamepad/GamepadService.cpp
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -1504,17 +1504,16 @@ nsGlobalWindow::FreeInnerObjects()
   if (mDoc) {
     // Remember the document's principal and URI.
     mDocumentPrincipal = mDoc->NodePrincipal();
     mDocumentURI = mDoc->GetDocumentURI();
     mDocBaseURI = mDoc->GetDocBaseURI();
   }
 
   // Remove our reference to the document and the document principal.
-  mDoc = nullptr;
   mFocusedNode = nullptr;
 
   if (mApplicationCache) {
     static_cast<nsDOMOfflineResourceList*>(mApplicationCache.get())->Disconnect();
     mApplicationCache = nullptr;
   }
 
   mIndexedDB = nullptr;
@@ -8906,16 +8905,19 @@ nsGlobalWindow::RemoveEventListener(cons
   return NS_OK;
 }
 
 NS_IMPL_REMOVE_SYSTEM_EVENT_LISTENER(nsGlobalWindow)
 
 NS_IMETHODIMP
 nsGlobalWindow::DispatchEvent(nsIDOMEvent* aEvent, bool* aRetVal)
 {
+  MOZ_ASSERT(!IsInnerWindow() || IsCurrentInnerWindow(),
+             "We should only fire events on the current inner window.");
+
   FORWARD_TO_INNER(DispatchEvent, (aEvent, aRetVal), NS_OK);
 
   if (!mDoc) {
     return NS_ERROR_FAILURE;
   }
 
   // Obtain a presentation shell
   nsIPresShell *shell = mDoc->GetShell();
@@ -9035,20 +9037,17 @@ nsGlobalWindow::GetExistingListenerManag
 
   return mListenerManager;
 }
 
 nsIScriptContext*
 nsGlobalWindow::GetContextForEventHandlers(nsresult* aRv)
 {
   *aRv = NS_ERROR_UNEXPECTED;
-  if (IsInnerWindow()) {
-    nsPIDOMWindow* outer = GetOuterWindow();
-    NS_ENSURE_TRUE(outer && outer->GetCurrentInnerWindow() == this, nullptr);
-  }
+  NS_ENSURE_TRUE(!IsInnerWindow() || IsCurrentInnerWindow(), nullptr);
 
   nsIScriptContext* scx;
   if ((scx = GetContext())) {
     *aRv = NS_OK;
     return scx;
   }
   return nullptr;
 }
@@ -10694,34 +10693,38 @@ nsGlobalWindow::Observe(nsISupports* aSu
   }
 
   if (!nsCRT::strcmp(aTopic, OBSERVER_TOPIC_IDLE)) {
     mCurrentlyIdle = true;
     if (IsFrozen()) {
       // need to fire only one idle event while the window is frozen.
       mNotifyIdleObserversIdleOnThaw = true;
       mNotifyIdleObserversActiveOnThaw = false;
-    } else if (mOuterWindow && mOuterWindow->GetCurrentInnerWindow() == this) {
+    } else if (IsCurrentInnerWindow()) {
       HandleIdleActiveEvent();
     }
     return NS_OK;
   }
 
   if (!nsCRT::strcmp(aTopic, OBSERVER_TOPIC_ACTIVE)) {
     mCurrentlyIdle = false;
     if (IsFrozen()) {
       mNotifyIdleObserversActiveOnThaw = true;
       mNotifyIdleObserversIdleOnThaw = false;
-    } else if (mOuterWindow && mOuterWindow->GetCurrentInnerWindow() == this) {
+    } else if (IsCurrentInnerWindow()) {
       ScheduleActiveTimerCallback();
     }
     return NS_OK;
   }
 
-  if (IsInnerWindow() && !nsCRT::strcmp(aTopic, "dom-storage2-changed")) {
+  if (!nsCRT::strcmp(aTopic, "dom-storage2-changed")) {
+    if (!IsInnerWindow() || !IsCurrentInnerWindow()) {
+      return NS_OK;
+    }
+
     nsIPrincipal *principal;
     nsresult rv;
 
     nsCOMPtr<nsIDOMStorageEvent> event = do_QueryInterface(aSubject, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsCOMPtr<nsIDOMStorage> changingStorage;
     rv = event->GetStorageArea(getter_AddRefs(changingStorage));
--- a/dom/base/nsPIDOMWindow.h
+++ b/dom/base/nsPIDOMWindow.h
@@ -322,16 +322,25 @@ public:
     return GetCurrentInnerWindow();
   }
 
   bool IsInnerWindow() const
   {
     return mIsInnerWindow;
   }
 
+  // Returns true if this object has an outer window and it is the current inner
+  // window of that outer. Only call this on inner windows.
+  bool IsCurrentInnerWindow() const
+  {
+    MOZ_ASSERT(IsInnerWindow(),
+               "It doesn't make sense to call this on outer windows.");
+    return mOuterWindow && mOuterWindow->GetCurrentInnerWindow() == this;
+  }
+
   bool IsOuterWindow() const
   {
     return !IsInnerWindow();
   }
 
   virtual bool WouldReuseInnerWindow(nsIDocument *aNewDocument) = 0;
 
   /**
--- a/dom/gamepad/GamepadService.cpp
+++ b/dom/gamepad/GamepadService.cpp
@@ -204,17 +204,17 @@ GamepadService::NewButtonEvent(uint32_t 
   // Hold on to listeners in a separate array because firing events
   // can mutate the mListeners array.
   nsTArray<nsRefPtr<nsGlobalWindow> > listeners(mListeners);
 
   for (uint32_t i = listeners.Length(); i > 0 ; ) {
     --i;
 
     // Only send events to non-background windows
-    if (!listeners[i]->GetOuterWindow() ||
+    if (!listeners[i]->IsCurrentInnerWindow() ||
         listeners[i]->GetOuterWindow()->IsBackground()) {
       continue;
     }
 
     bool first_time = false;
     if (!WindowHasSeenGamepad(listeners[i], aIndex)) {
       // This window hasn't seen this gamepad before, so
       // send a connection event first.
@@ -269,17 +269,17 @@ GamepadService::NewAxisMoveEvent(uint32_
   // Hold on to listeners in a separate array because firing events
   // can mutate the mListeners array.
   nsTArray<nsRefPtr<nsGlobalWindow> > listeners(mListeners);
 
   for (uint32_t i = listeners.Length(); i > 0 ; ) {
     --i;
 
     // Only send events to non-background windows
-    if (!listeners[i]->GetOuterWindow() ||
+    if (!listeners[i]->IsCurrentInnerWindow() ||
         listeners[i]->GetOuterWindow()->IsBackground()) {
       continue;
     }
 
     bool first_time = false;
     if (!WindowHasSeenGamepad(listeners[i], aIndex)) {
       // This window hasn't seen this gamepad before, so
       // send a connection event first.
@@ -335,17 +335,17 @@ GamepadService::NewConnectionEvent(uint3
   // can mutate the mListeners array.
   nsTArray<nsRefPtr<nsGlobalWindow> > listeners(mListeners);
 
   if (aConnected) {
     for (uint32_t i = listeners.Length(); i > 0 ; ) {
       --i;
 
       // Only send events to non-background windows
-      if (!listeners[i]->GetOuterWindow() ||
+      if (!listeners[i]->IsCurrentInnerWindow() ||
           listeners[i]->GetOuterWindow()->IsBackground()) {
         continue;
       }
 
       // We don't fire a connected event here unless the window
       // has seen input from at least one device.
       if (!listeners[i]->HasSeenGamepadInput()) {
         continue;
@@ -520,16 +520,17 @@ GamepadServiceTest::CreateService()
   }
   nsRefPtr<GamepadServiceTest> service = sSingleton;
   return service.forget();
 }
 
 GamepadServiceTest::GamepadServiceTest()
 {
   /* member initializers and constructor code */
+  nsRefPtr<GamepadService> service = GamepadService::GetService();
 }
 
 /* uint32_t addGamepad (in string id, in unsigned long mapping, in unsigned long numButtons, in unsigned long numAxes); */
 NS_IMETHODIMP GamepadServiceTest::AddGamepad(const char* aID,
                                              uint32_t aMapping,
                                              uint32_t aNumButtons,
                                              uint32_t aNumAxes,
                                              uint32_t* aRetval)