diff --git a/mozilla/content/base/public/nsIDocument.h b/mozilla/content/base/public/nsIDocument.h index 817eb4f6ec1..34dd8c85478 100644 --- a/mozilla/content/base/public/nsIDocument.h +++ b/mozilla/content/base/public/nsIDocument.h @@ -461,9 +461,10 @@ public: virtual nsIHTMLCSSStyleSheet* GetInlineStyleSheet() const = 0; /** - * Set the object from which a document can get a script context. - * This is the context within which all scripts (during document - * creation and during event handling) will run. + * Get/set the object from which a document can get a script context + * and scope. This is the context within which all scripts (during + * document creation and during event handling) will run. Note that + * this is the *inner* window object. */ virtual nsIScriptGlobalObject* GetScriptGlobalObject() const = 0; virtual void SetScriptGlobalObject(nsIScriptGlobalObject* aGlobalObject) = 0; diff --git a/mozilla/content/base/src/nsDocument.cpp b/mozilla/content/base/src/nsDocument.cpp index 0a2567b87d0..f7947965ee0 100644 --- a/mozilla/content/base/src/nsDocument.cpp +++ b/mozilla/content/base/src/nsDocument.cpp @@ -96,6 +96,7 @@ #include "nsIPrivateDOMImplementation.h" #include "nsIDOMWindowInternal.h" +#include "nsPIDOMWindow.h" #include "nsIDOMElement.h" #include "nsIBoxObject.h" @@ -2914,11 +2915,19 @@ nsDocument::CreateTreeWalker(nsIDOMNode *aRoot, NS_IMETHODIMP nsDocument::GetDefaultView(nsIDOMAbstractView** aDefaultView) { - if (mScriptGlobalObject) { - return CallQueryInterface(mScriptGlobalObject, aDefaultView); + *aDefaultView = nsnull; + + nsCOMPtr win(do_QueryInterface(mScriptGlobalObject)); + + if (win) { + // The default view is our outer window. + if (!win->IsInnerWindow()) { + return NS_ERROR_UNEXPECTED; + } + + return CallQueryInterface(win->GetOuterWindow(), aDefaultView); } - *aDefaultView = nsnull; return NS_OK; } diff --git a/mozilla/content/base/src/nsDocument.h b/mozilla/content/base/src/nsDocument.h index e70793fca14..0b9a8f10a8c 100644 --- a/mozilla/content/base/src/nsDocument.h +++ b/mozilla/content/base/src/nsDocument.h @@ -172,7 +172,6 @@ public: protected: PRInt32 mLength; nsIDocument* mDocument; - void* mScriptObject; }; class nsOnloadBlocker : public nsIRequest @@ -616,7 +615,12 @@ protected: // Basically always has at least 1 entry nsAutoVoidArray mObservers; + + // The document's script global object, the object from which the + // document can get its script context and scope. This is the + // *inner* window object. nsCOMPtr mScriptGlobalObject; + nsCOMPtr mListenerManager; nsCOMPtr mDOMStyleSheets; nsCOMPtr mScriptLoader; diff --git a/mozilla/content/base/src/nsScriptLoader.cpp b/mozilla/content/base/src/nsScriptLoader.cpp index 55f66a26de2..563e2e40f5e 100644 --- a/mozilla/content/base/src/nsScriptLoader.cpp +++ b/mozilla/content/base/src/nsScriptLoader.cpp @@ -749,9 +749,9 @@ nsScriptLoader::EvaluateScript(nsScriptLoadRequest* aRequest, mCurrentScript = aRequest->mElement; PRBool isUndefined; - context->EvaluateString(aScript, nsnull, principal, url.get(), - aRequest->mLineNo, aRequest->mJSVersion, nsnull, - &isUndefined); + context->EvaluateString(aScript, globalObject->GetGlobalJSObject(), + principal, url.get(), aRequest->mLineNo, + aRequest->mJSVersion, nsnull, &isUndefined); // Put the old script back in case it wants to do anything else. mCurrentScript = oldCurrent; diff --git a/mozilla/content/events/public/nsIEventListenerManager.h b/mozilla/content/events/public/nsIEventListenerManager.h index 7b42fbd85e9..3a029bfd3e7 100644 --- a/mozilla/content/events/public/nsIEventListenerManager.h +++ b/mozilla/content/events/public/nsIEventListenerManager.h @@ -48,6 +48,7 @@ class nsIScriptContext; class nsIDOMEventTarget; class nsIDOMEventGroup; class nsIAtom; +struct JSObject; /* * Event listener manager interface. @@ -115,6 +116,7 @@ public: * @param the name of an event listener */ NS_IMETHOD RegisterScriptEventListener(nsIScriptContext *aContext, + JSObject *aScopeObject, nsISupports *aObject, nsIAtom* aName) = 0; @@ -123,6 +125,7 @@ public: * script object for a given event type. * @param an event listener */ NS_IMETHOD CompileScriptEventListener(nsIScriptContext *aContext, + JSObject *aScopeObject, nsISupports *aObject, nsIAtom* aName, PRBool *aDidCompile) = 0; diff --git a/mozilla/content/events/src/nsEventListenerManager.cpp b/mozilla/content/events/src/nsEventListenerManager.cpp index 6c98ea3d711..4e532e22f26 100644 --- a/mozilla/content/events/src/nsEventListenerManager.cpp +++ b/mozilla/content/events/src/nsEventListenerManager.cpp @@ -88,7 +88,6 @@ #include "nsIPresShell.h" #include "nsMutationEvent.h" #include "nsIXPConnect.h" -#include "nsIDOMScriptObjectFactory.h" #include "nsDOMCID.h" #include "nsIScriptObjectOwner.h" // for nsIScriptEventHandlerOwner #include "nsIClassInfo.h" @@ -1102,7 +1101,8 @@ nsEventListenerManager::FindJSEventListener(EventArrayType aType) } nsresult -nsEventListenerManager::SetJSEventListener(nsIScriptContext *aContext, +nsEventListenerManager::SetJSEventListener(nsIScriptContext *aContext, + JSObject *aScopeObject, nsISupports *aObject, nsIAtom* aName, PRBool aIsString, @@ -1121,13 +1121,9 @@ nsEventListenerManager::SetJSEventListener(nsIScriptContext *aContext, if (nsnull == ls) { // If we didn't find a script listener or no listeners existed // create and add a new one. - nsCOMPtr factory = - do_GetService(kDOMScriptObjectFactoryCID); - NS_ENSURE_TRUE(factory, NS_ERROR_FAILURE); - nsCOMPtr scriptListener; - rv = factory->NewJSEventListener(aContext, aObject, - getter_AddRefs(scriptListener)); + rv = NS_NewJSEventListener(aContext, aScopeObject, aObject, + getter_AddRefs(scriptListener)); if (NS_SUCCEEDED(rv)) { AddEventListener(scriptListener, arrayType, NS_EVENT_BITS_NONE, nsnull, NS_EVENT_FLAG_BUBBLE | NS_PRIV_EVENT_FLAG_SCRIPT, nsnull); @@ -1172,6 +1168,8 @@ nsEventListenerManager::AddScriptEventListener(nsISupports *aObject, nsISupports *objiSupp = aObject; + JSObject *scope = nsnull; + if (content) { // Try to get context from doc doc = content->GetOwnerDoc(); @@ -1179,6 +1177,7 @@ nsEventListenerManager::AddScriptEventListener(nsISupports *aObject, if (doc && (global = doc->GetScriptGlobalObject())) { context = global->GetContext(); + scope = global->GetGlobalJSObject(); } } else { nsCOMPtr win(do_QueryInterface(aObject)); @@ -1199,11 +1198,13 @@ nsEventListenerManager::AddScriptEventListener(nsISupports *aObject, } if (global) { context = global->GetContext(); + scope = global->GetGlobalJSObject(); } } if (!context) { - // Get JSContext from stack. + // Get JSContext from stack, or use the safe context (and hidden + // window global) if no JS is running. nsCOMPtr stack = do_GetService("@mozilla.org/js/xpc/ContextStack;1"); NS_ENSURE_TRUE(stack, NS_ERROR_FAILURE); @@ -1216,6 +1217,13 @@ nsEventListenerManager::AddScriptEventListener(nsISupports *aObject, context = nsJSUtils::GetDynamicScriptContext(cx); NS_ENSURE_TRUE(context, NS_ERROR_FAILURE); + + scope = ::JS_GetGlobalObject(cx); + } else if (!scope) { + NS_ERROR("Context reachable, but no scope reachable in " + "AddScriptEventListener()!"); + + return NS_ERROR_NOT_AVAILABLE; } nsresult rv; @@ -1224,8 +1232,7 @@ nsEventListenerManager::AddScriptEventListener(nsISupports *aObject, JSContext *cx = (JSContext *)context->GetNativeContext(); nsCOMPtr holder; - rv = nsContentUtils::XPConnect()->WrapNative(cx, ::JS_GetGlobalObject(cx), - aObject, + rv = nsContentUtils::XPConnect()->WrapNative(cx, scope, aObject, NS_GET_IID(nsISupports), getter_AddRefs(holder)); NS_ENSURE_SUCCESS(rv, rv); @@ -1297,7 +1304,7 @@ nsEventListenerManager::AddScriptEventListener(nsISupports *aObject, } } - return SetJSEventListener(context, objiSupp, aName, aDeferCompilation, + return SetJSEventListener(context, scope, objiSupp, aName, aDeferCompilation, aPermitUntrustedEvents); } @@ -1335,6 +1342,7 @@ nsEventListenerManager::sAddListenerID = JSVAL_VOID; NS_IMETHODIMP nsEventListenerManager::RegisterScriptEventListener(nsIScriptContext *aContext, + JSObject *aScopeObject, nsISupports *aObject, nsIAtom *aName) { @@ -1357,8 +1365,8 @@ nsEventListenerManager::RegisterScriptEventListener(nsIScriptContext *aContext, nsCOMPtr holder; rv = nsContentUtils::XPConnect()-> - WrapNative(current_cx, ::JS_GetGlobalObject(current_cx), aObject, - NS_GET_IID(nsISupports), getter_AddRefs(holder)); + WrapNative(current_cx, aScopeObject, aObject, NS_GET_IID(nsISupports), + getter_AddRefs(holder)); NS_ENSURE_SUCCESS(rv, rv); // Since JSEventListeners only have a raw nsISupports pointer, it's @@ -1372,11 +1380,11 @@ nsEventListenerManager::RegisterScriptEventListener(nsIScriptContext *aContext, rv = holder->GetJSObject(&jsobj); NS_ENSURE_SUCCESS(rv, rv); - nsCOMPtr classInfo = do_QueryInterface(aObject); - - if (sAddListenerID == JSVAL_VOID && cx) { - sAddListenerID = - STRING_TO_JSVAL(::JS_InternString(cx, "addEventListener")); + if (cx) { + if (sAddListenerID == JSVAL_VOID) { + sAddListenerID = + STRING_TO_JSVAL(::JS_InternString(cx, "addEventListener")); + } rv = nsContentUtils::GetSecurityManager()-> CheckPropertyAccess(cx, jsobj, @@ -1391,12 +1399,13 @@ nsEventListenerManager::RegisterScriptEventListener(nsIScriptContext *aContext, // Untrusted events are always permitted for non-chrome script // handlers. - return SetJSEventListener(aContext, wrapper->Native(), aName, PR_FALSE, - !nsContentUtils::IsCallerChrome()); + return SetJSEventListener(aContext, aScopeObject, wrapper->Native(), aName, + PR_FALSE, !nsContentUtils::IsCallerChrome()); } nsresult nsEventListenerManager::CompileScriptEventListener(nsIScriptContext *aContext, + JSObject *aScopeObject, nsISupports *aObject, nsIAtom *aName, PRBool *aDidCompile) @@ -1419,7 +1428,8 @@ nsEventListenerManager::CompileScriptEventListener(nsIScriptContext *aContext, } if (ls->mHandlerIsString & subType) { - rv = CompileEventHandlerInternal(aContext, aObject, aName, ls, /*XXX fixme*/nsnull, subType); + rv = CompileEventHandlerInternal(aContext, aScopeObject, aObject, aName, + ls, /*XXX fixme*/nsnull, subType); } // Set *aDidCompile to true even if we didn't really compile @@ -1434,6 +1444,7 @@ nsEventListenerManager::CompileScriptEventListener(nsIScriptContext *aContext, nsresult nsEventListenerManager::CompileEventHandlerInternal(nsIScriptContext *aContext, + JSObject *aScopeObject, nsISupports *aObject, nsIAtom *aName, nsListenerStruct *aListenerStruct, @@ -1445,9 +1456,7 @@ nsEventListenerManager::CompileEventHandlerInternal(nsIScriptContext *aContext, JSContext *cx = (JSContext *)aContext->GetNativeContext(); nsCOMPtr holder; - result = nsContentUtils::XPConnect()->WrapNative(cx, - ::JS_GetGlobalObject(cx), - aObject, + result = nsContentUtils::XPConnect()->WrapNative(cx, aScopeObject, aObject, NS_GET_IID(nsISupports), getter_AddRefs(holder)); NS_ENSURE_SUCCESS(result, result); @@ -1561,6 +1570,7 @@ nsEventListenerManager::HandleEventSubType(nsListenerStruct* aListenerStruct, nsCOMPtr atom = do_GetAtom(NS_LITERAL_STRING("on") + eventString); result = CompileEventHandlerInternal(jslistener->GetEventContext(), + jslistener->GetEventScope(), jslistener->GetEventTarget(), atom, aListenerStruct, aCurrentTarget, @@ -2141,7 +2151,7 @@ nsEventListenerManager::FixContextMenuEvent(nsPresContext* aPresContext, currentTarget = do_QueryInterface(currentFocus); nsCOMPtr pEvent(do_QueryInterface(*aDOMEvent)); - pEvent->SetTarget (currentTarget); + pEvent->SetTarget(currentTarget); } } diff --git a/mozilla/content/events/src/nsEventListenerManager.h b/mozilla/content/events/src/nsEventListenerManager.h index 335db0e0e03..644bdd72edf 100644 --- a/mozilla/content/events/src/nsEventListenerManager.h +++ b/mozilla/content/events/src/nsEventListenerManager.h @@ -130,10 +130,12 @@ public: PRBool aDeferCompilation, PRBool aPermitUntrustedEvents); NS_IMETHOD RegisterScriptEventListener(nsIScriptContext *aContext, + JSObject *aScopeObject, nsISupports *aObject, nsIAtom* aName); NS_IMETHOD RemoveScriptEventListener(nsIAtom *aName); NS_IMETHOD CompileScriptEventListener(nsIScriptContext *aContext, + JSObject *aScopeObject, nsISupports *aObject, nsIAtom* aName, PRBool *aDidCompile); @@ -195,6 +197,7 @@ protected: PRUint32 aSubType, PRUint32 aPhaseFlags); nsresult CompileEventHandlerInternal(nsIScriptContext *aContext, + JSObject *aScopeObject, nsISupports *aObject, nsIAtom *aName, nsListenerStruct *aListenerStruct, @@ -202,8 +205,9 @@ protected: PRUint32 aSubType); nsListenerStruct* FindJSEventListener(EventArrayType aType); nsresult SetJSEventListener(nsIScriptContext *aContext, - nsISupports *aObject, nsIAtom* aName, - PRBool aIsString, PRBool aPermitUntrustedEvents); + JSObject *aScopeObject, nsISupports *aObject, + nsIAtom* aName, PRBool aIsString, + PRBool aPermitUntrustedEvents); nsresult AddEventListener(nsIDOMEventListener *aListener, EventArrayType aType, PRInt32 aSubType, diff --git a/mozilla/content/events/src/nsEventStateManager.cpp b/mozilla/content/events/src/nsEventStateManager.cpp index ab29645b3dd..61e3790c198 100644 --- a/mozilla/content/events/src/nsEventStateManager.cpp +++ b/mozilla/content/events/src/nsEventStateManager.cpp @@ -167,6 +167,43 @@ enum { MOUSE_SCROLL_TEXTSIZE }; +static nsIScriptGlobalObject * +GetDocumentOuterWindow(nsIDocument *aDocument) +{ + if (aDocument) { + nsIScriptGlobalObject *sgo = aDocument->GetScriptGlobalObject(); + nsCOMPtr win = do_QueryInterface(sgo); + + if (win) { + nsCOMPtr outersgo = + do_QueryInterface(win->GetOuterWindow()); + + return outersgo; + } + + return sgo; + } + + return nsnull; +} + +static nsIDocument * +GetInnerDocument(nsISupports *aWindow) +{ + nsCOMPtr win = do_QueryInterface(aWindow); + nsPIDOMWindow *innerWin; + nsIDocument *doc = nsnull; + + if (win && (innerWin = win->GetCurrentInnerWindow())) { + nsCOMPtr tmp = + do_QueryInterface(innerWin->GetExtantDocument()); + + doc = tmp; + } + + return doc; +} + /******************************************************************/ /* nsEventStateManager */ /******************************************************************/ @@ -514,7 +551,8 @@ nsEventStateManager::PreHandleEvent(nsPresContext* aPresContext, if (mDocument) { if (gLastFocusedDocument && gLastFocusedPresContext) { - nsCOMPtr ourWindow = do_QueryInterface(gLastFocusedDocument->GetScriptGlobalObject()); + nsCOMPtr ourWindow = + do_QueryInterface(GetDocumentOuterWindow(gLastFocusedDocument)); // If the focus controller is already suppressed, it means that we // are in the middle of an activate sequence. In this case, we do @@ -594,7 +632,7 @@ nsEventStateManager::PreHandleEvent(nsPresContext* aPresContext, // then the content node, then the window. nsCOMPtr globalObject = - mDocument->GetScriptGlobalObject(); + GetDocumentOuterWindow(mDocument); if (globalObject) { // We don't want there to be a focused content node while we're @@ -628,12 +666,14 @@ nsEventStateManager::PreHandleEvent(nsPresContext* aPresContext, if (gLastFocusedDocument && gLastFocusedDocument != mDocument) { nsIFocusController *lastController = nsnull; - nsCOMPtr lastWindow = do_QueryInterface(gLastFocusedDocument->GetScriptGlobalObject()); + nsCOMPtr lastWindow = + do_QueryInterface(GetDocumentOuterWindow(gLastFocusedDocument)); if (lastWindow) lastController = lastWindow->GetRootFocusController(); nsIFocusController *nextController = nsnull; - nsCOMPtr nextWindow = do_QueryInterface(mDocument->GetScriptGlobalObject()); + nsCOMPtr nextWindow = + do_QueryInterface(GetDocumentOuterWindow(mDocument)); if (nextWindow) nextController = nextWindow->GetRootFocusController(); @@ -680,15 +720,17 @@ nsEventStateManager::PreHandleEvent(nsPresContext* aPresContext, nsCOMPtr ourGlobal; if (gLastFocusedContent) { nsIDocument* doc = gLastFocusedContent->GetDocument(); - if (doc) - ourGlobal = doc->GetScriptGlobalObject(); - else { - ourGlobal = mDocument->GetScriptGlobalObject(); + + if (doc) { + ourGlobal = GetDocumentOuterWindow(doc); + } else { + ourGlobal = GetDocumentOuterWindow(mDocument); NS_RELEASE(gLastFocusedContent); } } - else - ourGlobal = mDocument->GetScriptGlobalObject(); + else { + ourGlobal = GetDocumentOuterWindow(mDocument); + } // Now fire blurs. We fire a blur on the focused document, element, // and window. @@ -724,7 +766,8 @@ nsEventStateManager::PreHandleEvent(nsPresContext* aPresContext, // get the window here, in case the event causes // gLastFocusedDocument to change. - nsCOMPtr globalObject = gLastFocusedDocument->GetScriptGlobalObject(); + nsCOMPtr globalObject = + GetDocumentOuterWindow(gLastFocusedDocument); gLastFocusedDocument->HandleDOMEvent(gLastFocusedPresContext, &event, nsnull, @@ -754,7 +797,8 @@ nsEventStateManager::PreHandleEvent(nsPresContext* aPresContext, EnsureDocument(aPresContext); - nsCOMPtr win(do_QueryInterface(mDocument->GetScriptGlobalObject())); + nsCOMPtr win = + do_QueryInterface(GetDocumentOuterWindow(mDocument)); if (!win) { NS_ERROR("win is null. this happens [often on xlib builds]. see bug #79213"); @@ -763,7 +807,8 @@ nsEventStateManager::PreHandleEvent(nsPresContext* aPresContext, // Hold a strong ref to the focus controller, since we need // it after event dispatch. - nsCOMPtr focusController = win->GetRootFocusController(); + nsCOMPtr focusController = + win->GetRootFocusController(); nsCOMPtr focusedElement; nsCOMPtr focusedWindow; @@ -785,11 +830,9 @@ nsEventStateManager::PreHandleEvent(nsPresContext* aPresContext, if (focusedWindow) { focusedWindow->Focus(); - nsCOMPtr domDoc; - focusedWindow->GetDocument(getter_AddRefs(domDoc)); + nsCOMPtr document = GetInnerDocument(focusedWindow); - if (domDoc) { - nsCOMPtr document = do_QueryInterface(domDoc); + if (document) { nsIPresShell *shell = document->GetShellAt(0); NS_ASSERTION(shell, "Focus events should not be getting thru when this is null!"); if (shell) { @@ -833,7 +876,8 @@ nsEventStateManager::PreHandleEvent(nsPresContext* aPresContext, { EnsureDocument(aPresContext); - nsCOMPtr ourGlobal = mDocument->GetScriptGlobalObject(); + nsCOMPtr ourGlobal = + GetDocumentOuterWindow(mDocument); // Suppress the focus controller for the duration of the // de-activation. This will cause it to remember the last @@ -1582,21 +1626,18 @@ nsEventStateManager::ChangeTextSize(PRInt32 change) { if(!gLastFocusedDocument) return NS_ERROR_FAILURE; - nsCOMPtr ourWindow = do_QueryInterface(gLastFocusedDocument->GetScriptGlobalObject()); + nsCOMPtr ourWindow = + do_QueryInterface(GetDocumentOuterWindow(gLastFocusedDocument)); if(!ourWindow) return NS_ERROR_FAILURE; nsIDOMWindowInternal *rootWindow = ourWindow->GetPrivateRoot(); if(!rootWindow) return NS_ERROR_FAILURE; - nsCOMPtr windowContent; - rootWindow->GetContent(getter_AddRefs(windowContent)); - if(!windowContent) return NS_ERROR_FAILURE; + nsCOMPtr contentWindow; + rootWindow->GetContent(getter_AddRefs(contentWindow)); + if(!contentWindow) return NS_ERROR_FAILURE; - nsCOMPtr domDoc; - windowContent->GetDocument(getter_AddRefs(domDoc)); - if(!domDoc) return NS_ERROR_FAILURE; - - nsCOMPtr doc = do_QueryInterface(domDoc); + nsIDocument *doc = GetInnerDocument(contentWindow); if(!doc) return NS_ERROR_FAILURE; nsIPresShell *presShell = doc->GetShellAt(0); @@ -3101,7 +3142,8 @@ PrintDocTree(nsIDocShellTreeNode * aParentNode, int aLevel) parentAsDocShell->GetPresContext(getter_AddRefs(presContext)); nsIDocument *doc = presShell->GetDocument(); - nsCOMPtr domwin(do_QueryInterface(doc->GetScriptGlobalObject())); + nsCOMPtr domwin = + do_QueryInterface(GetDocumentOuterWindow(doc)); nsCOMPtr widget; nsIViewManager* vm = presShell->GetViewManager(); @@ -4066,9 +4108,9 @@ nsEventStateManager::SendFocusBlur(nsPresContext* aPresContext, nsIFocusController *newFocusController = nsnull; nsIFocusController *oldFocusController = nsnull; nsCOMPtr newWindow = - do_QueryInterface(mDocument->GetScriptGlobalObject()); + do_QueryInterface(GetDocumentOuterWindow(mDocument)); nsCOMPtr oldWindow = - do_QueryInterface(gLastFocusedDocument->GetScriptGlobalObject()); + do_QueryInterface(GetDocumentOuterWindow(gLastFocusedDocument)); if(newWindow) newFocusController = newWindow->GetRootFocusController(); if(oldWindow) @@ -4108,7 +4150,7 @@ nsEventStateManager::SendFocusBlur(nsPresContext* aPresContext, nsCOMPtr globalObject; if(gLastFocusedDocument) - globalObject = gLastFocusedDocument->GetScriptGlobalObject(); + globalObject = GetDocumentOuterWindow(gLastFocusedDocument); EnsureDocument(presShell); @@ -4121,8 +4163,10 @@ nsEventStateManager::SendFocusBlur(nsPresContext* aPresContext, if (mDocument) { nsIFocusController *newFocusController = nsnull; nsIFocusController *oldFocusController = nsnull; - nsCOMPtr newWindow = do_QueryInterface(mDocument->GetScriptGlobalObject()); - nsCOMPtr oldWindow = do_QueryInterface(gLastFocusedDocument->GetScriptGlobalObject()); + nsCOMPtr newWindow = + do_QueryInterface(GetDocumentOuterWindow(mDocument)); + nsCOMPtr oldWindow = + do_QueryInterface(GetDocumentOuterWindow(gLastFocusedDocument)); if (newWindow) newFocusController = newWindow->GetRootFocusController(); diff --git a/mozilla/content/html/content/src/nsGenericHTMLElement.cpp b/mozilla/content/html/content/src/nsGenericHTMLElement.cpp index d719e1df708..82e5c926ba1 100644 --- a/mozilla/content/html/content/src/nsGenericHTMLElement.cpp +++ b/mozilla/content/html/content/src/nsGenericHTMLElement.cpp @@ -3437,9 +3437,15 @@ nsGenericHTMLFrameElement::GetContentWindow(nsIDOMWindow** aContentWindow) mFrameLoader->GetDocShell(getter_AddRefs(doc_shell)); nsCOMPtr win(do_GetInterface(doc_shell)); - win.swap(*aContentWindow); + nsCOMPtr piwin(do_QueryInterface(win)); - return NS_OK; + if (piwin && piwin->IsInnerWindow()) { + // We got an inner window here somehow, this just should not happen. + + return NS_ERROR_UNEXPECTED; + } + + return CallQueryInterface(piwin->GetOuterWindow(), aContentWindow); } nsresult diff --git a/mozilla/content/html/content/src/nsHTMLScriptElement.cpp b/mozilla/content/html/content/src/nsHTMLScriptElement.cpp index 9b605ab8d6b..173b6ffb043 100644 --- a/mozilla/content/html/content/src/nsHTMLScriptElement.cpp +++ b/mozilla/content/html/content/src/nsHTMLScriptElement.cpp @@ -207,12 +207,13 @@ nsHTMLScriptEventHandler::Invoke(nsISupports *aTargetObject, // Get the script context... nsCOMPtr domdoc; nsCOMPtr scriptContext; + nsIScriptGlobalObject *sgo; mOuter->GetOwnerDocument(getter_AddRefs(domdoc)); nsCOMPtr doc(do_QueryInterface(domdoc)); if (doc) { - nsIScriptGlobalObject *sgo = doc->GetScriptGlobalObject(); + sgo = doc->GetScriptGlobalObject(); if (sgo) { scriptContext = sgo->GetContext(); } @@ -227,7 +228,7 @@ nsHTMLScriptEventHandler::Invoke(nsISupports *aTargetObject, JSObject *scriptObject = nsnull; nsCOMPtr holder; - nsContentUtils::XPConnect()->WrapNative(cx, ::JS_GetGlobalObject(cx), + nsContentUtils::XPConnect()->WrapNative(cx, sgo->GetGlobalJSObject(), aTargetObject, NS_GET_IID(nsISupports), getter_AddRefs(holder)); diff --git a/mozilla/content/xbl/src/nsBindingManager.cpp b/mozilla/content/xbl/src/nsBindingManager.cpp index 8eb0d9ca037..28f049bfa7d 100644 --- a/mozilla/content/xbl/src/nsBindingManager.cpp +++ b/mozilla/content/xbl/src/nsBindingManager.cpp @@ -988,7 +988,7 @@ nsBindingManager::GetBindingImplementation(nsIContent* aContent, REFNSIID aIID, nsCOMPtr wrapper; xpConnect->GetWrappedNativeOfNativeObject(jscontext, - JS_GetGlobalObject(jscontext), + global->GetGlobalJSObject(), aContent, NS_GET_IID(nsISupports), getter_AddRefs(wrapper)); diff --git a/mozilla/content/xbl/src/nsXBLBinding.cpp b/mozilla/content/xbl/src/nsXBLBinding.cpp index b25a24cf2e0..447643229a3 100644 --- a/mozilla/content/xbl/src/nsXBLBinding.cpp +++ b/mozilla/content/xbl/src/nsXBLBinding.cpp @@ -879,7 +879,7 @@ nsXBLBinding::ChangeDocument(nsIDocument* aOldDocument, nsIDocument* aNewDocumen nsCOMPtr wrapper; nsresult rv = nsContentUtils::XPConnect()-> - WrapNative(jscontext, ::JS_GetGlobalObject(jscontext), + WrapNative(jscontext, global->GetGlobalJSObject(), mBoundElement, NS_GET_IID(nsISupports), getter_AddRefs(wrapper)); if (NS_FAILED(rv)) @@ -1113,11 +1113,18 @@ nsXBLBinding::InitClass(const nsCString& aClassName, // Obtain the bound element's current script object. JSContext* cx = (JSContext*)aContext->GetNativeContext(); + nsIDocument *ownerDoc = mBoundElement->GetOwnerDoc(); + nsIScriptGlobalObject *sgo; + + if (!ownerDoc || !(sgo = ownerDoc->GetScriptGlobalObject())) { + NS_ERROR("Can't find global object for bound content!"); + + return NS_ERROR_UNEXPECTED; + } + nsCOMPtr wrapper; - - JSObject* global = ::JS_GetGlobalObject(cx); - - rv = nsContentUtils::XPConnect()->WrapNative(cx, global, mBoundElement, + rv = nsContentUtils::XPConnect()->WrapNative(cx, sgo->GetGlobalJSObject(), + mBoundElement, NS_GET_IID(nsISupports), getter_AddRefs(wrapper)); NS_ENSURE_SUCCESS(rv, rv); @@ -1130,7 +1137,8 @@ nsXBLBinding::InitClass(const nsCString& aClassName, // First ensure our JS class is initialized. - rv = DoInitJSClass(cx, global, object, aClassName, aClassObject); + rv = DoInitJSClass(cx, sgo->GetGlobalJSObject(), object, aClassName, + aClassObject); NS_ENSURE_SUCCESS(rv, rv); // Root mBoundElement so that it doesn't lose it's binding diff --git a/mozilla/content/xbl/src/nsXBLDocumentInfo.cpp b/mozilla/content/xbl/src/nsXBLDocumentInfo.cpp index 8c0e72c0b9d..43a8d43419c 100644 --- a/mozilla/content/xbl/src/nsXBLDocumentInfo.cpp +++ b/mozilla/content/xbl/src/nsXBLDocumentInfo.cpp @@ -82,6 +82,7 @@ public: virtual JSObject *GetGlobalJSObject(); virtual void OnFinalize(JSObject *aObject); virtual void SetScriptsEnabled(PRBool aEnabled, PRBool aFireTimeouts); + virtual nsresult SetNewArguments(JSObject *aArguments); // nsIScriptObjectPrincipal methods virtual nsIPrincipal* GetPrincipal(); @@ -305,6 +306,12 @@ nsXBLDocGlobalObject::SetScriptsEnabled(PRBool aEnabled, PRBool aFireTimeouts) // We don't care... } +nsresult +nsXBLDocGlobalObject::SetNewArguments(JSObject *aArguments) +{ + NS_NOTREACHED("waaah!"); + return NS_ERROR_UNEXPECTED; +} //---------------------------------------------------------------------- // diff --git a/mozilla/content/xbl/src/nsXBLProtoImpl.cpp b/mozilla/content/xbl/src/nsXBLProtoImpl.cpp index ab9a7854557..3271a2c16bf 100644 --- a/mozilla/content/xbl/src/nsXBLProtoImpl.cpp +++ b/mozilla/content/xbl/src/nsXBLProtoImpl.cpp @@ -114,10 +114,19 @@ nsXBLProtoImpl::InitTargetObjects(nsXBLPrototypeBinding* aBinding, return NS_OK; // This can be ok, if all we've got are fields (and no methods/properties). } + nsIDocument *ownerDoc = aBoundElement->GetOwnerDoc(); + nsIScriptGlobalObject *sgo; + + if (!ownerDoc || !(sgo = ownerDoc->GetScriptGlobalObject())) { + NS_ERROR("Can't find global object for bound content!"); + + return NS_ERROR_UNEXPECTED; + } + // Because our prototype implementation has a class, we need to build up a corresponding // class for the concrete implementation in the bound document. JSContext* jscontext = (JSContext*)aContext->GetNativeContext(); - JSObject* global = ::JS_GetGlobalObject(jscontext); + JSObject* global = sgo->GetGlobalJSObject(); nsCOMPtr wrapper; rv = nsContentUtils::XPConnect()->WrapNative(jscontext, global, aBoundElement, @@ -165,7 +174,9 @@ nsXBLProtoImpl::CompilePrototypeMembers(nsXBLPrototypeBinding* aBinding) NS_ENSURE_TRUE(context, NS_ERROR_OUT_OF_MEMORY); void* classObject; - nsresult rv = aBinding->InitClass(mClassName, context, nsnull, &classObject); + nsresult rv = aBinding->InitClass(mClassName, context, + globalObject->GetGlobalJSObject(), + &classObject); if (NS_FAILED(rv)) return rv; diff --git a/mozilla/content/xbl/src/nsXBLProtoImplMethod.cpp b/mozilla/content/xbl/src/nsXBLProtoImplMethod.cpp index 38220786cd1..b0ae7b84340 100644 --- a/mozilla/content/xbl/src/nsXBLProtoImplMethod.cpp +++ b/mozilla/content/xbl/src/nsXBLProtoImplMethod.cpp @@ -135,13 +135,23 @@ nsXBLProtoImplMethod::InstallMember(nsIScriptContext* aContext, NS_PRECONDITION(mIsCompiled, "Should not be installing an uncompiled method"); JSContext* cx = (JSContext*) aContext->GetNativeContext(); + + nsIDocument *ownerDoc = aBoundElement->GetOwnerDoc(); + nsIScriptGlobalObject *sgo; + + if (!ownerDoc || !(sgo = ownerDoc->GetScriptGlobalObject())) { + NS_ERROR("Can't find global object for bound content!"); + + return NS_ERROR_UNEXPECTED; + } + JSObject * scriptObject = (JSObject *) aScriptObject; NS_ASSERTION(scriptObject, "uh-oh, script Object should NOT be null or bad things will happen"); if (!scriptObject) return NS_ERROR_FAILURE; JSObject * targetClassObject = (JSObject *) aTargetClassObject; - JSObject * globalObject = ::JS_GetGlobalObject(cx); + JSObject * globalObject = sgo->GetGlobalJSObject(); // now we want to reevaluate our property using aContext and the script object for this window... if (mJSMethodObject && targetClassObject) { @@ -290,7 +300,7 @@ nsXBLProtoImplAnonymousMethod::Execute(nsIContent* aBoundElement) JSContext* cx = (JSContext*) context->GetNativeContext(); - JSObject* globalObject = ::JS_GetGlobalObject(cx); + JSObject* globalObject = global->GetGlobalJSObject(); nsCOMPtr wrapper; nsresult rv = diff --git a/mozilla/content/xbl/src/nsXBLProtoImplProperty.cpp b/mozilla/content/xbl/src/nsXBLProtoImplProperty.cpp index 514e60cb1d7..0e9791f76a1 100644 --- a/mozilla/content/xbl/src/nsXBLProtoImplProperty.cpp +++ b/mozilla/content/xbl/src/nsXBLProtoImplProperty.cpp @@ -40,11 +40,13 @@ #include "nsString.h" #include "jsapi.h" #include "nsIContent.h" +#include "nsIDocument.h" #include "nsString.h" #include "nsXBLProtoImplProperty.h" #include "nsUnicharUtils.h" #include "nsReadableUtils.h" #include "nsIScriptContext.h" +#include "nsIScriptGlobalObject.h" MOZ_DECL_CTOR_COUNTER(nsXBLProtoImplProperty) @@ -170,13 +172,23 @@ nsXBLProtoImplProperty::InstallMember(nsIScriptContext* aContext, NS_PRECONDITION(mIsCompiled, "Should not be installing an uncompiled property"); JSContext* cx = (JSContext*) aContext->GetNativeContext(); + + nsIDocument *ownerDoc = aBoundElement->GetOwnerDoc(); + nsIScriptGlobalObject *sgo; + + if (!ownerDoc || !(sgo = ownerDoc->GetScriptGlobalObject())) { + NS_ERROR("Can't find global object for bound content!"); + + return NS_ERROR_UNEXPECTED; + } + JSObject * scriptObject = (JSObject *) aScriptObject; NS_ASSERTION(scriptObject, "uh-oh, script Object should NOT be null or bad things will happen"); if (!scriptObject) return NS_ERROR_FAILURE; JSObject * targetClassObject = (JSObject *) aTargetClassObject; - JSObject * globalObject = ::JS_GetGlobalObject(cx); + JSObject * globalObject = sgo->GetGlobalJSObject(); // now we want to reevaluate our property using aContext and the script object for this window... if ((mJSGetterObject || mJSSetterObject) && targetClassObject) { diff --git a/mozilla/content/xbl/src/nsXBLPrototypeBinding.cpp b/mozilla/content/xbl/src/nsXBLPrototypeBinding.cpp index b6b05134f96..656e4ed938d 100644 --- a/mozilla/content/xbl/src/nsXBLPrototypeBinding.cpp +++ b/mozilla/content/xbl/src/nsXBLPrototypeBinding.cpp @@ -743,9 +743,14 @@ nsXBLPrototypeBinding::InitClass(const nsCString& aClassName, JSContext* cx = (JSContext*)aContext->GetNativeContext(); JSObject* scriptObject = (JSObject*) aScriptObject; + JSObject* tmp, *global = scriptObject; - return nsXBLBinding::DoInitJSClass(cx, ::JS_GetGlobalObject(cx), - scriptObject, aClassName, aClassObject); + while ((tmp = ::JS_GetParent(cx, global))) { + global = tmp; + } + + return nsXBLBinding::DoInitJSClass(cx, global, scriptObject, aClassName, + aClassObject); } nsIContent* diff --git a/mozilla/content/xbl/src/nsXBLPrototypeHandler.cpp b/mozilla/content/xbl/src/nsXBLPrototypeHandler.cpp index 71b5bec49b9..db8c0b1821c 100644 --- a/mozilla/content/xbl/src/nsXBLPrototypeHandler.cpp +++ b/mozilla/content/xbl/src/nsXBLPrototypeHandler.cpp @@ -405,6 +405,11 @@ nsXBLPrototypeHandler::ExecuteHandler(nsIDOMEventReceiver* aReceiver, // that. if (focusedWin) { nsCOMPtr piWin(do_QueryInterface(focusedWin)); + + if (piWin && piWin->GetCurrentInnerWindow()) { + piWin = piWin->GetCurrentInnerWindow(); + } + boundGlobal = do_QueryInterface(piWin->GetPrivateRoot()); } else boundGlobal = do_QueryInterface(aReceiver); @@ -481,15 +486,9 @@ nsXBLPrototypeHandler::ExecuteHandler(nsIDOMEventReceiver* aReceiver, boundContext->BindCompiledEventHandler(scriptObject, onEventAtom, handler); // Execute it. - nsCOMPtr factory = - do_GetService(kDOMScriptObjectFactoryCID, &rv); - NS_ENSURE_SUCCESS(rv, rv); - nsCOMPtr eventListener; - - rv = factory->NewJSEventListener(boundContext, aReceiver, - getter_AddRefs(eventListener)); - NS_ENSURE_SUCCESS(rv, rv); + NS_NewJSEventListener(boundContext, boundGlobal->GetGlobalJSObject(), + aReceiver, getter_AddRefs(eventListener)); nsCOMPtr jsListener(do_QueryInterface(eventListener)); jsListener->SetEventName(onEventAtom); diff --git a/mozilla/content/xbl/src/nsXBLWindowKeyHandler.cpp b/mozilla/content/xbl/src/nsXBLWindowKeyHandler.cpp index 79c81f6f2b1..21ab296dfba 100644 --- a/mozilla/content/xbl/src/nsXBLWindowKeyHandler.cpp +++ b/mozilla/content/xbl/src/nsXBLWindowKeyHandler.cpp @@ -51,7 +51,6 @@ #include "nsIServiceManager.h" #include "nsHTMLAtoms.h" #include "nsIXBLDocumentInfo.h" -#include "nsIScriptGlobalObject.h" #include "nsIDOMElement.h" #include "nsXBLAtoms.h" #include "nsINativeKeyBindings.h" diff --git a/mozilla/content/xul/document/src/nsXULDocument.cpp b/mozilla/content/xul/document/src/nsXULDocument.cpp index a3db8f85027..fd30407c2fa 100644 --- a/mozilla/content/xul/document/src/nsXULDocument.cpp +++ b/mozilla/content/xul/document/src/nsXULDocument.cpp @@ -3505,7 +3505,9 @@ nsXULDocument::ExecuteScript(JSObject* aScriptObject) nsCOMPtr context; if (mScriptGlobalObject && (context = mScriptGlobalObject->GetContext())) - rv = context->ExecuteScript(aScriptObject, nsnull, nsnull, nsnull); + rv = context->ExecuteScript(aScriptObject, + mScriptGlobalObject->GetGlobalJSObject(), + nsnull, nsnull); return rv; } diff --git a/mozilla/content/xul/document/src/nsXULPrototypeDocument.cpp b/mozilla/content/xul/document/src/nsXULPrototypeDocument.cpp index ed69b297006..cc6c27ba75f 100644 --- a/mozilla/content/xul/document/src/nsXULPrototypeDocument.cpp +++ b/mozilla/content/xul/document/src/nsXULPrototypeDocument.cpp @@ -104,6 +104,7 @@ public: virtual JSObject *GetGlobalJSObject(); virtual void OnFinalize(JSObject *aObject); virtual void SetScriptsEnabled(PRBool aEnabled, PRBool aFireTimeouts); + virtual nsresult SetNewArguments(JSObject *aArguments); // nsIScriptObjectPrincipal methods virtual nsIPrincipal* GetPrincipal(); @@ -932,6 +933,12 @@ nsXULPDGlobalObject::SetScriptsEnabled(PRBool aEnabled, PRBool aFireTimeouts) // We don't care... } +nsresult +nsXULPDGlobalObject::SetNewArguments(JSObject *aArguments) +{ + NS_NOTREACHED("waaah!"); + return NS_ERROR_UNEXPECTED; +} //---------------------------------------------------------------------- // diff --git a/mozilla/content/xul/templates/src/nsXULTemplateBuilder.cpp b/mozilla/content/xul/templates/src/nsXULTemplateBuilder.cpp index 7982cf2ca22..f87d27c97d3 100644 --- a/mozilla/content/xul/templates/src/nsXULTemplateBuilder.cpp +++ b/mozilla/content/xul/templates/src/nsXULTemplateBuilder.cpp @@ -862,6 +862,8 @@ nsXULTemplateBuilder::InitHTMLTemplateRoot() if (! global) return NS_ERROR_UNEXPECTED; + JSObject *scope = global->GetGlobalJSObject(); + nsIScriptContext *context = global->GetContext(); if (! context) return NS_ERROR_UNEXPECTED; @@ -876,8 +878,7 @@ nsXULTemplateBuilder::InitHTMLTemplateRoot() JSObject* jselement = nsnull; nsCOMPtr wrapper; - rv = xpc->WrapNative(jscontext, ::JS_GetGlobalObject(jscontext), mRoot, - NS_GET_IID(nsIDOMElement), + rv = xpc->WrapNative(jscontext, scope, mRoot, NS_GET_IID(nsIDOMElement), getter_AddRefs(wrapper)); NS_ENSURE_SUCCESS(rv, rv); @@ -886,7 +887,7 @@ nsXULTemplateBuilder::InitHTMLTemplateRoot() { // database - rv = xpc->WrapNative(jscontext, ::JS_GetGlobalObject(jscontext), mDB, + rv = xpc->WrapNative(jscontext, scope, mDB, NS_GET_IID(nsIRDFCompositeDataSource), getter_AddRefs(wrapper)); NS_ENSURE_SUCCESS(rv, rv); diff --git a/mozilla/docshell/base/nsDocShell.cpp b/mozilla/docshell/base/nsDocShell.cpp index c467bfe886f..d69c087101e 100644 --- a/mozilla/docshell/base/nsDocShell.cpp +++ b/mozilla/docshell/base/nsDocShell.cpp @@ -7815,7 +7815,7 @@ NS_IMETHODIMP nsDocShell::EnsureFind() } // we promise that the nsIWebBrowserFind that we return has been set - // up to point to the focussed, or content window, so we have to + // up to point to the focused, or content window, so we have to // set that up each time. nsIScriptGlobalObject* scriptGO = GetScriptGlobalObject(); @@ -7825,17 +7825,17 @@ NS_IMETHODIMP nsDocShell::EnsureFind() nsCOMPtr rootWindow = do_QueryInterface(scriptGO); nsCOMPtr windowToSearch = rootWindow; - // if we can, search the focussed window + // if we can, search the focused window nsCOMPtr ourWindow = do_QueryInterface(scriptGO); nsIFocusController *focusController = nsnull; if (ourWindow) focusController = ourWindow->GetRootFocusController(); if (focusController) { - nsCOMPtr focussedWindow; - focusController->GetFocusedWindow(getter_AddRefs(focussedWindow)); - if (focussedWindow) - windowToSearch = focussedWindow; + nsCOMPtr focusedWindow; + focusController->GetFocusedWindow(getter_AddRefs(focusedWindow)); + if (focusedWindow) + windowToSearch = focusedWindow; } nsCOMPtr findInFrames = do_QueryInterface(mFind); diff --git a/mozilla/dom/public/base/nsPIDOMWindow.h b/mozilla/dom/public/base/nsPIDOMWindow.h index 76396294dd2..1a36f266b72 100644 --- a/mozilla/dom/public/base/nsPIDOMWindow.h +++ b/mozilla/dom/public/base/nsPIDOMWindow.h @@ -93,46 +93,94 @@ public: virtual nsresult Activate() = 0; virtual nsresult Deactivate() = 0; - nsIChromeEventHandler* GetChromeEventHandler() - { + nsIChromeEventHandler* GetChromeEventHandler() const + { return mChromeEventHandler; } - PRBool HasMutationListeners(PRUint32 aMutationEventType) + PRBool HasMutationListeners(PRUint32 aMutationEventType) const { - return (mMutationBits & aMutationEventType) != 0; + const nsPIDOMWindow *win = GetCurrentInnerWindow(); + + if (!win) { + win = this; + } + + return (win->mMutationBits & aMutationEventType) != 0; } - void SetMutationListeners(PRUint32 aType) { mMutationBits |= aType; } + void SetMutationListeners(PRUint32 aType) + { + nsPIDOMWindow *win = GetCurrentInnerWindow(); + + if (!win) { + win = this; + } + + win->mMutationBits |= aType; + } virtual nsIFocusController* GetRootFocusController() = 0; // GetExtantDocument provides a backdoor to the DOM GetDocument accessor - nsIDOMDocument* GetExtantDocument() { return mDocument; } + nsIDOMDocument* GetExtantDocument() const + { + return mDocument; + } // Internal getter/setter for the frame element, this version of the // getter crosses chrome boundaries whereas the public scriptable // one doesn't for security reasons. - nsIDOMElement* GetFrameElementInternal() { return mFrameElement; } + nsIDOMElement* GetFrameElementInternal() const + { + if (IsInnerWindow()) { + return mOuterWindow->GetFrameElementInternal(); + } + + return mFrameElement; + } + void SetFrameElementInternal(nsIDOMElement *aFrameElement) { + if (IsInnerWindow()) { + mOuterWindow->SetFrameElementInternal(aFrameElement); + } + mFrameElement = aFrameElement; } PRBool IsLoadingOrRunningTimeout() const { - return !mIsDocumentLoaded || mRunningTimeout; + const nsPIDOMWindow *win = GetCurrentInnerWindow(); + + if (!win) { + win = this; + } + + return !win->mIsDocumentLoaded || win->mRunningTimeout; } // Check whether a document is currently loading PRBool IsLoading() const { - return !mIsDocumentLoaded; + const nsPIDOMWindow *win = GetCurrentInnerWindow(); + + if (!win) { + win = this; + } + + return !win->mIsDocumentLoaded; } PRBool IsHandlingResizeEvent() const { - return mIsHandlingResizeEvent; + const nsPIDOMWindow *win = GetCurrentInnerWindow(); + + if (!win) { + win = this; + } + + return win->mIsHandlingResizeEvent; } virtual void SetOpenerScriptURL(nsIURI* aURI) = 0; @@ -143,30 +191,62 @@ public: virtual PopupControlState GetPopupControlState() const = 0; virtual OpenAllowValue GetOpenAllow(const nsAString &aName) = 0; - // Returns an object containing the window's state. This also suspends + // Returns an object containing the window's state. This also suspends // all running timeouts in the window. virtual nsresult SaveWindowState(nsISupports **aState) = 0; // Restore the window state from aState. virtual nsresult RestoreWindowState(nsISupports *aState) = 0; + nsPIDOMWindow *GetOuterWindow() + { + return mOuterWindow ? mOuterWindow : this; + } + + nsPIDOMWindow *GetCurrentInnerWindow() const + { + return mInnerWindow; + } + + PRBool IsInnerWindow() const + { + return mOuterWindow != nsnull; + } + + PRBool IsOuterWindow() const + { + return !IsInnerWindow(); + } + protected: - nsPIDOMWindow() - : mRunningTimeout(nsnull), mMutationBits(0), mIsDocumentLoaded(PR_FALSE), - mIsHandlingResizeEvent(PR_FALSE) + nsPIDOMWindow(nsPIDOMWindow *aOuterWindow) + : mFrameElement(nsnull), mRunningTimeout(nsnull), mMutationBits(0), + mIsDocumentLoaded(PR_FALSE), mIsHandlingResizeEvent(PR_FALSE), + mInnerWindow(nsnull), mOuterWindow(aOuterWindow) { } + // These two variables are special in that they're set to the same + // value on both the outer window and the current inner window. Make + // sure you keep them in sync! nsCOMPtr mChromeEventHandler; // strong nsCOMPtr mDocument; // strong + + // These members are only used on outer windows. nsIDOMElement *mFrameElement; // weak nsCOMPtr mOpenerScriptURL; // strong; used to determine whether to clear scope + + // These variables are only used on inner windows. nsTimeout *mRunningTimeout; PRUint32 mMutationBits; PRPackedBool mIsDocumentLoaded; PRPackedBool mIsHandlingResizeEvent; + + // And these are the references between inner and outer windows. + nsPIDOMWindow *mInnerWindow; + nsPIDOMWindow *mOuterWindow; }; diff --git a/mozilla/dom/public/nsIDOMScriptObjectFactory.h b/mozilla/dom/public/nsIDOMScriptObjectFactory.h index 08d9d6e88aa..c16ffec54a4 100644 --- a/mozilla/dom/public/nsIDOMScriptObjectFactory.h +++ b/mozilla/dom/public/nsIDOMScriptObjectFactory.h @@ -43,8 +43,8 @@ #include "nsString.h" #define NS_IDOM_SCRIPT_OBJECT_FACTORY_IID \ -{ 0xa6cf9064, 0x15b3, 0x11d2, \ - { 0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32 } } +{ 0xbac2482a, 0x456e, 0x4ea5, \ + { 0x83, 0xfb, 0x16, 0xe1, 0x24, 0x9c, 0x16, 0x6f } } class nsIScriptContext; class nsIScriptGlobalObject; @@ -57,10 +57,6 @@ public: NS_IMETHOD NewScriptContext(nsIScriptGlobalObject *aGlobal, nsIScriptContext **aContext) = 0; - NS_IMETHOD NewJSEventListener(nsIScriptContext *aContext, - nsISupports* aObject, - nsIDOMEventListener ** aInstancePtrResult) = 0; - NS_IMETHOD NewScriptGlobalObject(PRBool aIsChrome, nsIScriptGlobalObject **aGlobal) = 0; diff --git a/mozilla/dom/public/nsIJSEventListener.h b/mozilla/dom/public/nsIJSEventListener.h index 51ea9604513..134e5f6bea7 100644 --- a/mozilla/dom/public/nsIJSEventListener.h +++ b/mozilla/dom/public/nsIJSEventListener.h @@ -43,6 +43,7 @@ class nsIScriptObjectOwner; class nsIDOMEventListener; class nsIAtom; +struct JSObject; #define NS_IJSEVENTLISTENER_IID \ { 0xa6cf9118, 0x15b3, 0x11d2, \ @@ -55,8 +56,9 @@ class nsIJSEventListener : public nsISupports public: NS_DEFINE_STATIC_IID_ACCESSOR(NS_IJSEVENTLISTENER_IID) - nsIJSEventListener(nsIScriptContext *aContext, nsISupports *aTarget) - : mContext(aContext), mTarget(aTarget) + nsIJSEventListener(nsIScriptContext *aContext, JSObject *aScopeObject, + nsISupports *aTarget) + : mContext(aContext), mScopeObject(aScopeObject), mTarget(aTarget) { // mTarget is a weak reference. We are guaranteed because of the // ownership model that the target will be freed (and the @@ -76,6 +78,11 @@ public: return mTarget; } + JSObject *GetEventScope() + { + return mScopeObject; + } + virtual void SetEventName(nsIAtom* aName) = 0; protected: @@ -85,7 +92,13 @@ protected: } nsIScriptContext *mContext; + JSObject *mScopeObject; nsISupports *mTarget; }; +/* factory function */ +nsresult NS_NewJSEventListener(nsIScriptContext *aContext, + JSObject *aScopeObject, nsISupports *aObject, + nsIDOMEventListener **aReturn); + #endif // nsIJSEventListener_h__ diff --git a/mozilla/dom/public/nsIScriptContext.h b/mozilla/dom/public/nsIScriptContext.h index 3d4ec745145..8fb42726046 100644 --- a/mozilla/dom/public/nsIScriptContext.h +++ b/mozilla/dom/public/nsIScriptContext.h @@ -335,6 +335,21 @@ public: * Tell the context whether or not to GC when destroyed. */ virtual void SetGCOnDestruction(PRBool aGCOnDestruction) = 0; + + /** + * Initialize DOM classes on aGlobalObj + */ + virtual nsresult InitClasses(JSObject *aGlobalObj) = 0; + + /** + * Tell the context we're about to be reinitialize it. + */ + virtual void WillInitializeContext() = 0; + + /** + * Dell the context we're done reinitializing it. + */ + virtual void DidInitializeContext() = 0; }; inline nsIScriptContext * diff --git a/mozilla/dom/public/nsIScriptGlobalObject.h b/mozilla/dom/public/nsIScriptGlobalObject.h index e495cf8bb2b..cc16c6997de 100644 --- a/mozilla/dom/public/nsIScriptGlobalObject.h +++ b/mozilla/dom/public/nsIScriptGlobalObject.h @@ -107,6 +107,13 @@ public: * Called to enable/disable scripts. */ virtual void SetScriptsEnabled(PRBool aEnabled, PRBool aFireTimeouts) = 0; + + /** Set a new arguments object for this window. This will be set on + * the window right away (if there's an existing document) and it + * will also be installed on the window when the next document is + * loaded. + */ + virtual nsresult SetNewArguments(JSObject *aArguments) = 0; }; #endif diff --git a/mozilla/dom/src/base/nsDOMClassInfo.cpp b/mozilla/dom/src/base/nsDOMClassInfo.cpp index 081bf310431..fa5979f046e 100644 --- a/mozilla/dom/src/base/nsDOMClassInfo.cpp +++ b/mozilla/dom/src/base/nsDOMClassInfo.cpp @@ -46,7 +46,6 @@ #include "nsISupportsPrimitives.h" #include "nsIXPConnect.h" #include "nsIJSContextStack.h" -#include "nsIScriptContext.h" #include "nsIXPCSecurityManager.h" #include "nsIStringBundle.h" #include "nsIConsoleService.h" @@ -61,8 +60,10 @@ #include "jsapi.h" #include "jsnum.h" #include "jsdbgapi.h" +#include "jscntxt.h" // General helper includes +#include "nsGlobalWindow.h" #include "nsIContent.h" #include "nsIDocument.h" #include "nsIDOMDocument.h" @@ -486,6 +487,8 @@ static nsDOMClassInfoData sClassInfoData[] = { nsIXPCScriptable::WANT_ADDPROPERTY | nsIXPCScriptable::WANT_DELPROPERTY | nsIXPCScriptable::WANT_ENUMERATE | + nsIXPCScriptable::WANT_EQUALITY | + nsIXPCScriptable::WANT_OUTER_OBJECT | nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE) // Don't allow modifications to Location.prototype @@ -493,8 +496,9 @@ static nsDOMClassInfoData sClassInfoData[] = { DOM_DEFAULT_SCRIPTABLE_FLAGS & ~nsIXPCScriptable::ALLOW_PROP_MODS_TO_PROTOTYPE) - NS_DEFINE_CLASSINFO_DATA(Navigator, nsDOMGenericSH, - DOM_DEFAULT_SCRIPTABLE_FLAGS) + NS_DEFINE_CLASSINFO_DATA(Navigator, nsNavigatorSH, + DOM_DEFAULT_SCRIPTABLE_FLAGS | + nsIXPCScriptable::WANT_PRECREATE) NS_DEFINE_CLASSINFO_DATA(Plugin, nsPluginSH, ARRAY_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(PluginArray, nsPluginArraySH, @@ -3213,6 +3217,24 @@ nsDOMClassInfo::Mark(nsIXPConnectWrappedNative *wrapper, JSContext *cx, return NS_ERROR_UNEXPECTED; } +NS_IMETHODIMP +nsDOMClassInfo::Equality(nsIXPConnectWrappedNative *wrapper, JSContext * cx, + JSObject * obj, jsval val, PRBool *bp) +{ + NS_ERROR("Don't call me!"); + + return NS_ERROR_UNEXPECTED; +} + +NS_IMETHODIMP +nsDOMClassInfo::OuterObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx, + JSObject * obj, JSObject * *_retval) +{ + NS_ERROR("Don't call me!"); + + return NS_ERROR_UNEXPECTED; +} + // static nsIClassInfo * @@ -3487,13 +3509,13 @@ nsDOMClassInfo::doCheckPropertyAccess(JSContext *cx, JSObject *obj, jsval id, } nsIScriptContext *scx = sgo->GetContext(); + JSObject *global; - if (!scx || !scx->IsContextInitialized()) { + if (!scx || !scx->IsContextInitialized() || + !(global = sgo->GetGlobalJSObject())) { return NS_OK; } - JSObject *global = sgo->GetGlobalJSObject(); - return sSecMan->CheckPropertyAccess(cx, global, mData->mName, id, accessMode); } @@ -3680,8 +3702,8 @@ nsWindowSH::GlobalScopePolluterNewResolve(JSContext *cx, JSObject *obj, } // static -JSObject * -nsWindowSH::GetInvalidatedGlobalScopePolluter(JSContext *cx, JSObject *obj) +void +nsWindowSH::InvalidateGlobalScopePolluter(JSContext *cx, JSObject *obj) { JSObject *proto; @@ -3693,38 +3715,31 @@ nsWindowSH::GetInvalidatedGlobalScopePolluter(JSContext *cx, JSObject *obj) ::JS_SetPrivate(cx, proto, nsnull); - // Pull the global scope polluter out of the prototype chain. + // Pull the global scope polluter out of the prototype chain so + // that it can be freed. ::JS_SetPrototype(cx, obj, ::JS_GetPrototype(cx, proto)); - ::JS_ClearScope(cx, proto); - break; } obj = proto; } - - return proto; } // static nsresult nsWindowSH::InstallGlobalScopePolluter(JSContext *cx, JSObject *obj, - JSObject *oldPolluter, nsIHTMLDocument *doc) { - // If global scope pollution is disabled, do nothing - if (sDisableGlobalScopePollutionSupport) { + // If global scope pollution is disabled, or if our document is not + // a HTML document, do nothing + if (sDisableGlobalScopePollutionSupport || !doc) { return NS_OK; } - JSObject *gsp = oldPolluter; - + JSObject *gsp = ::JS_NewObject(cx, &sGlobalScopePolluterClass, nsnull, obj); if (!gsp) { - gsp = ::JS_NewObject(cx, &sGlobalScopePolluterClass, nsnull, obj); - if (!gsp) { - return NS_ERROR_OUT_OF_MEMORY; - } + return NS_ERROR_OUT_OF_MEMORY; } JSObject *o = obj, *proto; @@ -3756,18 +3771,16 @@ nsWindowSH::InstallGlobalScopePolluter(JSContext *cx, JSObject *obj, } // The global scope polluter will release doc on destruction (or - // reinitialzation). - NS_IF_ADDREF(doc); + // invalidation). + NS_ADDREF(doc); return NS_OK; } static already_AddRefed -GetChildFrame(nsIXPConnectWrappedNative *wrapper, jsval id) +GetChildFrame(nsGlobalWindow *win, jsval id) { - nsCOMPtr win(do_QueryWrappedNative(wrapper)); - nsCOMPtr frames; win->GetFrames(getter_AddRefs(frames)); @@ -3784,6 +3797,54 @@ NS_IMETHODIMP nsWindowSH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx, JSObject *obj, jsval id, jsval *vp, PRBool *_retval) { + nsGlobalWindow *win = nsGlobalWindow::FromWrapper(wrapper); + +#ifdef DEBUG_SH_FORWARDING + { + nsDependentJSString str(::JS_ValueToString(cx, id)); + + if (win->IsInnerWindow()) { +#ifdef DEBUG_PRINT_INNER + printf("Property '%s' get on inner window %p\n", + NS_ConvertUTF16toUTF8(str).get(), (void *)win); +#endif + } else { + printf("Property '%s' get on outer window %p\n", + NS_ConvertUTF16toUTF8(str).get(), (void *)win); + } + } +#endif + + if (win->IsOuterWindow() && !ObjectIsNativeWrapper(cx, obj)) { + // XXXjst: Do security checks here when we remove the security + // checks on the inner window. + + nsGlobalWindow *innerWin = win->GetCurrentInnerWindowInternal(); + + JSObject *innerObj; + if (innerWin && (innerObj = innerWin->GetGlobalJSObject())) { +#ifdef DEBUG_SH_FORWARDING + printf(" --- Forwarding get to inner window %p\n", (void *)innerWin); +#endif + + // Forward the get to the inner object + if (JSVAL_IS_STRING(id)) { + JSString *str = JSVAL_TO_STRING(id); + + *_retval = ::JS_GetUCProperty(cx, innerObj, ::JS_GetStringChars(str), + ::JS_GetStringLength(str), vp); + } else if (JSVAL_IS_INT(id)) { + *_retval = ::JS_GetElement(cx, innerObj, JSVAL_TO_INT(id), vp); + } else { + NS_ERROR("Write me!"); + + return NS_ERROR_NOT_IMPLEMENTED; + } + + return NS_OK; + } + } + // The order in which things are done in this method are a bit // whacky, that's because this method is *extremely* performace // critical. Don't touch this unless you know what you're doing. @@ -3794,7 +3855,7 @@ nsWindowSH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx, // if window.frames[n] is a child frame, wrap the frame and return // it without doing a security check. - nsCOMPtr frame = GetChildFrame(wrapper, id); + nsCOMPtr frame = GetChildFrame(win, id); nsresult rv = NS_OK; if (frame) { @@ -3802,8 +3863,7 @@ nsWindowSH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx, // child frame, wrap the child frame without doing a security // check and return. - rv = WrapNative(cx, ::JS_GetGlobalObject(cx), frame, - NS_GET_IID(nsIDOMWindow), vp); + rv = WrapNative(cx, obj, frame, NS_GET_IID(nsIDOMWindow), vp); } return NS_FAILED(rv) ? rv : NS_SUCCESS_I_DID_SOMETHING; @@ -3859,6 +3919,54 @@ NS_IMETHODIMP nsWindowSH::SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx, JSObject *obj, jsval id, jsval *vp, PRBool *_retval) { + nsGlobalWindow *win = nsGlobalWindow::FromWrapper(wrapper); + +#ifdef DEBUG_SH_FORWARDING + { + nsDependentJSString str(::JS_ValueToString(cx, id)); + + if (win->IsInnerWindow()) { +#ifdef DEBUG_PRINT_INNER + printf("Property '%s' set on inner window %p\n", + NS_ConvertUTF16toUTF8(str).get(), (void *)win); +#endif + } else { + printf("Property '%s' set on outer window %p\n", + NS_ConvertUTF16toUTF8(str).get(), (void *)win); + } + } +#endif + + if (win->IsOuterWindow() && !ObjectIsNativeWrapper(cx, obj)) { + // XXXjst: Do security checks here when we remove the security + // checks on the inner window. + + nsGlobalWindow *innerWin = win->GetCurrentInnerWindowInternal(); + + JSObject *innerObj; + if (innerWin && (innerObj = innerWin->GetGlobalJSObject())) { +#ifdef DEBUG_SH_FORWARDING + printf(" --- Forwarding set to inner window %p\n", (void *)innerWin); +#endif + + // Forward the set to the inner object + if (JSVAL_IS_STRING(id)) { + JSString *str = JSVAL_TO_STRING(id); + + *_retval = ::JS_SetUCProperty(cx, innerObj, ::JS_GetStringChars(str), + ::JS_GetStringLength(str), vp); + } else if (JSVAL_IS_INT(id)) { + *_retval = ::JS_SetElement(cx, innerObj, JSVAL_TO_INT(id), vp); + } else { + NS_ERROR("Write me!"); + + return NS_ERROR_NOT_IMPLEMENTED; + } + + return NS_OK; + } + } + if (needsSecurityCheck(cx, wrapper)) { nsresult rv = doCheckPropertyAccess(cx, obj, id, wrapper, @@ -3901,6 +4009,46 @@ nsWindowSH::AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx, JSObject *obj, jsval id, jsval *vp, PRBool *_retval) { + nsGlobalWindow *win = nsGlobalWindow::FromWrapper(wrapper); + +#ifdef DEBUG_SH_FORWARDING + { + nsDependentJSString str(::JS_ValueToString(cx, id)); + + if (win->IsInnerWindow()) { +#ifdef DEBUG_PRINT_INNER + printf("Property '%s' add on inner window %p\n", + NS_ConvertUTF16toUTF8(str).get(), (void *)win); +#endif + } else { + printf("Property '%s' add on outer window %p\n", + NS_ConvertUTF16toUTF8(str).get(), (void *)win); + } + } +#endif + + if (win->IsOuterWindow() && !ObjectIsNativeWrapper(cx, obj) ) { + // XXXjst: Do security checks here when we remove the security + // checks on the inner window. + + nsGlobalWindow *innerWin = win->GetCurrentInnerWindowInternal(); + + JSObject *innerObj; + if (innerWin && (innerObj = innerWin->GetGlobalJSObject())) { +#ifdef DEBUG_SH_FORWARDING + printf(" --- Forwarding add to inner window %p\n", (void *)innerWin); +#endif + + // Forward the add to the inner object + jsid interned_id; + *_retval = (::JS_ValueToId(cx, id, &interned_id) && + OBJ_DEFINE_PROPERTY(cx, innerObj, interned_id, *vp, nsnull, + nsnull, JSPROP_ENUMERATE, nsnull)); + + return NS_OK; + } + } + // If we're in a state where we're not supposed to do a security // check, return early. if (!sDoSecurityCheckInAddProperty) { @@ -3936,6 +4084,45 @@ nsWindowSH::DelProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx, JSObject *obj, jsval id, jsval *vp, PRBool *_retval) { + nsGlobalWindow *win = nsGlobalWindow::FromWrapper(wrapper); + +#ifdef DEBUG_SH_FORWARDING + { + nsDependentJSString str(::JS_ValueToString(cx, id)); + + if (win->IsInnerWindow()) { +#ifdef DEBUG_PRINT_INNER + printf("Property '%s' del on inner window %p\n", + NS_ConvertUTF16toUTF8(str).get(), (void *)win); +#endif + } else { + printf("Property '%s' del on outer window %p\n", + NS_ConvertUTF16toUTF8(str).get(), (void *)win); + } + } +#endif + + if (win->IsOuterWindow() && !ObjectIsNativeWrapper(cx, obj)) { + // XXXjst: Do security checks here when we remove the security + // checks on the inner window. + + nsGlobalWindow *innerWin = win->GetCurrentInnerWindowInternal(); + + JSObject *innerObj; + if (innerWin && (innerObj = innerWin->GetGlobalJSObject())) { +#ifdef DEBUG_SH_FORWARDING + printf(" --- Forwarding add to inner window %p\n", (void *)innerWin); +#endif + + // Forward the del to the inner object + jsid interned_id; + *_retval = (::JS_ValueToId(cx, id, &interned_id) && + OBJ_DELETE_PROPERTY(cx, innerObj, interned_id, vp)); + + return NS_OK; + } + } + if (id == sLocation_id) { // Don't allow deleting window.location, allowing that could lead // to security bugs (see bug 143369). @@ -4007,7 +4194,7 @@ BaseStubConstructor(const nsGlobalNameStruct *name_struct, JSContext *cx, return rv; } - rv = nsDOMGenericSH::WrapNative(cx, ::JS_GetGlobalObject(cx), native, + rv = nsDOMGenericSH::WrapNative(cx, GetGlobalJSObject(cx, obj), native, NS_GET_IID(nsISupports), rval); return NS_SUCCEEDED(rv) ? JS_TRUE : JS_FALSE; @@ -5052,8 +5239,7 @@ nsWindowSH::GlobalResolve(nsIScriptGlobalObject *global, JSContext *cx, prop_val = OBJECT_TO_JSVAL(prop_obj); } else { - rv = WrapNative(cx, ::JS_GetGlobalObject(cx), native, - NS_GET_IID(nsISupports), &prop_val); + rv = WrapNative(cx, obj, native, NS_GET_IID(nsISupports), &prop_val); } NS_ENSURE_SUCCESS(rv, rv); @@ -5083,26 +5269,122 @@ nsWindowSH::GlobalResolve(nsIScriptGlobalObject *global, JSContext *cx, return rv; } -// static -nsresult -nsWindowSH::OnDocumentChanged(JSContext *cx, JSObject *obj, - nsIDOMWindow *window) -{ - nsCOMPtr document; - nsresult rv = window->GetDocument(getter_AddRefs(document)); - NS_ENSURE_SUCCESS(rv, rv); - - // The PostCreate hook for the document will handle defining the property - - jsval v; - return WrapNative(cx, obj, document, NS_GET_IID(nsIDOMDocument), &v); -} - NS_IMETHODIMP nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx, JSObject *obj, jsval id, PRUint32 flags, JSObject **objp, PRBool *_retval) { + nsGlobalWindow *win = nsGlobalWindow::FromWrapper(wrapper); + +#ifdef DEBUG_SH_FORWARDING + { + nsDependentJSString str(::JS_ValueToString(cx, id)); + + if (win->IsInnerWindow()) { +#ifdef DEBUG_PRINT_INNER + printf("Property '%s' resolve on inner window %p\n", + NS_ConvertUTF16toUTF8(str).get(), (void *)win); +#endif + } else { + printf("Property '%s' resolve on outer window %p\n", + NS_ConvertUTF16toUTF8(str).get(), (void *)win); + } + } +#endif + + // Note, we won't forward resolve of the location property to the + // inner window, we need to deal with that one for the outer too + // since we've got special security protection code for that + // property. + if (win->IsOuterWindow() && id != sLocation_id && + !ObjectIsNativeWrapper(cx, obj)) { + // XXXjst: Do security checks here when we remove the security + // checks on the inner window. + + nsGlobalWindow *innerWin = win->GetCurrentInnerWindowInternal(); + + if (!innerWin || !innerWin->GetExtantDocument()) { + // We're resolving a property on an outer window for which there + // is no inner window yet. If the context is already initalized, + // trigger creation of a new inner window by calling + // GetDocument() on the outer window. This will create a + // synthetic about:blank document, and an inner window which may + // be reused by the actual document being loaded into this outer + // window. This way properties defined on the window while the + // document before the document load stated will be visible to + // the document once it's loaded, assuming same origin etc. + nsIScriptContext *scx = win->GetContextInternal(); + + if (scx && scx->IsContextInitialized()) { + nsCOMPtr doc; + win->GetDocument(getter_AddRefs(doc)); + + // Grab the new inner window. + innerWin = win->GetCurrentInnerWindowInternal(); + } + } + + JSObject *innerObj; + if (innerWin && (innerObj = innerWin->GetGlobalJSObject())) { +#ifdef DEBUG_SH_FORWARDING + printf(" --- Forwarding resolve to inner window %p\n", (void *)innerWin); +#endif + + jsid interned_id; + JSObject *pobj; + JSProperty *prop = nsnull; + + *_retval = (::JS_ValueToId(cx, id, &interned_id) && + OBJ_LOOKUP_PROPERTY(cx, innerObj, interned_id, &pobj, + &prop)); + + if (*_retval && prop) { +#ifdef DEBUG_SH_FORWARDING + printf(" --- Resolve on inner window found property.\n"); +#endif + + OBJ_DROP_PROPERTY(cx, pobj, prop); + + JSObject *proto; + if (pobj != innerObj && (proto = ::JS_GetPrototype(cx, obj))) { + // A property was found on one of innerObj's prototypes, + // this means the property could've been found on the + // XPCWrappedNative proto, which means that the property is + // likely a function (getter, setter, or a method). In this + // case we can't expose this method as a property of the + // outer since a call to it would be on the wrong object and + // XPConnect can't deal. In this case only, check if the + // property also exists on our prototype, and if it does, + // return it instead of the one found on the inner object's + // prototype chain. + +#ifdef DEBUG_SH_FORWARDING + printf(" ... but the propety was found on the prototype, " + "checking to see if the property also exists on our " + "prototype.\n"); +#endif + + JSObject *mypobj; + OBJ_LOOKUP_PROPERTY(cx, proto, interned_id, &mypobj, + &prop); + + if (prop) { + // We found the prop on obj's prototype too, use it + // instead. + + OBJ_DROP_PROPERTY(cx, mypobj, prop); + + pobj = mypobj; + } + } + + *objp = pobj; + } + + return NS_OK; + } + } + if (!JSVAL_IS_STRING(id)) { if (JSVAL_IS_INT(id) && !(flags & JSRESOLVE_ASSIGNING)) { // If we're resolving a numeric property, treat that as if @@ -5110,7 +5392,7 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx, // window), if window.frames[n] is a child frame, define a // property for this index. - nsCOMPtr frame = GetChildFrame(wrapper, id); + nsCOMPtr frame = GetChildFrame(win, id); if (frame) { // A numeric property accessed and the numeric property is a @@ -5128,10 +5410,7 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx, return NS_OK; } - nsCOMPtr sgo(do_QueryWrappedNative(wrapper)); - NS_ENSURE_TRUE(sgo, NS_ERROR_UNEXPECTED); - - nsIScriptContext *my_context = sgo->GetContext(); + nsIScriptContext *my_context = win->GetContextInternal(); nsresult rv = NS_OK; @@ -5145,7 +5424,7 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx, // initialization to behave as if it were done eagerly, on each // window's own context (not on some other window-caller's // context). - + JSContext *my_cx; if (!my_context) { @@ -5190,7 +5469,7 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx, JSString *str = JSVAL_TO_STRING(id); - nsCOMPtr dsn(do_QueryInterface(sgo->GetDocShell())); + nsCOMPtr dsn(do_QueryInterface(win->GetDocShell())); PRInt32 count = 0; @@ -5214,8 +5493,11 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx, // on the wrapper so that ::NewResolve() doesn't get called // again for this property name. + JSObject *wrapperObj; + wrapper->GetJSObject(&wrapperObj); + jsval v; - rv = WrapNative(cx, ::JS_GetGlobalObject(cx), child_win, + rv = WrapNative(cx, wrapperObj, child_win, NS_GET_IID(nsIDOMWindowInternal), &v); NS_ENSURE_SUCCESS(rv, rv); @@ -5258,7 +5540,7 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx, // which have been registered with the script namespace manager. JSBool did_resolve = JS_FALSE; - rv = GlobalResolve(sgo, cx, obj, str, flags, &did_resolve); + rv = GlobalResolve(win, cx, obj, str, flags, &did_resolve); NS_ENSURE_SUCCESS(rv, rv); if (did_resolve) { @@ -5304,15 +5586,28 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx, // here) since we must define window.location to prevent the // getter from being overriden (for security reasons). - nsCOMPtr window(do_QueryInterface(sgo)); - NS_ENSURE_TRUE(window, NS_ERROR_UNEXPECTED); - nsCOMPtr location; - rv = window->GetLocation(getter_AddRefs(location)); + rv = win->GetLocation(getter_AddRefs(location)); NS_ENSURE_SUCCESS(rv, rv); + // Make sure we wrap the location object in the inner window's + // scope if we've got an inner window. + JSObject *scope = nsnull; + if (win->IsOuterWindow()) { + nsGlobalWindow *innerWin = win->GetCurrentInnerWindowInternal(); + + if (innerWin) { + scope = innerWin->GetGlobalJSObject(); + } + } + + if (!scope) { + scope = obj; + } + jsval v; - rv = WrapNative(cx, obj, location, NS_GET_IID(nsIDOMLocation), &v); + rv = WrapNative(cx, GetGlobalJSObject(cx, scope), location, + NS_GET_IID(nsIDOMLocation), &v); NS_ENSURE_SUCCESS(rv, rv); sDoSecurityCheckInAddProperty = PR_FALSE; @@ -5354,11 +5649,8 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx, } } else { if (id == sNavigator_id) { - nsCOMPtr window(do_QueryInterface(sgo)); - NS_ENSURE_TRUE(window, NS_ERROR_UNEXPECTED); - nsCOMPtr navigator; - rv = window->GetNavigator(getter_AddRefs(navigator)); + rv = win->GetNavigator(getter_AddRefs(navigator)); NS_ENSURE_SUCCESS(rv, rv); jsval v; @@ -5377,25 +5669,33 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx, } if (id == sDocument_id) { - nsCOMPtr window(do_QueryInterface(sgo)); - NS_ENSURE_TRUE(window, NS_ERROR_UNEXPECTED); - - rv = OnDocumentChanged(cx, obj, window); + nsCOMPtr document; + nsresult rv = win->GetDocument(getter_AddRefs(document)); NS_ENSURE_SUCCESS(rv, rv); + jsval v; + rv = WrapNative(cx, obj, document, NS_GET_IID(nsIDOMDocument), &v); + NS_ENSURE_SUCCESS(rv, rv); + + if (!::JS_DefineUCProperty(cx, obj, ::JS_GetStringChars(str), + ::JS_GetStringLength(str), v, nsnull, + nsnull, JSPROP_READONLY | JSPROP_ENUMERATE)) { + return NS_ERROR_FAILURE; + } + *objp = obj; return NS_OK; } if (id == sWindow_id) { - jsval v; - rv = WrapNative(cx, obj, sgo, NS_GET_IID(nsIDOMWindow), &v); - NS_ENSURE_SUCCESS(rv, rv); + // window should *always* be the outer window object. + win = win->GetOuterWindowInternal(); if (!::JS_DefineUCProperty(cx, obj, ::JS_GetStringChars(str), - ::JS_GetStringLength(str), v, nsnull, - nsnull, + ::JS_GetStringLength(str), + OBJECT_TO_JSVAL(win->GetGlobalJSObject()), + nsnull, nsnull, JSPROP_READONLY | JSPROP_ENUMERATE)) { return NS_ERROR_FAILURE; } @@ -5441,6 +5741,49 @@ nsWindowSH::Finalize(nsIXPConnectWrappedNative *wrapper, JSContext *cx, return NS_OK; } +NS_IMETHODIMP +nsWindowSH::Equality(nsIXPConnectWrappedNative *wrapper, JSContext * cx, + JSObject * obj, jsval val, PRBool *bp) +{ + *bp = PR_FALSE; + + if (JSVAL_IS_PRIMITIVE(val)) { + return NS_OK; + } + + nsCOMPtr other_wrapper; + nsContentUtils::XPConnect()-> + GetWrappedNativeOfJSObject(cx, JSVAL_TO_OBJECT(val), + getter_AddRefs(other_wrapper)); + if (!other_wrapper) { + // Not equal. + + return NS_OK; + } + + nsGlobalWindow *win = nsGlobalWindow::FromWrapper(wrapper); + + nsCOMPtr other = do_QueryWrappedNative(other_wrapper); + + if (other) { + *bp = win->GetOuterWindow() == other->GetOuterWindow(); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsWindowSH::OuterObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx, + JSObject * obj, JSObject * *_retval) +{ + nsGlobalWindow *win = nsGlobalWindow::FromWrapper(wrapper); + + // Always return the outer window. + *_retval = win->GetOuterWindowInternal()->GetGlobalJSObject(); + + return NS_OK; +} + // DOM Location helper @@ -5462,12 +5805,42 @@ nsLocationSH::CheckAccess(nsIXPConnectWrappedNative *wrapper, JSContext *cx, } +// DOM Navigator helper +nsresult +nsNavigatorSH::PreCreate(nsISupports *nativeObj, JSContext *cx, + JSObject *globalObj, JSObject **parentObj) +{ + // window.navigator is persisted across document transitions if + // we're loading a page from the same origin. Because of that we + // need to parent the navigator wrapper at the outer window to avoid + // holding on to the inner window where the navigator was initially + // created too long. + *parentObj = globalObj; + + nsNavigator *nav = (nsNavigator *)(nsIDOMNavigator *)nativeObj; + nsIDocShell *ds = nav->GetDocShell(); + + nsCOMPtr sgo = do_GetInterface(ds); + + if (sgo) { + JSObject *global = sgo->GetGlobalJSObject(); + + if (global) { + *parentObj = global; + } + } + + return NS_OK; +} + // DOM Node helper NS_IMETHODIMP nsNodeSH::PreCreate(nsISupports *nativeObj, JSContext *cx, JSObject *globalObj, JSObject **parentObj) { + // XXXjst: Add code that asserts the the scope is an inner window + nsCOMPtr content(do_QueryInterface(nativeObj)); nsCOMPtr doc; @@ -5544,8 +5917,13 @@ nsNodeSH::PreCreate(nsISupports *nativeObj, JSContext *cx, JSObject *globalObj, } } + // XXXjst: Maybe we need to find the global to use from the + // nsIScriptGlobalObject that's reachable from the node we're about + // to wrap here? But that's not always reachable, let's use + // globalObj for now... + jsval v; - nsresult rv = WrapNative(cx, ::JS_GetGlobalObject(cx), native_parent, + nsresult rv = WrapNative(cx, globalObj, native_parent, NS_GET_IID(nsISupports), &v); *parentObj = JSVAL_TO_OBJECT(v); @@ -5786,13 +6164,16 @@ nsEventReceiverSH::RegisterCompileHandler(nsIXPConnectWrappedNative *wrapper, nsresult rv; + JSObject *scope = GetGlobalJSObject(cx, obj); + if (compile) { - rv = manager->CompileScriptEventListener(script_cx, receiver, atom, + rv = manager->CompileScriptEventListener(script_cx, scope, receiver, atom, did_define); } else if (remove) { rv = manager->RemoveScriptEventListener(atom); } else { - rv = manager->RegisterScriptEventListener(script_cx, receiver, atom); + rv = manager->RegisterScriptEventListener(script_cx, scope, receiver, + atom); } return NS_FAILED(rv) ? rv : NS_SUCCESS_I_DID_SOMETHING; @@ -6020,7 +6401,7 @@ nsArraySH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx, NS_ENSURE_SUCCESS(rv, rv); if (array_item) { - rv = WrapNative(cx, ::JS_GetGlobalObject(cx), array_item, + rv = WrapNative(cx, GetGlobalJSObject(cx, obj), array_item, NS_GET_IID(nsISupports), vp); NS_ENSURE_SUCCESS(rv, rv); @@ -6059,7 +6440,7 @@ nsNamedArraySH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx, NS_ENSURE_SUCCESS(rv, rv); if (item) { - rv = WrapNative(cx, ::JS_GetGlobalObject(cx), item, + rv = WrapNative(cx, GetGlobalJSObject(cx, obj), item, NS_GET_IID(nsISupports), vp); NS_ENSURE_SUCCESS(rv, rv); @@ -6159,7 +6540,7 @@ nsContentListSH::PreCreate(nsISupports *nativeObj, JSContext *cx, } jsval v; - nsresult rv = WrapNative(cx, ::JS_GetGlobalObject(cx), native_parent, + nsresult rv = WrapNative(cx, globalObj, native_parent, NS_GET_IID(nsISupports), &v); *parentObj = JSVAL_TO_OBJECT(v); @@ -6212,13 +6593,6 @@ documentNeedsSecurityCheck(JSContext *cx, nsIXPConnectWrappedNative *wrapper) } #endif - if (wrapper_global != ::JS_GetGlobalObject(cx)) { - // cx is not the context in the global object in wrapper, force - // a security check. - - return PR_TRUE; - } - // Check if the calling function comes from the same scope that the // wrapper comes from. If that's the case, or if there's no JS // running at the moment (i.e. someone is using the JS engine API @@ -6265,6 +6639,7 @@ documentNeedsSecurityCheck(JSContext *cx, nsIXPConnectWrappedNative *wrapper) // object in the scope that wrapper came from, no need to do a // security check now. cached_doc_needs_check = PR_FALSE; + return PR_FALSE; } @@ -6326,7 +6701,8 @@ nsDocumentSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx, jsval v; - rv = WrapNative(cx, obj, location, NS_GET_IID(nsIDOMLocation), &v); + rv = WrapNative(cx, GetGlobalJSObject(cx, obj), location, + NS_GET_IID(nsIDOMLocation), &v); NS_ENSURE_SUCCESS(rv, rv); sDoSecurityCheckInAddProperty = PR_FALSE; @@ -6433,7 +6809,8 @@ nsDocumentSH::SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx, rv = location->SetHref(nsDependentJSString(val)); NS_ENSURE_SUCCESS(rv, rv); - rv = WrapNative(cx, obj, location, NS_GET_IID(nsIDOMLocation), vp); + rv = WrapNative(cx, GetGlobalJSObject(cx, obj), location, + NS_GET_IID(nsIDOMLocation), vp); return NS_FAILED(rv) ? rv : NS_SUCCESS_I_DID_SOMETHING; } } @@ -6476,11 +6853,11 @@ nsDocumentSH::PostCreate(nsIXPConnectWrappedNative *wrapper, JSContext *cx, if (SameCOMIdentity(doc, currentDoc)) { jsval winVal; - - nsresult rv = WrapNative(cx, ::JS_GetGlobalObject(cx), win, + + nsresult rv = WrapNative(cx, GetGlobalJSObject(cx, obj), win, NS_GET_IID(nsIDOMWindow), &winVal); NS_ENSURE_SUCCESS(rv, rv); - + NS_NAMED_LITERAL_STRING(doc_str, "document"); if (!::JS_DefineUCProperty(cx, JSVAL_TO_OBJECT(winVal), @@ -6579,7 +6956,7 @@ nsHTMLDocumentSH::DocumentOpen(JSContext *cx, JSObject *obj, uintN argc, return JS_FALSE; } - rv = WrapNative(cx, ::JS_GetGlobalObject(cx), retval, + rv = WrapNative(cx, GetGlobalJSObject(cx, obj), retval, NS_GET_IID(nsIDOMDocument), rval); NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to wrap native!"); @@ -7189,8 +7566,7 @@ nsHTMLDocumentSH::GetProperty(nsIXPConnectWrappedNative *wrapper, NS_ENSURE_SUCCESS(rv, rv); if (result) { - rv = WrapNative(cx, ::JS_GetGlobalObject(cx), result, - NS_GET_IID(nsISupports), vp); + rv = WrapNative(cx, obj, result, NS_GET_IID(nsISupports), vp); if (NS_SUCCEEDED(rv)) { rv = NS_SUCCESS_I_DID_SOMETHING; } @@ -7325,7 +7701,7 @@ nsHTMLFormElementSH::GetProperty(nsIXPConnectWrappedNative *wrapper, if (result) { // Wrap result, result can be either an element or a list of // elements - nsresult rv = WrapNative(cx, ::JS_GetGlobalObject(cx), result, + nsresult rv = WrapNative(cx, GetGlobalJSObject(cx, obj), result, NS_GET_IID(nsISupports), vp); return NS_FAILED(rv) ? rv : NS_SUCCESS_I_DID_SOMETHING; } @@ -7340,7 +7716,7 @@ nsHTMLFormElementSH::GetProperty(nsIXPConnectWrappedNative *wrapper, form->GetElementAt(n, getter_AddRefs(control)); if (control) { - nsresult rv = WrapNative(cx, ::JS_GetGlobalObject(cx), control, + nsresult rv = WrapNative(cx, GetGlobalJSObject(cx, obj), control, NS_GET_IID(nsISupports), vp); return NS_FAILED(rv) ? rv : NS_SUCCESS_I_DID_SOMETHING; } @@ -7446,7 +7822,7 @@ nsHTMLSelectElementSH::GetProperty(nsIXPConnectWrappedNative *wrapper, options->Item(n, getter_AddRefs(node)); - rv = WrapNative(cx, ::JS_GetGlobalObject(cx), node, + rv = WrapNative(cx, GetGlobalJSObject(cx, obj), node, NS_GET_IID(nsIDOMNode), vp); if (NS_SUCCEEDED(rv)) { rv = NS_SUCCESS_I_DID_SOMETHING; @@ -8041,7 +8417,7 @@ nsHTMLPluginObjElementSH::NewResolve(nsIXPConnectWrappedNative *wrapper, } nsCOMPtr holder; - rv = sXPConnect->WrapNative(cx, ::JS_GetGlobalObject(cx), pi, *iid, + rv = sXPConnect->WrapNative(cx, GetGlobalJSObject(cx, obj), pi, *iid, getter_AddRefs(holder)); if (NS_SUCCEEDED(rv)) { diff --git a/mozilla/dom/src/base/nsDOMClassInfo.h b/mozilla/dom/src/base/nsDOMClassInfo.h index 29d5c365759..a2164f0d546 100644 --- a/mozilla/dom/src/base/nsDOMClassInfo.h +++ b/mozilla/dom/src/base/nsDOMClassInfo.h @@ -43,6 +43,7 @@ #include "nsIXPCScriptable.h" #include "jsapi.h" #include "nsIScriptSecurityManager.h" +#include "nsIScriptContext.h" class nsIDOMWindow; class nsIDOMNSHTMLOptionCollection; @@ -153,9 +154,18 @@ public: static PRBool ObjectIsNativeWrapper(JSContext* cx, JSObject* obj) { - NS_PRECONDITION(sXPCNativeWrapperClass, - "Must know what the XPCNativeWrapper class is!"); - return ::JS_GetClass(cx, obj) == sXPCNativeWrapperClass; +#ifdef DEBUG + { + nsIScriptContext *scx = GetScriptContextFromJSContext(cx); + + NS_PRECONDITION(!scx || !scx->IsContextInitialized() || + sXPCNativeWrapperClass, + "Must know what the XPCNativeWrapper class is!"); + } +#endif + + return sXPCNativeWrapperClass && + ::JS_GetClass(cx, obj) == sXPCNativeWrapperClass; } /** @@ -422,9 +432,10 @@ public: JSObject **objp, PRBool *_retval); NS_IMETHOD Finalize(nsIXPConnectWrappedNative *wrapper, JSContext *cx, JSObject *obj); - - static nsresult OnDocumentChanged(JSContext *cx, JSObject *obj, - nsIDOMWindow *window); + NS_IMETHOD Equality(nsIXPConnectWrappedNative *wrapper, JSContext * cx, + JSObject * obj, jsval val, PRBool *bp); + NS_IMETHOD OuterObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx, + JSObject * obj, JSObject * *_retval); static JSBool JS_DLL_CALLBACK GlobalScopePolluterNewResolve(JSContext *cx, JSObject *obj, @@ -438,10 +449,8 @@ public: static JSBool JS_DLL_CALLBACK SecurityCheckOnSetProp(JSContext *cx, JSObject *obj, jsval id, jsval *vp); - static JSObject *GetInvalidatedGlobalScopePolluter(JSContext *cx, - JSObject *obj); + static void InvalidateGlobalScopePolluter(JSContext *cx, JSObject *obj); static nsresult InstallGlobalScopePolluter(JSContext *cx, JSObject *obj, - JSObject *oldPolluter, nsIHTMLDocument *doc); static nsIClassInfo *doCreate(nsDOMClassInfoData* aData) @@ -476,6 +485,30 @@ public: }; +// Navigator scriptable helper + +class nsNavigatorSH : public nsDOMGenericSH +{ +protected: + nsNavigatorSH(nsDOMClassInfoData* aData) : nsDOMGenericSH(aData) + { + } + + virtual ~nsNavigatorSH() + { + } + +public: + NS_IMETHOD PreCreate(nsISupports *nativeObj, JSContext *cx, + JSObject *globalObj, JSObject **parentObj); + + static nsIClassInfo *doCreate(nsDOMClassInfoData* aData) + { + return new nsNavigatorSH(aData); + } +}; + + // DOM Node helper, this class deals with setting the parent for the // wrappers diff --git a/mozilla/dom/src/base/nsDOMScriptObjectFactory.cpp b/mozilla/dom/src/base/nsDOMScriptObjectFactory.cpp index 539490e76a1..9177299fb30 100644 --- a/mozilla/dom/src/base/nsDOMScriptObjectFactory.cpp +++ b/mozilla/dom/src/base/nsDOMScriptObjectFactory.cpp @@ -98,22 +98,14 @@ NS_IMPL_RELEASE(nsDOMScriptObjectFactory) NS_IMETHODIMP nsDOMScriptObjectFactory::NewScriptContext(nsIScriptGlobalObject *aGlobal, - nsIScriptContext **aContext) + nsIScriptContext **aContext) { return NS_CreateScriptContext(aGlobal, aContext); } -NS_IMETHODIMP -nsDOMScriptObjectFactory::NewJSEventListener(nsIScriptContext *aContext, - nsISupports *aObject, - nsIDOMEventListener **aInstancePtrResult) -{ - return NS_NewJSEventListener(aInstancePtrResult, aContext, aObject); -} - NS_IMETHODIMP nsDOMScriptObjectFactory::NewScriptGlobalObject(PRBool aIsChrome, - nsIScriptGlobalObject **aGlobal) + nsIScriptGlobalObject **aGlobal) { return NS_NewScriptGlobalObject(aIsChrome, aGlobal); } @@ -157,8 +149,8 @@ nsDOMScriptObjectFactory::GetExternalClassInfoInstance(const nsAString& aName) NS_IMETHODIMP nsDOMScriptObjectFactory::Observe(nsISupports *aSubject, - const char *aTopic, - const PRUnichar *someData) + const char *aTopic, + const PRUnichar *someData) { if (!nsCRT::strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) { #ifdef MOZ_XUL diff --git a/mozilla/dom/src/base/nsDOMScriptObjectFactory.h b/mozilla/dom/src/base/nsDOMScriptObjectFactory.h index ec4501f598f..b7ec607dbb1 100644 --- a/mozilla/dom/src/base/nsDOMScriptObjectFactory.h +++ b/mozilla/dom/src/base/nsDOMScriptObjectFactory.h @@ -73,10 +73,6 @@ public: NS_IMETHOD NewScriptContext(nsIScriptGlobalObject *aGlobal, nsIScriptContext **aContext); - NS_IMETHOD NewJSEventListener(nsIScriptContext *aContext, - nsISupports *aObject, - nsIDOMEventListener **aInstancePtrResult); - NS_IMETHOD NewScriptGlobalObject(PRBool aIsChrome, nsIScriptGlobalObject **aGlobal); diff --git a/mozilla/dom/src/base/nsFocusController.cpp b/mozilla/dom/src/base/nsFocusController.cpp index 4bca2019649..dd465de8c6d 100644 --- a/mozilla/dom/src/base/nsFocusController.cpp +++ b/mozilla/dom/src/base/nsFocusController.cpp @@ -150,18 +150,33 @@ nsFocusController::RewindFocusState() NS_IMETHODIMP nsFocusController::SetFocusedWindow(nsIDOMWindowInternal* aWindow) { - if (aWindow && (mCurrentWindow != aWindow)) { - nsCOMPtr sgo = do_QueryInterface(aWindow); + nsCOMPtr pwin = do_QueryInterface(aWindow); + + if (pwin) { + pwin = pwin->GetOuterWindow(); + } + + NS_ASSERTION(!pwin || !pwin->IsInnerWindow(), + "Uh, inner window can't have focus!"); + + nsCOMPtr win = do_QueryInterface(pwin); + + if (win && (mCurrentWindow != win)) { + nsCOMPtr sgo = do_QueryInterface(win); if (sgo) { nsCOMPtr basewin = do_QueryInterface(sgo->GetDocShell()); if (basewin) basewin->SetFocus(); } } - if(mCurrentWindow) mPreviousWindow = mCurrentWindow; - else if (aWindow) mPreviousWindow = aWindow; - mCurrentWindow = aWindow; + if (mCurrentWindow) { + mPreviousWindow = mCurrentWindow; + } else if (win) { + mPreviousWindow = win; + } + + mCurrentWindow = win; if (mUpdateWindowWatcher) { NS_ASSERTION(mActive, "This shouldn't happen"); @@ -306,18 +321,16 @@ nsFocusController::Focus(nsIDOMEvent* aEvent) // but we don't hear the subsequent focus to the Ender window. nsCOMPtr ownerDoc; domElement->GetOwnerDocument(getter_AddRefs(ownerDoc)); - nsCOMPtr domWindow; - GetParentWindowFromDocument(ownerDoc, getter_AddRefs(domWindow)); + nsCOMPtr domWindow = GetWindowFromDocument(ownerDoc); if (domWindow) SetFocusedWindow(domWindow); } else { // We're focusing a window. We only want to do an update commands // if no element is focused. - nsCOMPtr domWindow; nsCOMPtr domDoc = do_QueryInterface(t); if (domDoc) { - GetParentWindowFromDocument(domDoc, getter_AddRefs(domWindow)); + nsCOMPtr domWindow = GetWindowFromDocument(domDoc); if (domWindow) { SetFocusedWindow(domWindow); if (mCurrentElement) { @@ -361,10 +374,9 @@ nsFocusController::Blur(nsIDOMEvent* aEvent) SetFocusedElement(nsnull); } - nsCOMPtr domWindow; nsCOMPtr domDoc = do_QueryInterface(t); if (domDoc) { - GetParentWindowFromDocument(domDoc, getter_AddRefs(domWindow)); + nsCOMPtr domWindow = GetWindowFromDocument(domDoc); if (domWindow) SetFocusedWindow(nsnull); } @@ -372,20 +384,21 @@ nsFocusController::Blur(nsIDOMEvent* aEvent) return NS_OK; } -nsresult -nsFocusController::GetParentWindowFromDocument(nsIDOMDocument* aDocument, - nsIDOMWindowInternal** aWindow) +nsPIDOMWindow * +nsFocusController::GetWindowFromDocument(nsIDOMDocument* aDocument) { - NS_ENSURE_ARG_POINTER(aWindow); + nsCOMPtr doc = do_QueryInterface(aDocument); + if (!doc) + return NS_OK; - nsCOMPtr objectOwner = do_QueryInterface(aDocument); - if(!objectOwner) return NS_OK; + nsCOMPtr win = + do_QueryInterface(doc->GetScriptGlobalObject()); - nsCOMPtr domWindow = - do_QueryInterface(objectOwner->GetScriptGlobalObject()); - *aWindow = domWindow; - NS_IF_ADDREF(*aWindow); - return NS_OK; + if (win->IsInnerWindow()) { + return win->GetOuterWindow(); + } + + return win; } NS_IMETHODIMP @@ -412,9 +425,7 @@ nsFocusController::GetControllerForCommand(const char * aCommand, // Move up to the window. nsCOMPtr domDoc; mCurrentElement->GetOwnerDocument(getter_AddRefs(domDoc)); - nsCOMPtr domWindow; - GetParentWindowFromDocument(domDoc, getter_AddRefs(domWindow)); - currentWindow = do_QueryInterface(domWindow); + currentWindow = do_QueryInterface(GetWindowFromDocument(domDoc)); } else if (mCurrentWindow) { nsGlobalWindow *win = @@ -426,20 +437,20 @@ nsFocusController::GetControllerForCommand(const char * aCommand, while(currentWindow) { nsCOMPtr domWindow(do_QueryInterface(currentWindow)); - if(domWindow) { - nsCOMPtr controllers2; - domWindow->GetControllers(getter_AddRefs(controllers2)); - if(controllers2) { - nsCOMPtr controller; - controllers2->GetControllerForCommand(aCommand, - getter_AddRefs(controller)); - if(controller) { - *_retval = controller; - NS_ADDREF(*_retval); - return NS_OK; - } + + nsCOMPtr controllers2; + domWindow->GetControllers(getter_AddRefs(controllers2)); + if(controllers2) { + nsCOMPtr controller; + controllers2->GetControllerForCommand(aCommand, + getter_AddRefs(controller)); + if(controller) { + *_retval = controller; + NS_ADDREF(*_retval); + return NS_OK; } - } + } + nsGlobalWindow *win = NS_STATIC_CAST(nsGlobalWindow *, NS_STATIC_CAST(nsIDOMWindowInternal *, currentWindow)); diff --git a/mozilla/dom/src/base/nsFocusController.h b/mozilla/dom/src/base/nsFocusController.h index d5c75e88926..8f6db75b901 100644 --- a/mozilla/dom/src/base/nsFocusController.h +++ b/mozilla/dom/src/base/nsFocusController.h @@ -50,6 +50,7 @@ class nsIDOMElement; class nsIDOMWindow; +class nsPIDOMWindow; class nsIController; class nsIControllers; @@ -105,7 +106,7 @@ protected: void UpdateWWActiveWindow(); public: - static nsresult GetParentWindowFromDocument(nsIDOMDocument* aElement, nsIDOMWindowInternal** aWindow); + static nsPIDOMWindow *GetWindowFromDocument(nsIDOMDocument* aElement); // Members protected: diff --git a/mozilla/dom/src/base/nsGlobalWindow.cpp b/mozilla/dom/src/base/nsGlobalWindow.cpp index 26b4774e5e1..f11ec0da537 100644 --- a/mozilla/dom/src/base/nsGlobalWindow.cpp +++ b/mozilla/dom/src/base/nsGlobalWindow.cpp @@ -180,6 +180,43 @@ PRInt32 gTimeoutCnt = 0; #define DOM_MIN_TIMEOUT_VALUE 10 // 10ms +#define FORWARD_TO_OUTER(method, args) \ + PR_BEGIN_MACRO \ + if (IsInnerWindow()) { \ + return GetOuterWindowInternal()->method args; \ + } \ + PR_END_MACRO + +#define FORWARD_TO_OUTER_VOID(method, args) \ + PR_BEGIN_MACRO \ + if (IsInnerWindow()) { \ + GetOuterWindowInternal()->method args; \ + return; \ + } \ + PR_END_MACRO + +#define FORWARD_TO_OUTER_CHROME(method, args) \ + PR_BEGIN_MACRO \ + if (IsInnerWindow()) { \ + return ((nsGlobalChromeWindow *)mOuterWindow)->method args; \ + } \ + PR_END_MACRO + +#define FORWARD_TO_INNER(method, args) \ + PR_BEGIN_MACRO \ + if (mInnerWindow) { \ + return GetCurrentInnerWindowInternal()->method args; \ + } \ + PR_END_MACRO + +#define FORWARD_TO_INNER_VOID(method, args) \ + PR_BEGIN_MACRO \ + if (mInnerWindow) { \ + GetCurrentInnerWindowInternal()->method args; \ + return; \ + } \ + PR_END_MACRO + // CIDs static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); #ifdef OJI @@ -205,25 +242,30 @@ static const char kPkcs11ContractID[] = NS_PKCS11_CONTRACTID; //*** nsGlobalWindow: Object Management //***************************************************************************** -nsGlobalWindow::nsGlobalWindow() - : mFirstDocumentLoad(PR_TRUE), - mIsScopeClear(PR_TRUE), +nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow) + : nsPIDOMWindow(aOuterWindow), mFullScreen(PR_FALSE), mIsClosed(PR_FALSE), mInClose(PR_FALSE), mOpenerWasCleared(PR_FALSE), mIsPopupSpam(PR_FALSE), mJSObject(nsnull), + mArguments(nsnull), mTimeouts(nsnull), mTimeoutInsertionPoint(&mTimeouts), mTimeoutPublicIdCounter(1), mTimeoutFiringDepth(0), mGlobalObjectOwner(nsnull), - mDocShell(nsnull), - mCurrentEvent(0) + mDocShell(nsnull) { - // nsPIDOMWindow initializers - mFrameElement = nsnull; + // Window object's are also PRCList's, the list is for keeping all + // innter windows reachable from the outer so that the proper + // cleanup can be done on shutdown. + PR_INIT_CLIST(this); + + if (aOuterWindow) { + PR_INSERT_AFTER(aOuterWindow, this); + } // We could have failed the first time through trying // to create the entropy collector, so we should @@ -249,6 +291,33 @@ nsGlobalWindow::~nsGlobalWindow() printf("--DOMWINDOW == %d\n", gRefCnt); #endif + nsGlobalWindow *outer = GetOuterWindowInternal(); + if (outer->mInnerWindow == this) { + outer->mInnerWindow = nsnull; + } + + if (IsOuterWindow() && !PR_CLIST_IS_EMPTY(this)) { + // An outer window is destroyed with inner windows still alive, + // iterate through the inner windows and null out their back + // pointer to this outer, and pull them out of the list of inner + // windows. + + nsGlobalWindow *w = (nsGlobalWindow *)PR_LIST_HEAD(this); + + while ((w = (nsGlobalWindow *)PR_LIST_HEAD(this)) != this) { + NS_ASSERTION(w->mOuterWindow == this, "Uh, bad outer window pointer?"); + + w->mOuterWindow = nsnull; + + PR_REMOVE_AND_INIT_LINK(w); + } + } else { + // An inner window is destroyed, pull it out of the outer window's + // list if inner windows. + + PR_REMOVE_LINK(this); + } + mDocument = nsnull; // Forces Release CleanUp(); @@ -260,11 +329,6 @@ nsGlobalWindow::ShutDown() { NS_IF_RELEASE(sSecMan); NS_IF_RELEASE(sComputedDOMStyleFactory); - -#ifdef DEBUG_jst - printf ("---- Leaked %d nsGlobalWindow's\n", gRefCnt); - printf ("---- Leaked %d nsTimeout's\n", gTimeoutCnt); -#endif } void @@ -295,6 +359,14 @@ nsGlobalWindow::CleanUp() SetPopupSpamWindow(PR_FALSE); --gOpenPopupSpamCount; } + + nsGlobalWindow *inner = GetCurrentInnerWindowInternal(); + + if (inner) { + inner->CleanUp(); + } + + mInnerWindowHolder = nsnull; } void @@ -355,6 +427,8 @@ NS_IMPL_RELEASE(nsGlobalWindow) void nsGlobalWindow::SetContext(nsIScriptContext* aContext) { + NS_ASSERTION(IsOuterWindow(), "Uh, SetContext() called on inner window!"); + // if setting the context to null, then we won't get to clean up the // named reference, so do it now if (!aContext) { @@ -368,6 +442,7 @@ nsGlobalWindow::SetContext(nsIScriptContext* aContext) if (mContext) { mContext->SetOwner(nsnull); } + mContext = aContext; if (mContext) { @@ -384,12 +459,16 @@ nsGlobalWindow::SetContext(nsIScriptContext* aContext) nsIScriptContext * nsGlobalWindow::GetContext() { + FORWARD_TO_OUTER(GetContext, ()); + return mContext; } void nsGlobalWindow::SetOpenerScriptURL(nsIURI* aURI) { + FORWARD_TO_OUTER_VOID(SetOpenerScriptURL, (aURI)); + mOpenerScriptURL = aURI; } @@ -435,14 +514,35 @@ nsGlobalWindow::SetNewDocument(nsIDOMDocument* aDocument, PRBool aRemoveEventListeners, PRBool aClearScopeHint) { - if (!aDocument && mDocument) { - // Cache the old principal now that the document is being removed. - nsCOMPtr doc(do_QueryInterface(mDocument)); - NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE); + return SetNewDocument(aDocument, aRemoveEventListeners, aClearScopeHint, + PR_FALSE); +} - mDocumentPrincipal = doc->GetPrincipal(); +nsresult +nsGlobalWindow::SetNewDocument(nsIDOMDocument* aDocument, + PRBool aRemoveEventListeners, + PRBool aClearScopeHint, + PRBool aIsInternalCall) +{ + if (!aIsInternalCall && IsInnerWindow()) { + return GetOuterWindowInternal()->SetNewDocument(aDocument, + aRemoveEventListeners, + aClearScopeHint, PR_TRUE); } + if (!aDocument) { + NS_ERROR("SetNewDocument(null) called!"); + + return NS_ERROR_INVALID_ARG; + } + + nsCOMPtr newDoc(do_QueryInterface(aDocument)); + NS_ENSURE_TRUE(newDoc, NS_ERROR_FAILURE); + + nsresult rv = NS_OK; + + nsCOMPtr oldDoc(do_QueryInterface(mDocument)); + // Always clear watchpoints, to deal with two cases: // 1. The first document for this window is loading, and a miscreant has // preset watchpoints on the window object in order to attack the new @@ -456,119 +556,61 @@ nsGlobalWindow::SetNewDocument(nsIDOMDocument* aDocument, JSContext *cx = nsnull; - if (mContext) { - cx = (JSContext *)mContext->GetNativeContext(); + // XXXjst: Update above comment. + nsIScriptContext *scx = GetContextInternal(); + if (scx) { + cx = (JSContext *)scx->GetNativeContext(); + } - if (mJSObject) { - ::JS_ClearWatchPointsForObject(cx, mJSObject); + // clear smartcard events, our document has gone away. + if (mCrypto) { + mCrypto->SetEnableSmartCardEvents(PR_FALSE); + } + + if (!mDocument) { + // First document load. + + // Get our private root. If it is equal to us, then we need to + // attach our global key bindings that handle browser scrolling + // and other browser commands. + nsIDOMWindowInternal *internal = nsGlobalWindow::GetPrivateRoot(); + + if (internal == NS_STATIC_CAST(nsIDOMWindowInternal *, this)) { + nsCOMPtr xblService = do_GetService("@mozilla.org/xbl;1"); + if (xblService) { + nsCOMPtr rec = + do_QueryInterface(mChromeEventHandler); + xblService->AttachGlobalKeyHandler(rec); + + // for now, the only way to get drag/drop is to use the XUL + // wrapper. There are just too many things that need to be + // added to hookup DnD with XBL (pinkerton) + //xblService->AttachGlobalDragHandler(rec); + } } } - if (aDocument) { - if (mNavigator && mDocumentPrincipal) { - // Loading a new document. Compare its principal against the - // old principal to see whether we are allowed to keep the old - // navigator object. - nsCOMPtr doc(do_QueryInterface(aDocument)); - NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE); - - nsIPrincipal *newPrincipal = doc->GetPrincipal(); - nsresult rv = NS_ERROR_FAILURE; - if (newPrincipal) { - rv = sSecMan->CheckSameOriginPrincipal(mDocumentPrincipal, - newPrincipal); - } - - if (NS_SUCCEEDED(rv)) { - // Same origins. Notify the navigator object that we are - // loading a new document, so it can make sure it is ready - // for the new document. - mNavigator->LoadingNewDocument(); - } else { - // Different origins. Destroy the navigator object so it gets - // recreated for the new document. The plugins or mime types - // arrays may have changed. See bug 150087. - mNavigatorHolder = nsnull; - - mNavigator->SetDocShell(nsnull); - - mNavigator = nsnull; - } - } - - // Let go of the cached principal since we no longer need it. - mDocumentPrincipal = nsnull; - - // clear smartcard events, our document has gone away. - if (mCrypto) { - mCrypto->SetEnableSmartCardEvents(PR_FALSE); - } - } - - if (mFirstDocumentLoad) { - if (aDocument) { - mFirstDocumentLoad = PR_FALSE; - } - - mDocument = aDocument; - - if (mDocument) { - // Get our private root. If it is equal to us, then we - // need to attach our global key bindings that handle - // browser scrolling and other browser commands. - nsIDOMWindowInternal *internal = nsGlobalWindow::GetPrivateRoot(); - - if (internal == NS_STATIC_CAST(nsIDOMWindowInternal *, this)) { - nsCOMPtr xblService = - do_GetService("@mozilla.org/xbl;1"); - if (xblService) { - nsCOMPtr rec = - do_QueryInterface(mChromeEventHandler); - xblService->AttachGlobalKeyHandler(rec); - - // for now, the only way to get drag/drop is to use the XUL - // wrapper. There are just too many things that need to be - // added to hookup DnD with XBL (pinkerton) - //xblService->AttachGlobalDragHandler(rec); - } - } - - nsCOMPtr html_doc(do_QueryInterface(aDocument)); - - nsWindowSH::InstallGlobalScopePolluter(cx, mJSObject, nsnull, html_doc); - } - - return NS_OK; - } - - /* No mDocShell means we've already been partially closed down. - When that happens, setting status isn't a big requirement, - so don't. (Doesn't happen under normal circumstances, but - bug 49615 describes a case.) */ + /* No mDocShell means we've either an inner window or we're already + been partially closed down. When that happens, setting status + isn't a big requirement, so don't. (Doesn't happen under normal + circumstances, but bug 49615 describes a case.) */ /* We only want to do this when we're setting a new document rather than going away. See bug 61840. */ - if (mDocShell && aDocument) { + if (mDocShell) { SetStatus(EmptyString()); SetDefaultStatus(EmptyString()); } - if (mDocument) { - nsCOMPtr doc(do_QueryInterface(mDocument)); - nsIURI *docURL; + // If we're in the middle of shutdown, nsContentUtils may have + // already been notified of shutdown and may return null here. + nsIXPConnect *xpc = nsContentUtils::XPConnect(); + PRBool reUseInnerWindow = PR_FALSE; - // If we had a document in this window the document most likely - // made our scope "unclear" + if (oldDoc) { + nsIURI *oldURL = oldDoc->GetDocumentURI(); - mIsScopeClear = PR_FALSE; - - if (doc) { - docURL = doc->GetDocumentURI(); - } else { - docURL = nsnull; - } - - if (docURL) { + if (oldURL) { nsCOMPtr treeItem(do_QueryInterface(mDocShell)); PRBool isContentWindow = PR_FALSE; @@ -579,122 +621,265 @@ nsGlobalWindow::SetNewDocument(nsIDOMDocument* aDocument, isContentWindow = itemType != nsIDocShellTreeItem::typeChrome; } - nsCAutoString url; - docURL->GetSpec(url); - PRBool isAboutBlank = url.EqualsLiteral("about:blank"); - PRBool isSameOrigin = PR_FALSE; - if (isAboutBlank && mOpenerScriptURL) { - nsCOMPtr webNav(do_QueryInterface(mDocShell)); - if (webNav) { - nsCOMPtr newDocURL; - webNav->GetCurrentURI(getter_AddRefs(newDocURL)); - if (newDocURL && sSecMan) { - sSecMan->SecurityCompareURIs(mOpenerScriptURL, - newDocURL, - &isSameOrigin); + PRBool isAboutBlank = PR_FALSE; + PRBool isAbout; + if (NS_SUCCEEDED(oldURL->SchemeIs("about", &isAbout)) && isAbout) { + nsCAutoString url; + oldURL->GetSpec(url); + isAboutBlank = url.EqualsLiteral("about:blank"); + + if (isAboutBlank && mOpenerScriptURL) { + nsCOMPtr webNav(do_QueryInterface(mDocShell)); + if (webNav) { + nsCOMPtr newURI; + webNav->GetCurrentURI(getter_AddRefs(newURI)); + if (newURI && sSecMan) { + // XXXjst: Uh, don't we want to compare the new URI + // against the calling URI (JS_GetScopeChain()?) and not + // the opener script URL? + sSecMan->SecurityCompareURIs(mOpenerScriptURL, newURI, + &isSameOrigin); + } } } } - if (!isAboutBlank || - (isContentWindow && aClearScopeHint && !isSameOrigin)) { - // the current document is *not* about:blank, - // or aClearScopeHint is true and the new document - // has a different origin than the calling script. - // clear timeouts and clear the scope - ClearAllTimeouts(); + reUseInnerWindow = + isAboutBlank && (!isContentWindow || !aClearScopeHint || + isSameOrigin); - if (mContext && mJSObject) { - // If we're in the middle of shutdown, nsContentUtils may have - // already been notified of shutdown. - nsIXPConnect *xpc = nsContentUtils::XPConnect(); - - if (mNavigator && xpc) { - nsIDOMNavigator* navigator = - NS_STATIC_CAST(nsIDOMNavigator*, mNavigator.get()); - xpc->WrapNative(cx, mJSObject, navigator, - NS_GET_IID(nsIDOMNavigator), - getter_AddRefs(mNavigatorHolder)); - } - - JSObject *gsp = - nsWindowSH::GetInvalidatedGlobalScopePolluter(cx, mJSObject); - - ::JS_ClearScope(cx, mJSObject); - ::JS_ClearRegExpStatics(cx); - - if (gsp) { - nsCOMPtr html_doc(do_QueryInterface(aDocument)); - - nsWindowSH::InstallGlobalScopePolluter(cx, mJSObject, gsp, - html_doc); - } - - mIsScopeClear = PR_TRUE; - } - } + // XXXjst: Remove the aRemoveEventListeners argument, it's + // always passed the same value as aClearScopeHint. // Don't remove event listeners in similar conditions aRemoveEventListeners = aRemoveEventListeners && (!isAboutBlank || (isContentWindow && !isSameOrigin)); - - } - - if (aRemoveEventListeners && mListenerManager) { - mListenerManager->RemoveAllListeners(PR_FALSE); - mListenerManager = nsnull; } } - if (mContext && aDocument) { - if (mNavigator && mJSObject) { - // Make our JS wrapper hold on to the navigator object so - // that it doesn't go away when transitioning from page to - // page. We do this by just asking for the navigator - // property on the global object. That causes the global - // object's resolve hook to cache the property on the - // global, and thus root it which prevents GC from getting - // rid of the object. - jsval dummy; - ::JS_GetProperty(cx, mJSObject, "navigator", &dummy); + // Drop our reference to the navigator object unless we're reusing + // the existing inner window or the new document is from the same + // origin as the old document. + nsIPrincipal *oldPrincipal; + if (!reUseInnerWindow && mNavigator && oldDoc && + (oldPrincipal = oldDoc->GetPrincipal())) { + nsIPrincipal *newPrincipal = newDoc->GetPrincipal(); + rv = NS_ERROR_FAILURE; + + if (newPrincipal) { + rv = sSecMan->CheckSameOriginPrincipal(oldPrincipal, newPrincipal); } - // Add an extra ref in case we release mContext during GC. - nsCOMPtr kungFuDeathGrip = mContext; - kungFuDeathGrip->GC(); + if (NS_FAILED(rv)) { + // Different origins. Release the navigator object so it gets + // recreated for the new document. The plugins or mime types + // arrays may have changed. See bug 150087. + mNavigator->SetDocShell(nsnull); + + mNavigator = nsnull; + } } + if (mNavigator && newDoc != oldDoc) { + // We didn't drop our reference to our old navigator object and + // we're loading a new document. Notify the navigator object about + // the new document load so that it can make sure it is ready for + // the new document. + + mNavigator->LoadingNewDocument(); + } + + // Set mDocument even if this is an outer window to avoid + // having to *always* reach into the inner window to find the + // document. + mDocument = aDocument; - if (mDocument && mContext) { - JSObject *gsp = - nsWindowSH::GetInvalidatedGlobalScopePolluter(cx, mJSObject); + if (IsOuterWindow()) { + scx->WillInitializeContext(); + } - // Lock gsp to keep it from being collected by a last-ditch GC under - // mContext->InitContext(this), or possibly other indirect GC-thing - // allocations that might nest between here and the point in - // nsWindowSH::InstallGlobalScopePolluter that puts gsp back into the - // window object's prototype chain. + if (xpc && IsOuterWindow()) { + nsGlobalWindow *currentInner = GetCurrentInnerWindowInternal(); - ::JS_LockGCThing(cx, gsp); + // In case we're not removing event listeners, move the event + // listener manager over to the new inner window. + nsCOMPtr listenerManager; - if (mIsScopeClear) { - mContext->InitContext(this); - } else { - // If we didn't clear the scope (i.e. the old document was - // about:blank) then we need to update the cached document - // property on the window to reflect the new document and not the - // old one. + if (currentInner) { + if (!reUseInnerWindow) { + currentInner->ClearAllTimeouts(); - nsWindowSH::OnDocumentChanged(cx, mJSObject, this); + currentInner->mChromeEventHandler = nsnull; + } + + if (aRemoveEventListeners && currentInner->mListenerManager) { + currentInner->mListenerManager->RemoveAllListeners(PR_FALSE); + currentInner->mListenerManager = nsnull; + } else { + listenerManager = currentInner->mListenerManager; + } + + nsWindowSH::InvalidateGlobalScopePolluter(cx, currentInner->mJSObject); } - nsCOMPtr html_doc(do_QueryInterface(mDocument)); + nsRefPtr newInnerWindow; - nsWindowSH::InstallGlobalScopePolluter(cx, mJSObject, gsp, html_doc); + nsCOMPtr thisChrome = + do_QueryInterface(NS_STATIC_CAST(nsIDOMWindow *, this)); + nsCOMPtr navigatorHolder; - ::JS_UnlockGCThing(cx, gsp); + PRUint32 flags = 0; + + if (reUseInnerWindow) { + // We're reusing the current inner window. + newInnerWindow = currentInner; + } else { + if (thisChrome) { + newInnerWindow = new nsGlobalChromeWindow(this); + + flags = nsIXPConnect::FLAG_SYSTEM_GLOBAL_OBJECT; + } else { + newInnerWindow = new nsGlobalWindow(this); + } + + if (!newInnerWindow) { + return NS_ERROR_OUT_OF_MEMORY; + } + + nsIScriptGlobalObject *sgo = + (nsIScriptGlobalObject *)newInnerWindow.get(); + + nsresult rv = xpc-> + InitClassesWithNewWrappedGlobal(cx, sgo, NS_GET_IID(nsISupports), + flags, + getter_AddRefs(mInnerWindowHolder)); + NS_ENSURE_SUCCESS(rv, rv); + + mInnerWindowHolder->GetJSObject(&newInnerWindow->mJSObject); + + if (currentInner && currentInner->mJSObject) { + if (mNavigator) { + // Hold on to the navigator wrapper so that we can set + // window.navigator in the new window to point to the same + // object (assuming we didn't change origins etc). See bug + // 163645 for more on why we need this. + + nsIDOMNavigator* navigator = + NS_STATIC_CAST(nsIDOMNavigator*, mNavigator.get()); + xpc->WrapNative(cx, currentInner->mJSObject, navigator, + NS_GET_IID(nsIDOMNavigator), + getter_AddRefs(navigatorHolder)); + } + + PRBool termFuncSet = PR_FALSE; + + if (oldDoc == newDoc) { + nsCOMPtr stack = + do_GetService(sJSStackContractID); + + JSContext *cx = nsnull; + + if (stack) { + stack->Peek(&cx); + } + + nsIScriptContext *callerScx; + if (cx && (callerScx = GetScriptContextFromJSContext(cx))) { + // We're called from document.open() (and document.open() is + // called from JS), clear the scope etc in a termination + // function on the calling context to prevent clearing the + // calling scope. + callerScx->SetTerminationFunction(ClearWindowScope, + NS_STATIC_CAST(nsIDOMWindow *, + currentInner)); + + termFuncSet = PR_TRUE; + } + } + + // Clear scope on the outer window + ::JS_ClearScope(cx, mJSObject); + ::JS_ClearWatchPointsForObject(cx, mJSObject); + + // Re-initialize the outer window. + scx->InitContext(this); + + if (!termFuncSet) { + ::JS_ClearScope(cx, currentInner->mJSObject); + ::JS_ClearWatchPointsForObject(cx, currentInner->mJSObject); + ::JS_ClearRegExpStatics(cx); + } + + // Make the current inner window release its strong references to + // the document to prevent it from keeping everything around. + currentInner->mDocument = nsnull; + } + + mInnerWindow = newInnerWindow; + + // InitClassesWithNewWrappedGlobal() sets the global object in + // cx to be the new wrapped global. We don't want that, so set + // it back to our own JS object. + + ::JS_SetGlobalObject(cx, mJSObject); + + if (newDoc != oldDoc) { + nsCOMPtr html_doc(do_QueryInterface(mDocument)); + nsWindowSH::InstallGlobalScopePolluter(cx, newInnerWindow->mJSObject, + html_doc); + } + } + + if (newDoc) { + newDoc->SetScriptGlobalObject(newInnerWindow); + } + + if (reUseInnerWindow) { + newInnerWindow->mDocument = aDocument; + } else { + rv = newInnerWindow->SetNewDocument(aDocument, aRemoveEventListeners, + aClearScopeHint, PR_TRUE); + NS_ENSURE_SUCCESS(rv, rv); + + // Initialize DOM classes etc on the inner window. + rv = scx->InitClasses(newInnerWindow->mJSObject); + NS_ENSURE_SUCCESS(rv, rv); + + if (navigatorHolder) { + // Restore window.navigator onto the new inner window. + JSObject *nav; + navigatorHolder->GetJSObject(&nav); + + jsval navVal = OBJECT_TO_JSVAL(nav); + ::JS_SetProperty(cx, newInnerWindow->mJSObject, "navigator", &navVal); + } + + newInnerWindow->mListenerManager = listenerManager; + } + + if (mArguments) { + jsval args = OBJECT_TO_JSVAL(mArguments); + + ::JS_SetProperty(cx, newInnerWindow->mJSObject, "arguments", + &args); + + ::JS_UnlockGCThing(cx, mArguments); + mArguments = nsnull; + } + + // Give the new inner window our chrome event handler (since it + // doesn't have one). + newInnerWindow->mChromeEventHandler = mChromeEventHandler; + } + + if (scx && IsOuterWindow()) { + // Add an extra ref in case we release mContext during GC. + nsCOMPtr kungFuDeathGrip = scx; + scx->GC(); + + scx->DidInitializeContext(); } // Clear our mutation bitfield. @@ -706,6 +891,8 @@ nsGlobalWindow::SetNewDocument(nsIDOMDocument* aDocument, void nsGlobalWindow::SetDocShell(nsIDocShell* aDocShell) { + NS_ASSERTION(IsOuterWindow(), "Uh, SetDocShell() called on inner window!"); + if (aDocShell == mDocShell) return; @@ -718,6 +905,49 @@ nsGlobalWindow::SetDocShell(nsIDocShell* aDocShell) if (!aDocShell && mContext) { ClearAllTimeouts(); + JSContext *cx = (JSContext *)mContext->GetNativeContext(); + + nsGlobalWindow *currentInner = GetCurrentInnerWindowInternal(); + if (currentInner) { + currentInner->ClearAllTimeouts(); + + if (currentInner->mListenerManager) { + currentInner->mListenerManager->RemoveAllListeners(PR_FALSE); + currentInner->mListenerManager = nsnull; + } + + JSContext *cx = (JSContext *)mContext->GetNativeContext(); + + // XXXjst: We shouldn't need to do this, but if we don't we leak + // the world... actually, even with this we leak the + // world... need to figure this out. + if (currentInner->mJSObject) { + ::JS_ClearScope(cx, currentInner->mJSObject); + ::JS_ClearWatchPointsForObject(cx, currentInner->mJSObject); + + // Release the current inner window's document references. + currentInner->mDocument = nsnull; + nsWindowSH::InvalidateGlobalScopePolluter(cx, currentInner->mJSObject); + } + + // Release the our document reference + mDocument = nsnull; + + if (mJSObject) { + ::JS_ClearScope(cx, mJSObject); + ::JS_ClearWatchPointsForObject(cx, mJSObject); + + // An outer window shouldn't have a global scope polluter, but + // in case code on a webpage took one and put it in an outer + // object's prototype, we need to invalidate it nonetheless. + nsWindowSH::InvalidateGlobalScopePolluter(cx, mJSObject); + } + + ::JS_ClearRegExpStatics(cx); + + currentInner->mChromeEventHandler = nsnull; + } + // if we are closing the window while in full screen mode, be sure // to restore os chrome if (mFullScreen) { @@ -738,7 +968,16 @@ nsGlobalWindow::SetDocShell(nsIDocShell* aDocShell) ClearControllers(); - mNavigatorHolder = nsnull; + mChromeEventHandler = nsnull; // force release now + + if (mArguments) { + // We got no new document after someone called + // SetNewArguments(), drop our reference to the arguments. + ::JS_UnlockGCThing(cx, mArguments); + mArguments = nsnull; + } + + mInnerWindowHolder = nsnull; mContext->GC(); @@ -746,7 +985,6 @@ nsGlobalWindow::SetDocShell(nsIDocShell* aDocShell) mContext->SetOwner(nsnull); mContext = nsnull; // force release now } - mChromeEventHandler = nsnull; // force release now } mDocShell = aDocShell; // Weak Reference @@ -794,24 +1032,30 @@ nsGlobalWindow::SetDocShell(nsIDocShell* aDocShell) nsIDocShell * nsGlobalWindow::GetDocShell() { - return mDocShell; + return GetDocShellInternal(); } void nsGlobalWindow::SetOpenerWindow(nsIDOMWindowInternal* aOpener) { + FORWARD_TO_OUTER_VOID(SetOpenerWindow, (aOpener)); + mOpener = aOpener; } void nsGlobalWindow::SetGlobalObjectOwner(nsIScriptGlobalObjectOwner* aOwner) { + FORWARD_TO_OUTER_VOID(SetGlobalObjectOwner, (aOwner)); + mGlobalObjectOwner = aOwner; // Note this is supposed to be a weak ref. } nsIScriptGlobalObjectOwner * nsGlobalWindow::GetGlobalObjectOwner() { + FORWARD_TO_OUTER(GetGlobalObjectOwner, ()); + return mGlobalObjectOwner; } @@ -820,6 +1064,11 @@ nsGlobalWindow::HandleDOMEvent(nsPresContext* aPresContext, nsEvent* aEvent, nsIDOMEvent** aDOMEvent, PRUint32 aFlags, nsEventStatus* aEventStatus) { + FORWARD_TO_INNER(HandleDOMEvent, + (aPresContext, aEvent, aDOMEvent, aFlags, aEventStatus)); + + nsGlobalWindow *outer = GetOuterWindowInternal(); + // Make sure to tell the event that dispatch has started. NS_MARK_EVENT_DISPATCH_STARTED(aEvent); @@ -828,14 +1077,11 @@ nsGlobalWindow::HandleDOMEvent(nsPresContext* aPresContext, nsEvent* aEvent, nsIDOMEvent *domEvent = nsnull; static PRUint32 count = 0; - nsEvent *oldEvent = mCurrentEvent; - mCurrentEvent = aEvent; - /* mChromeEventHandler and mContext go dangling in the middle of this function under some circumstances (events that destroy the window) without this addref. */ nsCOMPtr kungFuDeathGrip1(mChromeEventHandler); - nsCOMPtr kungFuDeathGrip2(mContext); + nsCOMPtr kungFuDeathGrip2(GetContextInternal()); /* If this is a mouse event, use the struct to provide entropy for * the system. @@ -866,7 +1112,7 @@ nsGlobalWindow::HandleDOMEvent(nsPresContext* aPresContext, nsEvent* aEvent, // if the window is deactivated while in full screen mode, // restore OS chrome, and hide it again upon re-activation - if (mFullScreen && (NS_EVENT_FLAG_BUBBLE & aFlags)) { + if (outer->mFullScreen && (NS_EVENT_FLAG_BUBBLE & aFlags)) { if (aEvent->message == NS_DEACTIVATE || aEvent->message == NS_ACTIVATE) { nsCOMPtr fullScreen = do_GetService("@mozilla.org/browser/fullscreen;1"); @@ -954,9 +1200,10 @@ nsGlobalWindow::HandleDOMEvent(nsPresContext* aPresContext, nsEvent* aEvent, } if (aEvent->message == NS_PAGE_LOAD) { - nsCOMPtr content(do_QueryInterface(mFrameElement)); + nsCOMPtr content(do_QueryInterface(GetFrameElementInternal())); - nsCOMPtr treeItem(do_QueryInterface(mDocShell)); + nsCOMPtr treeItem = + do_QueryInterface(GetDocShellInternal()); PRInt32 itemType = nsIDocShellTreeItem::typeChrome; @@ -1006,7 +1253,6 @@ nsGlobalWindow::HandleDOMEvent(nsPresContext* aPresContext, nsEvent* aEvent, NS_MARK_EVENT_DISPATCH_DONE(aEvent); } - mCurrentEvent = oldEvent; return ret; } @@ -1031,6 +1277,8 @@ nsGlobalWindow::OnFinalize(JSObject *aJSObject) void nsGlobalWindow::SetScriptsEnabled(PRBool aEnabled, PRBool aFireTimeouts) { + FORWARD_TO_INNER(SetScriptsEnabled, (aEnabled, aFireTimeouts)); + if (aEnabled && aFireTimeouts) { // Scripts are enabled (again?) on this context, run timeouts that // fired on this context while scripts were disabled. @@ -1039,6 +1287,33 @@ nsGlobalWindow::SetScriptsEnabled(PRBool aEnabled, PRBool aFireTimeouts) } } +nsresult +nsGlobalWindow::SetNewArguments(JSObject *aArguments) +{ + FORWARD_TO_OUTER(SetNewArguments, (aArguments)); + + JSContext *cx; + NS_ENSURE_TRUE(aArguments && mContext && + (cx = (JSContext *)mContext->GetNativeContext()), + NS_ERROR_NOT_INITIALIZED); + + nsGlobalWindow *currentInner = GetCurrentInnerWindowInternal(); + + jsval args = OBJECT_TO_JSVAL(aArguments); + + if (currentInner && currentInner->mJSObject) { + if (!::JS_SetProperty(cx, currentInner->mJSObject, "arguments", &args)) { + return NS_ERROR_FAILURE; + } + } + + // Hold on to the arguments so that we can re-set them once the next + // document is loaded. + mArguments = aArguments; + ::JS_LockGCThing(cx, mArguments); + + return NS_OK; +} //***************************************************************************** // nsGlobalWindow::nsIScriptObjectPrincipal @@ -1047,6 +1322,8 @@ nsGlobalWindow::SetScriptsEnabled(PRBool aEnabled, PRBool aFireTimeouts) nsIPrincipal* nsGlobalWindow::GetPrincipal() { + // XXXjst: figure out inner window stuff... + if (mDocument) { // If we have a document, get the principal from the document nsCOMPtr doc(do_QueryInterface(mDocument)); @@ -1055,10 +1332,6 @@ nsGlobalWindow::GetPrincipal() return doc->GetPrincipal(); } - if (mDocumentPrincipal) { - return mDocumentPrincipal; - } - // If we don't have a principal and we don't have a document we // ask the parent window for the principal. This can happen when // loading a frameset that has a , in @@ -1087,8 +1360,9 @@ nsGlobalWindow::GetDocument(nsIDOMDocument** aDocument) // thing as our mDocument, but we don't have to explicitly set the // member variable because the docshell has already called // SetNewDocument(). - if (!mDocument && mDocShell) - nsCOMPtr domdoc(do_GetInterface(mDocShell)); + nsIDocShell *docShell; + if (!mDocument && (docShell = GetDocShellInternal())) + nsCOMPtr domdoc(do_GetInterface(docShell)); NS_IF_ADDREF(*aDocument = mDocument); @@ -1102,6 +1376,8 @@ nsGlobalWindow::GetDocument(nsIDOMDocument** aDocument) NS_IMETHODIMP nsGlobalWindow::GetWindow(nsIDOMWindowInternal** aWindow) { + FORWARD_TO_OUTER(GetWindow, (aWindow)); + *aWindow = NS_STATIC_CAST(nsIDOMWindowInternal *, this); NS_ADDREF(*aWindow); return NS_OK; @@ -1110,6 +1386,8 @@ nsGlobalWindow::GetWindow(nsIDOMWindowInternal** aWindow) NS_IMETHODIMP nsGlobalWindow::GetSelf(nsIDOMWindowInternal** aWindow) { + FORWARD_TO_OUTER(GetSelf, (aWindow)); + *aWindow = NS_STATIC_CAST(nsIDOMWindowInternal *, this); NS_ADDREF(*aWindow); return NS_OK; @@ -1118,6 +1396,8 @@ nsGlobalWindow::GetSelf(nsIDOMWindowInternal** aWindow) NS_IMETHODIMP nsGlobalWindow::GetNavigator(nsIDOMNavigator** aNavigator) { + FORWARD_TO_OUTER(GetNavigator, (aNavigator)); + *aNavigator = nsnull; if (!mNavigator) { @@ -1135,6 +1415,8 @@ nsGlobalWindow::GetNavigator(nsIDOMNavigator** aNavigator) NS_IMETHODIMP nsGlobalWindow::GetScreen(nsIDOMScreen** aScreen) { + FORWARD_TO_OUTER(GetScreen, (aScreen)); + *aScreen = nsnull; if (!mScreen && mDocShell) { @@ -1152,6 +1434,8 @@ nsGlobalWindow::GetScreen(nsIDOMScreen** aScreen) NS_IMETHODIMP nsGlobalWindow::GetHistory(nsIDOMHistory** aHistory) { + FORWARD_TO_OUTER(GetHistory, (aHistory)); + *aHistory = nsnull; if (!mHistory && mDocShell) { @@ -1168,7 +1452,8 @@ nsGlobalWindow::GetHistory(nsIDOMHistory** aHistory) NS_IMETHODIMP nsGlobalWindow::GetParent(nsIDOMWindow** aParent) { - NS_ENSURE_ARG_POINTER(aParent); + FORWARD_TO_OUTER(GetParent, (aParent)); + *aParent = nsnull; if (!mDocShell) return NS_OK; @@ -1194,6 +1479,8 @@ nsGlobalWindow::GetParent(nsIDOMWindow** aParent) NS_IMETHODIMP nsGlobalWindow::GetTop(nsIDOMWindow** aTop) { + FORWARD_TO_OUTER(GetTop, (aTop)); + nsresult ret = NS_OK; *aTop = nsnull; @@ -1214,6 +1501,8 @@ nsGlobalWindow::GetTop(nsIDOMWindow** aTop) NS_IMETHODIMP nsGlobalWindow::GetContent(nsIDOMWindow** aContent) { + FORWARD_TO_OUTER(GetContent, (aContent)); + *aContent = nsnull; nsCOMPtr primaryContent; @@ -1254,6 +1543,8 @@ nsGlobalWindow::GetContent(nsIDOMWindow** aContent) NS_IMETHODIMP nsGlobalWindow::GetPrompter(nsIPrompt** aPrompt) { + FORWARD_TO_OUTER(GetPrompter, (aPrompt)); + if (!mDocShell) return NS_ERROR_FAILURE; @@ -1267,6 +1558,8 @@ nsGlobalWindow::GetPrompter(nsIPrompt** aPrompt) NS_IMETHODIMP nsGlobalWindow::GetMenubar(nsIDOMBarProp** aMenubar) { + FORWARD_TO_OUTER(GetMenubar, (aMenubar)); + *aMenubar = nsnull; if (!mMenubar) { @@ -1289,6 +1582,8 @@ nsGlobalWindow::GetMenubar(nsIDOMBarProp** aMenubar) NS_IMETHODIMP nsGlobalWindow::GetToolbar(nsIDOMBarProp** aToolbar) { + FORWARD_TO_OUTER(GetToolbar, (aToolbar)); + *aToolbar = nsnull; if (!mToolbar) { @@ -1311,6 +1606,8 @@ nsGlobalWindow::GetToolbar(nsIDOMBarProp** aToolbar) NS_IMETHODIMP nsGlobalWindow::GetLocationbar(nsIDOMBarProp** aLocationbar) { + FORWARD_TO_OUTER(GetLocationbar, (aLocationbar)); + *aLocationbar = nsnull; if (!mLocationbar) { @@ -1333,6 +1630,8 @@ nsGlobalWindow::GetLocationbar(nsIDOMBarProp** aLocationbar) NS_IMETHODIMP nsGlobalWindow::GetPersonalbar(nsIDOMBarProp** aPersonalbar) { + FORWARD_TO_OUTER(GetPersonalbar, (aPersonalbar)); + *aPersonalbar = nsnull; if (!mPersonalbar) { @@ -1355,6 +1654,8 @@ nsGlobalWindow::GetPersonalbar(nsIDOMBarProp** aPersonalbar) NS_IMETHODIMP nsGlobalWindow::GetStatusbar(nsIDOMBarProp** aStatusbar) { + FORWARD_TO_OUTER(GetStatusbar, (aStatusbar)); + *aStatusbar = nsnull; if (!mStatusbar) { @@ -1377,6 +1678,8 @@ nsGlobalWindow::GetStatusbar(nsIDOMBarProp** aStatusbar) NS_IMETHODIMP nsGlobalWindow::GetScrollbars(nsIDOMBarProp** aScrollbars) { + FORWARD_TO_OUTER(GetScrollbars, (aScrollbars)); + *aScrollbars = nsnull; if (!mScrollbars) { @@ -1405,6 +1708,8 @@ nsGlobalWindow::GetDirectories(nsIDOMBarProp** aDirectories) NS_IMETHODIMP nsGlobalWindow::GetClosed(PRBool* aClosed) { + FORWARD_TO_OUTER(GetClosed, (aClosed)); + // If someone called close(), or if we don't have a docshell, we're // closed. *aClosed = mIsClosed || !mDocShell; @@ -1415,6 +1720,8 @@ nsGlobalWindow::GetClosed(PRBool* aClosed) NS_IMETHODIMP nsGlobalWindow::GetFrames(nsIDOMWindowCollection** aFrames) { + FORWARD_TO_OUTER(GetFrames, (aFrames)); + *aFrames = nsnull; if (!mFrames && mDocShell) { @@ -1432,6 +1739,8 @@ nsGlobalWindow::GetFrames(nsIDOMWindowCollection** aFrames) NS_IMETHODIMP nsGlobalWindow::GetCrypto(nsIDOMCrypto** aCrypto) { + FORWARD_TO_OUTER(GetCrypto, (aCrypto)); + if (!mCrypto) { mCrypto = do_CreateInstance(kCryptoContractID); } @@ -1444,6 +1753,8 @@ nsGlobalWindow::GetCrypto(nsIDOMCrypto** aCrypto) NS_IMETHODIMP nsGlobalWindow::GetPkcs11(nsIDOMPkcs11** aPkcs11) { + FORWARD_TO_OUTER(GetPkcs11, (aPkcs11)); + if (!mPkcs11) { mPkcs11 = do_CreateInstance(kPkcs11ContractID); } @@ -1456,6 +1767,8 @@ nsGlobalWindow::GetPkcs11(nsIDOMPkcs11** aPkcs11) NS_IMETHODIMP nsGlobalWindow::GetControllers(nsIControllers** aResult) { + FORWARD_TO_OUTER(GetControllers, (aResult)); + if (!mControllers) { nsresult rv; mControllers = do_CreateInstance(kXULControllersCID, &rv); @@ -1481,6 +1794,8 @@ nsGlobalWindow::GetControllers(nsIControllers** aResult) NS_IMETHODIMP nsGlobalWindow::GetOpener(nsIDOMWindowInternal** aOpener) { + FORWARD_TO_OUTER(GetOpener, (aOpener)); + *aOpener = nsnull; // First, check if we were called from a privileged chrome script @@ -1518,6 +1833,8 @@ nsGlobalWindow::GetOpener(nsIDOMWindowInternal** aOpener) NS_IMETHODIMP nsGlobalWindow::SetOpener(nsIDOMWindowInternal* aOpener) { + FORWARD_TO_OUTER(SetOpener, (aOpener)); + // check if we were called from a privileged chrome script. // If not, opener is settable only to null. if (aOpener && !IsCallerChrome()) { @@ -1534,6 +1851,8 @@ nsGlobalWindow::SetOpener(nsIDOMWindowInternal* aOpener) NS_IMETHODIMP nsGlobalWindow::GetStatus(nsAString& aStatus) { + FORWARD_TO_OUTER(GetStatus, (aStatus)); + aStatus = mStatus; return NS_OK; } @@ -1541,6 +1860,8 @@ nsGlobalWindow::GetStatus(nsAString& aStatus) NS_IMETHODIMP nsGlobalWindow::SetStatus(const nsAString& aStatus) { + FORWARD_TO_OUTER(SetStatus, (aStatus)); + /* * If caller is not chrome and dom.disable_window_status_change is true, * prevent setting window.status by exiting early @@ -1565,6 +1886,8 @@ nsGlobalWindow::SetStatus(const nsAString& aStatus) NS_IMETHODIMP nsGlobalWindow::GetDefaultStatus(nsAString& aDefaultStatus) { + FORWARD_TO_OUTER(GetDefaultStatus, (aDefaultStatus)); + aDefaultStatus = mDefaultStatus; return NS_OK; } @@ -1572,6 +1895,8 @@ nsGlobalWindow::GetDefaultStatus(nsAString& aDefaultStatus) NS_IMETHODIMP nsGlobalWindow::SetDefaultStatus(const nsAString& aDefaultStatus) { + FORWARD_TO_OUTER(SetDefaultStatus, (aDefaultStatus)); + /* * If caller is not chrome and dom.disable_window_status_change is true, * prevent setting window.defaultStatus by exiting early @@ -1596,6 +1921,8 @@ nsGlobalWindow::SetDefaultStatus(const nsAString& aDefaultStatus) NS_IMETHODIMP nsGlobalWindow::GetName(nsAString& aName) { + FORWARD_TO_OUTER(GetName, (aName)); + nsXPIDLString name; nsCOMPtr docShellAsItem(do_QueryInterface(mDocShell)); if (docShellAsItem) @@ -1608,6 +1935,8 @@ nsGlobalWindow::GetName(nsAString& aName) NS_IMETHODIMP nsGlobalWindow::SetName(const nsAString& aName) { + FORWARD_TO_OUTER(SetName, (aName)); + nsresult result = NS_OK; nsCOMPtr docShellAsItem(do_QueryInterface(mDocShell)); if (docShellAsItem) @@ -1618,6 +1947,8 @@ nsGlobalWindow::SetName(const nsAString& aName) NS_IMETHODIMP nsGlobalWindow::GetInnerWidth(PRInt32* aInnerWidth) { + FORWARD_TO_OUTER(GetInnerWidth, (aInnerWidth)); + EnsureSizeUpToDate(); nsCOMPtr docShellWin(do_QueryInterface(mDocShell)); @@ -1632,6 +1963,8 @@ nsGlobalWindow::GetInnerWidth(PRInt32* aInnerWidth) NS_IMETHODIMP nsGlobalWindow::SetInnerWidth(PRInt32 aInnerWidth) { + FORWARD_TO_OUTER(SetInnerWidth, (aInnerWidth)); + /* * If caller is not chrome and dom.disable_window_move_resize is true, * prevent setting window.innerWidth by exiting early @@ -1662,6 +1995,8 @@ nsGlobalWindow::SetInnerWidth(PRInt32 aInnerWidth) NS_IMETHODIMP nsGlobalWindow::GetInnerHeight(PRInt32* aInnerHeight) { + FORWARD_TO_OUTER(GetInnerHeight, (aInnerHeight)); + EnsureSizeUpToDate(); nsCOMPtr docShellWin(do_QueryInterface(mDocShell)); @@ -1676,6 +2011,8 @@ nsGlobalWindow::GetInnerHeight(PRInt32* aInnerHeight) NS_IMETHODIMP nsGlobalWindow::SetInnerHeight(PRInt32 aInnerHeight) { + FORWARD_TO_OUTER(SetInnerHeight, (aInnerHeight)); + /* * If caller is not chrome and dom.disable_window_move_resize is true, * prevent setting window.innerHeight by exiting early @@ -1707,6 +2044,8 @@ nsGlobalWindow::SetInnerHeight(PRInt32 aInnerHeight) NS_IMETHODIMP nsGlobalWindow::GetOuterWidth(PRInt32* aOuterWidth) { + FORWARD_TO_OUTER(GetOuterWidth, (aOuterWidth)); + nsCOMPtr treeOwnerAsWin; GetTreeOwner(getter_AddRefs(treeOwnerAsWin)); NS_ENSURE_TRUE(treeOwnerAsWin, NS_ERROR_FAILURE); @@ -1726,6 +2065,8 @@ nsGlobalWindow::GetOuterWidth(PRInt32* aOuterWidth) NS_IMETHODIMP nsGlobalWindow::SetOuterWidth(PRInt32 aOuterWidth) { + FORWARD_TO_OUTER(SetOuterWidth, (aOuterWidth)); + /* * If caller is not chrome and dom.disable_window_move_resize is true, * prevent setting window.outerWidth by exiting early @@ -1754,6 +2095,8 @@ nsGlobalWindow::SetOuterWidth(PRInt32 aOuterWidth) NS_IMETHODIMP nsGlobalWindow::GetOuterHeight(PRInt32* aOuterHeight) { + FORWARD_TO_OUTER(GetOuterHeight, (aOuterHeight)); + nsCOMPtr treeOwnerAsWin; GetTreeOwner(getter_AddRefs(treeOwnerAsWin)); NS_ENSURE_TRUE(treeOwnerAsWin, NS_ERROR_FAILURE); @@ -1774,6 +2117,8 @@ nsGlobalWindow::GetOuterHeight(PRInt32* aOuterHeight) NS_IMETHODIMP nsGlobalWindow::SetOuterHeight(PRInt32 aOuterHeight) { + FORWARD_TO_OUTER(SetOuterHeight, (aOuterHeight)); + /* * If caller is not chrome and dom.disable_window_move_resize is true, * prevent setting window.outerHeight by exiting early @@ -1802,6 +2147,8 @@ nsGlobalWindow::SetOuterHeight(PRInt32 aOuterHeight) NS_IMETHODIMP nsGlobalWindow::GetScreenX(PRInt32* aScreenX) { + FORWARD_TO_OUTER(GetScreenX, (aScreenX)); + nsCOMPtr treeOwnerAsWin; GetTreeOwner(getter_AddRefs(treeOwnerAsWin)); NS_ENSURE_TRUE(treeOwnerAsWin, NS_ERROR_FAILURE); @@ -1817,6 +2164,8 @@ nsGlobalWindow::GetScreenX(PRInt32* aScreenX) NS_IMETHODIMP nsGlobalWindow::SetScreenX(PRInt32 aScreenX) { + FORWARD_TO_OUTER(SetScreenX, (aScreenX)); + /* * If caller is not chrome and dom.disable_window_move_resize is true, * prevent setting window.screenX by exiting early @@ -1846,6 +2195,8 @@ nsGlobalWindow::SetScreenX(PRInt32 aScreenX) NS_IMETHODIMP nsGlobalWindow::GetScreenY(PRInt32* aScreenY) { + FORWARD_TO_OUTER(GetScreenY, (aScreenY)); + nsCOMPtr treeOwnerAsWin; GetTreeOwner(getter_AddRefs(treeOwnerAsWin)); NS_ENSURE_TRUE(treeOwnerAsWin, NS_ERROR_FAILURE); @@ -1861,6 +2212,8 @@ nsGlobalWindow::GetScreenY(PRInt32* aScreenY) NS_IMETHODIMP nsGlobalWindow::SetScreenY(PRInt32 aScreenY) { + FORWARD_TO_OUTER(SetScreenY, (aScreenY)); + /* * If caller is not chrome and dom.disable_window_move_resize is true, * prevent setting window.screenY by exiting early @@ -2007,6 +2360,8 @@ nsGlobalWindow::GetPageYOffset(PRInt32* aPageYOffset) nsresult nsGlobalWindow::GetScrollMaxXY(PRInt32* aScrollMaxX, PRInt32* aScrollMaxY) { + FORWARD_TO_OUTER(GetScrollMaxXY, (aScrollMaxX, aScrollMaxY)); + nsresult rv; nsIScrollableView *view = nsnull; // no addref/release for views float p2t, t2p; @@ -2052,6 +2407,8 @@ nsresult nsGlobalWindow::GetScrollXY(PRInt32* aScrollX, PRInt32* aScrollY, PRBool aDoFlush) { + FORWARD_TO_OUTER(GetScrollXY, (aScrollX, aScrollY, aDoFlush)); + nsresult rv; nsIScrollableView *view = nsnull; // no addref/release for views float p2t, t2p; @@ -2169,10 +2526,11 @@ nsGlobalWindow::WindowExists(const nsAString& aName) if (!caller) { // If we can't reach a caller, try to use our own docshell - caller = do_QueryInterface(mDocShell); + caller = do_QueryInterface(GetDocShellInternal()); } - nsCOMPtr docShell(do_QueryInterface(mDocShell)); + nsCOMPtr docShell = + do_QueryInterface(GetDocShellInternal()); if (docShell) { nsCOMPtr namedItem; @@ -2218,6 +2576,8 @@ nsGlobalWindow::GetMainWidget() NS_IMETHODIMP nsGlobalWindow::SetFullScreen(PRBool aFullScreen) { + FORWARD_TO_OUTER(SetFullScreen, (aFullScreen)); + // Only chrome can change our fullScreen mode. if (aFullScreen == mFullScreen || !IsCallerChrome()) { return NS_OK; @@ -2262,6 +2622,8 @@ nsGlobalWindow::SetFullScreen(PRBool aFullScreen) NS_IMETHODIMP nsGlobalWindow::GetFullScreen(PRBool* aFullScreen) { + FORWARD_TO_OUTER(GetFullScreen, (aFullScreen)); + *aFullScreen = mFullScreen; return NS_OK; } @@ -2331,6 +2693,8 @@ nsGlobalWindow::EnsureReflowFlushAndPaint() NS_IMETHODIMP nsGlobalWindow::GetTextZoom(float *aZoom) { + FORWARD_TO_OUTER(GetTextZoom, (aZoom)); + if (mDocShell) { nsCOMPtr contentViewer; mDocShell->GetContentViewer(getter_AddRefs(contentViewer)); @@ -2346,6 +2710,8 @@ nsGlobalWindow::GetTextZoom(float *aZoom) NS_IMETHODIMP nsGlobalWindow::SetTextZoom(float aZoom) { + FORWARD_TO_OUTER(SetTextZoom, (aZoom)); + if (mDocShell) { nsCOMPtr contentViewer; mDocShell->GetContentViewer(getter_AddRefs(contentViewer)); @@ -2461,6 +2827,8 @@ nsGlobalWindow::MakeScriptDialogTitle(const nsAString &aInTitle, NS_IMETHODIMP nsGlobalWindow::Alert(const nsAString& aString) { + FORWARD_TO_OUTER(Alert, (aString)); + nsCOMPtr prompter(do_GetInterface(mDocShell)); NS_ENSURE_TRUE(prompter, NS_ERROR_FAILURE); @@ -2498,6 +2866,8 @@ nsGlobalWindow::Alert(const nsAString& aString) NS_IMETHODIMP nsGlobalWindow::Confirm(const nsAString& aString, PRBool* aReturn) { + FORWARD_TO_OUTER(Confirm, (aString, aReturn)); + nsCOMPtr prompter(do_GetInterface(mDocShell)); NS_ENSURE_TRUE(prompter, NS_ERROR_FAILURE); @@ -2580,6 +2950,8 @@ nsGlobalWindow::Prompt(const nsAString& aMessage, const nsAString& aInitial, NS_IMETHODIMP nsGlobalWindow::Prompt(nsAString& aReturn) { + FORWARD_TO_OUTER(Prompt, (aReturn)); + NS_ENSURE_STATE(mDocShell); nsresult rv = NS_OK; @@ -2629,6 +3001,8 @@ nsGlobalWindow::Prompt(nsAString& aReturn) NS_IMETHODIMP nsGlobalWindow::Focus() { + FORWARD_TO_OUTER(Focus, ()); + /* * If caller is not chrome and dom.disable_window_flip is true, * prevent setting window.focus() by exiting early @@ -2672,8 +3046,9 @@ nsGlobalWindow::Focus() else { nsIFocusController *focusController = nsGlobalWindow::GetRootFocusController(); - if (focusController) + if (focusController) { focusController->SetFocusedWindow(this); + } } return result; @@ -2682,6 +3057,8 @@ nsGlobalWindow::Focus() NS_IMETHODIMP nsGlobalWindow::Blur() { + FORWARD_TO_OUTER(Blur, ()); + nsresult rv = NS_ERROR_FAILURE; nsCOMPtr treeOwner; @@ -2699,6 +3076,8 @@ nsGlobalWindow::Blur() NS_IMETHODIMP nsGlobalWindow::Back() { + FORWARD_TO_OUTER(Back, ()); + nsCOMPtr webNav(do_QueryInterface(mDocShell)); NS_ENSURE_TRUE(webNav, NS_ERROR_FAILURE); @@ -2708,6 +3087,8 @@ nsGlobalWindow::Back() NS_IMETHODIMP nsGlobalWindow::Forward() { + FORWARD_TO_OUTER(Forward, ()); + nsCOMPtr webNav(do_QueryInterface(mDocShell)); NS_ENSURE_TRUE(webNav, NS_ERROR_FAILURE); @@ -2717,6 +3098,8 @@ nsGlobalWindow::Forward() NS_IMETHODIMP nsGlobalWindow::Home() { + FORWARD_TO_OUTER(Home, ()); + if (!mDocShell) return NS_OK; @@ -2746,6 +3129,8 @@ nsGlobalWindow::Home() NS_IMETHODIMP nsGlobalWindow::Stop() { + FORWARD_TO_OUTER(Stop, ()); + nsCOMPtr webNav(do_QueryInterface(mDocShell)); return webNav->Stop(nsIWebNavigation::STOP_ALL); } @@ -2909,6 +3294,12 @@ nsGlobalWindow::ResizeBy(PRInt32 aWidthDif, PRInt32 aHeightDif) NS_IMETHODIMP nsGlobalWindow::SizeToContent() { + FORWARD_TO_OUTER(SizeToContent, ()); + + if (!mDocShell) { + return NS_OK; + } + /* * If caller is not chrome and dom.disable_window_move_resize is true, * block window.SizeToContent() by exiting @@ -3209,6 +3600,8 @@ nsGlobalWindow::CanSetProperty(const char *aPrefName) PopupControlState nsGlobalWindow::CheckForAbusePoint() { + FORWARD_TO_OUTER(CheckForAbusePoint, ()); + nsCOMPtr item(do_QueryInterface(mDocShell)); if (item) { @@ -3516,6 +3909,8 @@ nsGlobalWindow::OpenDialog(nsIDOMWindow** _retval) NS_IMETHODIMP nsGlobalWindow::GetFrames(nsIDOMWindow** aFrames) { + FORWARD_TO_OUTER(GetFrames, (aFrames)); + *aFrames = this; NS_ADDREF(*aFrames); @@ -3569,6 +3964,8 @@ nsCloseEvent::PostCloseEvent() NS_IMETHODIMP nsGlobalWindow::Close() { + FORWARD_TO_OUTER(Close, ()); + if (IsFrame() || !mDocShell) { // window.close() is called on a frame in a frameset, or on a // window that's already closed. Ignore such calls. @@ -3713,6 +4110,8 @@ nsGlobalWindow::Close() void nsGlobalWindow::ReallyCloseWindow() { + FORWARD_TO_OUTER_VOID(ReallyCloseWindow, ()); + nsCOMPtr treeOwnerAsWin; GetTreeOwner(getter_AddRefs(treeOwnerAsWin)); @@ -3758,6 +4157,8 @@ nsGlobalWindow::ReallyCloseWindow() NS_IMETHODIMP nsGlobalWindow::GetFrameElement(nsIDOMElement** aFrameElement) { + FORWARD_TO_OUTER(GetFrameElement, (aFrameElement)); + *aFrameElement = nsnull; nsCOMPtr docShellTI(do_QueryInterface(mDocShell)); @@ -3785,22 +4186,18 @@ nsGlobalWindow::GetFrameElement(nsIDOMElement** aFrameElement) NS_IMETHODIMP nsGlobalWindow::UpdateCommands(const nsAString& anAction) { - nsIDOMWindowInternal *rootWindow = nsGlobalWindow::GetPrivateRoot(); + nsPIDOMWindow *rootWindow = nsGlobalWindow::GetPrivateRoot(); if (!rootWindow) return NS_OK; - nsCOMPtr document; - rootWindow->GetDocument(getter_AddRefs(document)); - - if (document) { - // See if we contain a XUL document. - nsCOMPtr xulDoc = do_QueryInterface(document); - if (xulDoc) { - // Retrieve the command dispatcher and call updateCommands on it. - nsCOMPtr xulCommandDispatcher; - xulDoc->GetCommandDispatcher(getter_AddRefs(xulCommandDispatcher)); - xulCommandDispatcher->UpdateCommands(anAction); - } + nsCOMPtr xulDoc = + do_QueryInterface(rootWindow->GetExtantDocument()); + // See if we contain a XUL document. + if (xulDoc) { + // Retrieve the command dispatcher and call updateCommands on it. + nsCOMPtr xulCommandDispatcher; + xulDoc->GetCommandDispatcher(getter_AddRefs(xulCommandDispatcher)); + xulCommandDispatcher->UpdateCommands(anAction); } return NS_OK; @@ -3882,6 +4279,8 @@ nsGlobalWindow::GetBlurSuppression() NS_IMETHODIMP nsGlobalWindow::GetSelection(nsISelection** aSelection) { + FORWARD_TO_OUTER(GetSelection, (aSelection)); + NS_ENSURE_ARG_POINTER(aSelection); *aSelection = nsnull; @@ -3995,6 +4394,10 @@ nsGlobalWindow::FindInternal(const nsAString& aStr, PRBool caseSensitive, PRBool wholeWord, PRBool searchInFrames, PRBool showDialog, PRBool *aDidFind) { + FORWARD_TO_OUTER(FindInternal, (aStr, caseSensitive, backwards, wrapAround, + wholeWord, searchInFrames, showDialog, + aDidFind)); + NS_ENSURE_ARG_POINTER(aDidFind); nsresult rv = NS_OK; *aDidFind = PR_FALSE; @@ -4165,6 +4568,8 @@ nsGlobalWindow::AddEventListener(const nsAString& aType, nsIDOMEventListener* aListener, PRBool aUseCapture) { + FORWARD_TO_INNER(AddEventListener, (aType, aListener, aUseCapture)); + nsCOMPtr doc(do_QueryInterface(mDocument)); return AddEventListener(aType, aListener, aUseCapture, @@ -4182,6 +4587,8 @@ nsGlobalWindow::RemoveEventListener(const nsAString& aType, NS_IMETHODIMP nsGlobalWindow::DispatchEvent(nsIDOMEvent* aEvent, PRBool* _retval) { + FORWARD_TO_INNER(DispatchEvent, (aEvent, _retval)); + nsCOMPtr doc(do_QueryInterface(mDocument)); if (!doc) { return NS_ERROR_FAILURE; @@ -4210,6 +4617,9 @@ nsGlobalWindow::AddGroupedEventListener(const nsAString & aType, PRBool aUseCapture, nsIDOMEventGroup *aEvtGrp) { + FORWARD_TO_INNER(AddGroupedEventListener, + (aType, aListener, aUseCapture, aEvtGrp)); + nsCOMPtr manager; if (NS_SUCCEEDED(GetListenerManager(getter_AddRefs(manager)))) { @@ -4227,10 +4637,14 @@ nsGlobalWindow::RemoveGroupedEventListener(const nsAString & aType, PRBool aUseCapture, nsIDOMEventGroup *aEvtGrp) { + FORWARD_TO_INNER(RemoveGroupedEventListener, + (aType, aListener, aUseCapture, aEvtGrp)); + if (mListenerManager) { PRInt32 flags = aUseCapture ? NS_EVENT_FLAG_CAPTURE : NS_EVENT_FLAG_BUBBLE; - mListenerManager->RemoveEventListenerByType(aListener, aType, flags, aEvtGrp); + mListenerManager->RemoveEventListenerByType(aListener, aType, flags, + aEvtGrp); return NS_OK; } return NS_ERROR_FAILURE; @@ -4288,6 +4702,8 @@ NS_IMETHODIMP nsGlobalWindow::RemoveEventListenerByIID(nsIDOMEventListener* aListener, const nsIID& aIID) { + FORWARD_TO_INNER(RemoveEventListenerByIID, (aListener, aIID)); + if (mListenerManager) { mListenerManager->RemoveEventListenerByIID(aListener, aIID, NS_EVENT_FLAG_BUBBLE); @@ -4299,6 +4715,8 @@ nsGlobalWindow::RemoveEventListenerByIID(nsIDOMEventListener* aListener, NS_IMETHODIMP nsGlobalWindow::GetListenerManager(nsIEventListenerManager **aResult) { + FORWARD_TO_INNER(GetListenerManager, (aResult)); + if (!mListenerManager) { static NS_DEFINE_CID(kEventListenerManagerCID, NS_EVENTLISTENERMANAGER_CID); @@ -4308,7 +4726,9 @@ nsGlobalWindow::GetListenerManager(nsIEventListenerManager **aResult) NS_ENSURE_SUCCESS(rv, rv); } - return CallQueryInterface(mListenerManager, aResult); + NS_ADDREF(*aResult = mListenerManager); + + return NS_OK; } NS_IMETHODIMP @@ -4335,6 +4755,8 @@ nsGlobalWindow::GetSystemEventGroup(nsIDOMEventGroup **aGroup) nsPIDOMWindow* nsGlobalWindow::GetPrivateParent() { + FORWARD_TO_OUTER(GetPrivateParent, ()); + nsCOMPtr parent; GetParent(getter_AddRefs(parent)); @@ -4365,6 +4787,8 @@ nsGlobalWindow::GetPrivateParent() nsPIDOMWindow* nsGlobalWindow::GetPrivateRoot() { + FORWARD_TO_OUTER(GetPrivateRoot, ()); + nsCOMPtr parent; GetTop(getter_AddRefs(parent)); @@ -4389,24 +4813,21 @@ nsGlobalWindow::GetPrivateRoot() if (parent) { nsCOMPtr tempParent; parent->GetTop(getter_AddRefs(tempParent)); - return NS_STATIC_CAST(nsGlobalWindow *, - NS_STATIC_CAST(nsIDOMWindow*, tempParent)); + tempParent.swap(parent); } } } - if (parent) { - return NS_STATIC_CAST(nsGlobalWindow *, - NS_STATIC_CAST(nsIDOMWindow*, parent)); - } - - return nsnull; + return NS_STATIC_CAST(nsGlobalWindow *, + NS_STATIC_CAST(nsIDOMWindow *, parent)); } NS_IMETHODIMP nsGlobalWindow::GetLocation(nsIDOMLocation ** aLocation) { + FORWARD_TO_OUTER(GetLocation, (aLocation)); + *aLocation = nsnull; if (!mLocation && mDocShell) { @@ -4425,6 +4846,8 @@ nsresult nsGlobalWindow::GetObjectProperty(const PRUnichar *aProperty, nsISupports ** aObject) { + FORWARD_TO_INNER(GetObjectProperty, (aProperty, aObject)); + NS_ENSURE_TRUE(mJSObject, NS_ERROR_NOT_AVAILABLE); // Get JSContext from stack. @@ -4458,6 +4881,8 @@ nsGlobalWindow::GetObjectProperty(const PRUnichar *aProperty, nsresult nsGlobalWindow::Activate() { + FORWARD_TO_OUTER(Activate, ()); + /* nsCOMPtr treeOwnerAsWin; GetTreeOwner(getter_AddRefs(treeOwnerAsWin)); @@ -4525,6 +4950,8 @@ nsGlobalWindow::Activate() nsresult nsGlobalWindow::Deactivate() { + FORWARD_TO_OUTER(Deactivate, ()); + nsCOMPtr presShell; mDocShell->GetPresShell(getter_AddRefs(presShell)); NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE); @@ -4579,6 +5006,8 @@ nsGlobalWindow::GetComputedStyle(nsIDOMElement* aElt, const nsAString& aPseudoElt, nsIDOMCSSStyleDeclaration** aReturn) { + FORWARD_TO_OUTER(GetComputedStyle, (aElt, aPseudoElt, aReturn)); + NS_ENSURE_ARG_POINTER(aReturn); *aReturn = nsnull; @@ -4654,6 +5083,8 @@ nsGlobalWindow::GetInterface(const nsIID & aIID, void **aSink) *aSink = nsnull; if (aIID.Equals(NS_GET_IID(nsIDocCharset))) { + FORWARD_TO_OUTER(GetInterface, (aIID, aSink)); + if (mDocShell) { nsCOMPtr docCharset(do_QueryInterface(mDocShell)); if (docCharset) { @@ -4663,6 +5094,8 @@ nsGlobalWindow::GetInterface(const nsIID & aIID, void **aSink) } } else if (aIID.Equals(NS_GET_IID(nsIWebNavigation))) { + FORWARD_TO_OUTER(GetInterface, (aIID, aSink)); + if (mDocShell) { nsCOMPtr webNav(do_QueryInterface(mDocShell)); if (webNav) { @@ -4672,6 +5105,8 @@ nsGlobalWindow::GetInterface(const nsIID & aIID, void **aSink) } } else if (aIID.Equals(NS_GET_IID(nsIWebBrowserPrint))) { + FORWARD_TO_OUTER(GetInterface, (aIID, aSink)); + if (mDocShell) { nsCOMPtr viewer; mDocShell->GetContentViewer(getter_AddRefs(viewer)); @@ -4695,6 +5130,8 @@ nsGlobalWindow::GetInterface(const nsIID & aIID, void **aSink) } } else if (aIID.Equals(NS_GET_IID(nsIDOMWindowUtils))) { + FORWARD_TO_OUTER(GetInterface, (aIID, aSink)); + nsCOMPtr utils(do_QueryReferent(mWindowUtils)); if (utils) { *aSink = utils; @@ -4724,6 +5161,8 @@ nsGlobalWindow::GetInterface(const nsIID & aIID, void **aSink) nsIDOMWindowInternal * nsGlobalWindow::GetParentInternal() { + FORWARD_TO_OUTER(GetParentInternal, ()); + nsIDOMWindowInternal *parentInternal = nsnull; nsCOMPtr parent; @@ -4746,6 +5185,9 @@ nsGlobalWindow::OpenInternal(const nsAString& aUrl, const nsAString& aName, nsISupports *aExtraArgument, nsIDOMWindow **aReturn) { + FORWARD_TO_OUTER(OpenInternal, (aUrl, aName, aOptions, aDialog, argv, argc, + aExtraArgument, aReturn)); + nsXPIDLCString url; nsresult rv = NS_OK; @@ -4938,6 +5380,7 @@ nsGlobalWindow::OpenInternal(const nsAString& aUrl, const nsAString& aName, return rv; } +// static void nsGlobalWindow::CloseWindow(nsISupports *aWindow) { @@ -4947,6 +5390,27 @@ nsGlobalWindow::CloseWindow(nsISupports *aWindow) NS_STATIC_CAST(nsPIDOMWindow*, win))->ReallyCloseWindow(); } +// static +void +nsGlobalWindow::ClearWindowScope(nsISupports *aWindow) +{ + nsCOMPtr sgo(do_QueryInterface(aWindow)); + + nsIScriptContext *scx = sgo->GetContext(); + + if (scx) { + JSContext *cx = (JSContext *)scx->GetNativeContext(); + JSObject *global = sgo->GetGlobalJSObject(); + + if (global) { + ::JS_ClearScope(cx, global); + ::JS_ClearWatchPointsForObject(cx, global); + } + + ::JS_ClearRegExpStatics(cx); + } +} + //***************************************************************************** // nsGlobalWindow: Timeout Functions //***************************************************************************** @@ -4957,7 +5421,11 @@ static const char kSetTimeoutStr[] = "setTimeout"; nsresult nsGlobalWindow::SetTimeoutOrInterval(PRBool aIsInterval, PRInt32 *aReturn) { - if (!mContext) { + FORWARD_TO_INNER(SetTimeoutOrInterval, (aIsInterval, aReturn)); + + nsIScriptContext *scx = GetContextInternal(); + + if (!scx) { // This window was already closed, or never properly initialized, // don't let a timer be scheduled on such a window. @@ -5044,7 +5512,7 @@ nsGlobalWindow::SetTimeoutOrInterval(PRBool aIsInterval, PRInt32 *aReturn) if (expr) { if (!::JS_AddNamedRoot(cx, &timeout->mExpr, "timeout.mExpr")) { - timeout->Release(mContext); + timeout->Release(scx); return NS_ERROR_OUT_OF_MEMORY; } @@ -5056,13 +5524,13 @@ nsGlobalWindow::SetTimeoutOrInterval(PRBool aIsInterval, PRInt32 *aReturn) timeout->mArgv = (jsval *) PR_MALLOC((argc - 1) * sizeof(jsval)); if (!timeout->mArgv) { - timeout->Release(mContext); + timeout->Release(scx); return NS_ERROR_OUT_OF_MEMORY; } if (!::JS_AddNamedRoot(cx, &timeout->mFunObj, "timeout.mFunObj")) { - timeout->Release(mContext); + timeout->Release(scx); return NS_ERROR_FAILURE; } @@ -5074,7 +5542,7 @@ nsGlobalWindow::SetTimeoutOrInterval(PRBool aIsInterval, PRInt32 *aReturn) timeout->mArgv[i - 2] = argv[i]; if (!::JS_AddNamedRoot(cx, &timeout->mArgv[i - 2], "timeout.mArgv[i]")) { - timeout->Release(mContext); + timeout->Release(scx); return NS_ERROR_FAILURE; } @@ -5088,7 +5556,7 @@ nsGlobalWindow::SetTimeoutOrInterval(PRBool aIsInterval, PRInt32 *aReturn) timeout->mFileName = PL_strdup(filename); if (!timeout->mFileName) { - timeout->Release(mContext); + timeout->Release(scx); return NS_ERROR_OUT_OF_MEMORY; } @@ -5101,7 +5569,7 @@ nsGlobalWindow::SetTimeoutOrInterval(PRBool aIsInterval, PRInt32 *aReturn) rv = sSecMan->GetSubjectPrincipal(getter_AddRefs(timeout->mPrincipal)); if (NS_FAILED(rv)) { - timeout->Release(mContext); + timeout->Release(scx); return NS_ERROR_FAILURE; } @@ -5112,7 +5580,7 @@ nsGlobalWindow::SetTimeoutOrInterval(PRBool aIsInterval, PRInt32 *aReturn) timeout->mTimer = do_CreateInstance("@mozilla.org/timer;1", &rv); if (NS_FAILED(rv)) { - timeout->Release(mContext); + timeout->Release(scx); return rv; } @@ -5121,7 +5589,7 @@ nsGlobalWindow::SetTimeoutOrInterval(PRBool aIsInterval, PRInt32 *aReturn) (PRInt32)interval, nsITimer::TYPE_ONE_SHOT); if (NS_FAILED(rv)) { - timeout->Release(mContext); + timeout->Release(scx); return rv; } @@ -5157,14 +5625,20 @@ nsGlobalWindow::SetTimeoutOrInterval(PRBool aIsInterval, PRInt32 *aReturn) void nsGlobalWindow::RunTimeout(nsTimeout *aTimeout) { - if (!mContext) { + NS_ASSERTION(IsInnerWindow(), "Timeout running on outer window!"); + + // Make sure that the script context doesn't go away as a result of + // running timeouts + nsCOMPtr scx = GetContextInternal(); + + if (!scx) { // No context means this window was closed or never properly // initialized. return; } - if (!mContext->GetScriptsEnabled()) { + if (!scx->GetScriptsEnabled()) { // Scripts were enabled once in this window (unless aTimeout == // nsnull) but now scripts are disabled (we might be in // print-preview, for instance), this means we shouldn't run any @@ -5186,9 +5660,8 @@ nsGlobalWindow::RunTimeout(nsTimeout *aTimeout) // Make sure that the window and the script context don't go away as // a result of running timeouts nsCOMPtr windowKungFuDeathGrip(this); - nsCOMPtr contextKungFuDeathGrip(mContext); - cx = (JSContext *)mContext->GetNativeContext(); + cx = (JSContext *)scx->GetNativeContext(); // A native timer has gone off. See which of our timeouts need // servicing @@ -5289,10 +5762,10 @@ nsGlobalWindow::RunTimeout(nsTimeout *aTimeout) ::JS_GetStringChars(timeout->mExpr)); PRBool is_undefined; - mContext->EvaluateString(nsDependentString(script), mJSObject, - timeout->mPrincipal, timeout->mFileName, - timeout->mLineNo, timeout->mVersion, nsnull, - &is_undefined); + scx->EvaluateString(nsDependentString(script), mJSObject, + timeout->mPrincipal, timeout->mFileName, + timeout->mLineNo, timeout->mVersion, nsnull, + &is_undefined); } else { PRInt64 lateness64; PRInt32 lateness; @@ -5305,8 +5778,8 @@ nsGlobalWindow::RunTimeout(nsTimeout *aTimeout) timeout->mArgv[timeout->mArgc] = INT_TO_JSVAL((jsint) lateness); jsval dummy; - mContext->CallEventHandler(mJSObject, timeout->mFunObj, - timeout->mArgc + 1, timeout->mArgv, &dummy); + scx->CallEventHandler(mJSObject, timeout->mFunObj, timeout->mArgc + 1, + timeout->mArgv, &dummy); } --mTimeoutFiringDepth; @@ -5328,7 +5801,7 @@ nsGlobalWindow::RunTimeout(nsTimeout *aTimeout) // it was cleared before releasing it. PRBool timeout_was_cleared = timeout->mCleared; - timeout->Release(contextKungFuDeathGrip); + timeout->Release(scx); if (timeout_was_cleared) { // The running timeout's window was cleared, this means that @@ -5393,7 +5866,7 @@ nsGlobalWindow::RunTimeout(nsTimeout *aTimeout) // Now that the OS timer no longer has a reference to the // timeout we need to drop that reference. - timeout->Release(contextKungFuDeathGrip); + timeout->Release(scx); } } @@ -5410,7 +5883,7 @@ nsGlobalWindow::RunTimeout(nsTimeout *aTimeout) timeout->mTimer->Cancel(); timeout->mTimer = nsnull; - timeout->Release(mContext); + timeout->Release(scx); } } @@ -5425,7 +5898,7 @@ nsGlobalWindow::RunTimeout(nsTimeout *aTimeout) } // Release the timeout struct since it's out of the list - timeout->Release(contextKungFuDeathGrip); + timeout->Release(scx); if (isInterval) { // Reschedule an interval timeout. Insert interval timeout @@ -5531,6 +6004,8 @@ nsTimeout::AddRef() nsresult nsGlobalWindow::ClearTimeoutOrInterval() { + FORWARD_TO_INNER(ClearTimeoutOrInterval, ()); + nsresult rv = NS_OK; nsCOMPtr ncc; @@ -5572,6 +6047,7 @@ nsGlobalWindow::ClearTimeoutOrInterval() PRUint32 public_id = (PRUint32)timer_id; nsTimeout **top, *timeout; + nsIScriptContext *scx = GetContextInternal(); for (top = &mTimeouts; (timeout = *top) != NULL; top = &timeout->mNext) { if (timeout->mPublicId == public_id) { @@ -5588,9 +6064,9 @@ nsGlobalWindow::ClearTimeoutOrInterval() if (timeout->mTimer) { timeout->mTimer->Cancel(); timeout->mTimer = nsnull; - timeout->Release(mContext); + timeout->Release(scx); } - timeout->Release(mContext); + timeout->Release(scx); } break; } @@ -5603,6 +6079,7 @@ void nsGlobalWindow::ClearAllTimeouts() { nsTimeout *timeout, *next; + nsIScriptContext *scx = GetContextInternal(); for (timeout = mTimeouts; timeout; timeout = next) { /* If RunTimeout() is higher up on the stack for this @@ -5621,7 +6098,7 @@ nsGlobalWindow::ClearAllTimeouts() // Drop the count since the timer isn't going to hold on // anymore. - timeout->Release(mContext); + timeout->Release(scx); } // Set timeout->mCleared to true to indicate that the timeout was @@ -5629,7 +6106,7 @@ nsGlobalWindow::ClearAllTimeouts() timeout->mCleared = PR_TRUE; // Drop the count since we're removing it from the list. - timeout->Release(mContext); + timeout->Release(scx); } mTimeouts = NULL; @@ -5639,6 +6116,9 @@ void nsGlobalWindow::InsertTimeoutIntoList(nsTimeout **aList, nsTimeout *aTimeout) { + NS_ASSERTION(IsInnerWindow(), + "InsertTimeoutIntoList() called on outer window!"); + nsTimeout *to; NS_ASSERTION(aList, @@ -5680,6 +6160,8 @@ nsGlobalWindow::TimerCallback(nsITimer *aTimer, void *aClosure) nsresult nsGlobalWindow::GetTreeOwner(nsIDocShellTreeOwner **aTreeOwner) { + FORWARD_TO_OUTER(GetTreeOwner, (aTreeOwner)); + nsCOMPtr docShellAsItem(do_QueryInterface(mDocShell)); // If there's no docShellAsItem, this window must have been closed, @@ -5697,6 +6179,8 @@ nsGlobalWindow::GetTreeOwner(nsIDocShellTreeOwner **aTreeOwner) nsresult nsGlobalWindow::GetTreeOwner(nsIBaseWindow **aTreeOwner) { + FORWARD_TO_OUTER(GetTreeOwner, (aTreeOwner)); + nsCOMPtr docShellAsItem(do_QueryInterface(mDocShell)); nsCOMPtr treeOwner; @@ -5731,6 +6215,8 @@ nsresult nsGlobalWindow::GetScrollInfo(nsIScrollableView **aScrollableView, float *aP2T, float *aT2P) { + FORWARD_TO_OUTER(GetScrollInfo, (aScrollableView, aP2T, aT2P)); + *aScrollableView = nsnull; *aP2T = 0.0f; *aT2P = 0.0f; @@ -5757,6 +6243,7 @@ nsGlobalWindow::BuildURIfromBase(const char *aURL, nsIURI **aBuiltURI, PRBool *aFreeSecurityPass, JSContext **aCXused) { + nsIScriptContext *scx = GetContextInternal(); JSContext *cx = nsnull; *aBuiltURI = nsnull; @@ -5765,9 +6252,9 @@ nsGlobalWindow::BuildURIfromBase(const char *aURL, nsIURI **aBuiltURI, *aCXused = nsnull; // get JSContext - NS_ASSERTION(mContext, "opening window missing its context"); + NS_ASSERTION(scx, "opening window missing its context"); NS_ASSERTION(mDocument, "opening window missing its document"); - if (!mContext || !mDocument) + if (!scx || !mDocument) return NS_ERROR_FAILURE; nsCOMPtr chrome_win = @@ -5780,7 +6267,7 @@ nsGlobalWindow::BuildURIfromBase(const char *aURL, nsIURI **aBuiltURI, // such a way. This also makes us get the appropriate base URI for // the below URI resolution code. - cx = (JSContext *)mContext->GetNativeContext(); + cx = (JSContext *)scx->GetNativeContext(); } else { // get the JSContext from the call stack nsCOMPtr stack(do_GetService(sJSStackContractID)); @@ -5892,7 +6379,7 @@ public: nsTimeout** GetTimeoutInsertionPoint() { return mTimeoutInsertionPoint; } void ClearSavedTimeouts() { mSavedTimeouts = nsnull; } -private: +protected: ~WindowStateHolder(); JSRuntime *mRuntime; @@ -6065,12 +6552,15 @@ nsGlobalWindow::SaveWindowState(nsISupports **aState) { *aState = nsnull; - if (!mContext || !mJSObject) { + if (IsOuterWindow() && (!mContext || !mJSObject)) { // The window may be getting torn down; don't bother saving state. return NS_OK; } - JSContext *cx = NS_STATIC_CAST(JSContext*, mContext->GetNativeContext()); + FORWARD_TO_INNER(SaveWindowState, (aState)); + + JSContext *cx = NS_STATIC_CAST(JSContext*, + GetContextInternal()->GetNativeContext()); NS_ENSURE_TRUE(cx, NS_ERROR_FAILURE); JSObject *stateObj = ::JS_NewObject(cx, &sWindowStateClass, NULL, NULL); @@ -6097,12 +6587,18 @@ nsGlobalWindow::SaveWindowState(nsISupports **aState) nsresult nsGlobalWindow::RestoreWindowState(nsISupports *aState) { - if (!mContext || !mJSObject) { + // SetNewDocument() has already been called so we should have a + // new clean inner window to restore stat into here. + + if (IsOuterWindow() && (!mContext || !mJSObject)) { // The window may be getting torn down; don't bother restoring state. return NS_OK; } - JSContext *cx = NS_STATIC_CAST(JSContext*, mContext->GetNativeContext()); + FORWARD_TO_INNER(RestoreWindowState, (aState)); + + JSContext *cx = NS_STATIC_CAST(JSContext*, + GetContextInternal()->GetNativeContext()); NS_ENSURE_TRUE(cx, NS_ERROR_FAILURE); // Note that we don't need to call JS_ClearScope here. The scope is already @@ -6176,6 +6672,8 @@ nsGlobalWindow::RestoreWindowState(nsISupports *aState) void nsGlobalWindow::SuspendTimeouts() { + FORWARD_TO_INNER_VOID(SuspendTimeouts, ()); + nsInt64 now = PR_IntervalNow(); for (nsTimeout *t = mTimeouts; t; t = t->mNext) { // Change mWhen to be the time remaining for this timer. @@ -6216,13 +6714,15 @@ nsGlobalWindow::SuspendTimeouts() nsresult nsGlobalWindow::ResumeTimeouts() { + FORWARD_TO_INNER(ResumeTimeouts, ()); + // Restore all of the timeouts, using the stored time remaining. nsInt64 now = PR_IntervalNow(); nsresult rv; for (nsTimeout *t = mTimeouts; t; t = t->mNext) { - PRInt32 interval = PR_MAX(t->mWhen, DOM_MIN_TIMEOUT_VALUE); + PRInt32 interval = (PRInt32)PR_MAX(t->mWhen, DOM_MIN_TIMEOUT_VALUE); t->mWhen = now + nsInt64(t->mWhen); t->mTimer = do_CreateInstance("@mozilla.org/timer;1"); @@ -6403,6 +6903,8 @@ nsGlobalChromeWindow::GetAttentionWithCycleCount(PRInt32 aCycleCount) NS_IMETHODIMP nsGlobalChromeWindow::SetCursor(const nsAString& aCursor) { + FORWARD_TO_OUTER_CHROME(SetCursor, (aCursor)); + nsresult rv = NS_OK; PRInt32 cursor; @@ -6430,7 +6932,10 @@ nsGlobalChromeWindow::SetCursor(const nsAString& aCursor) } nsCOMPtr presContext; - mDocShell->GetPresContext(getter_AddRefs(presContext)); + if (mDocShell) { + mDocShell->GetPresContext(getter_AddRefs(presContext)); + } + if (presContext) { // Need root widget. nsCOMPtr presShell; @@ -6459,6 +6964,8 @@ nsGlobalChromeWindow::SetCursor(const nsAString& aCursor) NS_IMETHODIMP nsGlobalChromeWindow::GetBrowserDOMWindow(nsIBrowserDOMWindow **aBrowserWindow) { + FORWARD_TO_OUTER_CHROME(GetBrowserDOMWindow, (aBrowserWindow)); + NS_ENSURE_ARG_POINTER(aBrowserWindow); *aBrowserWindow = mBrowserDOMWindow; @@ -6469,6 +6976,8 @@ nsGlobalChromeWindow::GetBrowserDOMWindow(nsIBrowserDOMWindow **aBrowserWindow) NS_IMETHODIMP nsGlobalChromeWindow::SetBrowserDOMWindow(nsIBrowserDOMWindow *aBrowserWindow) { + FORWARD_TO_OUTER_CHROME(SetBrowserDOMWindow, (aBrowserWindow)); + mBrowserDOMWindow = aBrowserWindow; return NS_OK; } @@ -6485,9 +6994,9 @@ NS_NewScriptGlobalObject(PRBool aIsChrome, nsIScriptGlobalObject **aResult) nsGlobalWindow *global; if (aIsChrome) { - global = new nsGlobalChromeWindow(); + global = new nsGlobalChromeWindow(nsnull); } else { - global = new nsGlobalWindow(); + global = new nsGlobalWindow(nsnull); } NS_ENSURE_TRUE(global, NS_ERROR_OUT_OF_MEMORY); @@ -6528,7 +7037,8 @@ NS_IMPL_ADDREF(nsNavigator) NS_IMPL_RELEASE(nsNavigator) -void nsNavigator::SetDocShell(nsIDocShell *aDocShell) +void +nsNavigator::SetDocShell(nsIDocShell *aDocShell) { mDocShell = aDocShell; if (mPlugins) diff --git a/mozilla/dom/src/base/nsGlobalWindow.h b/mozilla/dom/src/base/nsGlobalWindow.h index 66e1b9e9697..39b47a051d2 100644 --- a/mozilla/dom/src/base/nsGlobalWindow.h +++ b/mozilla/dom/src/base/nsGlobalWindow.h @@ -70,6 +70,7 @@ #include "nsIDOMJSWindow.h" #include "nsIDOMChromeWindow.h" #include "nsIScriptGlobalObject.h" +#include "nsIScriptContext.h" #include "nsIScriptObjectPrincipal.h" #include "nsITimer.h" #include "nsIWebBrowserChrome.h" @@ -86,6 +87,7 @@ #include "nsPoint.h" #include "nsSize.h" #include "mozFlushType.h" +#include "prclist.h" #define DEFAULT_HOME_PAGE "www.mozilla.org" #define PREF_BROWSER_STARTUP_HOMEPAGE "browser.startup.homepage" @@ -126,7 +128,8 @@ class nsGlobalWindow : public nsIScriptGlobalObject, public nsIDOMNSEventTarget, public nsIDOMViewCSS, public nsSupportsWeakReference, - public nsIInterfaceRequestor + public nsIInterfaceRequestor, + public PRCListStr { public: // public methods @@ -155,6 +158,7 @@ public: virtual JSObject *GetGlobalJSObject(); virtual void OnFinalize(JSObject *aJSObject); virtual void SetScriptsEnabled(PRBool aEnabled, PRBool aFireTimeouts); + virtual nsresult SetNewArguments(JSObject *aArguments); // nsIScriptObjectPrincipal virtual nsIPrincipal* GetPrincipal(); @@ -206,7 +210,7 @@ public: virtual NS_HIDDEN_(nsresult) SaveWindowState(nsISupports **aState); virtual NS_HIDDEN_(nsresult) RestoreWindowState(nsISupports *aState); - + // nsIDOMViewCSS NS_DECL_NSIDOMVIEWCSS @@ -217,7 +221,37 @@ public: NS_DECL_NSIINTERFACEREQUESTOR // Object Management - nsGlobalWindow(); + nsGlobalWindow(nsGlobalWindow *aOuterWindow); + + static nsGlobalWindow *FromWrapper(nsIXPConnectWrappedNative *wrapper) + { + // Make sure this matches the casts we do in QueryInterface(). + return (nsGlobalWindow *)(nsIScriptGlobalObject *)wrapper->Native(); + } + + nsIScriptContext *GetContextInternal() + { + if (IsInnerWindow()) { + return GetOuterWindowInternal()->mContext; + } + + return mContext; + } + + nsGlobalWindow *GetOuterWindowInternal() + { + return NS_STATIC_CAST(nsGlobalWindow *, GetOuterWindow()); + } + + nsGlobalWindow *GetCurrentInnerWindowInternal() + { + return NS_STATIC_CAST(nsGlobalWindow *, mInnerWindow); + } + + nsIDocShell *GetDocShellInternal() + { + return GetOuterWindowInternal()->mDocShell; + } static void ShutDown(); static PRBool IsCallerChrome(); @@ -230,12 +264,24 @@ protected: void CleanUp(); void ClearControllers(); + nsresult SetNewDocument(nsIDOMDocument *aDocument, + PRBool aRemoveEventListeners, + PRBool aClearScopeHint, + PRBool aIsInternalCall); + // Get the parent, returns null if this is a toplevel window nsIDOMWindowInternal *GetParentInternal(); // popup tracking - PRBool IsPopupSpamWindow() const { return mIsPopupSpam; } - void SetPopupSpamWindow(PRBool aPopup) { mIsPopupSpam = aPopup; } + PRBool IsPopupSpamWindow() + { + return GetOuterWindowInternal()->mIsPopupSpam; + } + + void SetPopupSpamWindow(PRBool aPopup) + { + GetOuterWindowInternal()->mIsPopupSpam = aPopup; + } // Window Control Functions NS_IMETHOD OpenInternal(const nsAString& aUrl, @@ -244,6 +290,7 @@ protected: PRBool aDialog, jsval *argv, PRUint32 argc, nsISupports *aExtraArgument, nsIDOMWindow **aReturn); static void CloseWindow(nsISupports* aWindow); + static void ClearWindowScope(nsISupports* aWindow); // Timeout Functions nsresult SetTimeoutOrInterval(PRBool aIsInterval, PRInt32* aReturn); @@ -318,18 +365,20 @@ protected: // objects will keep the global object (this object) alive. To prevent // these cycles, ownership of such members must be released in // |CleanUp| and |SetDocShell|. - PRPackedBool mFirstDocumentLoad; - PRPackedBool mIsScopeClear; + + // These members are only used on outer window objects. Make sure + // you never set any of these on an inner object! PRPackedBool mFullScreen; PRPackedBool mIsClosed; PRPackedBool mInClose; PRPackedBool mOpenerWasCleared; PRPackedBool mIsPopupSpam; + nsCOMPtr mContext; nsCOMPtr mOpener; nsCOMPtr mControllers; - nsCOMPtr mListenerManager; JSObject* mJSObject; + JSObject* mArguments; nsRefPtr mNavigator; nsRefPtr mScreen; nsRefPtr mHistory; @@ -351,19 +400,13 @@ protected: nsIScriptGlobalObjectOwner* mGlobalObjectOwner; // Weak Reference nsIDocShell* mDocShell; // Weak Reference - nsEvent* mCurrentEvent; nsCOMPtr mCrypto; nsCOMPtr mPkcs11; - nsCOMPtr mDocumentPrincipal; - // XXX We need mNavigatorHolder because we make two SetNewDocument() - // calls when transitioning from page to page. This keeps a reference - // to the JSObject holder for the navigator object in between - // SetNewDocument() calls so that the JSObject doesn't get garbage - // collected in between these calls. - // See bug 163645 for more on why we need this and bug 209607 for info - // on how we can remove the need for this. - nsCOMPtr mNavigatorHolder; + nsCOMPtr mInnerWindowHolder; + + // This member variable is used only on the inner window. + nsCOMPtr mListenerManager; friend class nsDOMScriptableHelper; friend class nsDOMWindowUtils; @@ -385,6 +428,11 @@ public: // nsIDOMChromeWindow interface NS_DECL_NSIDOMCHROMEWINDOW + nsGlobalChromeWindow(nsGlobalWindow *aOuterWindow) + : nsGlobalWindow(aOuterWindow) + { + } + protected: nsCOMPtr mBrowserDOMWindow; }; @@ -496,6 +544,11 @@ public: NS_DECL_NSIDOMJSNAVIGATOR void SetDocShell(nsIDocShell *aDocShell); + nsIDocShell *GetDocShell() + { + return mDocShell; + } + void LoadingNewDocument(); nsresult RefreshMIMEArray(); diff --git a/mozilla/dom/src/base/nsJSEnvironment.cpp b/mozilla/dom/src/base/nsJSEnvironment.cpp index c9e8d720051..24aacc779b1 100644 --- a/mozilla/dom/src/base/nsJSEnvironment.cpp +++ b/mozilla/dom/src/base/nsJSEnvironment.cpp @@ -1609,7 +1609,9 @@ nsJSContext::InitContext(nsIScriptGlobalObject *aGlobalObject) // or Release() methods are called mGlobalWrapperRef = holder; - rv = InitClasses(); // this will complete global object initialization + holder->GetJSObject(&global); + + rv = InitClasses(global); // this will complete global object initialization NS_ENSURE_SUCCESS(rv, rv); mIsInitialized = PR_TRUE; @@ -1626,7 +1628,7 @@ nsJSContext::InitializeExternalClasses() } nsresult -nsJSContext::InitializeLiveConnectClasses() +nsJSContext::InitializeLiveConnectClasses(JSObject *aGlobalObj) { nsresult rv = NS_OK; @@ -1644,7 +1646,7 @@ nsJSContext::InitializeLiveConnectClasses() do_QueryInterface(jvmManager); if (liveConnectManager) { - rv = liveConnectManager->InitLiveConnectClasses(mContext, ::JS_GetGlobalObject(mContext)); + rv = liveConnectManager->InitLiveConnectClasses(mContext, aGlobalObj); } } } @@ -1937,22 +1939,21 @@ static JSFunctionSpec JProfFunctions[] = { #endif /* defined(MOZ_JPROF) */ nsresult -nsJSContext::InitClasses() +nsJSContext::InitClasses(JSObject *aGlobalObj) { nsresult rv = NS_OK; - JSObject *globalObj = ::JS_GetGlobalObject(mContext); rv = InitializeExternalClasses(); NS_ENSURE_SUCCESS(rv, rv); - rv = InitializeLiveConnectClasses(); + rv = InitializeLiveConnectClasses(aGlobalObj); NS_ENSURE_SUCCESS(rv, rv); - rv = nsDOMClassInfo::InitDOMJSClass(mContext, globalObj); + rv = nsDOMClassInfo::InitDOMJSClass(mContext, aGlobalObj); NS_ENSURE_SUCCESS(rv, rv); // Initialize the options object and set default options in mContext - JSObject *optionsObj = ::JS_DefineObject(mContext, globalObj, "_options", + JSObject *optionsObj = ::JS_DefineObject(mContext, aGlobalObj, "_options", &OptionsClass, nsnull, 0); if (optionsObj && ::JS_DefineProperties(mContext, optionsObj, OptionsProperties)) { @@ -1963,17 +1964,29 @@ nsJSContext::InitClasses() #ifdef NS_TRACE_MALLOC // Attempt to initialize TraceMalloc functions - ::JS_DefineFunctions(mContext, globalObj, TraceMallocFunctions); + ::JS_DefineFunctions(mContext, aGlobalObj, TraceMallocFunctions); #endif #ifdef MOZ_JPROF // Attempt to initialize JProf functions - ::JS_DefineFunctions(mContext, globalObj, JProfFunctions); + ::JS_DefineFunctions(mContext, aGlobalObj, JProfFunctions); #endif return rv; } +void +nsJSContext::WillInitializeContext() +{ + mIsInitialized = PR_FALSE; +} + +void +nsJSContext::DidInitializeContext() +{ + mIsInitialized = PR_TRUE; +} + PRBool nsJSContext::IsContextInitialized() { diff --git a/mozilla/dom/src/base/nsJSEnvironment.h b/mozilla/dom/src/base/nsJSEnvironment.h index 70aae755df3..bbe5c54c711 100644 --- a/mozilla/dom/src/base/nsJSEnvironment.h +++ b/mozilla/dom/src/base/nsJSEnvironment.h @@ -130,14 +130,18 @@ public: virtual void SetGCOnDestruction(PRBool aGCOnDestruction); + virtual nsresult InitClasses(JSObject *aGlobalObj); + + virtual void WillInitializeContext(); + virtual void DidInitializeContext(); + NS_DECL_NSIXPCSCRIPTNOTIFY NS_DECL_NSITIMERCALLBACK protected: - nsresult InitClasses(); nsresult InitializeExternalClasses(); - nsresult InitializeLiveConnectClasses(); + nsresult InitializeLiveConnectClasses(JSObject *aGlobalObj); // aHolder should be holding our global object nsresult FindXPCNativeWrapperClass(nsIXPConnectJSObjectHolder *aHolder); @@ -153,14 +157,16 @@ protected: struct TerminationFuncHolder; friend struct TerminationFuncHolder; - struct TerminationFuncClosure { + struct TerminationFuncClosure + { TerminationFuncClosure(nsScriptTerminationFunc aFunc, nsISupports* aArg, TerminationFuncClosure* aNext) : mTerminationFunc(aFunc), mTerminationFuncArg(aArg), mNext(aNext) - {} + { + } ~TerminationFuncClosure() { delete mNext; @@ -171,14 +177,16 @@ protected: TerminationFuncClosure* mNext; }; - struct TerminationFuncHolder { - TerminationFuncHolder(nsJSContext* aContext) : - mContext(aContext), - mTerminations(aContext->mTerminations) + struct TerminationFuncHolder + { + TerminationFuncHolder(nsJSContext* aContext) + : mContext(aContext), + mTerminations(aContext->mTerminations) { aContext->mTerminations = nsnull; } - ~TerminationFuncHolder() { + ~TerminationFuncHolder() + { // Have to be careful here. mContext might have picked up new // termination funcs while the script was evaluating. Prepend whatever // we have to the current termination funcs on the context (since our diff --git a/mozilla/dom/src/events/nsJSEventListener.cpp b/mozilla/dom/src/events/nsJSEventListener.cpp index 593054aa5d5..0da4399686f 100644 --- a/mozilla/dom/src/events/nsJSEventListener.cpp +++ b/mozilla/dom/src/events/nsJSEventListener.cpp @@ -51,9 +51,10 @@ /* * nsJSEventListener implementation */ -nsJSEventListener::nsJSEventListener(nsIScriptContext *aContext, +nsJSEventListener::nsJSEventListener(nsIScriptContext *aContext, + JSObject *aScopeObject, nsISupports *aObject) - : nsIJSEventListener(aContext, aObject), + : nsIJSEventListener(aContext, aScopeObject, aObject), mReturnResult(nsReturnResult_eNotSet) { } @@ -119,8 +120,8 @@ nsJSEventListener::HandleEvent(nsIDOMEvent* aEvent) // root nsCOMPtr wrapper; - rv = xpc->WrapNative(cx, ::JS_GetGlobalObject(cx), mTarget, - NS_GET_IID(nsISupports), getter_AddRefs(wrapper)); + rv = xpc->WrapNative(cx, mScopeObject, mTarget, NS_GET_IID(nsISupports), + getter_AddRefs(wrapper)); NS_ENSURE_SUCCESS(rv, rv); JSObject* obj = nsnull; @@ -221,16 +222,16 @@ nsJSEventListener::HandleEvent(nsIDOMEvent* aEvent) */ nsresult -NS_NewJSEventListener(nsIDOMEventListener ** aInstancePtrResult, - nsIScriptContext *aContext, nsISupports *aObject) +NS_NewJSEventListener(nsIScriptContext *aContext, JSObject *aScopeObject, + nsISupports *aObject, nsIDOMEventListener ** aReturn) { - nsJSEventListener* it = new nsJSEventListener(aContext, aObject); + nsJSEventListener* it = + new nsJSEventListener(aContext, aScopeObject, aObject); if (!it) { return NS_ERROR_OUT_OF_MEMORY; } - *aInstancePtrResult = it; - NS_ADDREF(*aInstancePtrResult); + NS_ADDREF(*aReturn = it); return NS_OK; } diff --git a/mozilla/dom/src/events/nsJSEventListener.h b/mozilla/dom/src/events/nsJSEventListener.h index f134f5dead6..526e5f4a0bc 100644 --- a/mozilla/dom/src/events/nsJSEventListener.h +++ b/mozilla/dom/src/events/nsJSEventListener.h @@ -51,7 +51,8 @@ class nsJSEventListener : public nsIDOMEventListener, public nsIJSEventListener { public: - nsJSEventListener(nsIScriptContext *aContext, nsISupports* aObject); + nsJSEventListener(nsIScriptContext *aContext, JSObject *aScopeObject, + nsISupports* aObject); virtual ~nsJSEventListener(); NS_DECL_ISUPPORTS @@ -74,10 +75,5 @@ protected: nsReturnResult mReturnResult; }; -/* factory function */ -nsresult NS_NewJSEventListener(nsIDOMEventListener **aInstancePtrResult, - nsIScriptContext *aContext, - nsISupports *aObject); - #endif //nsJSEventListener_h__ diff --git a/mozilla/embedding/components/windowwatcher/src/nsWindowWatcher.cpp b/mozilla/embedding/components/windowwatcher/src/nsWindowWatcher.cpp index d6cdc561c45..aa4c12eea2d 100644 --- a/mozilla/embedding/components/windowwatcher/src/nsWindowWatcher.cpp +++ b/mozilla/embedding/components/windowwatcher/src/nsWindowWatcher.cpp @@ -908,6 +908,15 @@ nsWindowWatcher::GetActiveWindow(nsIDOMWindow **aActiveWindow) NS_IMETHODIMP nsWindowWatcher::SetActiveWindow(nsIDOMWindow *aActiveWindow) { +#ifdef DEBUG + { + nsCOMPtr win(do_QueryInterface(aActiveWindow)); + + NS_ASSERTION(!win || win->IsOuterWindow(), + "Uh, the active window must be an outer window!"); + } +#endif + if (FindWindowEntry(aActiveWindow)) { mActiveWindow = aActiveWindow; return NS_OK; @@ -924,6 +933,15 @@ nsWindowWatcher::AddWindow(nsIDOMWindow *aWindow, nsIWebBrowserChrome *aChrome) if (!aWindow) return NS_ERROR_INVALID_ARG; +#ifdef DEBUG + { + nsCOMPtr win(do_QueryInterface(aWindow)); + + NS_ASSERTION(win->IsOuterWindow(), + "Uh, the active window must be an outer window!"); + } +#endif + { nsWatcherWindowEntry *info; nsAutoLock lock(mListLock); @@ -1730,43 +1748,20 @@ nsWindowWatcher::AttachArguments(nsIDOMWindow *aWindow, NS_ENSURE_TRUE(scriptGlobal, NS_ERROR_UNEXPECTED); nsIScriptContext *scriptContext = scriptGlobal->GetContext(); + nsresult rv = NS_OK; + if (scriptContext) { JSContext *cx; cx = (JSContext *)scriptContext->GetNativeContext(); - nsresult rv; - nsCOMPtr xpc(do_GetService(nsIXPConnect::GetCID(), &rv)); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr wrapper; - rv = xpc->WrapNative(cx, ::JS_GetGlobalObject(cx), aWindow, - NS_GET_IID(nsIDOMWindow), getter_AddRefs(wrapper)); - NS_ENSURE_SUCCESS(rv, rv); - - JSObject *window_obj; - rv = wrapper->GetJSObject(&window_obj); - NS_ENSURE_SUCCESS(rv, rv); - JSObject *args; args = ::JS_NewArrayObject(cx, argc, argv); if (args) { - // If this is an existing window that we're opening into, the document - // change in it will wipe out the JS scope. In particular it would clear - // the "arguments" property we're about to set. So set the document in - // the window to null right away, so that when the new document loads we - // don't clear the scope. - nsCOMPtr globalObject(do_GetInterface(aWindow)); - if (globalObject) { - globalObject->SetNewDocument(nsnull, PR_TRUE, PR_TRUE); - } - jsval argsVal = OBJECT_TO_JSVAL(args); - // ::JS_DefineProperty(cx, window_obj, "arguments", - // argsVal, NULL, NULL, JSPROP_PERMANENT); - ::JS_SetProperty(cx, window_obj, "arguments", &argsVal); + rv = scriptGlobal->SetNewArguments(args); } } - return NS_OK; + return rv; } nsresult diff --git a/mozilla/js/src/jsapi.h b/mozilla/js/src/jsapi.h index 1f590d4326b..9efdb873b77 100644 --- a/mozilla/js/src/jsapi.h +++ b/mozilla/js/src/jsapi.h @@ -815,7 +815,13 @@ struct JSClass { struct JSExtendedClass { JSClass base; JSEqualityOp equality; - jsword reserved[7]; + JSObjectOp outerObject; + jsword reserved0; + jsword reserved1; + jsword reserved2; + jsword reserved3; + jsword reserved4; + jsword reserved5; }; #define JSCLASS_HAS_PRIVATE (1<<0) /* objects have private slot */ @@ -853,7 +859,7 @@ struct JSExtendedClass { /* Initializer for unused members of statically initialized JSClass structs. */ #define JSCLASS_NO_OPTIONAL_MEMBERS 0,0,0,0,0,0,0,0 -#define JSCLASS_NO_RESERVED_MEMBERS {0,0,0,0,0,0,0} +#define JSCLASS_NO_RESERVED_MEMBERS 0,0,0,0,0,0 /* For detailed comments on these function pointer types, see jspubtd.h. */ struct JSObjectOps { diff --git a/mozilla/js/src/jsinterp.c b/mozilla/js/src/jsinterp.c index 39c9103b7cc..cb71837e56f 100644 --- a/mozilla/js/src/jsinterp.c +++ b/mozilla/js/src/jsinterp.c @@ -3781,7 +3781,22 @@ js_Interpret(JSContext *cx, jsbytecode *pc, jsval *result) break; case JSOP_THIS: - PUSH_OPND(OBJECT_TO_JSVAL(fp->thisp)); + obj = fp->thisp; + clasp = OBJ_GET_CLASS(cx, obj); + if (clasp->flags & JSCLASS_IS_EXTENDED) { + JSExtendedClass *xclasp; + + xclasp = (JSExtendedClass *) clasp; + if (xclasp->outerObject) { + obj = xclasp->outerObject(cx, obj); + if (!obj) { + ok = JS_FALSE; + goto out; + } + } + } + + PUSH_OPND(OBJECT_TO_JSVAL(obj)); obj = NULL; break; diff --git a/mozilla/js/src/jsobj.c b/mozilla/js/src/jsobj.c index b6f5186ee89..58b68cbdcb3 100644 --- a/mozilla/js/src/jsobj.c +++ b/mozilla/js/src/jsobj.c @@ -143,6 +143,9 @@ obj_getSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp) jsid propid; JSAccessMode mode; uintN attrs; + JSObject *pobj; + JSClass *clasp; + JSExtendedClass *xclasp; slot = (uint32) JSVAL_TO_INT(id); if (id == INT_TO_JSVAL(JSSLOT_PROTO)) { @@ -152,9 +155,24 @@ obj_getSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp) propid = ATOM_TO_JSID(cx->runtime->atomState.parentAtom); mode = JSACC_PARENT; } + + /* Let OBJ_CHECK_ACCESS get the slot's value, based on the access mode. */ if (!OBJ_CHECK_ACCESS(cx, obj, propid, mode, vp, &attrs)) return JS_FALSE; - *vp = OBJ_GET_SLOT(cx, obj, slot); + + pobj = JSVAL_TO_OBJECT(*vp); + if (pobj) { + clasp = OBJ_GET_CLASS(cx, pobj); + if (clasp->flags & JSCLASS_IS_EXTENDED) { + xclasp = (JSExtendedClass *) clasp; + if (xclasp->outerObject) { + pobj = xclasp->outerObject(cx, pobj); + if (!pobj) + return JS_FALSE; + *vp = OBJECT_TO_JSVAL(pobj); + } + } + } return JS_TRUE; } @@ -2175,7 +2193,7 @@ HidePropertyName(JSContext *cx, jsid *idp) { jsid id; JSAtom *atom, *hidden; - + id = *idp; JS_ASSERT(JSID_IS_ATOM(id)); diff --git a/mozilla/js/src/jsxml.c b/mozilla/js/src/jsxml.c index d70cc163560..c2f8b659d96 100644 --- a/mozilla/js/src/jsxml.c +++ b/mozilla/js/src/jsxml.c @@ -252,6 +252,7 @@ JS_FRIEND_DATA(JSExtendedClass) js_NamespaceClass = { NULL, NULL, NULL, NULL, NULL, NULL, namespace_mark, NULL }, namespace_equality, + NULL, JSCLASS_NO_RESERVED_MEMBERS }; @@ -454,6 +455,7 @@ JS_FRIEND_DATA(JSExtendedClass) js_QNameClass = { NULL, NULL, NULL, NULL, NULL, NULL, qname_mark, NULL }, qname_equality, + NULL, JSCLASS_NO_RESERVED_MEMBERS }; diff --git a/mozilla/js/src/xpconnect/idl/nsIXPCScriptable.idl b/mozilla/js/src/xpconnect/idl/nsIXPCScriptable.idl index ff581356da9..b2c9799d920 100644 --- a/mozilla/js/src/xpconnect/idl/nsIXPCScriptable.idl +++ b/mozilla/js/src/xpconnect/idl/nsIXPCScriptable.idl @@ -53,7 +53,7 @@ * to *_retval unless they want to return PR_FALSE. */ -[uuid(3a592a93-bf40-4ca1-9025-ef05dc2b0cd9)] +[uuid(f617776f-c0f8-465f-8e60-268a1bf05a76)] interface nsIXPCScriptable : nsISupports { /* bitflags used for 'flags' (only 32 bits available!) */ @@ -86,6 +86,8 @@ interface nsIXPCScriptable : nsISupports const PRUint32 ALLOW_PROP_MODS_TO_PROTOTYPE = 1 << 25; const PRUint32 DONT_SHARE_PROTOTYPE = 1 << 26; const PRUint32 DONT_REFLECT_INTERFACE_NAMES = 1 << 27; + const PRUint32 WANT_EQUALITY = 1 << 28; + const PRUint32 WANT_OUTER_OBJECT = 1 << 29; // The high order bit is RESERVED for consumers of these flags. // No implementor of this interface should ever return flags @@ -160,4 +162,10 @@ interface nsIXPCScriptable : nsISupports PRUint32 mark(in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in voidPtr arg); + + PRBool equality(in nsIXPConnectWrappedNative wrapper, + in JSContextPtr cx, in JSObjectPtr obj, in JSVal val); + + JSObjectPtr outerObject(in nsIXPConnectWrappedNative wrapper, + in JSContextPtr cx, in JSObjectPtr obj); }; diff --git a/mozilla/js/src/xpconnect/idl/xpccomponents.idl b/mozilla/js/src/xpconnect/idl/xpccomponents.idl index 06b1b8d59ad..2b5af7f7085 100644 --- a/mozilla/js/src/xpconnect/idl/xpccomponents.idl +++ b/mozilla/js/src/xpconnect/idl/xpccomponents.idl @@ -177,7 +177,7 @@ interface nsIXPCComponents : nsISupports readonly attribute nsIStackFrame stack; readonly attribute nsIXPCComponents_Results results; readonly attribute nsIComponentManager manager; - readonly attribute nsIXPCComponents_Utils utils; + readonly attribute nsIXPCComponents_Utils utils; readonly attribute nsIXPCComponents_ID ID; readonly attribute nsIXPCComponents_Exception Exception; diff --git a/mozilla/js/src/xpconnect/public/xpc_map_end.h b/mozilla/js/src/xpconnect/public/xpc_map_end.h index 355841c38e6..50262799a6b 100644 --- a/mozilla/js/src/xpconnect/public/xpc_map_end.h +++ b/mozilla/js/src/xpconnect/public/xpc_map_end.h @@ -112,6 +112,12 @@ NS_IMETHODIMP XPC_MAP_CLASSNAME::GetScriptableFlags(PRUint32 *aFlags) #ifdef XPC_MAP_WANT_MARK nsIXPCScriptable::WANT_MARK | #endif +#ifdef XPC_MAP_WANT_EQUALITY + nsIXPCScriptable::WANT_EQUALITY | +#endif +#ifdef XPC_MAP_WANT_OUTER_OBJECT + nsIXPCScriptable::WANT_OUTER_OBJECT | +#endif #ifdef XPC_MAP_FLAGS XPC_MAP_FLAGS | @@ -208,6 +214,16 @@ NS_IMETHODIMP XPC_MAP_CLASSNAME::Mark(nsIXPConnectWrappedNative *wrapper, JSCont {NS_ERROR("never called"); return NS_ERROR_NOT_IMPLEMENTED;} #endif +#ifndef XPC_MAP_WANT_EQUALITY +NS_IMETHODIMP XPC_MAP_CLASSNAME::Equality(nsIXPConnectWrappedNative *wrapper, JSContext * cx, JSObject * obj, jsval val, PRBool *bp) + {NS_ERROR("never called"); return NS_ERROR_NOT_IMPLEMENTED;} +#endif + +#ifndef XPC_MAP_WANT_OUTER_OBJECT +NS_IMETHODIMP XPC_MAP_CLASSNAME::OuterObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx, JSObject * obj, JSObject * *_retval) + {NS_ERROR("never called"); return NS_ERROR_NOT_IMPLEMENTED;} +#endif + /**************************************************************/ #undef XPC_MAP_CLASSNAME @@ -281,6 +297,14 @@ NS_IMETHODIMP XPC_MAP_CLASSNAME::Mark(nsIXPConnectWrappedNative *wrapper, JSCont #undef XPC_MAP_WANT_MARK #endif +#ifdef XPC_MAP_WANT_EQUALITY +#undef XPC_MAP_WANT_EQUALITY +#endif + +#ifdef XPC_MAP_WANT_OUTER_OBJECT +#undef XPC_MAP_WANT_OUTER_OBJECT +#endif + #ifdef XPC_MAP_FLAGS #undef XPC_MAP_FLAGS #endif diff --git a/mozilla/js/src/xpconnect/src/xpcprivate.h b/mozilla/js/src/xpconnect/src/xpcprivate.h index 118c59f1c0d..f101988ddd8 100644 --- a/mozilla/js/src/xpconnect/src/xpcprivate.h +++ b/mozilla/js/src/xpconnect/src/xpcprivate.h @@ -139,7 +139,7 @@ #define DEBUG_xpc_hacker #endif -#if defined(DEBUG_brendan) || defined(DEBUG_bzbarsky) || defined(DEBUG_jst) +#if defined(DEBUG_brendan) || defined(DEBUG_bzbarsky) #define DEBUG_XPCNativeWrapper 1 #endif @@ -1433,6 +1433,8 @@ public: JSBool WantConstruct() GET_IT(WANT_CONSTRUCT) JSBool WantHasInstance() GET_IT(WANT_HASINSTANCE) JSBool WantMark() GET_IT(WANT_MARK) + JSBool WantEquality() GET_IT(WANT_EQUALITY) + JSBool WantOuterObject() GET_IT(WANT_OUTER_OBJECT) JSBool UseJSStubForAddProperty() GET_IT(USE_JSSTUB_FOR_ADDPROPERTY) JSBool UseJSStubForDelProperty() GET_IT(USE_JSSTUB_FOR_DELPROPERTY) JSBool UseJSStubForSetProperty() GET_IT(USE_JSSTUB_FOR_SETPROPERTY) diff --git a/mozilla/js/src/xpconnect/src/xpcwrappednativejsops.cpp b/mozilla/js/src/xpconnect/src/xpcwrappednativejsops.cpp index 0f9a2809160..e3041c4bfeb 100644 --- a/mozilla/js/src/xpconnect/src/xpcwrappednativejsops.cpp +++ b/mozilla/js/src/xpconnect/src/xpcwrappednativejsops.cpp @@ -740,13 +740,12 @@ GetIdentityObject(JSContext *cx, JSObject *obj) { XPCWrappedNative *wrapper; - if (XPCNativeWrapper::IsNativeWrapper(cx, obj)) { + if(XPCNativeWrapper::IsNativeWrapper(cx, obj)) wrapper = XPCNativeWrapper::GetWrappedNative(cx, obj); - } else { + else wrapper = XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj); - } - if (!wrapper) { + if(!wrapper) { return nsnull; } @@ -756,18 +755,68 @@ GetIdentityObject(JSContext *cx, JSObject *obj) JS_STATIC_DLL_CALLBACK(JSBool) XPC_WN_Equality(JSContext *cx, JSObject *obj, jsval v, JSBool *bp) { - if (JSVAL_IS_PRIMITIVE(v)) { *bp = JS_FALSE; + XPCWrappedNative *wrapper = + XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj); + THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper); + + XPCNativeScriptableInfo* si = wrapper->GetScriptableInfo(); + if(si && si->GetFlags().WantEquality()) + { + nsresult rv = si->GetCallback()->Equality(wrapper, cx, obj, v, bp); + + if(NS_FAILED(rv)) + return Throw(rv, cx); + } + else if(!JSVAL_IS_PRIMITIVE(v)) + { + JSObject *other = JSVAL_TO_OBJECT(v); + + *bp = (obj == other || + GetIdentityObject(cx, obj) == GetIdentityObject(cx, other)); + } + return JS_TRUE; - } +} - JSObject *other = JSVAL_TO_OBJECT(v); +JS_STATIC_DLL_CALLBACK(JSObject *) +XPC_WN_OuterObject(JSContext *cx, JSObject *obj) +{ + XPCWrappedNative *wrapper = + XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj); + if(!wrapper) + { + Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO, cx); - *bp = (obj == other || - GetIdentityObject(cx, obj) == GetIdentityObject(cx, other)); + return nsnull; + } - return JS_TRUE; + if(!wrapper->IsValid()) + { + Throw(NS_ERROR_XPC_HAS_BEEN_SHUTDOWN, cx); + + return nsnull; + } + + XPCNativeScriptableInfo* si = wrapper->GetScriptableInfo(); + if(si && si->GetFlags().WantOuterObject()) + { + JSObject *newThis; + nsresult rv = + si->GetCallback()->OuterObject(wrapper, cx, obj, &newThis); + + if(NS_FAILED(rv)) + { + Throw(rv, cx); + + return nsnull; + } + + obj = newThis; + } + + return obj; } @@ -798,7 +847,8 @@ JSExtendedClass XPC_WN_NoHelper_JSClass = { XPC_WN_Shared_Mark, // mark; nsnull // spare; }, - XPC_WN_Equality + XPC_WN_Equality, + XPC_WN_OuterObject }; @@ -1326,6 +1376,7 @@ XPCNativeScriptableShared::PopulateJSClass() mJSClass.base.mark = XPC_WN_Shared_Mark; mJSClass.equality = XPC_WN_Equality; + mJSClass.outerObject = XPC_WN_OuterObject; } /***************************************************************************/ diff --git a/mozilla/layout/base/nsDocumentViewer.cpp b/mozilla/layout/base/nsDocumentViewer.cpp index 4fe46345bb2..74ea98db21c 100644 --- a/mozilla/layout/base/nsDocumentViewer.cpp +++ b/mozilla/layout/base/nsDocumentViewer.cpp @@ -840,7 +840,6 @@ DocumentViewerImpl::InitInternal(nsIWidget* aParentWidget, getter_AddRefs(global)); if (global) { - mDocument->SetScriptGlobalObject(global); nsCOMPtr domdoc(do_QueryInterface(mDocument)); if (domdoc) { @@ -1259,14 +1258,6 @@ DocumentViewerImpl::Close(nsISHEntry *aSHEntry) } #endif - // Break global object circular reference on the document created - // in the DocViewer Init - nsIScriptGlobalObject* globalObject = mDocument->GetScriptGlobalObject(); - - if (globalObject) { - globalObject->SetNewDocument(nsnull, PR_TRUE, PR_TRUE); - } - #ifdef NS_PRINTING // A Close was called while we were printing // so don't clear the ScriptGlobalObject @@ -1511,19 +1502,21 @@ DocumentViewerImpl::SetDOMDocument(nsIDOMDocument *aDocument) nsCOMPtr container = do_QueryReferent(mContainer); newDoc->SetContainer(container); - // Replace the old document with the new one - mDocument = newDoc; + if (mDocument != newDoc) { + // Replace the old document with the new one. Do this only when + // the new document really is a new document. + mDocument = newDoc; - // Set the script global object on the new document - nsCOMPtr global = do_GetInterface(container); - if (global) { - mDocument->SetScriptGlobalObject(global); - global->SetNewDocument(aDocument, PR_TRUE, PR_TRUE); - - rv = SyncParentSubDocMap(); - NS_ENSURE_SUCCESS(rv, rv); + // Set the script global object on the new document + nsCOMPtr global = do_GetInterface(container); + if (global) { + global->SetNewDocument(aDocument, PR_TRUE, PR_TRUE); + } } + rv = SyncParentSubDocMap(); + NS_ENSURE_SUCCESS(rv, rv); + // Replace the current pres shell with a new shell for the new document nsCOMPtr linkHandler; @@ -3210,7 +3203,7 @@ nsDocViewerFocusListener::Focus(nsIDOMEvent* aEvent) nsCOMPtr selCon; selCon = do_QueryInterface(shell); PRInt16 selectionStatus; - selCon->GetDisplaySelection( &selectionStatus); + selCon->GetDisplaySelection(&selectionStatus); //if selection was nsISelectionController::SELECTION_OFF, do nothing //otherwise re-enable it. diff --git a/mozilla/layout/base/nsPresContext.h b/mozilla/layout/base/nsPresContext.h index 3d0cfb37681..775e0fa4d9c 100644 --- a/mozilla/layout/base/nsPresContext.h +++ b/mozilla/layout/base/nsPresContext.h @@ -713,7 +713,7 @@ protected: #endif -private: +protected: ~nsPresContext() NS_HIDDEN; diff --git a/mozilla/layout/base/nsPresShell.cpp b/mozilla/layout/base/nsPresShell.cpp index 22c0d0837c7..ac6498fbaf5 100644 --- a/mozilla/layout/base/nsPresShell.cpp +++ b/mozilla/layout/base/nsPresShell.cpp @@ -2671,6 +2671,9 @@ static void CheckForFocus(nsPIDOMWindow* aOurWindow, nsIFocusController* aFocusController, nsIDocument* aDocument) { + NS_ASSERTION(aOurWindow->IsOuterWindow(), + "Uh, our window has to be an outer window!"); + // Now that we have a root frame, we can set focus on the presshell. // We do this only if our DOM window is currently focused or is an // an ancestor of a previously focused window. @@ -2711,8 +2714,10 @@ static void CheckForFocus(nsPIDOMWindow* aOurWindow, } while (curDoc) { - nsCOMPtr curWin = do_QueryInterface(curDoc->GetScriptGlobalObject()); - if (curWin == ourWin || !curWin) + nsCOMPtr curWin = + do_QueryInterface(curDoc->GetScriptGlobalObject()); + + if (!curWin || curWin->GetOuterWindow() == ourWin) break; curDoc = curDoc->GetParentDocument(); @@ -4359,12 +4364,13 @@ PresShell::GoToAnchor(const nsAString& aAnchorName, PRBool aScroll) // Now focus the document itself if focus is on an element within it. nsCOMPtr win = do_QueryInterface(mDocument->GetScriptGlobalObject()); + if (win) { nsCOMPtr focusController = win->GetRootFocusController(); if (focusController) { nsCOMPtr focusedWin; focusController->GetFocusedWindow(getter_AddRefs(focusedWin)); - if (SameCOMIdentity(win, focusedWin)) { + if (SameCOMIdentity(win->GetOuterWindow(), focusedWin)) { esm->ChangeFocusWith(nsnull, nsIEventStateManager::eEventFocusedByApplication); } }