Bug 784142, assertion and crash calling alert while closing a window, r=smaug
authorNeil Deakin <neil@mozilla.com>
Thu, 30 Aug 2012 15:39:39 -0400
changeset 110231 1d89bc229215fd8477b2068e359f9b9b8c249a18
parent 110230 021eea9c166beb065e84ca77162a91d13cfdc15c
child 110232 2ff5338aa8c608a875d04c3fc7626363572091de
push idunknown
push userunknown
push dateunknown
reviewerssmaug
bugs784142
milestone18.0a1
Bug 784142, assertion and crash calling alert while closing a window, r=smaug
browser/base/content/test/Makefile.in
browser/base/content/test/browser_bug784142.js
dom/base/nsGlobalWindow.cpp
--- a/browser/base/content/test/Makefile.in
+++ b/browser/base/content/test/Makefile.in
@@ -269,16 +269,17 @@ endif
                  browser_social_chatwindow.js \
                  social_panel.html \
                  social_share_image.png \
                  social_sidebar.html \
                  social_chat.html \
                  social_flyout.html \
                  social_window.html \
                  social_worker.js \
+                 browser_bug784142.js \
                  $(NULL)
 
 ifneq (cocoa,$(MOZ_WIDGET_TOOLKIT))
 _BROWSER_FILES += \
 		browser_bug462289.js \
 		$(NULL)
 else
 _BROWSER_FILES += \
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/browser_bug784142.js
@@ -0,0 +1,61 @@
+const windowMediator = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);
+
+function test()
+{
+  waitForExplicitFinish();
+
+  // Need to enable modal dialogs for this test.
+  Services.prefs.setBoolPref("prompts.tab_modal.enabled", false);
+
+  windowMediator.addListener(promptListener);
+
+  // Open a new tab and have that tab open a new window. This is done to
+  // ensure that the new window is a normal browser window.
+  var script = "window.open('data:text/html,<button id=\"button\" onclick=\"window.close(); alert(5);\">Close</button>', null, 'width=200,height=200');";
+  gBrowser.selectedTab = 
+    gBrowser.addTab("data:text/html,<body onload='setTimeout(dotest, 0)'><script>function dotest() { " + script + "}</script></body>");
+}
+
+function windowOpened(win)
+{
+  // Wait for the page in the window to load.
+  waitForFocus(clickButton, win.content);
+}
+
+function clickButton(win)
+{
+  // Set the window in the prompt listener to indicate that the alert window
+  // is now expected to open.
+  promptListener.window = win;
+
+  // Click the Close button in the window.
+  EventUtils.synthesizeMouseAtCenter(win.content.document.getElementById("button"), { }, win);
+
+  windowMediator.removeListener(promptListener);
+  gBrowser.removeTab(gBrowser.selectedTab);
+
+  is(promptListener.message, "window appeared", "modal prompt closer didn't crash");
+  Services.prefs.clearUserPref("prompts.tab_modal.enabled", false);
+  finish();
+}
+
+var promptListener = {
+  onWindowTitleChange: function () {},
+  onOpenWindow: function (win) {
+    let domWin = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow);
+    if (!promptListener.window) {
+      // The first window that is open is the one opened by the new tab.
+      waitForFocus(windowOpened, domWin);
+    }
+    else {
+      // The second window is the alert opened when clicking the Close button in the window
+      ok(promptListener.window.closed, "window has closed");
+
+      // Assign a message so that it can be checked just before the test
+      // finishes to ensure that the alert opened properly.
+      promptListener.message = "window appeared";
+      executeSoon(function () { domWin.close() });
+    }
+  },
+  onCloseWindow: function () {}
+};
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -2513,17 +2513,17 @@ nsGlobalWindow::PreHandleEvent(nsEventCh
 
 bool
 nsGlobalWindow::DialogsAreBlocked(bool *aBeingAbused)
 {
   *aBeingAbused = false;
 
   nsGlobalWindow *topWindow = GetScriptableTop();
   if (!topWindow) {
-    NS_ERROR("DialogsAreBlocked() called without a top window?");
+    NS_ASSERTION(!mDocShell, "DialogsAreBlocked() called without a top window?");
     return true;
   }
 
   topWindow = topWindow->GetCurrentInnerWindowInternal();
   if (!topWindow) {
     return true;
   }
 
@@ -7647,19 +7647,21 @@ nsGlobalWindow::ActivateOrDeactivate(boo
   } else {
     // This is a workaround for the following problem:
     // When a window with an open sheet loses focus, only the sheet window
     // receives the NS_DEACTIVATE event. However, it's not the sheet that
     // should lose the active styling, but the containing top level window.
 
     // widgetListener should be a nsXULWindow
     nsIWidgetListener* listener = topLevelWidget->GetWidgetListener();
-    nsCOMPtr<nsIXULWindow> window = listener->GetXULWindow();
-    nsCOMPtr<nsIInterfaceRequestor> req(do_QueryInterface(window));
-    topLevelWindow = do_GetInterface(req);
+    if (listener) {
+      nsCOMPtr<nsIXULWindow> window = listener->GetXULWindow();
+      nsCOMPtr<nsIInterfaceRequestor> req(do_QueryInterface(window));
+      topLevelWindow = do_GetInterface(req);
+    }
   }
   if (topLevelWindow) {
     nsCOMPtr<nsPIDOMWindow> piWin(do_QueryInterface(topLevelWindow));
     piWin->SetActive(aActivate);
   }
 }
 
 static bool