From 78222de2c120bdc922a4271546d5c2ccff4bb260 Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Thu, 26 Apr 2012 14:16:10 +0200 Subject: [PATCH] Bug 640904 - Check for null window globals within PreCreate hooks and assert IsClosedOrClosing(). r=peterv --- dom/base/nsDOMClassInfo.cpp | 61 +++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index 035ddd60380..cf48e02f8e9 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -535,6 +535,8 @@ using mozilla::dom::indexedDB::IDBWrapperCache; #include "DOMError.h" #include "DOMRequest.h" +#include "mozilla/Likely.h" + #undef None // something included above defines this preprocessor symbol, maybe Xlib headers #include "WebGLContext.h" @@ -1968,6 +1970,24 @@ WrapNativeParent(JSContext *cx, JSObject *scope, nsISupports *native, return NS_OK; } +// Helper to handle torn-down inner windows. +static inline nsresult +SetParentToWindow(nsGlobalWindow *win, JSObject **parent) +{ + MOZ_ASSERT(win); + MOZ_ASSERT(win->IsInnerWindow()); + *parent = win->FastGetGlobalJSObject(); + + if (MOZ_UNLIKELY(!*parent)) { + // The only known case where this can happen is when the inner window has + // been torn down. See bug 691178 comment 11. + NS_ASSERTION(win->IsClosedOrClosing(), + "Window shouldn't be null. But we'll deal."); + return NS_ERROR_FAILURE; + } + return NS_OK; +} + // static nsISupports * @@ -4629,8 +4649,9 @@ nsDOMClassInfo::PreCreate(nsISupports *nativeObj, JSContext *cx, } if (piwin->IsOuterWindow()) { - *parentObj = ((nsGlobalWindow *)piwin.get())-> - GetCurrentInnerWindowInternal()->GetGlobalJSObject(); + nsGlobalWindow *win = ((nsGlobalWindow *)piwin.get())-> + GetCurrentInnerWindowInternal(); + return SetParentToWindow(win, parentObj); } return NS_OK; @@ -5165,20 +5186,11 @@ nsWindowSH::PreCreate(nsISupports *nativeObj, JSContext *cx, nsGlobalWindow *win = nsGlobalWindow::FromSupports(nativeObj); NS_ASSERTION(win->IsInnerWindow(), "Should be inner window."); - JSObject *winObj = win->FastGetGlobalJSObject(); - if (!winObj) { - - // See bug 691178 comment 11 for why this is necessary. - if (win->IsClosedOrClosing()) - return NS_ERROR_FAILURE; - - NS_ASSERTION(win->GetOuterWindowInternal()->IsCreatingInnerWindow(), - "should have a JS object by this point"); + // If we're bootstrapping, we don't have a JS object yet. + if (win->GetOuterWindowInternal()->IsCreatingInnerWindow()) return NS_OK; - } - *parentObj = winObj; - return NS_OK; + return SetParentToWindow(win, parentObj); } // This JS class piggybacks on nsHTMLDocumentSH::ReleaseDocument()... @@ -6029,8 +6041,7 @@ nsDOMConstructor::PreCreate(JSContext *cx, JSObject *globalObj, JSObject **paren } nsGlobalWindow *win = static_cast(owner.get()); - *parentObj = win->FastGetGlobalJSObject(); - return NS_OK; + return SetParentToWindow(win, parentObj); } nsresult @@ -7480,7 +7491,7 @@ nsLocationSH::PreCreate(nsISupports *nativeObj, JSContext *cx, } *parentObj = sgo->GetGlobalJSObject(); - return NS_OK; + return *parentObj ? NS_OK : NS_ERROR_FAILURE; } // DOM Navigator helper @@ -7579,14 +7590,7 @@ nsNavigatorSH::PreCreate(nsISupports *nativeObj, JSContext *cx, return NS_ERROR_UNEXPECTED; } - - JSObject *global = win->GetGlobalJSObject(); - - if (global) { - *parentObj = global; - } - - return NS_OK; + return SetParentToWindow(win, parentObj); } // DOM Node helper @@ -7853,7 +7857,7 @@ nsEventTargetSH::PreCreate(nsISupports *nativeObj, JSContext *cx, *parentObj = native_parent ? native_parent->GetGlobalJSObject() : globalObj; - return NS_OK; + return *parentObj ? NS_OK : NS_ERROR_FAILURE; } NS_IMETHODIMP @@ -10005,9 +10009,8 @@ nsHistorySH::PreCreate(nsISupports *nativeObj, JSContext *cx, NS_WARNING("refusing to create history object in the wrong scope"); return NS_ERROR_FAILURE; } - - *parentObj = static_cast(innerWindow.get())->FastGetGlobalJSObject(); - return NS_OK; + return SetParentToWindow(static_cast(innerWindow.get()), + parentObj); } NS_IMETHODIMP