Bug 932309 - Don't null out mDoc in nsGlobalWindow::FreeInnerObjects. r=smaug.
authorPeter Van der Beken <peterv@propagandism.org>
Wed, 16 Oct 2013 18:11:24 +0200
changeset 153606 e30f630191b93194f4f94cf91bc05d8c5b7a3d5d
parent 153529 9b23ec089b2447f01ecb658131e213f0f885fa47
child 153607 d4fdcf5f3c04afaef636a1777cf0bc35a6c2e0f9
push id25596
push userryanvm@gmail.com
push dateTue, 05 Nov 2013 20:28:59 +0000
treeherdermozilla-central@8b89e6626298 [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)