Simpler approach to bug 523885. r=jst

This commit is contained in:
Ben Newman 2010-03-11 20:42:05 -08:00
Родитель 119924bbe0
Коммит dfbfcd12c0
3 изменённых файлов: 88 добавлений и 31 удалений

Просмотреть файл

@ -4342,13 +4342,17 @@ nsDOMClassInfo::PostCreatePrototype(JSContext * cx, JSObject * proto)
}
nsGlobalWindow *win = nsGlobalWindow::FromSupports(globalNative);
if (win->IsClosedOrClosing()) {
return NS_OK;
}
if (win->IsOuterWindow()) {
// XXXjst: Do security checks here when we remove the security
// checks on the inner window.
win = win->GetCurrentInnerWindowInternal();
if (!win || !(global = win->GetGlobalJSObject())) {
if (!win || !(global = win->GetGlobalJSObject()) ||
win->IsClosedOrClosing()) {
return NS_OK;
}
}

Просмотреть файл

@ -643,6 +643,8 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow)
#ifdef DEBUG
, mSetOpenerWindowCalled(PR_FALSE)
#endif
, mCleanedUp(PR_FALSE)
, mCallCleanUpAfterModalDialogCloses(PR_FALSE)
{
memset(mScriptGlobals, 0, sizeof(mScriptGlobals));
nsLayoutStatics::AddRef();
@ -806,7 +808,7 @@ nsGlobalWindow::~nsGlobalWindow()
NS_ASSERTION(!mArguments, "mArguments wasn't cleaned up properly!");
CleanUp();
CleanUp(PR_TRUE);
#ifdef DEBUG
nsCycleCollector_DEBUG_wasFreed(static_cast<nsIScriptGlobalObject*>(this));
@ -847,8 +849,39 @@ nsGlobalWindow::CleanupCachedXBLHandlers(nsGlobalWindow* aWindow)
}
void
nsGlobalWindow::CleanUp()
nsGlobalWindow::MaybeForgiveSpamCount()
{
if (IsOuterWindow() &&
IsPopupSpamWindow())
{
SetPopupSpamWindow(PR_FALSE);
--gOpenPopupSpamCount;
NS_ASSERTION(gOpenPopupSpamCount >= 0,
"Unbalanced decrement of gOpenPopupSpamCount");
}
}
void
nsGlobalWindow::CleanUp(PRBool aIgnoreModalDialog)
{
if (IsOuterWindow() && !aIgnoreModalDialog) {
nsGlobalWindow* inner = GetCurrentInnerWindowInternal();
nsCOMPtr<nsIDOMModalContentWindow>
dlg(do_QueryInterface(static_cast<nsPIDOMWindow*>(inner)));
if (dlg) {
// The window we're trying to clean up is the outer window of a
// modal dialog. Defer cleanup until the window closes, and let
// ShowModalDialog take care of calling CleanUp.
mCallCleanUpAfterModalDialogCloses = PR_TRUE;
return;
}
}
// Guarantee idempotence.
if (mCleanedUp)
return;
mCleanedUp = PR_TRUE;
mNavigator = nsnull;
mScreen = nsnull;
mHistory = nsnull;
@ -876,7 +909,7 @@ nsGlobalWindow::CleanUp()
nsGlobalWindow *inner = GetCurrentInnerWindowInternal();
if (inner) {
inner->CleanUp();
inner->CleanUp(aIgnoreModalDialog);
}
if (mHasAcceleration) {
@ -2117,15 +2150,6 @@ nsGlobalWindow::SetDocShell(nsIDocShell* aDocShell)
if (aDocShell == mDocShell)
return;
if (!aDocShell && // window is closing
IsOuterWindow() && IsPopupSpamWindow())
{
SetPopupSpamWindow(PR_FALSE);
--gOpenPopupSpamCount;
NS_ASSERTION(gOpenPopupSpamCount >= 0,
"Unbalanced decrement of gOpenPopupSpamCount");
}
PRUint32 lang_id;
nsIScriptContext *langCtx;
// SetDocShell(nsnull) means the window is being torn down. Drop our
@ -2217,7 +2241,10 @@ nsGlobalWindow::SetDocShell(nsIDocShell* aDocShell)
if (mScreen)
mScreen->SetDocShell(aDocShell);
if (mDocShell) {
if (!mDocShell) {
MaybeForgiveSpamCount();
CleanUp(PR_FALSE);
} else {
// tell our member elements about the new browserwindow
if (mMenubar) {
nsCOMPtr<nsIWebBrowserChrome> browserChrome;
@ -5329,9 +5356,10 @@ PostMessageEvent::Run()
NS_ABORT_IF_FALSE(!mSource || mSource->IsOuterWindow(),
"should have been passed an outer window!");
nsRefPtr<nsGlobalWindow> targetWindow =
mTargetWindow->GetCurrentInnerWindowInternal();
if (!targetWindow)
nsRefPtr<nsGlobalWindow> targetWindow;
if (mTargetWindow->IsClosedOrClosing() ||
!(targetWindow = mTargetWindow->GetCurrentInnerWindowInternal()) ||
targetWindow->IsClosedOrClosing())
return NS_OK;
NS_ABORT_IF_FALSE(targetWindow->IsInnerWindow(),
@ -5503,19 +5531,30 @@ nsGlobalWindow::PostMessageMoz(const nsAString& aMessage, const nsAString& aOrig
}
class nsCloseEvent : public nsRunnable {
public:
nsCloseEvent (nsGlobalWindow *aWindow)
nsRefPtr<nsGlobalWindow> mWindow;
nsCloseEvent(nsGlobalWindow *aWindow)
: mWindow(aWindow)
{
{}
public:
static nsresult
PostCloseEvent(nsGlobalWindow* aWindow) {
nsCOMPtr<nsIRunnable> ev = new nsCloseEvent(aWindow);
nsresult rv = NS_DispatchToCurrentThread(ev);
if (NS_SUCCEEDED(rv))
aWindow->MaybeForgiveSpamCount();
return rv;
}
NS_IMETHOD Run() {
if (mWindow)
mWindow->ReallyCloseWindow();
return NS_OK;
}
nsRefPtr<nsGlobalWindow> mWindow;
};
PRBool
@ -5683,8 +5722,7 @@ nsGlobalWindow::FinalClose()
// to really close the window.
rv = NS_ERROR_FAILURE;
if (!nsContentUtils::IsCallerChrome()) {
nsCOMPtr<nsIRunnable> ev = new nsCloseEvent(this);
rv = NS_DispatchToCurrentThread(ev);
rv = nsCloseEvent::PostCloseEvent(this);
}
if (NS_FAILED(rv)) {
@ -5746,7 +5784,7 @@ nsGlobalWindow::ReallyCloseWindow()
}
}
CleanUp();
CleanUp(PR_FALSE);
}
}
@ -6231,8 +6269,9 @@ nsGlobalWindow::ShowModalDialog(const nsAString& aURI, nsIVariant *aArgs,
}
}
nsCOMPtr<nsPIDOMWindow> win(do_QueryInterface(dlgWin));
if (canAccess) {
nsCOMPtr<nsPIDOMWindow> win(do_QueryInterface(dlgWin));
nsPIDOMWindow *inner = win->GetCurrentInnerWindow();
nsCOMPtr<nsIDOMModalContentWindow> dlgInner(do_QueryInterface(inner));
@ -6241,6 +6280,13 @@ nsGlobalWindow::ShowModalDialog(const nsAString& aURI, nsIVariant *aArgs,
dlgInner->GetReturnValue(aRetVal);
}
}
nsRefPtr<nsGlobalWindow> winInternal =
static_cast<nsGlobalWindow*>(win.get());
if (winInternal->mCallCleanUpAfterModalDialogCloses) {
winInternal->mCallCleanUpAfterModalDialogCloses = PR_FALSE;
winInternal->CleanUp(PR_TRUE);
}
}
return NS_OK;
@ -7941,10 +7987,7 @@ nsGlobalWindow::CloseWindow(nsISupports *aWindow)
// Need to post an event for closing, otherwise window and
// presshell etc. may get destroyed while creating frames, bug 338897.
nsCOMPtr<nsIRunnable> ev = new nsCloseEvent(globalWin);
if (ev) {
NS_DispatchToCurrentThread(ev);
}
nsCloseEvent::PostCloseEvent(globalWin);
// else if OOM, better not to close. That might cause a crash.
}

Просмотреть файл

@ -452,10 +452,18 @@ public:
static PRBool DOMWindowDumpEnabled();
void MaybeForgiveSpamCount();
PRBool IsClosedOrClosing() {
return (mIsClosed ||
mInClose ||
mHavePendingClose ||
mCleanedUp);
}
protected:
// Object Management
virtual ~nsGlobalWindow();
void CleanUp();
void CleanUp(PRBool aIgnoreModalDialog);
void ClearControllers();
nsresult FinalClose();
@ -785,6 +793,8 @@ protected:
nsCOMPtr<nsIURI> mLastOpenedURI;
#endif
PRBool mCleanedUp, mCallCleanUpAfterModalDialogCloses;
nsCOMPtr<nsIDOMOfflineResourceList> mApplicationCache;
nsDataHashtable<nsVoidPtrHashKey, void*> mCachedXBLPrototypeHandlers;