From 1d9a51417fcfd2ca476e237399cc874aff806926 Mon Sep 17 00:00:00 2001 From: "bent.mozilla@gmail.com" Date: Tue, 15 Jan 2008 10:23:46 -0800 Subject: [PATCH] Bug 352791 - "Permission denied to get property XULElement.ownerDocument". Patch by Blake Kaplan . r=jst,bzbarsky. sr=brendan. a=blocking1.9. --- js/src/xpconnect/src/xpccontext.cpp | 11 +++++++++++ js/src/xpconnect/src/xpcprivate.h | 15 +++++++++++++-- js/src/xpconnect/src/xpcwrappedjsclass.cpp | 18 ++++++++++++++++-- js/src/xpconnect/src/xpcwrappednativescope.cpp | 9 +++++++++ 4 files changed, 49 insertions(+), 4 deletions(-) diff --git a/js/src/xpconnect/src/xpccontext.cpp b/js/src/xpconnect/src/xpccontext.cpp index f4dfae5bdcd..10c6fee1c2b 100644 --- a/js/src/xpconnect/src/xpccontext.cpp +++ b/js/src/xpconnect/src/xpccontext.cpp @@ -71,6 +71,7 @@ XPCContext::XPCContext(XPCJSRuntime* aRuntime, { MOZ_COUNT_CTOR(XPCContext); + PR_INIT_CLIST(&mScopes); for(const char** p = XPC_ARG_FORMATTER_FORMAT_STRINGS; *p; p++) JS_AddArgumentFormatter(mJSContext, *p, XPC_JSArgumentFormatter); } @@ -80,6 +81,16 @@ XPCContext::~XPCContext() MOZ_COUNT_DTOR(XPCContext); NS_IF_RELEASE(mException); NS_IF_RELEASE(mSecurityManager); + + // Iterate over our scopes and tell them that we have been destroyed + for(PRCList *scopeptr = PR_NEXT_LINK(&mScopes); + scopeptr != &mScopes; + scopeptr = PR_NEXT_LINK(scopeptr)) + { + XPCWrappedNativeScope *scope = (XPCWrappedNativeScope *)scopeptr; + scope->SetContext(nsnull); + } + // we do not call JS_RemoveArgumentFormatter because we now only // delete XPCContext *after* the underlying JSContext is dead } diff --git a/js/src/xpconnect/src/xpcprivate.h b/js/src/xpconnect/src/xpcprivate.h index 14e610f733e..df397e0697e 100644 --- a/js/src/xpconnect/src/xpcprivate.h +++ b/js/src/xpconnect/src/xpcprivate.h @@ -748,12 +748,14 @@ private: public: #endif + // For use by XPCWrappedNativeScope. + JSContext2XPCContextMap* GetContextMap() const {return mContextMap;} + private: XPCJSRuntime(); // no implementation XPCJSRuntime(nsXPConnect* aXPConnect, nsIJSRuntimeService* aJSRuntimeService); - JSContext2XPCContextMap* GetContextMap() const {return mContextMap;} JSBool GenerateStringIDs(JSContext* cx); void PurgeXPCContextList(); @@ -884,6 +886,8 @@ public: } void DebugDump(PRInt16 depth); + void AddScope(PRCList *scope) { PR_INSERT_AFTER(scope, &mScopes); } + void RemoveScope(PRCList *scope) { PR_REMOVE_LINK(scope); } ~XPCContext(); @@ -901,6 +905,9 @@ private: LangType mCallingLangType; PRUint16 mSecurityManagerFlags; JSPackedBool mMarked; + + // A linked list of scopes to notify when we are destroyed. + PRCList mScopes; }; /***************************************************************************/ @@ -1198,7 +1205,7 @@ xpc_TraceForValidWrapper(JSTracer *trc, XPCWrappedNative* wrapper); /***************************************************************************/ // XPCWrappedNativeScope is one-to-one with a JS global object. -class XPCWrappedNativeScope +class XPCWrappedNativeScope : public PRCList { public: @@ -1289,6 +1296,9 @@ public: static void InitStatics() { gScopes = nsnull; gDyingScopes = nsnull; } + XPCContext *GetContext() { return mContext; } + void SetContext(XPCContext *xpcc) { mContext = nsnull; } + #ifndef XPCONNECT_STANDALONE /** * Fills the hash mapping global object to principal. @@ -1321,6 +1331,7 @@ private: JSObject* mGlobalJSObject; JSObject* mPrototypeJSObject; JSObject* mPrototypeJSFunction; + XPCContext* mContext; #ifndef XPCONNECT_STANDALONE // The script object principal instance corresponding to our current global diff --git a/js/src/xpconnect/src/xpcwrappedjsclass.cpp b/js/src/xpconnect/src/xpcwrappedjsclass.cpp index 3196181e9c7..5f44138d0a2 100644 --- a/js/src/xpconnect/src/xpcwrappedjsclass.cpp +++ b/js/src/xpconnect/src/xpcwrappedjsclass.cpp @@ -500,6 +500,17 @@ nsXPCWrappedJSClass::IsWrappedJS(nsISupports* aPtr) result == WrappedJSIdentity::GetSingleton(); } +static JSContext * +GetContextFromObject(JSObject *obj) +{ + // In order to get a context, we need a context. + XPCCallContext ccx(NATIVE_CALLER); + XPCWrappedNativeScope* scope = + XPCWrappedNativeScope::FindInJSObjectScope(ccx, obj); + XPCContext *xpcc = scope->GetContext(); + return xpcc ? xpcc->GetJSContext() : nsnull; +} + NS_IMETHODIMP nsXPCWrappedJSClass::DelegatedQueryInterface(nsXPCWrappedJS* self, REFNSIID aIID, @@ -544,7 +555,9 @@ nsXPCWrappedJSClass::DelegatedQueryInterface(nsXPCWrappedJS* self, return NS_OK; } - XPCCallContext ccx(NATIVE_CALLER); + + JSContext *context = GetContextFromObject(self->GetJSObject()); + XPCCallContext ccx(NATIVE_CALLER, context); if(!ccx.IsValid()) { *aInstancePtr = nsnull; @@ -1048,7 +1061,8 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16 methodIndex, // the whole nsIXPCFunctionThisTranslator bit. That code uses ccx to // convert natives to JSObjects, but we do NOT plan to pass those JSObjects // to our real callee. - XPCCallContext ccx(NATIVE_CALLER); + JSContext *context = GetContextFromObject(wrapper->GetJSObject()); + XPCCallContext ccx(NATIVE_CALLER, context); if(ccx.IsValid()) { xpcc = ccx.GetXPCContext(); diff --git a/js/src/xpconnect/src/xpcwrappednativescope.cpp b/js/src/xpconnect/src/xpcwrappednativescope.cpp index 24befddad12..e9641cb7cc4 100644 --- a/js/src/xpconnect/src/xpcwrappednativescope.cpp +++ b/js/src/xpconnect/src/xpcwrappednativescope.cpp @@ -152,6 +152,12 @@ XPCWrappedNativeScope::XPCWrappedNativeScope(XPCCallContext& ccx, mNext = gScopes; gScopes = this; + + // Grab the XPCContext associated with our context. + mContext = mRuntime->GetContextMap()->Find(ccx.GetJSContext()); + NS_ASSERTION(mContext, "Context map is not synchronized"); + + mContext->AddScope(this); } if(aGlobal) @@ -274,6 +280,9 @@ XPCWrappedNativeScope::~XPCWrappedNativeScope() delete mWrapperMap; } + if(mContext) + mContext->RemoveScope(this); + // XXX we should assert that we are dead or that xpconnect has shutdown // XXX might not want to do this at xpconnect shutdown time??? NS_IF_RELEASE(mComponents);