From 591866c51a0918f42f850e8307d2792bbe4c7d87 Mon Sep 17 00:00:00 2001 From: Peter Van der Beken Date: Tue, 30 Aug 2011 16:22:01 +0200 Subject: [PATCH] Fix for bug 669096 (Injecting function from chrome extends the lifetime of navigated-away inner window). r=mrbkap. --HG-- extra : rebase_source : 3375132c3e507e09dd79e63d277769090040f6bf --- dom/base/nsGlobalWindow.cpp | 41 +++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 15e1fcaace1b..f1bb6318cd12 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -1817,6 +1817,34 @@ WindowStateHolder::~WindowStateHolder() NS_IMPL_ISUPPORTS1(WindowStateHolder, WindowStateHolder) + +struct ReparentWaiverClosure +{ + JSContext *mCx; + JSObject *mNewInner; +}; + +static JSDHashOperator +ReparentWaiverWrappers(JSDHashTable *table, JSDHashEntryHdr *hdr, + uint32 number, void *arg) +{ + ReparentWaiverClosure *closure = static_cast(arg); + JSObject *value = static_cast(hdr)->value; + + // We reparent wrappers that have as their parent an inner window whose + // outer has the new inner window as its current inner. + JSObject *parent = JS_GetParent(closure->mCx, value); + JSObject *outer = JS_ObjectToOuterObject(closure->mCx, parent); + if (outer) { + JSObject *inner = JS_ObjectToInnerObject(closure->mCx, outer); + if (inner == closure->mNewInner && inner != parent) + JS_SetParent(closure->mCx, value, closure->mNewInner); + } else { + JS_ClearPendingException(closure->mCx); + } + return JS_DHASH_NEXT; +} + nsresult nsGlobalWindow::SetNewDocument(nsIDocument* aDocument, nsISupports* aState, @@ -2163,6 +2191,19 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument, JS_SetParent(cx, mJSObject, newInnerWindow->mJSObject); mContext->SetOuterObject(mJSObject); + + JSCompartment *compartment = js::GetObjectCompartment(mJSObject); + xpc::CompartmentPrivate *priv = + static_cast(JS_GetCompartmentPrivate(cx, compartment)); + if (priv && priv->waiverWrapperMap) { + NS_ASSERTION(!JS_IsExceptionPending(cx), + "We might overwrite a pending exception!"); + ReparentWaiverClosure closure = { + cx, + newInnerWindow->mJSObject + }; + priv->waiverWrapperMap->Enumerate(ReparentWaiverWrappers, &closure); + } } }