Bug 1004458. Maintain modal state on outer windows only instead of relying on forwarding from inner to outer. r=peterv

This commit is contained in:
Boris Zbarsky 2014-05-15 10:26:23 -07:00
parent b2710f328c
commit 45d3ff5181
4 changed files with 20 additions and 19 deletions

View File

@ -8430,7 +8430,7 @@ nsGlobalWindow::ReallyCloseWindow()
void
nsGlobalWindow::EnterModalState()
{
FORWARD_TO_OUTER_VOID(EnterModalState, ());
MOZ_ASSERT(IsOuterWindow(), "Modal state is maintained on outer windows");
// GetScriptableTop, not GetTop, so that EnterModalState works properly with
// <iframe mozbrowser>.
@ -8563,7 +8563,7 @@ private:
void
nsGlobalWindow::LeaveModalState()
{
FORWARD_TO_OUTER_VOID(LeaveModalState, ());
MOZ_ASSERT(IsOuterWindow(), "Modal state is maintained on outer windows");
nsGlobalWindow* topWin = GetScriptableTop();

View File

@ -19,23 +19,19 @@ using namespace mozilla::dom;
****************** nsAutoWindowStateHelper *********************
****************************************************************/
nsAutoWindowStateHelper::nsAutoWindowStateHelper(nsIDOMWindow *aWindow)
nsAutoWindowStateHelper::nsAutoWindowStateHelper(nsPIDOMWindow *aWindow)
: mWindow(aWindow),
mDefaultEnabled(DispatchEventToChrome("DOMWillOpenModalDialog"))
{
nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(aWindow));
if (window) {
window->EnterModalState();
if (mWindow) {
mWindow->EnterModalState();
}
}
nsAutoWindowStateHelper::~nsAutoWindowStateHelper()
{
nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(mWindow));
if (window) {
window->LeaveModalState();
if (mWindow) {
mWindow->LeaveModalState();
}
if (mDefaultEnabled) {
@ -46,14 +42,15 @@ nsAutoWindowStateHelper::~nsAutoWindowStateHelper()
bool
nsAutoWindowStateHelper::DispatchEventToChrome(const char *aEventName)
{
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(mWindow);
if (!window || (window->IsInnerWindow() && !window->IsCurrentInnerWindow())) {
// XXXbz should we skip dispatching the event if the inner changed?
// That is, should we store both the inner and the outer?
if (!mWindow) {
return true;
}
// The functions of nsContentUtils do not provide the required behavior,
// so the following is inlined.
nsIDocument* doc = window->GetExtantDoc();
nsIDocument* doc = mWindow->GetExtantDoc();
if (!doc) {
return true;
}
@ -67,7 +64,7 @@ nsAutoWindowStateHelper::DispatchEventToChrome(const char *aEventName)
event->SetTrusted(true);
event->GetInternalNSEvent()->mFlags.mOnlyChromeDispatch = true;
nsCOMPtr<EventTarget> target = do_QueryInterface(window);
nsCOMPtr<EventTarget> target = do_QueryInterface(mWindow);
bool defaultActionEnabled;
target->DispatchEvent(event, &defaultActionEnabled);
return defaultActionEnabled;

View File

@ -7,18 +7,19 @@
#define __nsAutoWindowStateHelper_h
#include "nsCOMPtr.h"
#include "nsPIDOMWindow.h"
/**
* Helper class for dealing with notifications around opening modal
* windows.
*/
class nsIDOMWindow;
class nsPIDOMWindow;
class nsAutoWindowStateHelper
{
public:
nsAutoWindowStateHelper(nsIDOMWindow *aWindow);
nsAutoWindowStateHelper(nsPIDOMWindow *aWindow);
~nsAutoWindowStateHelper();
bool DefaultEnabled()
@ -29,7 +30,7 @@ public:
protected:
bool DispatchEventToChrome(const char *aEventName);
nsIDOMWindow *mWindow;
nsCOMPtr<nsPIDOMWindow> mWindow;
bool mDefaultEnabled;
};

View File

@ -955,7 +955,10 @@ nsWindowWatcher::OpenWindowInternal(nsIDOMWindow *aParent,
// we're opening a modal content window (the helper classes are
// no-ops if given no window), for chrome dialogs we don't want to
// do any of that (it's done elsewhere for us).
nsAutoWindowStateHelper windowStateHelper(aParent);
// Make sure we maintain the state on an outer window, because
// that's where it lives; inner windows assert if you try to
// maintain the state on them.
nsAutoWindowStateHelper windowStateHelper(parentWindow->GetOuterWindow());
if (!windowStateHelper.DefaultEnabled()) {
// Default to cancel not opening the modal window.