зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
2b8eff64df
Коммит
b548e78f8a
|
@ -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;
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
|
||||
rv = WrapNative(cx, obj, nsGlobalWindow::ToSupports(win), PR_TRUE,
|
||||
&winVal, getter_AddRefs(holder));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
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);
|
||||
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,39 +1933,41 @@ 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;
|
||||
}
|
||||
|
||||
if (aState) {
|
||||
if (nsIXPConnectJSObjectHolder *holder = wsh->GetOuterRealProto()) {
|
||||
holder->GetJSObject(&proto);
|
||||
} else {
|
||||
proto = nsnull;
|
||||
}
|
||||
mJSObject = outerObject;
|
||||
SetWrapper(mJSObject);
|
||||
|
||||
if (!JS_SetPrototype(cx, mJSObject, proto)) {
|
||||
NS_ERROR("can't set prototype");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
mContext->SetOuterObject(mJSObject);
|
||||
}
|
||||
|
||||
// XXX Not sure if this is needed.
|
||||
if (aState) {
|
||||
JSObject *proto;
|
||||
if (nsIXPConnectJSObjectHolder *holder = wsh->GetOuterRealProto()) {
|
||||
holder->GetJSObject(&proto);
|
||||
} else {
|
||||
proto = nsnull;
|
||||
}
|
||||
|
||||
if (!JS_SetPrototype(cx, mJSObject, proto)) {
|
||||
NS_ERROR("can't set prototype");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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.
|
||||
return sgo;
|
||||
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,376 +1148,244 @@ 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
|
||||
// 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();
|
||||
|
||||
#ifndef XPC_DO_DOUBLE_WRAP
|
||||
// is this a wrapped JS object?
|
||||
if(nsXPCWrappedJSClass::IsWrappedJS(src))
|
||||
XPCWrappedNativeScope* xpcscope =
|
||||
XPCWrappedNativeScope::FindInJSObjectScope(cx, scope);
|
||||
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;
|
||||
JSScript *script;
|
||||
|
||||
PRBool tryConstructSlimWrapper = PR_FALSE;
|
||||
JSObject *flat;
|
||||
if(cache)
|
||||
{
|
||||
NS_ASSERTION(!isGlobal, "The global object must be native");
|
||||
flat = cache->GetWrapper();
|
||||
if(cache->IsProxy())
|
||||
{
|
||||
XPCCallContext &ccx = lccx.GetXPCCallContext();
|
||||
if(!ccx.IsValid())
|
||||
return JS_FALSE;
|
||||
|
||||
// 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;
|
||||
if(!flat)
|
||||
flat = ConstructProxyObject(ccx, aHelper, xpcscope);
|
||||
|
||||
*d = OBJECT_TO_JSVAL(flat);
|
||||
if(dest)
|
||||
holder.swap(*dest);
|
||||
return JS_TRUE;
|
||||
ComputeWrapperInfo(ccx, &callee, &script);
|
||||
if(!callee)
|
||||
{
|
||||
callee = xpcscope->GetGlobalJSObject();
|
||||
OBJ_TO_INNER_OBJECT(ccx, callee);
|
||||
if(!callee)
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
JSAutoEnterCompartment ac;
|
||||
if(!ac.enter(ccx, callee) || !JS_WrapObject(ccx, &flat))
|
||||
return JS_FALSE;
|
||||
|
||||
return CreateHolderIfNeeded(ccx, flat, d, dest);
|
||||
}
|
||||
|
||||
if(!dest)
|
||||
{
|
||||
if(!flat)
|
||||
{
|
||||
tryConstructSlimWrapper = PR_TRUE;
|
||||
}
|
||||
else if(IS_SLIM_WRAPPER_OBJECT(flat))
|
||||
{
|
||||
JSObject* global = JS_GetGlobalForObject(cx, flat);
|
||||
if(global == xpcscope->GetGlobalJSObject())
|
||||
{
|
||||
*d = OBJECT_TO_JSVAL(flat);
|
||||
return JS_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* XPC_DO_DOUBLE_WRAP */
|
||||
{
|
||||
JSContext* cx = lccx.GetJSContext();
|
||||
flat = nsnull;
|
||||
}
|
||||
|
||||
XPCWrappedNativeScope* xpcscope =
|
||||
XPCWrappedNativeScope::FindInJSObjectScope(cx, scope);
|
||||
if(!xpcscope)
|
||||
// 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();
|
||||
if(!ccx.IsValid())
|
||||
return JS_FALSE;
|
||||
|
||||
nsWrapperCache *cache = aHelper.GetWrapperCache();
|
||||
|
||||
JSObject *callee = nsnull;
|
||||
JSScript *script = nsnull;
|
||||
|
||||
PRBool tryConstructSlimWrapper = PR_FALSE;
|
||||
JSObject *flat;
|
||||
if(cache)
|
||||
jsval slim;
|
||||
if(ConstructSlimWrapper(ccx, aHelper, xpcscope, &slim))
|
||||
{
|
||||
flat = cache->GetWrapper();
|
||||
if(cache->IsProxy())
|
||||
{
|
||||
if(flat)
|
||||
{
|
||||
XPCCallContext &ccx = lccx.GetXPCCallContext();
|
||||
if(!ccx.IsValid())
|
||||
return JS_FALSE;
|
||||
*d = slim;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
ComputeWrapperInfo(ccx, &callee, &script);
|
||||
if(!callee)
|
||||
callee = xpcscope->GetGlobalJSObject();
|
||||
// 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 an XPCWrappedNative.
|
||||
flat = cache->GetWrapper();
|
||||
}
|
||||
|
||||
JSAutoCrossCompartmentCall accc;
|
||||
if(!accc.enter(ccx, callee) || !JS_WrapObject(ccx, &flat))
|
||||
return JS_FALSE;
|
||||
// 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)
|
||||
{
|
||||
XPCCallContext &ccx = lccx.GetXPCCallContext();
|
||||
if(!ccx.IsValid())
|
||||
return JS_FALSE;
|
||||
|
||||
return CreateHolderIfNeeded(ccx, flat, d, dest);
|
||||
}
|
||||
else
|
||||
{
|
||||
tryConstructSlimWrapper = PR_TRUE;
|
||||
}
|
||||
}
|
||||
iface.Init(ccx);
|
||||
|
||||
if(!dest)
|
||||
{
|
||||
if(!flat)
|
||||
{
|
||||
tryConstructSlimWrapper = PR_TRUE;
|
||||
}
|
||||
else if(IS_SLIM_WRAPPER_OBJECT(flat))
|
||||
{
|
||||
JSObject* global = JS_GetGlobalForObject(cx, flat);
|
||||
if(global == xpcscope->GetGlobalJSObject())
|
||||
{
|
||||
*d = OBJECT_TO_JSVAL(flat);
|
||||
return JS_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(Interface)
|
||||
iface = *Interface;
|
||||
|
||||
if(!iface)
|
||||
{
|
||||
iface = XPCNativeInterface::GetNewOrUsed(ccx, iid);
|
||||
if(!iface)
|
||||
return JS_FALSE;
|
||||
|
||||
if(Interface)
|
||||
*Interface = iface;
|
||||
}
|
||||
}
|
||||
|
||||
NS_ASSERTION(!flat || IS_WRAPPER_CLASS(flat->getClass()),
|
||||
"What kind of wrapper is this?");
|
||||
|
||||
nsresult rv;
|
||||
XPCWrappedNative* wrapper;
|
||||
nsRefPtr<XPCWrappedNative> strongWrapper;
|
||||
if(!flat)
|
||||
{
|
||||
XPCCallContext &ccx = lccx.GetXPCCallContext();
|
||||
if(!ccx.IsValid())
|
||||
return JS_FALSE;
|
||||
|
||||
rv = XPCWrappedNative::GetNewOrUsed(ccx, aHelper, xpcscope, iface,
|
||||
isGlobal,
|
||||
getter_AddRefs(strongWrapper));
|
||||
|
||||
wrapper = strongWrapper;
|
||||
}
|
||||
else if(IS_WN_WRAPPER_OBJECT(flat))
|
||||
{
|
||||
wrapper = static_cast<XPCWrappedNative*>(xpc_GetJSPrivate(flat));
|
||||
|
||||
// If asked to return the wrapper we'll return a strong reference,
|
||||
// otherwise we'll just return its JSObject in d (which should be
|
||||
// rooted in that case).
|
||||
if(dest)
|
||||
strongWrapper = wrapper;
|
||||
// If iface is not null we know lccx.GetXPCCallContext() returns
|
||||
// a valid XPCCallContext because we checked when calling Init on
|
||||
// iface.
|
||||
if(iface)
|
||||
wrapper->FindTearOff(lccx.GetXPCCallContext(), iface, JS_FALSE,
|
||||
&rv);
|
||||
else
|
||||
rv = NS_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_ASSERTION(IS_SLIM_WRAPPER(flat),
|
||||
"What kind of wrapper is this?");
|
||||
|
||||
XPCCallContext &ccx = lccx.GetXPCCallContext();
|
||||
if(!ccx.IsValid())
|
||||
return JS_FALSE;
|
||||
|
||||
SLIM_LOG(("***** morphing from XPCConvert::NativeInterface2JSObject"
|
||||
"(%p)\n",
|
||||
static_cast<nsISupports*>(xpc_GetJSPrivate(flat))));
|
||||
|
||||
rv = XPCWrappedNative::Morph(ccx, flat, iface, cache,
|
||||
getter_AddRefs(strongWrapper));
|
||||
wrapper = strongWrapper;
|
||||
}
|
||||
|
||||
if(pErr)
|
||||
*pErr = rv;
|
||||
|
||||
// If creating the wrapped native failed, then return early.
|
||||
if(NS_FAILED(rv) || !wrapper)
|
||||
return JS_FALSE;
|
||||
|
||||
// If we're not creating security wrappers, we can return the
|
||||
// XPCWrappedNative as-is here.
|
||||
flat = wrapper->GetFlatJSObject();
|
||||
jsval v = OBJECT_TO_JSVAL(flat);
|
||||
if(!XPCPerThreadData::IsMainThread(lccx.GetJSContext()) ||
|
||||
!allowNativeWrapper)
|
||||
{
|
||||
*d = v;
|
||||
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
|
||||
{
|
||||
flat = nsnull;
|
||||
}
|
||||
|
||||
if(tryConstructSlimWrapper)
|
||||
{
|
||||
XPCCallContext &ccx = lccx.GetXPCCallContext();
|
||||
if(!ccx.IsValid())
|
||||
nsRefPtr<XPCJSObjectHolder> objHolder =
|
||||
XPCJSObjectHolder::newHolder(ccx, JSVAL_TO_OBJECT(*d));
|
||||
if(!objHolder)
|
||||
return JS_FALSE;
|
||||
|
||||
jsval slim;
|
||||
if(ConstructSlimWrapper(ccx, aHelper, xpcscope, &slim))
|
||||
{
|
||||
*d = slim;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
// 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.
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
AutoMarkingNativeInterfacePtr iface;
|
||||
if(iid)
|
||||
{
|
||||
XPCCallContext &ccx = lccx.GetXPCCallContext();
|
||||
if(!ccx.IsValid())
|
||||
return JS_FALSE;
|
||||
|
||||
iface.Init(ccx);
|
||||
|
||||
if(Interface)
|
||||
iface = *Interface;
|
||||
|
||||
if(!iface)
|
||||
{
|
||||
iface = XPCNativeInterface::GetNewOrUsed(ccx, iid);
|
||||
if(!iface)
|
||||
return JS_FALSE;
|
||||
|
||||
if(Interface)
|
||||
*Interface = iface;
|
||||
}
|
||||
}
|
||||
|
||||
NS_ASSERTION(!flat || IS_WRAPPER_CLASS(flat->getClass()) ||
|
||||
cache->IsProxy(),
|
||||
"What kind of wrapper is this?");
|
||||
|
||||
nsresult rv;
|
||||
XPCWrappedNative* wrapper;
|
||||
nsRefPtr<XPCWrappedNative> strongWrapper;
|
||||
if(!flat)
|
||||
{
|
||||
XPCCallContext &ccx = lccx.GetXPCCallContext();
|
||||
if(!ccx.IsValid())
|
||||
return JS_FALSE;
|
||||
|
||||
rv = XPCWrappedNative::GetNewOrUsed(ccx, aHelper, xpcscope, iface,
|
||||
isGlobal,
|
||||
getter_AddRefs(strongWrapper));
|
||||
|
||||
wrapper = strongWrapper;
|
||||
}
|
||||
else if(IS_WN_WRAPPER_OBJECT(flat))
|
||||
{
|
||||
wrapper = static_cast<XPCWrappedNative*>(xpc_GetJSPrivate(flat));
|
||||
|
||||
// If asked to return the wrapper we'll return a strong reference,
|
||||
// otherwise we'll just return its JSObject in d (which should be
|
||||
// rooted in that case).
|
||||
if(dest)
|
||||
strongWrapper = wrapper;
|
||||
// If iface is not null we know lccx.GetXPCCallContext() returns
|
||||
// a valid XPCCallContext because we checked when calling Init on
|
||||
// iface.
|
||||
if(iface)
|
||||
wrapper->FindTearOff(lccx.GetXPCCallContext(), iface, JS_FALSE,
|
||||
&rv);
|
||||
else
|
||||
rv = NS_OK;
|
||||
}
|
||||
else if(!cache->IsProxy())
|
||||
{
|
||||
NS_ASSERTION(IS_SLIM_WRAPPER(flat),
|
||||
"What kind of wrapper is this?");
|
||||
|
||||
XPCCallContext &ccx = lccx.GetXPCCallContext();
|
||||
if(!ccx.IsValid())
|
||||
return JS_FALSE;
|
||||
|
||||
SLIM_LOG(("***** morphing from XPCConvert::NativeInterface2JSObject"
|
||||
"(%p)\n",
|
||||
static_cast<nsISupports*>(xpc_GetJSPrivate(flat))));
|
||||
|
||||
rv = XPCWrappedNative::Morph(ccx, flat, iface, cache,
|
||||
getter_AddRefs(strongWrapper));
|
||||
wrapper = strongWrapper;
|
||||
}
|
||||
|
||||
if(pErr)
|
||||
*pErr = rv;
|
||||
if(NS_SUCCEEDED(rv) && wrapper)
|
||||
{
|
||||
XPCCallContext &ccx = lccx.GetXPCCallContext();
|
||||
if(!ccx.IsValid())
|
||||
return JS_FALSE;
|
||||
|
||||
uint32 flags = 0;
|
||||
flat = wrapper->GetFlatJSObject();
|
||||
jsval v = OBJECT_TO_JSVAL(flat);
|
||||
|
||||
JSBool sameOrigin;
|
||||
if (allowNativeWrapper &&
|
||||
!xpc_SameScope(wrapper->GetScope(), xpcscope, &sameOrigin))
|
||||
{
|
||||
// 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;
|
||||
*dest = objHolder.forget().get();
|
||||
}
|
||||
}
|
||||
return JS_FALSE;
|
||||
|
||||
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,15 +3897,11 @@ 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");
|
||||
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());
|
||||
return obj;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
|
Загрузка…
Ссылка в новой задаче