Get principals for XPConnect wrapped natives off their scope instead of walking

their parent chain.  Add some asserts to check that this actually does give the
same result, which it should with splitwindow.  Bug 289655, r=dbradley, sr=jst
This commit is contained in:
bzbarsky%mit.edu 2005-11-16 02:12:21 +00:00
parent e28b1599b2
commit f02076fb6f
7 changed files with 139 additions and 18 deletions

View File

@ -386,7 +386,11 @@ private:
// Returns null if a principal cannot be found; generally callers
// should error out at that point.
static nsIPrincipal*
doGetObjectPrincipal(JSContext *cx, JSObject *obj);
doGetObjectPrincipal(JSContext *cx, JSObject *obj
#ifdef DEBUG
, PRBool aAllowShortCircuit = PR_TRUE
#endif
);
// Returns null if a principal cannot be found. Note that rv can be NS_OK
// when this happens -- this means that there was no JS running.

View File

@ -2083,7 +2083,11 @@ nsScriptSecurityManager::GetObjectPrincipal(JSContext *aCx, JSObject *aObj,
// static
nsIPrincipal*
nsScriptSecurityManager::doGetObjectPrincipal(JSContext *aCx, JSObject *aObj)
nsScriptSecurityManager::doGetObjectPrincipal(JSContext *aCx, JSObject *aObj
#ifdef DEBUG
, PRBool aAllowShortCircuit
#endif
)
{
NS_ASSERTION(aCx && aObj, "Bad call to doGetObjectPrincipal()!");
nsIPrincipal* result = nsnull;
@ -2097,7 +2101,6 @@ nsScriptSecurityManager::doGetObjectPrincipal(JSContext *aCx, JSObject *aObj)
{
// No need to refcount |priv| here.
nsISupports *priv = (nsISupports *)JS_GetPrivate(aCx, aObj);
nsCOMPtr<nsIScriptObjectPrincipal> objPrin;
/*
* If it's a wrapped native (as most
@ -2107,16 +2110,37 @@ nsScriptSecurityManager::doGetObjectPrincipal(JSContext *aCx, JSObject *aObj)
nsCOMPtr<nsIXPConnectWrappedNative> xpcWrapper =
do_QueryInterface(priv);
if (xpcWrapper)
if (NS_LIKELY(xpcWrapper != nsnull))
{
objPrin = do_QueryWrappedNative(xpcWrapper);
#ifdef DEBUG
if (aAllowShortCircuit)
{
#endif
result = xpcWrapper->GetObjectPrincipal();
#ifdef DEBUG
}
else
{
nsCOMPtr<nsIScriptObjectPrincipal> objPrin;
objPrin = do_QueryWrappedNative(xpcWrapper);
if (objPrin)
{
result = objPrin->GetPrincipal();
}
}
#endif
}
else
{
nsCOMPtr<nsIScriptObjectPrincipal> objPrin;
objPrin = do_QueryInterface(priv);
if (objPrin)
{
result = objPrin->GetPrincipal();
}
}
if (objPrin && (result = objPrin->GetPrincipal()))
if (result)
{
break;
}
@ -2125,6 +2149,10 @@ nsScriptSecurityManager::doGetObjectPrincipal(JSContext *aCx, JSObject *aObj)
aObj = JS_GetParent(aCx, aObj);
} while (aObj);
NS_ASSERTION(!aAllowShortCircuit ||
result == doGetObjectPrincipal(aCx, aObj, PR_FALSE),
"Principal mismatch. Not good");
return result;
}

View File

@ -147,6 +147,12 @@ interface nsIXPConnectWrappedNative;
interface nsIInterfaceInfo;
interface nsIXPCSecurityManager;
%{C++
#ifndef XPCONNECT_STANDALONE
class nsIPrincipal;
#endif
%}
/***************************************************************************/
[uuid(8916a320-d118-11d3-8f3a-0010a4e73d9a)]
interface nsIXPConnectJSObjectHolder : nsISupports
@ -154,7 +160,7 @@ interface nsIXPConnectJSObjectHolder : nsISupports
readonly attribute JSObjectPtr JSObject;
};
[uuid(215DBE02-94A7-11d2-BA58-00805F8A5DD7)]
[uuid(7021D99D-6344-4CC0-96E7-943ED58792B8)]
interface nsIXPConnectWrappedNative : nsIXPConnectJSObjectHolder
{
/* attribute 'JSObject' inherited from nsIXPConnectJSObjectHolder */
@ -179,12 +185,28 @@ interface nsIXPConnectWrappedNative : nsIXPConnectJSObjectHolder
*/
voidPtrPtr GetSecurityInfoAddress();
/*
* NOTE: Add new IDL methods _before_ the C++ block below if you
* add them. Otherwise the vtable won't be what xpidl thinks it
* is, since GetObjectPrincipal() is virtual.
*/
%{C++
/**
* Faster access to the native object from C++. Will never return null.
*/
nsISupports* Native() const { return mIdentity; }
#ifndef XPCONNECT_STANDALONE
/**
* Get the object principal for this wrapper. Note that this may well end
* up being null; in that case one should seek principals elsewhere. Null
* here does NOT indicate system principal or no principals at all, just
* that this wrapper doesn't have an intrinsic one.
*/
virtual nsIPrincipal* GetObjectPrincipal() const = 0;
#endif
protected:
nsISupports *mIdentity;
public:

View File

@ -2250,16 +2250,8 @@ nsXPCComponents_utils_Sandbox::CallOrConstruct(nsIXPConnectWrappedNative *wrappe
if (!sandbox)
return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
rv = xpc->InitClasses(cx, sandbox);
if (NS_SUCCEEDED(rv) &&
!JS_DefineFunctions(cx, sandbox, SandboxFunctions)) {
rv = NS_ERROR_FAILURE;
}
if (NS_FAILED(rv))
return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
// Make sure to set up principals on the sandbox before initing classes
nsIScriptObjectPrincipal *sop = nsnull;
if (JSVAL_IS_STRING(argv[0])) {
JSString *codebasestr = JSVAL_TO_STRING(argv[0]);
nsCAutoString codebase(JS_GetStringBytes(codebasestr),
@ -2316,6 +2308,17 @@ nsXPCComponents_utils_Sandbox::CallOrConstruct(nsIXPConnectWrappedNative *wrappe
return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
}
// After this point |sop| will be released when |sandbox| is
// finalized, so no need to worry about it from now on.
rv = xpc->InitClasses(cx, sandbox);
if (NS_SUCCEEDED(rv) &&
!JS_DefineFunctions(cx, sandbox, SandboxFunctions)) {
rv = NS_ERROR_FAILURE;
}
if (NS_FAILED(rv))
return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
if (vp)
*vp = OBJECT_TO_JSVAL(sandbox);

View File

@ -109,8 +109,11 @@
#include "nsSupportsArray.h"
#include "nsIXPCScriptNotify.h" // used to notify: ScriptEvaluated
#ifndef XPCONNECT_STANDALONE
#define XPC_USE_SECURITY_CHECKED_COMPONENT
#include "nsIScriptObjectPrincipal.h"
#include "nsIPrincipal.h"
#endif
#ifdef XPC_USE_SECURITY_CHECKED_COMPONENT
@ -1025,6 +1028,13 @@ public:
JSObject*
GetPrototypeJSObject() const {return mPrototypeJSObject;}
#ifndef XPCONNECT_STANDALONE
nsIPrincipal*
GetPrincipal() const
{return mScriptObjectPrincipal ?
mScriptObjectPrincipal->GetPrincipal() : nsnull;}
#endif
JSObject*
GetPrototypeJSFunction() const {return mPrototypeJSFunction;}
@ -1088,9 +1098,22 @@ private:
ClassInfo2WrappedNativeProtoMap* mWrappedNativeProtoMap;
nsXPCComponents* mComponents;
XPCWrappedNativeScope* mNext;
// The JS global object for this scope. If non-null, this will be the
// default parent for the XPCWrappedNatives that have us as the scope,
// unless a PreCreate hook overrides it. Note that this _may_ be null (see
// constructor).
JSObject* mGlobalJSObject;
JSObject* mPrototypeJSObject;
JSObject* mPrototypeJSFunction;
#ifndef XPCONNECT_STANDALONE
// The script object principal instance corresponding to our current global
// JS object.
// XXXbz what happens if someone calls JS_SetPrivate on mGlobalJSObject.
// How do we deal? Do we need to? I suspect this isn't worth worrying
// about, since all of our scope objects are verified as not doing that.
nsCOMPtr<nsIScriptObjectPrincipal> mScriptObjectPrincipal;
#endif
};
/***************************************************************************/
@ -1787,6 +1810,10 @@ public:
NS_DECL_NSIXPCONNECTJSOBJECTHOLDER
NS_DECL_NSIXPCONNECTWRAPPEDNATIVE
#ifndef XPCONNECT_STANDALONE
virtual nsIPrincipal* GetObjectPrincipal() const;
#endif
JSBool
IsValid() const {return nsnull != mFlatJSObject;}
@ -2866,8 +2893,6 @@ private:
#ifndef XPCONNECT_STANDALONE
#include "nsIScriptSecurityManager.h"
#include "nsIPrincipal.h"
#include "nsIScriptObjectPrincipal.h"
class BackstagePass : public nsIScriptObjectPrincipal, public nsIXPCScriptable
{

View File

@ -2360,6 +2360,20 @@ NS_IMETHODIMP XPCWrappedNative::GetJSObjectPrototype(JSObject * *aJSObjectProtot
return NS_OK;
}
#ifndef XPCONNECT_STANDALONE
nsIPrincipal*
XPCWrappedNative::GetObjectPrincipal() const
{
nsIPrincipal* principal = GetScope()->GetPrincipal();
#ifdef DEBUG
nsCOMPtr<nsIScriptObjectPrincipal> objPrin(do_QueryInterface(mIdentity));
NS_ASSERTION(!objPrin || objPrin->GetPrincipal() == principal,
"Principal mismatch. Expect bad things to happen");
#endif
return principal;
}
#endif
/* readonly attribute nsIXPConnect XPConnect; */
NS_IMETHODIMP XPCWrappedNative::GetXPConnect(nsIXPConnect * *aXPConnect)
{

View File

@ -176,6 +176,31 @@ XPCWrappedNativeScope::SetGlobal(XPCCallContext& ccx, JSObject* aGlobal)
// nsXPConnect::InitClassesWithNewWrappedGlobal.
mGlobalJSObject = aGlobal;
#ifndef XPCONNECT_STANDALONE
mScriptObjectPrincipal = nsnull;
// Now init our script object principal, if the new global has one
if (aGlobal)
{
JSContext* cx = ccx.GetJSContext();
const JSClass* jsClass = JS_GetClass(cx, aGlobal);
if (jsClass && !(~jsClass->flags & (JSCLASS_HAS_PRIVATE |
JSCLASS_PRIVATE_IS_NSISUPPORTS)))
{
// Our global has an nsISupports native pointer. Let's
// see whether it's what we want.
nsISupports* priv = (nsISupports*)JS_GetPrivate(cx, aGlobal);
nsCOMPtr<nsIXPConnectWrappedNative> native =
do_QueryInterface(priv);
if (native)
{
mScriptObjectPrincipal = do_QueryWrappedNative(native);
}
if (!mScriptObjectPrincipal) {
mScriptObjectPrincipal = do_QueryInterface(priv);
}
}
}
#endif
// Lookup 'globalObject.Object.prototype' for our wrapper's proto
{