mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 563106 - Tie XPConnect to compartments. r=jorendorff/gal/jst
This commit is contained in:
parent
9870b95ead
commit
de74d9d8f4
@ -61,7 +61,7 @@ bool SendSyncMessageToParent(void* aCallbackData,
|
||||
nsTArray<nsCOMPtr<nsIRunnable> > asyncMessages;
|
||||
asyncMessages.SwapElements(tabChild->mASyncMessages);
|
||||
PRUint32 len = asyncMessages.Length();
|
||||
for (PRInt32 i = 0; i < len; ++i) {
|
||||
for (PRUint32 i = 0; i < len; ++i) {
|
||||
nsCOMPtr<nsIRunnable> async = asyncMessages[i];
|
||||
async->Run();
|
||||
}
|
||||
@ -286,8 +286,9 @@ nsInProcessTabChildGlobal::InitTabChildGlobal()
|
||||
|
||||
nsresult rv =
|
||||
xpc->InitClassesWithNewWrappedGlobal(cx, scopeSupports,
|
||||
NS_GET_IID(nsISupports), flags,
|
||||
getter_AddRefs(mGlobal));
|
||||
NS_GET_IID(nsISupports),
|
||||
GetPrincipal(), EmptyCString(),
|
||||
flags, getter_AddRefs(mGlobal));
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
JSObject* global = nsnull;
|
||||
|
@ -1302,7 +1302,10 @@ nsGlobalWindow::SetScriptContext(PRUint32 lang_id, nsIScriptContext *aScriptCont
|
||||
aScriptContext->SetGCOnDestruction(PR_FALSE);
|
||||
}
|
||||
|
||||
aScriptContext->CreateOuterObject(this);
|
||||
nsCOMPtr<nsIPrincipal> principal =
|
||||
do_CreateInstance("@mozilla.org/nullprincipal;1", &rv);
|
||||
|
||||
aScriptContext->CreateOuterObject(this, principal);
|
||||
aScriptContext->DidInitializeContext();
|
||||
mJSObject = (JSObject *)aScriptContext->GetNativeGlobal();
|
||||
}
|
||||
@ -1617,6 +1620,8 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
|
||||
Thaw();
|
||||
}
|
||||
|
||||
// XXX Brain transplant outer window JSObject and create new one!
|
||||
|
||||
NS_ASSERTION(!GetCurrentInnerWindow() ||
|
||||
GetCurrentInnerWindow()->GetExtantDocument() == mDocument,
|
||||
"Uh, mDocument doesn't match the current inner window "
|
||||
@ -1815,6 +1820,7 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
|
||||
void *&newGlobal = (void *&)newInnerWindow->mJSObject;
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> &holder = mInnerWindowHolder;
|
||||
rv = mContext->CreateNativeGlobalForInner(sgo, isChrome,
|
||||
aDocument->NodePrincipal(),
|
||||
&newGlobal,
|
||||
getter_AddRefs(holder));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv) && newGlobal && holder,
|
||||
|
@ -72,10 +72,10 @@ public:
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIScriptContextPrincipal,
|
||||
NS_ISCRIPTCONTEXTPRINCIPAL_IID)
|
||||
|
||||
// 5a5d683e-f387-4694-9ff0-3a90b3e6749e
|
||||
// 5b6d04a3-f095-4924-ad84-4f44f9b3fae0
|
||||
#define NS_ISCRIPTCONTEXT_IID \
|
||||
{ 0x5a5d683e, 0xf387, 0x4694, \
|
||||
{ 0x9f, 0xf0, 0x3a, 0x90, 0xb3, 0xe6, 0x74, 0x9e } }
|
||||
{ 0x5b6d04a3, 0xf095, 0x4924, \
|
||||
{ 0xad, 0x84, 0x4f, 0x44, 0xf9, 0xb3, 0xfa, 0xe0 } }
|
||||
|
||||
/* This MUST match JSVERSION_DEFAULT. This version stuff if we don't
|
||||
know what language we have is a little silly... */
|
||||
@ -320,6 +320,7 @@ public:
|
||||
virtual nsresult CreateNativeGlobalForInner(
|
||||
nsIScriptGlobalObject *aNewInner,
|
||||
PRBool aIsChrome,
|
||||
nsIPrincipal *aPrincipal,
|
||||
void **aNativeGlobal,
|
||||
nsISupports **aHolder) = 0;
|
||||
|
||||
@ -342,7 +343,8 @@ public:
|
||||
*
|
||||
* @param aGlobalObject The script global object to use as our global.
|
||||
*/
|
||||
virtual nsresult CreateOuterObject(nsIScriptGlobalObject *aGlobalObject) = 0;
|
||||
virtual nsresult CreateOuterObject(nsIScriptGlobalObject *aGlobalObject,
|
||||
nsIPrincipal *aPrincipal) = 0;
|
||||
|
||||
/**
|
||||
* Prepares this context for use with the current inner window for the
|
||||
|
@ -1590,6 +1590,13 @@ nsJSContext::EvaluateStringWithValue(const nsAString& aScript,
|
||||
JSAutoRequest ar(mContext);
|
||||
nsJSVersionSetter setVersion(mContext, aVersion);
|
||||
|
||||
JSAutoCrossCompartmentCall accc;
|
||||
if (!accc.enter(mContext, (JSObject *)aScopeObject)) {
|
||||
JSPRINCIPALS_DROP(mContext, jsprin);
|
||||
stack->Pop(nsnull);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
++mExecuteDepth;
|
||||
|
||||
ok = ::JS_EvaluateUCScriptForPrincipals(mContext,
|
||||
@ -1777,6 +1784,13 @@ nsJSContext::EvaluateString(const nsAString& aScript,
|
||||
// check it isn't JSVERSION_UNKNOWN.
|
||||
if (ok && ((JSVersion)aVersion) != JSVERSION_UNKNOWN) {
|
||||
JSAutoRequest ar(mContext);
|
||||
JSAutoCrossCompartmentCall accc;
|
||||
if (!accc.enter(mContext, (JSObject *)aScopeObject)) {
|
||||
stack->Pop(nsnull);
|
||||
JSPRINCIPALS_DROP(mContext, jsprin);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsJSVersionSetter setVersion(mContext, aVersion);
|
||||
|
||||
ok = ::JS_EvaluateUCScriptForPrincipals(mContext,
|
||||
@ -2202,6 +2216,12 @@ nsJSContext::CallEventHandler(nsISupports* aTarget, void *aScope, void *aHandler
|
||||
|
||||
jsval funval = OBJECT_TO_JSVAL(static_cast<JSObject *>(aHandler));
|
||||
JSAutoRequest ar(mContext);
|
||||
JSAutoCrossCompartmentCall accc;
|
||||
if (!accc.enter(mContext, target)) {
|
||||
stack->Pop(nsnull);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
++mExecuteDepth;
|
||||
PRBool ok = ::JS_CallFunctionValue(mContext, target,
|
||||
funval, argc, argv, &rval);
|
||||
@ -2517,6 +2537,7 @@ nsresult
|
||||
nsJSContext::CreateNativeGlobalForInner(
|
||||
nsIScriptGlobalObject *aNewInner,
|
||||
PRBool aIsChrome,
|
||||
nsIPrincipal *aPrincipal,
|
||||
void **aNativeGlobal, nsISupports **aHolder)
|
||||
{
|
||||
nsIXPConnect *xpc = nsContentUtils::XPConnect();
|
||||
@ -2525,6 +2546,7 @@ nsJSContext::CreateNativeGlobalForInner(
|
||||
nsresult rv = xpc->
|
||||
InitClassesWithNewWrappedGlobal(mContext,
|
||||
aNewInner, NS_GET_IID(nsISupports),
|
||||
aPrincipal, EmptyCString(),
|
||||
flags,
|
||||
getter_AddRefs(jsholder));
|
||||
if (NS_FAILED(rv))
|
||||
@ -2605,7 +2627,8 @@ nsJSContext::InitContext()
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsJSContext::CreateOuterObject(nsIScriptGlobalObject *aGlobalObject)
|
||||
nsJSContext::CreateOuterObject(nsIScriptGlobalObject *aGlobalObject,
|
||||
nsIPrincipal *aPrincipal)
|
||||
{
|
||||
NS_PRECONDITION(!JS_GetGlobalObject(mContext),
|
||||
"Outer window already initialized");
|
||||
@ -2631,6 +2654,7 @@ nsJSContext::CreateOuterObject(nsIScriptGlobalObject *aGlobalObject)
|
||||
nsresult rv =
|
||||
xpc->InitClassesWithNewWrappedGlobal(mContext, aGlobalObject,
|
||||
NS_GET_IID(nsISupports),
|
||||
aPrincipal, EmptyCString(),
|
||||
flags, getter_AddRefs(holder));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
|
@ -135,12 +135,14 @@ public:
|
||||
virtual nsresult CreateNativeGlobalForInner(
|
||||
nsIScriptGlobalObject *aGlobal,
|
||||
PRBool aIsChrome,
|
||||
nsIPrincipal *aPrincipal,
|
||||
void **aNativeGlobal,
|
||||
nsISupports **aHolder);
|
||||
virtual nsresult ConnectToInner(nsIScriptGlobalObject *aNewInner,
|
||||
void *aOuterGlobal);
|
||||
virtual nsresult InitContext();
|
||||
virtual nsresult CreateOuterObject(nsIScriptGlobalObject *aGlobalObject);
|
||||
virtual nsresult CreateOuterObject(nsIScriptGlobalObject *aGlobalObject,
|
||||
nsIPrincipal *aPrincipal);
|
||||
virtual nsresult InitOuterWindow();
|
||||
virtual PRBool IsContextInitialized();
|
||||
virtual void FinalizeContext();
|
||||
|
@ -993,8 +993,9 @@ TabChild::InitTabChildGlobal()
|
||||
|
||||
nsresult rv =
|
||||
xpc->InitClassesWithNewWrappedGlobal(cx, scopeSupports,
|
||||
NS_GET_IID(nsISupports), flags,
|
||||
getter_AddRefs(mRootGlobal));
|
||||
NS_GET_IID(nsISupports),
|
||||
scope->GetPrincipal(), EmptyCString(),
|
||||
flags, getter_AddRefs(mRootGlobal));
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
nsCOMPtr<nsPIWindowRoot> root = do_QueryInterface(chromeHandler);
|
||||
|
@ -1611,10 +1611,14 @@ nsDOMWorker::CompileGlobalObject(JSContext* aCx)
|
||||
const PRUint32 flags = nsIXPConnect::INIT_JS_STANDARD_CLASSES |
|
||||
nsIXPConnect::OMIT_COMPONENTS_OBJECT;
|
||||
|
||||
nsCAutoString origin("DOM worker: ");
|
||||
origin.AppendInt((PRUint64)this);
|
||||
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> globalWrapper;
|
||||
nsresult rv =
|
||||
xpc->InitClassesWithNewWrappedGlobal(aCx, scopeSupports,
|
||||
NS_GET_IID(nsISupports), flags,
|
||||
NS_GET_IID(nsISupports), nsnull,
|
||||
origin, flags,
|
||||
getter_AddRefs(globalWrapper));
|
||||
NS_ENSURE_SUCCESS(rv, PR_FALSE);
|
||||
|
||||
|
@ -270,7 +270,7 @@ GetLine(char *bufp,
|
||||
const char *prompt)
|
||||
{
|
||||
char line[256];
|
||||
fprintf(stdout, prompt);
|
||||
fputs(prompt, stdout);
|
||||
fflush(stdout);
|
||||
if (!fgets(line, sizeof line, file))
|
||||
return JS_FALSE;
|
||||
@ -1171,6 +1171,8 @@ XPCShellEnvironment::Init()
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
|
||||
rv = xpc->InitClassesWithNewWrappedGlobal(cx, backstagePass,
|
||||
NS_GET_IID(nsISupports),
|
||||
principal,
|
||||
EmptyCString(),
|
||||
nsIXPConnect::
|
||||
FLAG_SYSTEM_GLOBAL_OBJECT,
|
||||
getter_AddRefs(holder));
|
||||
|
@ -1081,6 +1081,14 @@ JS_GetImplementationVersion(void)
|
||||
return "JavaScript-C 1.8.0 pre-release 1 2007-10-03";
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSCompartmentCallback)
|
||||
JS_SetCompartmentCallback(JSRuntime *rt, JSCompartmentCallback callback)
|
||||
{
|
||||
JSCompartmentCallback old = rt->compartmentCallback;
|
||||
rt->compartmentCallback = callback;
|
||||
return old;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSWrapObjectCallback)
|
||||
JS_SetWrapObjectCallback(JSContext *cx, JSWrapObjectCallback callback)
|
||||
{
|
||||
@ -1115,6 +1123,50 @@ JS_LeaveCrossCompartmentCall(JSCrossCompartmentCall *call)
|
||||
delete realcall;
|
||||
}
|
||||
|
||||
bool
|
||||
JSAutoCrossCompartmentCall::enter(JSContext *cx, JSObject *target)
|
||||
{
|
||||
JS_ASSERT(!call);
|
||||
if (cx->compartment == target->getCompartment(cx))
|
||||
return true;
|
||||
call = JS_EnterCrossCompartmentCall(cx, target);
|
||||
return call != NULL;
|
||||
}
|
||||
|
||||
JSAutoEnterCompartment::JSAutoEnterCompartment(JSContext *cx,
|
||||
JSCompartment *newCompartment)
|
||||
: cx(cx), compartment(cx->compartment)
|
||||
{
|
||||
cx->compartment = newCompartment;
|
||||
}
|
||||
|
||||
JSAutoEnterCompartment::JSAutoEnterCompartment(JSContext *cx, JSObject *target)
|
||||
: cx(cx), compartment(cx->compartment)
|
||||
{
|
||||
cx->compartment = target->getCompartment(cx);
|
||||
}
|
||||
|
||||
JSAutoEnterCompartment::~JSAutoEnterCompartment()
|
||||
{
|
||||
cx->compartment = compartment;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void *)
|
||||
JS_SetCompartmentPrivate(JSContext *cx, JSCompartment *compartment, void *data)
|
||||
{
|
||||
CHECK_REQUEST(cx);
|
||||
void *old = compartment->data;
|
||||
compartment->data = data;
|
||||
return old;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void *)
|
||||
JS_GetCompartmentPrivate(JSContext *cx, JSCompartment *compartment)
|
||||
{
|
||||
CHECK_REQUEST(cx);
|
||||
return compartment->data;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSObject *)
|
||||
JS_GetGlobalObject(JSContext *cx)
|
||||
{
|
||||
|
@ -937,6 +937,9 @@ JS_ToggleOptions(JSContext *cx, uint32 options);
|
||||
extern JS_PUBLIC_API(const char *)
|
||||
JS_GetImplementationVersion(void);
|
||||
|
||||
extern JS_PUBLIC_API(JSCompartmentCallback)
|
||||
JS_SetCompartmentCallback(JSRuntime *rt, JSCompartmentCallback callback);
|
||||
|
||||
extern JS_PUBLIC_API(JSWrapObjectCallback)
|
||||
JS_SetWrapObjectCallback(JSContext *cx, JSWrapObjectCallback callback);
|
||||
|
||||
@ -946,20 +949,22 @@ JS_EnterCrossCompartmentCall(JSContext *cx, JSObject *target);
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_LeaveCrossCompartmentCall(JSCrossCompartmentCall *call);
|
||||
|
||||
extern JS_PUBLIC_API(void *)
|
||||
JS_SetCompartmentPrivate(JSContext *cx, JSCompartment *compartment, void *data);
|
||||
|
||||
extern JS_PUBLIC_API(void *)
|
||||
JS_GetCompartmentPrivate(JSContext *cx, JSCompartment *compartment);
|
||||
|
||||
#ifdef __cplusplus
|
||||
JS_END_EXTERN_C
|
||||
|
||||
class JSAutoCrossCompartmentCall
|
||||
class JS_PUBLIC_API(JSAutoCrossCompartmentCall)
|
||||
{
|
||||
JSCrossCompartmentCall *call;
|
||||
public:
|
||||
JSAutoCrossCompartmentCall() : call(NULL) {}
|
||||
|
||||
bool enter(JSContext *cx, JSObject *target) {
|
||||
JS_ASSERT(!call);
|
||||
call = JS_EnterCrossCompartmentCall(cx, target);
|
||||
return call != NULL;
|
||||
}
|
||||
bool enter(JSContext *cx, JSObject *target);
|
||||
|
||||
~JSAutoCrossCompartmentCall() {
|
||||
if (call)
|
||||
@ -967,6 +972,16 @@ class JSAutoCrossCompartmentCall
|
||||
}
|
||||
};
|
||||
|
||||
class JS_FRIEND_API(JSAutoEnterCompartment)
|
||||
{
|
||||
JSContext *cx;
|
||||
JSCompartment *compartment;
|
||||
public:
|
||||
JSAutoEnterCompartment(JSContext *cx, JSCompartment *newCompartment);
|
||||
JSAutoEnterCompartment(JSContext *cx, JSObject *target);
|
||||
~JSAutoEnterCompartment();
|
||||
};
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
#endif
|
||||
|
||||
|
@ -1183,6 +1183,7 @@ class AutoIdVector;
|
||||
struct JSCompartment {
|
||||
JSRuntime *rt;
|
||||
JSPrincipals *principals;
|
||||
void *data;
|
||||
bool marked;
|
||||
js::WrapperMap crossCompartmentWrappers;
|
||||
|
||||
@ -1220,6 +1221,9 @@ struct JSRuntime {
|
||||
/* Context create/destroy callback. */
|
||||
JSContextCallback cxCallback;
|
||||
|
||||
/* Compartment create/destroy callback. */
|
||||
JSCompartmentCallback compartmentCallback;
|
||||
|
||||
/*
|
||||
* Shape regenerated whenever a prototype implicated by an "add property"
|
||||
* property cache fill and induced trace guard has a readonly property or a
|
||||
|
@ -2967,6 +2967,7 @@ static void
|
||||
SweepCompartments(JSContext *cx)
|
||||
{
|
||||
JSRuntime *rt = cx->runtime;
|
||||
JSCompartmentCallback callback = rt->compartmentCallback;
|
||||
JSCompartment **read = rt->compartments.begin();
|
||||
JSCompartment **end = rt->compartments.end();
|
||||
JSCompartment **write = read;
|
||||
@ -2978,6 +2979,8 @@ SweepCompartments(JSContext *cx)
|
||||
/* Remove dead wrappers from the compartment map. */
|
||||
compartment->sweep(cx);
|
||||
} else {
|
||||
if (callback)
|
||||
(void) callback(cx, compartment, JSCOMPARTMENT_DESTROY);
|
||||
if (compartment->principals)
|
||||
JSPRINCIPALS_DROP(cx, compartment->principals);
|
||||
delete compartment;
|
||||
@ -3568,7 +3571,7 @@ NewCompartment(JSContext *cx, JSPrincipals *principals)
|
||||
JSCompartment *compartment = new JSCompartment(rt);
|
||||
if (!compartment || !compartment->init()) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (principals) {
|
||||
@ -3576,12 +3579,21 @@ NewCompartment(JSContext *cx, JSPrincipals *principals)
|
||||
JSPRINCIPALS_HOLD(cx, principals);
|
||||
}
|
||||
|
||||
AutoLockGC lock(rt);
|
||||
{
|
||||
AutoLockGC lock(rt);
|
||||
|
||||
if (!rt->compartments.append(compartment)) {
|
||||
AutoUnlockGC unlock(rt);
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
if (!rt->compartments.append(compartment)) {
|
||||
AutoUnlockGC unlock(rt);
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
JSCompartmentCallback callback = rt->compartmentCallback;
|
||||
if (callback && !callback(cx, compartment, JSCOMPARTMENT_NEW)) {
|
||||
AutoLockGC lock(rt);
|
||||
rt->compartments.popBack();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return compartment;
|
||||
|
@ -594,6 +594,14 @@ typedef JSBool
|
||||
typedef JSObject *
|
||||
(* JSWrapObjectCallback)(JSContext *cx, JSObject *obj, JSObject *proto, uintN flags);
|
||||
|
||||
typedef enum {
|
||||
JSCOMPARTMENT_NEW, /* XXX Does it make sense to have a NEW? */
|
||||
JSCOMPARTMENT_DESTROY
|
||||
} JSCompartmentOp;
|
||||
|
||||
typedef JSBool
|
||||
(* JSCompartmentCallback)(JSContext *cx, JSCompartment *compartment, uintN compartmentOp);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jspubtd_h___ */
|
||||
|
@ -289,7 +289,7 @@ TransparentObjectWrapper(JSContext *cx, JSObject *obj, JSObject *wrappedProto, u
|
||||
}
|
||||
|
||||
JSCompartment::JSCompartment(JSRuntime *rt)
|
||||
: rt(rt), principals(NULL), marked(false)
|
||||
: rt(rt), principals(NULL), data(NULL), marked(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -144,7 +144,7 @@ class JSCrossCompartmentWrapper : public JSWrapper {
|
||||
|
||||
namespace js {
|
||||
|
||||
class AutoCompartment
|
||||
class JS_FRIEND_API(AutoCompartment)
|
||||
{
|
||||
public:
|
||||
JSContext * const context;
|
||||
|
@ -397,7 +397,7 @@ interface nsIXPCFunctionThisTranslator : nsISupports
|
||||
{ 0xbd, 0xd6, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } }
|
||||
%}
|
||||
|
||||
[uuid(c53c54ac-afc1-458a-98f5-cadb52574e40)]
|
||||
[uuid(68090BF7-EA5A-4C9E-BAF9-DB7AF857AC09)]
|
||||
interface nsIXPConnect : nsISupports
|
||||
{
|
||||
%{ C++
|
||||
@ -427,12 +427,27 @@ interface nsIXPConnect : nsISupports
|
||||
* below). If you do not pass INIT_JS_STANDARD_CLASSES, then aCOMObj
|
||||
* must implement nsIXPCScriptable so it can resolve the standard
|
||||
* classes when asked by the JS engine.
|
||||
*
|
||||
* @param aJSContext the context to use while creating the global object.
|
||||
* @param aCOMObj the native object that represents the global object.
|
||||
* @param aIID the IID used to wrap the global object.
|
||||
* @param aPrincipal the principal of the code that will run in this
|
||||
* compartment. Can be null. If no specific origin is
|
||||
* passed, will be used to compute the origin.
|
||||
* @param aOrigin must be passed if aPrincipal is null. If non-empty,
|
||||
* overrides aPrincipal's origin. (can be used to separate
|
||||
* code from the same principals into different
|
||||
* comartments, like sandboxes).
|
||||
* @param aFlags one of the flags below specifying what options this
|
||||
* global object wants.
|
||||
*/
|
||||
nsIXPConnectJSObjectHolder
|
||||
initClassesWithNewWrappedGlobal(
|
||||
in JSContextPtr aJSContext,
|
||||
in nsISupports aCOMObj,
|
||||
in nsIIDRef aIID,
|
||||
in nsIPrincipal aPrincipal,
|
||||
in ACString aOrigin,
|
||||
in PRUint32 aFlags);
|
||||
|
||||
const PRUint32 INIT_JS_STANDARD_CLASSES = 1 << 0;
|
||||
|
@ -1208,6 +1208,8 @@ mozJSComponentLoader::GlobalForLocation(nsILocalFile *aComponentFile,
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
|
||||
rv = xpc->InitClassesWithNewWrappedGlobal(cx, backstagePass,
|
||||
NS_GET_IID(nsISupports),
|
||||
mSystemPrincipal,
|
||||
EmptyCString(),
|
||||
nsIXPConnect::
|
||||
FLAG_SYSTEM_GLOBAL_OBJECT,
|
||||
getter_AddRefs(holder));
|
||||
|
@ -1867,25 +1867,26 @@ main(int argc, char **argv)
|
||||
xpc->SetSecurityManagerForJSContext(cx, secman, 0xFFFF);
|
||||
|
||||
#ifndef XPCONNECT_STANDALONE
|
||||
nsCOMPtr<nsIPrincipal> systemprincipal;
|
||||
|
||||
// Fetch the system principal and store it away in a global, to use for
|
||||
// script compilation in Load() and ProcessFile() (including interactive
|
||||
// eval loop)
|
||||
{
|
||||
nsCOMPtr<nsIPrincipal> princ;
|
||||
|
||||
nsCOMPtr<nsIScriptSecurityManager> securityManager =
|
||||
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
|
||||
if (NS_SUCCEEDED(rv) && securityManager) {
|
||||
rv = securityManager->GetSystemPrincipal(getter_AddRefs(princ));
|
||||
rv = securityManager->GetSystemPrincipal(getter_AddRefs(systemprincipal));
|
||||
if (NS_FAILED(rv)) {
|
||||
fprintf(gErrFile, "+++ Failed to obtain SystemPrincipal from ScriptSecurityManager service.\n");
|
||||
} else {
|
||||
// fetch the JS principals and stick in a global
|
||||
rv = princ->GetJSPrincipals(cx, &gJSPrincipals);
|
||||
rv = systemprincipal->GetJSPrincipals(cx, &gJSPrincipals);
|
||||
if (NS_FAILED(rv)) {
|
||||
fprintf(gErrFile, "+++ Failed to obtain JS principals from SystemPrincipal.\n");
|
||||
}
|
||||
secman->SetSystemPrincipal(princ);
|
||||
secman->SetSystemPrincipal(systemprincipal);
|
||||
}
|
||||
} else {
|
||||
fprintf(gErrFile, "+++ Failed to get ScriptSecurityManager service, running without principals");
|
||||
@ -1921,6 +1922,8 @@ main(int argc, char **argv)
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
|
||||
rv = xpc->InitClassesWithNewWrappedGlobal(cx, backstagePass,
|
||||
NS_GET_IID(nsISupports),
|
||||
systemprincipal,
|
||||
EmptyCString(),
|
||||
nsIXPConnect::
|
||||
FLAG_SYSTEM_GLOBAL_OBJECT,
|
||||
getter_AddRefs(holder));
|
||||
|
@ -1102,17 +1102,60 @@ static JSClass xpcTempGlobalClass = {
|
||||
JSCLASS_NO_OPTIONAL_MEMBERS
|
||||
};
|
||||
|
||||
nsresult
|
||||
xpc_CreateGlobalObject(JSContext *cx, JSClass *clasp,
|
||||
const nsACString &origin, nsIPrincipal *principal,
|
||||
JSObject **global, JSCompartment **compartment)
|
||||
{
|
||||
XPCCompartmentMap& map = nsXPConnect::GetRuntimeInstance()->GetCompartmentMap();
|
||||
JSObject *tempGlobal;
|
||||
if(!map.Get(origin, compartment))
|
||||
{
|
||||
JSPrincipals *principals = nsnull;
|
||||
if(principal)
|
||||
principal->GetJSPrincipals(cx, &principals);
|
||||
tempGlobal = JS_NewCompartmentAndGlobalObject(cx, clasp, principals);
|
||||
if(principals)
|
||||
JSPRINCIPALS_DROP(cx, principals);
|
||||
|
||||
if(!tempGlobal)
|
||||
return UnexpectedFailure(NS_ERROR_FAILURE);
|
||||
|
||||
JSAutoEnterCompartment autocompartment(cx, tempGlobal);
|
||||
|
||||
*global = tempGlobal;
|
||||
*compartment = tempGlobal->getCompartment(cx);
|
||||
|
||||
JS_SetCompartmentPrivate(cx, *compartment, ToNewCString(origin));
|
||||
map.Put(origin, *compartment);
|
||||
}
|
||||
else
|
||||
{
|
||||
JSAutoEnterCompartment autocompartment(cx, *compartment);
|
||||
|
||||
tempGlobal = JS_NewGlobalObject(cx, clasp);
|
||||
if(!tempGlobal)
|
||||
return UnexpectedFailure(NS_ERROR_FAILURE);
|
||||
*global = tempGlobal;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* nsIXPConnectJSObjectHolder initClassesWithNewWrappedGlobal (in JSContextPtr aJSContext, in nsISupports aCOMObj, in nsIIDRef aIID, in PRUint32 aFlags); */
|
||||
NS_IMETHODIMP
|
||||
nsXPConnect::InitClassesWithNewWrappedGlobal(JSContext * aJSContext,
|
||||
nsISupports *aCOMObj,
|
||||
const nsIID & aIID,
|
||||
nsIPrincipal * aPrincipal,
|
||||
const nsACString & aOrigin,
|
||||
PRUint32 aFlags,
|
||||
nsIXPConnectJSObjectHolder **_retval)
|
||||
{
|
||||
NS_ASSERTION(aJSContext, "bad param");
|
||||
NS_ASSERTION(aCOMObj, "bad param");
|
||||
NS_ASSERTION(_retval, "bad param");
|
||||
NS_ASSERTION(!aOrigin.IsEmpty() || aPrincipal, "must be able to assign an origin");
|
||||
|
||||
// XXX This is not pretty. We make a temporary global object and
|
||||
// init it with all the Components object junk just so we have a
|
||||
@ -1121,13 +1164,25 @@ nsXPConnect::InitClassesWithNewWrappedGlobal(JSContext * aJSContext,
|
||||
|
||||
XPCCallContext ccx(NATIVE_CALLER, aJSContext);
|
||||
|
||||
PRBool system = (aFlags & nsIXPConnect::FLAG_SYSTEM_GLOBAL_OBJECT) != 0;
|
||||
JSObject* tempGlobal = JS_NewGlobalObject(aJSContext, &xpcTempGlobalClass);
|
||||
nsCString origin;
|
||||
if(aOrigin.IsEmpty())
|
||||
aPrincipal->GetOrigin(getter_Copies(origin));
|
||||
else
|
||||
origin = aOrigin;
|
||||
|
||||
if(!tempGlobal ||
|
||||
(system && !JS_MakeSystemObject(aJSContext, tempGlobal)) ||
|
||||
!JS_SetParent(aJSContext, tempGlobal, nsnull) ||
|
||||
!JS_SetPrototype(aJSContext, tempGlobal, nsnull))
|
||||
SaveFrame sf(ccx);
|
||||
|
||||
JSCompartment* compartment;
|
||||
JSObject* tempGlobal;
|
||||
|
||||
nsresult rv = xpc_CreateGlobalObject(ccx, &xpcTempGlobalClass, origin,
|
||||
aPrincipal, &tempGlobal, &compartment);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
JSAutoEnterCompartment autocompartment(ccx, compartment);
|
||||
|
||||
PRBool system = (aFlags & nsIXPConnect::FLAG_SYSTEM_GLOBAL_OBJECT) != 0;
|
||||
if(system && !JS_MakeSystemObject(aJSContext, tempGlobal))
|
||||
return UnexpectedFailure(NS_ERROR_FAILURE);
|
||||
|
||||
jsval v;
|
||||
@ -1140,7 +1195,6 @@ nsXPConnect::InitClassesWithNewWrappedGlobal(JSContext * aJSContext,
|
||||
if(NS_FAILED(InitClasses(aJSContext, tempGlobal)))
|
||||
return UnexpectedFailure(NS_ERROR_FAILURE);
|
||||
|
||||
nsresult rv;
|
||||
if(!XPCConvert::NativeInterface2JSObject(ccx, &v,
|
||||
getter_AddRefs(holder),
|
||||
aCOMObj, &aIID, nsnull,
|
||||
@ -1193,7 +1247,6 @@ nsXPConnect::InitClassesWithNewWrappedGlobal(JSContext * aJSContext,
|
||||
|
||||
if(!(aFlags & nsIXPConnect::OMIT_COMPONENTS_OBJECT)) {
|
||||
// XPCCallContext gives us an active request needed to save/restore.
|
||||
SaveFrame sf(ccx);
|
||||
if(!nsXPCComponents::AttachNewComponentsObject(ccx, scope, globalJSObj))
|
||||
return UnexpectedFailure(NS_ERROR_FAILURE);
|
||||
|
||||
|
@ -3242,15 +3242,20 @@ xpc_CreateSandboxObject(JSContext * cx, jsval * vp, nsISupports *prinOrSop)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
JSPrincipals *jsPrincipals;
|
||||
rv = sop->GetPrincipal()->GetJSPrincipals(cx, &jsPrincipals);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
JSObject *sandbox = JS_NewCompartmentAndGlobalObject(cx, &SandboxClass, jsPrincipals);
|
||||
if (jsPrincipals)
|
||||
JSPRINCIPALS_DROP(cx, jsPrincipals);
|
||||
if (!sandbox)
|
||||
return NS_ERROR_XPC_UNEXPECTED;
|
||||
nsIPrincipal *principal = sop->GetPrincipal();
|
||||
nsAdoptingCString principalorigin;
|
||||
principal->GetOrigin(getter_Copies(principalorigin));
|
||||
|
||||
nsCAutoString origin("sandbox:");
|
||||
origin.Append(principalorigin);
|
||||
|
||||
JSCompartment *compartment;
|
||||
JSObject *sandbox;
|
||||
|
||||
rv = xpc_CreateGlobalObject(cx, &SandboxClass, origin, principal, &sandbox,
|
||||
&compartment);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
js::AutoObjectRooter tvr(cx, sandbox);
|
||||
|
||||
{
|
||||
|
@ -243,6 +243,32 @@ ContextCallback(JSContext *cx, uintN operation)
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
CompartmentCallback(JSContext *cx, JSCompartment *compartment, uintN op)
|
||||
{
|
||||
if(op == JSCOMPARTMENT_NEW)
|
||||
return JS_TRUE;
|
||||
|
||||
XPCJSRuntime* self = nsXPConnect::GetRuntimeInstance();
|
||||
if(!self)
|
||||
return JS_TRUE;
|
||||
|
||||
XPCCompartmentMap& map = self->GetCompartmentMap();
|
||||
nsAdoptingCString origin;
|
||||
origin.Adopt(static_cast<char *>(JS_SetCompartmentPrivate(cx, compartment, nsnull)));
|
||||
|
||||
#ifdef DEBUG
|
||||
{
|
||||
JSCompartment *current;
|
||||
NS_ASSERTION(map.Get(origin, ¤t), "no compartment?");
|
||||
NS_ASSERTION(current == compartment, "compartment mismatch");
|
||||
}
|
||||
#endif
|
||||
|
||||
map.Remove(origin);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
struct ObjectHolder : public JSDHashEntryHdr
|
||||
{
|
||||
void *holder;
|
||||
@ -1092,6 +1118,7 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect)
|
||||
// the GC's allocator.
|
||||
JS_SetGCParameter(mJSRuntime, JSGC_MAX_BYTES, 0xffffffff);
|
||||
JS_SetContextCallback(mJSRuntime, ContextCallback);
|
||||
JS_SetCompartmentCallback(mJSRuntime, CompartmentCallback);
|
||||
JS_SetGCCallbackRT(mJSRuntime, GCCallback);
|
||||
JS_SetExtraGCRoots(mJSRuntime, TraceJS, this);
|
||||
mWatchdogWakeup = JS_NEW_CONDVAR(mJSRuntime->gcLock);
|
||||
@ -1105,6 +1132,8 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect)
|
||||
sizeof(ObjectHolder), 512))
|
||||
mJSHolders.ops = nsnull;
|
||||
|
||||
mCompartmentMap.Init();
|
||||
|
||||
// Install a JavaScript 'debugger' keyword handler in debug builds only
|
||||
#ifdef DEBUG
|
||||
if(mJSRuntime && !JS_GetGlobalDebugHooks(mJSRuntime)->debuggerHandler)
|
||||
|
@ -95,6 +95,7 @@
|
||||
#include "nsXPIDLString.h"
|
||||
#include "nsAutoJSValHolder.h"
|
||||
#include "mozilla/AutoRestore.h"
|
||||
#include "nsDataHashtable.h"
|
||||
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsIJSContextStack.h"
|
||||
@ -243,6 +244,8 @@ extern const char XPC_SCRIPT_ERROR_CONTRACTID[];
|
||||
extern const char XPC_ID_CONTRACTID[];
|
||||
extern const char XPC_XPCONNECT_CONTRACTID[];
|
||||
|
||||
typedef nsDataHashtableMT<nsCStringHashKey, JSCompartment *> XPCCompartmentMap;
|
||||
|
||||
/***************************************************************************/
|
||||
// useful macros...
|
||||
|
||||
@ -623,6 +626,9 @@ public:
|
||||
XPCNativeWrapperMap* GetExplicitNativeWrapperMap() const
|
||||
{return mExplicitNativeWrapperMap;}
|
||||
|
||||
XPCCompartmentMap& GetCompartmentMap()
|
||||
{return mCompartmentMap;}
|
||||
|
||||
XPCLock* GetMapLock() const {return mMapLock;}
|
||||
|
||||
JSBool OnJSContextNew(JSContext* cx);
|
||||
@ -741,6 +747,7 @@ private:
|
||||
XPCWrappedNativeProtoMap* mDyingWrappedNativeProtoMap;
|
||||
XPCWrappedNativeProtoMap* mDetachedWrappedNativeProtoMap;
|
||||
XPCNativeWrapperMap* mExplicitNativeWrapperMap;
|
||||
XPCCompartmentMap mCompartmentMap;
|
||||
XPCLock* mMapLock;
|
||||
PRThread* mThreadRunningGC;
|
||||
nsTArray<nsXPCWrappedJS*> mWrappedJSToReleaseArray;
|
||||
@ -3778,6 +3785,11 @@ xpc_DumpJSObject(JSObject* obj);
|
||||
extern JSBool
|
||||
xpc_InstallJSDebuggerKeywordHandler(JSRuntime* rt);
|
||||
|
||||
nsresult
|
||||
xpc_CreateGlobalObject(JSContext *cx, JSClass *clasp,
|
||||
const nsACString &origin, nsIPrincipal *principal,
|
||||
JSObject **global, JSCompartment **compartment);
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
// Definition of nsScriptError, defined here because we lack a place to put
|
||||
|
@ -1308,6 +1308,8 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16 methodIndex,
|
||||
|
||||
obj = thisObj = wrapper->GetJSObject();
|
||||
|
||||
JSAutoEnterCompartment autoCompartment(ccx, obj);
|
||||
|
||||
// XXX ASSUMES that retval is last arg. The xpidl compiler ensures this.
|
||||
paramCount = info->num_args;
|
||||
argc = paramCount -
|
||||
|
Loading…
Reference in New Issue
Block a user