bug 580128 - Create a proxy for the outer window and use it. Note: this turns on new wrappers for all objects. r=peterv

This commit is contained in:
Blake Kaplan 2010-09-17 14:54:40 -07:00
Родитель 2b8eff64df
Коммит b548e78f8a
12 изменённых файлов: 394 добавлений и 583 удалений

Просмотреть файл

@ -5317,17 +5317,6 @@ nsCommonWindowSH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
rv = WrapNative(cx, frameWin->GetGlobalJSObject(), frame,
&NS_GET_IID(nsIDOMWindow), PR_TRUE, vp,
getter_AddRefs(holder));
if (NS_SUCCEEDED(rv) && !win->IsChromeWindow()) {
JSObject *scopeobj = JS_GetScopeChain(cx);
if (!scopeobj) {
*_retval = JS_FALSE;
return NS_ERROR_FAILURE;
}
rv = sXPConnect->GetXOWForObject(cx, scopeobj, JSVAL_TO_OBJECT(*vp),
vp);
}
}
return NS_FAILED(rv) ? rv : NS_SUCCESS_I_DID_SOMETHING;
@ -5532,21 +5521,6 @@ nsCommonWindowSH::DelProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
}
}
// Notify any XOWs on our outer window.
nsGlobalWindow *outerWin = win->GetOuterWindowInternal();
if (outerWin) {
nsCOMPtr<nsIXPConnectWrappedNative> wn;
nsIXPConnect *xpc = nsContentUtils::XPConnect();
nsresult rv =
xpc->GetWrappedNativeOfJSObject(cx, outerWin->GetGlobalJSObject(),
getter_AddRefs(wn));
NS_ENSURE_SUCCESS(rv, rv);
rv = xpc->UpdateXOWs(cx, wn, nsIXPConnect::XPC_XOW_CLEARSCOPE);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}
@ -6950,17 +6924,6 @@ nsCommonWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
&v, getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv);
#ifdef DEBUG
if (!win->IsChromeWindow()) {
NS_ASSERTION(JSVAL_IS_OBJECT(v) &&
!strcmp(JSVAL_TO_OBJECT(v)->getClass()->name,
"XPCCrossOriginWrapper"),
"Didn't wrap a location object!");
}
#endif
JSAutoRequest ar(cx);
JSBool ok = ::JS_DefinePropertyById(cx, obj, id, v, nsnull, nsnull,
JSPROP_PERMANENT | JSPROP_ENUMERATE);
@ -7060,29 +7023,15 @@ nsCommonWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
if (id == sWindow_id) {
// window should *always* be the outer window object.
nsGlobalWindow *oldWin = win;
win = win->GetOuterWindowInternal();
NS_ENSURE_TRUE(win, NS_ERROR_NOT_AVAILABLE);
JSAutoRequest ar(cx);
jsval winVal = OBJECT_TO_JSVAL(win->GetGlobalJSObject());
if (!win->IsChromeWindow()) {
JSObject *scope;
nsGlobalWindow *innerWin;
if (oldWin->IsInnerWindow()) {
scope = oldWin->GetGlobalJSObject();
} else if ((innerWin = oldWin->GetCurrentInnerWindowInternal())) {
scope = innerWin->GetGlobalJSObject();
} else {
NS_ERROR("I don't know what scope to use!");
scope = oldWin->GetGlobalJSObject();
}
rv = sXPConnect->GetXOWForObject(cx, scope, JSVAL_TO_OBJECT(winVal),
&winVal);
jsval winVal;
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv = WrapNative(cx, obj, nsGlobalWindow::ToSupports(win), PR_TRUE,
&winVal, getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv);
}
PRBool ok =
::JS_DefinePropertyById(cx, obj, id, winVal, JS_PropertyStub, JS_PropertyStub,
JSPROP_READONLY | JSPROP_ENUMERATE);

Просмотреть файл

@ -656,6 +656,30 @@ nsPIDOMWindow::nsPIDOMWindow(nsPIDOMWindow *aOuterWindow)
nsPIDOMWindow::~nsPIDOMWindow() {}
//*****************************************************************************
// nsOuterWindowProxy: Outer Window Proxy
//*****************************************************************************
JSString *
nsOuterWindowProxy::obj_toString(JSContext *cx, JSObject *proxy)
{
JS_ASSERT(proxy->isProxy());
return JS_NewStringCopyZ(cx, "[object WindowProxy]");
}
nsOuterWindowProxy
nsOuterWindowProxy::singleton;
JSObject *
NS_NewOuterWindowProxy(JSContext *cx, JSObject *parent)
{
JSObject *obj = JSWrapper::New(cx, parent, parent->getProto(), parent,
&nsOuterWindowProxy::singleton);
NS_ASSERTION(obj->getClass()->ext.innerObject, "bad class");
return obj;
}
//*****************************************************************************
//*** nsGlobalWindow: Object Management
//*****************************************************************************
@ -740,6 +764,7 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow)
Freeze();
mObserver = nsnull;
SetIsProxy();
}
// We could have failed the first time through trying
@ -1156,6 +1181,13 @@ nsGlobalWindow::FreeInnerObjects(PRBool aClearScope)
} \
} else
#define OUTER_WINDOW_ONLY \
if (IsOuterWindow()) {
#define END_OUTER_WINDOW_ONLY \
foundInterface = 0; \
} else
NS_IMPL_CYCLE_COLLECTION_CLASS(nsGlobalWindow)
DOMCI_DATA(Window, nsGlobalWindow)
@ -1182,6 +1214,9 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsGlobalWindow)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
WINDOW_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Window)
OUTER_WINDOW_ONLY
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
END_OUTER_WINDOW_ONLY
NS_INTERFACE_MAP_END
@ -1898,29 +1933,32 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
if (!mJSObject) {
mContext->CreateOuterObject(this, newInnerWindow);
mContext->DidInitializeContext();
mJSObject = (JSObject *)mContext->GetNativeGlobal();
} else {
// XXX New global object and brain transplant!
rv = xpc->GetWrappedNativeOfJSObject(cx, mJSObject,
getter_AddRefs(wrapper));
NS_ENSURE_SUCCESS(rv, rv);
// Restore our object's prototype to its original value so we're sure to
// update it under ReparentWrappedNativeIfFound.
JSObject *proto;
wrapper->GetJSObjectPrototype(&proto);
if (!JS_SetPrototype(cx, mJSObject, proto)) {
NS_ERROR("Can't set prototype");
return NS_ERROR_UNEXPECTED;
mJSObject = (JSObject *)mContext->GetNativeGlobal();
SetWrapper(mJSObject);
} else {
JSObject *outerObject =
NS_NewOuterWindowProxy(cx, newInnerWindow->mJSObject);
if (!outerObject) {
NS_ERROR("out of memory");
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
xpc->ReparentWrappedNativeIfFound(cx, currentInner->mJSObject,
newInnerWindow->mJSObject,
ToSupports(this),
getter_AddRefs(holder));
outerObject = JS_TransplantWrapper(cx, mJSObject, outerObject);
if (!outerObject) {
NS_ERROR("unable to transplant wrappers, probably OOM");
return NS_ERROR_FAILURE;
}
mJSObject = outerObject;
SetWrapper(mJSObject);
mContext->SetOuterObject(mJSObject);
}
// XXX Not sure if this is needed.
if (aState) {
JSObject *proto;
if (nsIXPConnectJSObjectHolder *holder = wsh->GetOuterRealProto()) {
holder->GetJSObject(&proto);
} else {
@ -1933,7 +1971,6 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
}
}
}
}
if (!aState && !reUseInnerWindow) {
// Loading a new page and creating a new inner window, *not*
@ -2050,16 +2087,6 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
mContext->GC();
mContext->DidInitializeContext();
if (!wrapper) {
rv = xpc->GetWrappedNativeOfJSObject(cx, mJSObject,
getter_AddRefs(wrapper));
NS_ENSURE_SUCCESS(rv, rv);
}
rv = xpc->UpdateXOWs((JSContext *)GetContextInternal()->GetNativeContext(),
wrapper, nsIXPConnect::XPC_XOW_NAVIGATED);
NS_ENSURE_SUCCESS(rv, rv);
if (!aState && !reUseInnerWindow) {
nsContentUtils::AddScriptRunner(
NS_NewRunnableMethod(this, &nsGlobalWindow::DispatchDOMWindowCreated));

Просмотреть файл

@ -110,6 +110,10 @@
#include "nsFrameMessageManager.h"
#include "mozilla/TimeStamp.h"
// JS includes
#include "jsapi.h"
#include "jswrapper.h"
#define DEFAULT_HOME_PAGE "www.mozilla.org"
#define PREF_BROWSER_STARTUP_HOMEPAGE "browser.startup.homepage"
@ -226,6 +230,25 @@ private:
nsAutoRefCnt mRefCnt;
};
//*****************************************************************************
// nsOuterWindow: Outer Window Proxy
//*****************************************************************************
class nsOuterWindowProxy : public JSWrapper
{
public:
nsOuterWindowProxy() : JSWrapper(0) {}
virtual bool isOuterWindow() {
return true;
}
JSString *obj_toString(JSContext *cx, JSObject *wrapper);
static nsOuterWindowProxy singleton;
};
JSObject *NS_NewOuterWindowProxy(JSContext *cx, JSObject *parent);
//*****************************************************************************
// nsGlobalWindow: Global Object for Scripting
//*****************************************************************************
@ -257,6 +280,7 @@ class nsGlobalWindow : public nsPIDOMWindow,
public nsIDOMStorageWindow,
public nsSupportsWeakReference,
public nsIInterfaceRequestor,
public nsWrapperCache,
public PRCListStr
{
public:

Просмотреть файл

@ -72,10 +72,10 @@ public:
NS_DEFINE_STATIC_IID_ACCESSOR(nsIScriptContextPrincipal,
NS_ISCRIPTCONTEXTPRINCIPAL_IID)
// 5b6d04a3-f095-4924-ad84-4f44f9b3fae0
// a7139c0e-962c-44b6-bec3-e4166bfe84eb
#define NS_ISCRIPTCONTEXT_IID \
{ 0x5b6d04a3, 0xf095, 0x4924, \
{ 0xad, 0x84, 0x4f, 0x44, 0xf9, 0xb3, 0xfa, 0xe0 } }
{ 0xa7139c0e, 0x962c, 0x44b6, \
{ 0xbe, 0xc3, 0xe4, 0x16, 0x6b, 0xfe, 0x84, 0xeb } }
/* This MUST match JSVERSION_DEFAULT. This version stuff if we don't
know what language we have is a little silly... */
@ -346,6 +346,11 @@ public:
virtual nsresult CreateOuterObject(nsIScriptGlobalObject *aGlobalObject,
nsIScriptGlobalObject *aCurrentInner) = 0;
/**
* Given an outer object, updates this context with that outer object.
*/
virtual nsresult SetOuterObject(void *aOuterObject) = 0;
/**
* Prepares this context for use with the current inner window for the
* context's global object. This must be called after CreateOuterObject.

Просмотреть файл

@ -102,10 +102,7 @@
#include "nsITimelineService.h"
#include "nsDOMScriptObjectHolder.h"
#include "prmem.h"
#ifdef NS_DEBUG
#include "nsGlobalWindow.h"
#endif
#ifdef MOZ_JSDEBUGGER
#include "jsdIDebuggerService.h"
@ -2407,7 +2404,11 @@ nsJSContext::GetGlobalObject()
JSObject *global = ::JS_GetGlobalObject(mContext);
if (!global) {
NS_WARNING("Context has no global.");
return nsnull;
}
OBJ_TO_INNER_OBJECT(mContext, global);
if (!global) {
return nsnull;
}
@ -2436,7 +2437,11 @@ nsJSContext::GetGlobalObject()
// This'll return a pointer to something we're about to release, but
// that's ok, the JS object will hold it alive long enough.
nsCOMPtr<nsPIDOMWindow> pwin(do_QueryInterface(sgo));
if (!pwin)
return sgo;
return static_cast<nsGlobalWindow *>(pwin->GetOuterWindow());
}
void *
@ -2564,17 +2569,28 @@ nsJSContext::CreateOuterObject(nsIScriptGlobalObject *aGlobalObject,
JS_SetOptions(mContext, JS_GetOptions(mContext) | JSOPTION_XML);
}
JSObject *outer =
NS_NewOuterWindowProxy(mContext, aCurrentInner->GetGlobalJSObject());
if (!outer) {
return NS_ERROR_FAILURE;
}
return SetOuterObject(outer);
}
nsresult
nsJSContext::SetOuterObject(void *aOuterObject)
{
JSObject *outer = static_cast<JSObject *>(aOuterObject);
nsIXPConnect *xpc = nsContentUtils::XPConnect();
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
nsresult rv = xpc->WrapNative(mContext, aCurrentInner->GetGlobalJSObject(),
aGlobalObject, NS_GET_IID(nsISupports),
getter_AddRefs(holder));
nsresult rv = xpc->HoldObject(mContext, outer, getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv);
// Force our context's global object to be the outer.
JSObject *globalObj;
holder->GetJSObject(&globalObj);
JS_SetGlobalObject(mContext, globalObj);
JS_SetGlobalObject(mContext, outer);
// Hold a strong reference to the wrapper for the global to avoid
// rooting and unrooting the global object every time its AddRef()
@ -2587,32 +2603,8 @@ nsresult
nsJSContext::InitOuterWindow()
{
JSObject *global = JS_GetGlobalObject(mContext);
nsIScriptGlobalObject *sgo = GetGlobalObject();
// Call ClearScope to nuke any properties (e.g. Function and Object) on the
// outer object. From now on, anybody asking the outer object for these
// properties will be forwarded to the inner window.
JS_ClearScope(mContext, global);
nsresult rv = NS_OK;
nsCOMPtr<nsIClassInfo> ci(do_QueryInterface(sgo));
if (ci) {
jsval v;
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv = nsContentUtils::WrapNative(mContext, global, sgo, &v,
getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIXPConnectWrappedNative> wrapper(do_QueryInterface(holder));
NS_ENSURE_TRUE(wrapper, NS_ERROR_FAILURE);
rv = wrapper->RefreshPrototype();
NS_ENSURE_SUCCESS(rv, rv);
}
rv = InitClasses(global); // this will complete global object initialization
nsresult rv = InitClasses(global); // this will complete global object initialization
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;

Просмотреть файл

@ -143,6 +143,7 @@ public:
virtual nsresult InitContext();
virtual nsresult CreateOuterObject(nsIScriptGlobalObject *aGlobalObject,
nsIScriptGlobalObject *aCurrentInner);
virtual nsresult SetOuterObject(void *aOuterObject);
virtual nsresult InitOuterWindow();
virtual PRBool IsContextInitialized();
virtual void FinalizeContext();

Просмотреть файл

@ -43,6 +43,7 @@
#include "XPCWrapper.h"
#include "XPCNativeWrapper.h"
#include "nsPIDOMWindow.h"
#include "jswrapper.h"
namespace XPCWrapper {
@ -61,6 +62,14 @@ const PRUint32 sSecMgrGetProp = nsIXPCSecurityManager::ACCESS_GET_PROPERTY;
JSObject *
Unwrap(JSContext *cx, JSObject *wrapper)
{
if (wrapper->isProxy()) {
if (wrapper->getProxyHandler() != &JSCrossCompartmentWrapper::singleton) {
// XXX Security check!
}
return wrapper->unwrap();
}
js::Class *clasp = wrapper->getClass();
if (clasp == &XPCCrossOriginWrapper::XOWClass) {
return UnwrapXOW(cx, wrapper);

Просмотреть файл

@ -1148,42 +1148,13 @@ XPCConvert::NativeInterface2JSObject(XPCLazyCallContext& lccx,
if(pErr)
*pErr = NS_ERROR_XPC_BAD_CONVERT_NATIVE;
// #define this if we want to 'double wrap' of JSObjects.
// This is for the case where we have a JSObject wrapped for native use
// which needs to be converted to a JSObject. Originally, we were unwrapping
// and just exposing the underlying JSObject. This causes anomolies when
// JSComponents are accessed from other JS code - they don't act like
// other xpconnect wrapped components. Eventually we want to build a new
// kind of wrapper especially for JS <-> JS. For now we are building a wrapper
// around a wrapper. This is not optimal, but good enough for now.
#define XPC_DO_DOUBLE_WRAP 1
#ifndef XPC_DO_DOUBLE_WRAP
// is this a wrapped JS object?
if(nsXPCWrappedJSClass::IsWrappedJS(src))
{
NS_ASSERTION(!isGlobal, "The global object must be native");
// verify that this wrapper is for the right interface
nsCOMPtr<nsISupports> wrapper;
if(iid)
src->QueryInterface(*iid, (void**)getter_AddRefs(wrapper));
else
wrapper = do_QueryInterface(src);
nsCOMPtr<nsIXPConnectJSObjectHolder> holder =
do_QueryInterface(wrapper);
JSObject* flat;
if(!holder || !(flat = holder->GetFlatJSObject()))
return JS_FALSE;
*d = OBJECT_TO_JSVAL(flat);
if(dest)
holder.swap(*dest);
return JS_TRUE;
}
else
#endif /* XPC_DO_DOUBLE_WRAP */
{
// We used to have code here that unwrapped and simply exposed the
// underlying JSObject. That caused anomolies when JSComponents were
// accessed from other JS code - they didn't act like other xpconnect
// wrapped components. So, instead, we create "double wrapped" objects
// (that means an XPCWrappedNative around an nsXPCWrappedJS). This isn't
// optimal -- we could detect this and roll the functionality into a
// single wrapper, but the current solution is good enough for now.
JSContext* cx = lccx.GetJSContext();
XPCWrappedNativeScope* xpcscope =
@ -1191,10 +1162,16 @@ XPCConvert::NativeInterface2JSObject(XPCLazyCallContext& lccx,
if(!xpcscope)
return JS_FALSE;
// First, see if this object supports the wrapper cache.
// Note: If |cache->IsProxy()| is true, then it means that the object
// implementing it doesn't want a wrapped native as its JS Object, but
// instead it provides its own proxy object. In that case, the object
// to use is found as cache->GetWrapper(). If that is null, then the
// object will create (and fill the cache) from its PreCreate call.
nsWrapperCache *cache = aHelper.GetWrapperCache();
JSObject *callee = nsnull;
JSScript *script = nsnull;
JSObject *callee;
JSScript *script;
PRBool tryConstructSlimWrapper = PR_FALSE;
JSObject *flat;
@ -1202,28 +1179,29 @@ XPCConvert::NativeInterface2JSObject(XPCLazyCallContext& lccx,
{
flat = cache->GetWrapper();
if(cache->IsProxy())
{
if(flat)
{
XPCCallContext &ccx = lccx.GetXPCCallContext();
if(!ccx.IsValid())
return JS_FALSE;
if(!flat)
flat = ConstructProxyObject(ccx, aHelper, xpcscope);
ComputeWrapperInfo(ccx, &callee, &script);
if(!callee)
{
callee = xpcscope->GetGlobalJSObject();
OBJ_TO_INNER_OBJECT(ccx, callee);
if(!callee)
return JS_FALSE;
}
JSAutoCrossCompartmentCall accc;
if(!accc.enter(ccx, callee) || !JS_WrapObject(ccx, &flat))
JSAutoEnterCompartment ac;
if(!ac.enter(ccx, callee) || !JS_WrapObject(ccx, &flat))
return JS_FALSE;
return CreateHolderIfNeeded(ccx, flat, d, dest);
}
else
{
tryConstructSlimWrapper = PR_TRUE;
}
}
if(!dest)
{
@ -1247,6 +1225,8 @@ XPCConvert::NativeInterface2JSObject(XPCLazyCallContext& lccx,
flat = nsnull;
}
// If we're not handing this wrapper to an nsIXPConnectJSObjectHolder, and
// the object supports slim wrappers, try to create one here.
if(tryConstructSlimWrapper)
{
XPCCallContext &ccx = lccx.GetXPCCallContext();
@ -1263,26 +1243,15 @@ XPCConvert::NativeInterface2JSObject(XPCLazyCallContext& lccx,
// Even if ConstructSlimWrapper returns JS_FALSE it might have created a
// wrapper (while calling the PreCreate hook). In that case we need to
// fall through because we either have a slim wrapper that needs to be
// morphed or we have an XPCWrappedNative.
// morphed or an XPCWrappedNative.
flat = cache->GetWrapper();
if(cache->IsProxy())
{
XPCCallContext &ccx = lccx.GetXPCCallContext();
if(!ccx.IsValid())
return JS_FALSE;
ComputeWrapperInfo(ccx, &callee, &script);
if(!callee)
callee = xpcscope->GetGlobalJSObject();
JSAutoCrossCompartmentCall accc;
if(!accc.enter(ccx, callee) || !JS_WrapObject(ccx, &flat))
return JS_FALSE;
return CreateHolderIfNeeded(ccx, flat, d, dest);
}
}
// We can't simply construct a slim wrapper. Go ahead and create an
// XPCWrappedNative for this object. At this point, |flat| could be
// non-null, meaning that either we already have a wrapped native from
// the cache (which might need to be QI'd to the new interface) or that
// we found a slim wrapper that we'll have to morph.
AutoMarkingNativeInterfacePtr iface;
if(iid)
{
@ -1306,8 +1275,7 @@ XPCConvert::NativeInterface2JSObject(XPCLazyCallContext& lccx,
}
}
NS_ASSERTION(!flat || IS_WRAPPER_CLASS(flat->getClass()) ||
cache->IsProxy(),
NS_ASSERTION(!flat || IS_WRAPPER_CLASS(flat->getClass()),
"What kind of wrapper is this?");
nsresult rv;
@ -1343,7 +1311,7 @@ XPCConvert::NativeInterface2JSObject(XPCLazyCallContext& lccx,
else
rv = NS_OK;
}
else if(!cache->IsProxy())
else
{
NS_ASSERTION(IS_SLIM_WRAPPER(flat),
"What kind of wrapper is this?");
@ -1363,161 +1331,61 @@ XPCConvert::NativeInterface2JSObject(XPCLazyCallContext& lccx,
if(pErr)
*pErr = rv;
if(NS_SUCCEEDED(rv) && wrapper)
{
XPCCallContext &ccx = lccx.GetXPCCallContext();
if(!ccx.IsValid())
// If creating the wrapped native failed, then return early.
if(NS_FAILED(rv) || !wrapper)
return JS_FALSE;
uint32 flags = 0;
// If we're not creating security wrappers, we can return the
// XPCWrappedNative as-is here.
flat = wrapper->GetFlatJSObject();
jsval v = OBJECT_TO_JSVAL(flat);
JSBool sameOrigin;
if (allowNativeWrapper &&
!xpc_SameScope(wrapper->GetScope(), xpcscope, &sameOrigin))
if(!XPCPerThreadData::IsMainThread(lccx.GetJSContext()) ||
!allowNativeWrapper)
{
// Cross scope access detected. Check if chrome code
// is accessing non-chrome objects, and if so, wrap
// the XPCWrappedNative with an XPCNativeWrapper to
// prevent user-defined properties from shadowing DOM
// properties from chrome code.
// printf("Wrapped native accessed across scope boundary\n");
ComputeWrapperInfo(ccx, &callee, &script);
flags = script ? JS_GetScriptFilenameFlags(script) : 0;
NS_ASSERTION(flags != JSFILENAME_NULL, "null script filename");
if(!JS_IsSystemObject(ccx, flat))
{
// From here on we might create new JSObjects, so we need to
// make sure that wrapper stays alive.
if(!strongWrapper)
strongWrapper = wrapper;
JSObject *destObj = nsnull;
JSBool triedWrapping = JS_FALSE;
if(flags & JSFILENAME_PROTECTED)
{
#ifdef DEBUG_XPCNativeWrapper
{
char *s = wrapper->ToString(ccx);
printf("Content accessed from chrome, wrapping "
"wrapper (%s) in XPCNativeWrapper\n", s);
if (s)
JS_smprintf_free(s);
}
#endif
nsIScriptSecurityManager *ssm =
XPCWrapper::GetSecurityManager();
nsCOMPtr<nsIPrincipal> objPrincipal;
if(callee)
{
// Prefer getting the object princpal here.
nsresult rv =
ssm->GetObjectPrincipal(ccx, callee,
getter_AddRefs(objPrincipal));
if(NS_FAILED(rv))
return JS_FALSE;
}
else
{
JSPrincipals *scriptPrincipal =
JS_GetScriptPrincipals(ccx, script);
if(scriptPrincipal)
{
nsJSPrincipals *nsjsp =
static_cast<nsJSPrincipals *>(scriptPrincipal);
objPrincipal = nsjsp->nsIPrincipalPtr;
}
}
destObj =
XPCNativeWrapper::GetNewOrUsed(ccx, wrapper,
scope, objPrincipal);
triedWrapping = JS_TRUE;
}
else if (flags & JSFILENAME_SYSTEM)
{
#ifdef DEBUG_mrbkap
printf("Content accessed from chrome, wrapping in an "
"XPCSafeJSObjectWrapper\n");
#endif
if(XPCSafeJSObjectWrapper::WrapObject(ccx, scope, v, &v))
destObj = JSVAL_TO_OBJECT(v);
triedWrapping = JS_TRUE;
}
else if (!sameOrigin)
{
// Reaching across scopes from content code. Wrap
// the new object in a XOW.
if (XPCCrossOriginWrapper::WrapObject(ccx, scope, &v))
destObj = JSVAL_TO_OBJECT(v);
triedWrapping = JS_TRUE;
}
if(triedWrapping)
{
if(!destObj)
return JS_FALSE;
jsval wrappedObjVal = OBJECT_TO_JSVAL(destObj);
AUTO_MARK_JSVAL(ccx, &wrappedObjVal);
if(wrapper->NeedsSOW())
{
using SystemOnlyWrapper::WrapObject;
if(!WrapObject(ccx, xpcscope->GetGlobalJSObject(),
OBJECT_TO_JSVAL(destObj),
&wrappedObjVal))
return JS_FALSE;
}
return CreateHolderIfNeeded(ccx, JSVAL_TO_OBJECT(wrappedObjVal),
d, dest);
}
}
}
const char *name = flat->getClass()->name;
if(allowNativeWrapper &&
!(flags & JSFILENAME_SYSTEM) &&
!JS_IsSystemObject(ccx, flat) &&
XPCCrossOriginWrapper::ClassNeedsXOW(name))
{
// From here on we might create new JSObjects, so we need to
// make sure that wrapper stays alive.
if(!strongWrapper)
strongWrapper = wrapper;
AUTO_MARK_JSVAL(ccx, &v);
return XPCCrossOriginWrapper::WrapObject(ccx, scope, &v) &&
(!wrapper->NeedsSOW() ||
SystemOnlyWrapper::WrapObject(ccx, xpcscope->GetGlobalJSObject(),
v, &v)) &&
CreateHolderIfNeeded(ccx, JSVAL_TO_OBJECT(v), d, dest);
}
*d = v;
if(allowNativeWrapper)
{
if(wrapper->NeedsSOW())
if(!SystemOnlyWrapper::WrapObject(ccx,
xpcscope->GetGlobalJSObject(),
v, d))
return JS_FALSE;
if(wrapper->NeedsCOW())
if(!ChromeObjectWrapper::WrapObject(ccx, xpcscope->GetGlobalJSObject(), v, d))
return JS_FALSE;
}
if(dest)
*dest = strongWrapper.forget().get();
return JS_TRUE;
}
}
XPCCallContext &ccx = lccx.GetXPCCallContext();
if(!ccx.IsValid())
return JS_FALSE;
ComputeWrapperInfo(ccx, &callee, &script);
if(!callee)
{
callee = xpcscope->GetGlobalJSObject();
OBJ_TO_INNER_OBJECT(cx, callee);
if(!callee)
return JS_FALSE;
}
JSAutoEnterCompartment ac;
if(!ac.enter(ccx, callee) || !JS_WrapObject(ccx, &flat))
return JS_FALSE;
*d = OBJECT_TO_JSVAL(flat);
if(dest)
{
// The strongWrapper still holds the original flat object.
if(OBJECT_TO_JSVAL(flat) == *d)
{
*dest = strongWrapper.forget().get();
}
else
{
nsRefPtr<XPCJSObjectHolder> objHolder =
XPCJSObjectHolder::newHolder(ccx, JSVAL_TO_OBJECT(*d));
if(!objHolder)
return JS_FALSE;
*dest = objHolder.forget().get();
}
}
return JS_TRUE;
}
/***************************************************************************/

Просмотреть файл

@ -41,6 +41,7 @@
/* Per JSRuntime object */
#include "xpcprivate.h"
#include "WrapperFactory.h"
#include "dom_quickstubs.h"
#include "jsgcchunk.h"
@ -1144,6 +1145,7 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect)
JS_SetCompartmentCallback(mJSRuntime, CompartmentCallback);
JS_SetGCCallbackRT(mJSRuntime, GCCallback);
JS_SetExtraGCRoots(mJSRuntime, TraceJS, this);
JS_SetWrapObjectCallback(mJSRuntime, xpc::WrapperFactory::Rewrap);
mWatchdogWakeup = JS_NEW_CONDVAR(mJSRuntime->gcLock);
mJSRuntime->setActivityCallback(ActivityCallback, this);

Просмотреть файл

@ -2282,6 +2282,10 @@ private:
};
class xpcObjectHelper;
JSObject *
ConstructProxyObject(XPCCallContext &ccx,
xpcObjectHelper &aHelper,
XPCWrappedNativeScope *xpcscope);
extern JSBool ConstructSlimWrapper(XPCCallContext &ccx,
xpcObjectHelper &aHelper,
XPCWrappedNativeScope* xpcScope,

Просмотреть файл

@ -1778,17 +1778,6 @@ return_tearoff:
pTearOff);
}
// If we didn't find a wrapper using the given funobj and obj, try
// again with obj's outer object, if it's got one.
if(JSObjectOp op = obj->getClass()->ext.outerObject)
{
JSObject *outer = op(cx, obj);
if(outer && outer != obj)
return GetWrappedNativeOfJSObject(cx, outer, funobj, pobj2,
pTearOff);
}
if(pobj2)
*pobj2 = nsnull;
return nsnull;
@ -3852,6 +3841,35 @@ MorphSlimWrapper(JSContext *cx, JSObject *obj)
static PRUint32 sSlimWrappers;
#endif
JSObject *
ConstructProxyObject(XPCCallContext &ccx,
xpcObjectHelper &aHelper,
XPCWrappedNativeScope *xpcscope)
{
nsISupports *identityObj = aHelper.GetCanonical();
nsXPCClassInfo *classInfoHelper = aHelper.GetXPCClassInfo();
#ifdef DEBUG
{
JSUint32 flagsInt;
nsresult debug_rv = classInfoHelper->GetScriptableFlags(&flagsInt);
XPCNativeScriptableFlags flags(flagsInt);
NS_ASSERTION(NS_SUCCEEDED(debug_rv) && flags.WantPreCreate(),
"bad flags, cache->IsProxy() implies WantPreCreate()");
}
#endif
// We re-use the PreCreate hook to create the actual proxy object.
JSObject* parent = xpcscope->GetGlobalJSObject();
nsresult rv = classInfoHelper->PreCreate(identityObj, ccx, parent, &parent);
NS_ENSURE_SUCCESS(rv, nsnull);
nsWrapperCache *cache = aHelper.GetWrapperCache();
JSObject *flat = cache->GetWrapper();
NS_ASSERTION(flat, "PreCreate is supposed to create the wrapper");
return flat;
}
JSBool
ConstructSlimWrapper(XPCCallContext &ccx,
xpcObjectHelper &aHelper,
@ -3879,14 +3897,10 @@ ConstructSlimWrapper(XPCCallContext &ccx,
return JS_FALSE;
}
nsWrapperCache *cache = aHelper.GetWrapperCache();
JSObject* plannedParent = parent;
rv = classInfoHelper->PreCreate(identityObj, ccx, parent, &parent);
if(rv != NS_SUCCESS_ALLOW_SLIM_WRAPPERS)
{
if(cache->IsProxy())
NS_ASSERTION(cache->GetWrapper(), "out of memory?");
else
SLIM_LOG_NOT_CREATED(ccx, identityObj, "PreCreate hook refused");
return JS_FALSE;
@ -3906,6 +3920,7 @@ ConstructSlimWrapper(XPCCallContext &ccx,
// The PreCreate hook could have forced the creation of a wrapper, need
// to check for that here and return early.
nsWrapperCache *cache = aHelper.GetWrapperCache();
JSObject* wrapper = cache->GetWrapper();
if(wrapper)
{

Просмотреть файл

@ -1468,92 +1468,7 @@ XPC_WN_JSOp_ThisObject(JSContext *cx, JSObject *obj)
return obj;
OBJ_TO_OUTER_OBJECT(cx, obj);
if(!obj)
return nsnull;
JSObject *scope = JS_GetGlobalForScopeChain(cx);
if(!scope)
{
XPCThrower::Throw(NS_ERROR_FAILURE, cx);
return nsnull;
}
// Note that by innerizing the incoming object instead of outerizing the
// scope, we are doing an implicit security check: if the window has
// already navigated, then we don't want to use our cache.
JSObject* innerobj = obj;
OBJ_TO_INNER_OBJECT(cx, innerobj);
if(!innerobj)
return nsnull;
if(innerobj == scope)
{
// Fast-path for the common case: a window being wrapped in its own
// scope. Check to see if the object actually needs a XOW, and then
// give it one in its own scope.
XPCWrappedNative *wn =
static_cast<XPCWrappedNative *>(xpc_GetJSPrivate(obj));
if(!wn->NeedsXOW())
return obj;
XPCWrappedNativeWithXOW *wnxow =
static_cast<XPCWrappedNativeWithXOW *>(wn);
JSObject *wrapper = wnxow->GetXOW();
if(wrapper)
return wrapper;
// Otherwise, this is our first time through,
// XPCCrossOriginWrapper::WrapObject will fill the cache.
}
XPCPerThreadData *threadData = XPCPerThreadData::GetData(cx);
if(!threadData)
{
XPCThrower::Throw(NS_ERROR_FAILURE, cx);
return nsnull;
}
AutoPopJSContext popper(threadData->GetJSContextStack());
popper.PushIfNotTop(cx);
nsIScriptSecurityManager* secMan = XPCWrapper::GetSecurityManager();
if(!secMan)
{
XPCThrower::Throw(NS_ERROR_FAILURE, cx);
return nsnull;
}
JSStackFrame *fp;
nsIPrincipal *principal = secMan->GetCxSubjectPrincipalAndFrame(cx, &fp);
js::AutoValueRooter retval(cx, js::ObjectValue(*obj));
if(principal && fp)
{
JSScript* script = JS_GetFrameScript(cx, fp);
PRUint32 flags = script ? JS_GetScriptFilenameFlags(script) : 0;
NS_ASSERTION(flags != JSFILENAME_NULL, "Null filename!");
nsXPConnect *xpc = nsXPConnect::GetXPConnect();
if(!xpc)
{
XPCThrower::Throw(NS_ERROR_FAILURE, cx);
return nsnull;
}
nsresult rv = xpc->GetWrapperForObject(cx, obj, scope, principal, flags,
retval.jsval_addr());
if(NS_FAILED(rv))
{
XPCThrower::Throw(rv, cx);
return nsnull;
}
}
return JSVAL_TO_OBJECT(retval.jsval_value());
}
/***************************************************************************/