Bug 480205 - Implement a wrapper for exposing chrome objects to content (aka COWs). r+sr=jst sr=bzbarsky on some parts.

This commit is contained in:
Blake Kaplan 2009-05-21 01:17:51 -07:00
parent 5fa3fbd1cb
commit 8fc20a0ce4
12 changed files with 857 additions and 122 deletions

View File

@ -845,8 +845,6 @@ FeedWriter.prototype = {
// nsIDomEventListener
handleEvent: function(event) {
// see comments in init()
event = new XPCNativeWrapper(event);
if (event.target.ownerDocument != this._document) {
LOG("FeedWriter.handleEvent: Someone passed the feed writer as a listener to the events of another document!");
return;
@ -1152,10 +1150,7 @@ FeedWriter.prototype = {
// nsIFeedWriter
init: function FW_init(aWindow) {
// Explicitly wrap |window| in an XPCNativeWrapper to make sure
// it's a real native object! This will throw an exception if we
// get a non-native object.
var window = new XPCNativeWrapper(aWindow);
var window = aWindow;
this._feedURI = this._getOriginalURI(window);
if (!this._feedURI)
return;
@ -1332,9 +1327,6 @@ FeedWriter.prototype = {
// nsIObserver
observe: function FW_observe(subject, topic, data) {
// see init()
subject = new XPCNativeWrapper(subject);
if (!this._window) {
// this._window is null unless this.init was called with a trusted
// window object.
@ -1401,9 +1393,6 @@ FeedWriter.prototype = {
// nsINavHistoryService
onPageChanged: function FW_onPageChanged(aURI, aWhat, aValue) {
// see init()
aURI = new XPCNativeWrapper(aURI);
if (aWhat == Ci.nsINavHistoryObserver.ATTRIBUTE_FAVICON) {
// Go through the readers menu and look for the corresponding
// reader menu-item for the page if any.

View File

@ -1638,7 +1638,7 @@ nsDOMClassInfo::DefineStaticJSVals(JSContext *cx)
// static
nsresult
nsDOMClassInfo::WrapNative(JSContext *cx, JSObject *scope, nsISupports *native,
const nsIID* aIID, jsval *vp,
const nsIID* aIID, PRBool aAllowWrapping, jsval *vp,
nsIXPConnectJSObjectHolder **aHolder)
{
if (!native) {
@ -1652,7 +1652,42 @@ nsDOMClassInfo::WrapNative(JSContext *cx, JSObject *scope, nsISupports *native,
NS_ENSURE_TRUE(sXPConnect, NS_ERROR_UNEXPECTED);
return sXPConnect->WrapNativeToJSVal(cx, ::JS_GetGlobalForObject(cx, scope),
native, aIID, vp, aHolder);
native, aIID, aAllowWrapping, vp,
aHolder);
}
static nsresult
CreateExceptionFromResult(JSContext *cx, nsresult aResult)
{
nsCOMPtr<nsIExceptionService> xs =
do_GetService(NS_EXCEPTIONSERVICE_CONTRACTID);
if (!xs) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIExceptionManager> xm;
nsresult rv = xs->GetCurrentExceptionManager(getter_AddRefs(xm));
if (NS_FAILED(rv)) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIException> exception;
rv = xm->GetExceptionFromProvider(aResult, 0, getter_AddRefs(exception));
if (NS_FAILED(rv) || !exception) {
return NS_ERROR_FAILURE;
}
jsval jv;
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv = nsDOMClassInfo::WrapNative(cx, ::JS_GetGlobalObject(cx), exception,
&NS_GET_IID(nsIException), PR_FALSE, &jv,
getter_AddRefs(holder));
if (NS_FAILED(rv) || JSVAL_IS_NULL(jv)) {
return NS_ERROR_FAILURE;
}
JS_SetPendingException(cx, jv);
return NS_OK;
}
// static
@ -1661,36 +1696,9 @@ nsDOMClassInfo::ThrowJSException(JSContext *cx, nsresult aResult)
{
JSAutoRequest ar(cx);
do {
nsCOMPtr<nsIExceptionService> xs =
do_GetService(NS_EXCEPTIONSERVICE_CONTRACTID);
if (!xs) {
break;
}
nsCOMPtr<nsIExceptionManager> xm;
nsresult rv = xs->GetCurrentExceptionManager(getter_AddRefs(xm));
if (NS_FAILED(rv)) {
break;
}
nsCOMPtr<nsIException> exception;
rv = xm->GetExceptionFromProvider(aResult, 0, getter_AddRefs(exception));
if (NS_FAILED(rv) || !exception) {
break;
}
jsval jv;
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv = WrapNative(cx, ::JS_GetGlobalObject(cx), exception,
&NS_GET_IID(nsIException), &jv, getter_AddRefs(holder));
if (NS_FAILED(rv) || JSVAL_IS_NULL(jv)) {
break;
}
JS_SetPendingException(cx, jv);
if (NS_SUCCEEDED(CreateExceptionFromResult(cx, aResult))) {
return NS_OK;
} while (0);
}
// XXX This probably wants to be localized, but that can fail in ways that
// are hard to report correctly.
@ -4559,7 +4567,8 @@ nsWindowSH::GlobalScopePolluterNewResolve(JSContext *cx, JSObject *obj,
if (result) {
jsval v;
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
nsresult rv = WrapNative(cx, obj, result, &v, getter_AddRefs(holder));
nsresult rv = WrapNative(cx, obj, result, PR_TRUE, &v,
getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, JS_FALSE);
if (!::JS_DefineUCProperty(cx, obj, ::JS_GetStringChars(jsstr),
@ -4753,7 +4762,7 @@ nsWindowSH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv = WrapNative(cx, frameWin->GetGlobalJSObject(), frame,
&NS_GET_IID(nsIDOMWindow), vp,
&NS_GET_IID(nsIDOMWindow), PR_TRUE, vp,
getter_AddRefs(holder));
}
@ -4870,8 +4879,8 @@ nsWindowSH::SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
NS_ENSURE_TRUE(NS_SUCCEEDED(rv) && location, rv);
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv = WrapNative(cx, obj, location, &NS_GET_IID(nsIDOMLocation), vp,
getter_AddRefs(holder));
rv = WrapNative(cx, obj, location, &NS_GET_IID(nsIDOMLocation), PR_TRUE,
vp, getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv);
rv = location->SetHref(nsDependentJSString(val));
@ -5118,8 +5127,8 @@ BaseStubConstructor(nsIWeakReference* aWeakOwner,
}
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv = nsDOMGenericSH::WrapNative(cx, obj, native, rval,
getter_AddRefs(holder));
rv = nsDOMClassInfo::WrapNative(cx, obj, native, PR_TRUE,
rval, getter_AddRefs(holder));
return rv;
}
@ -5573,8 +5582,8 @@ ResolvePrototype(nsIXPConnect *aXPConnect, nsGlobalWindow *aWin, JSContext *cx,
jsval v;
rv = nsDOMClassInfo::WrapNative(cx, obj, constructor,
&NS_GET_IID(nsIDOMDOMConstructor), &v,
getter_AddRefs(holder));
&NS_GET_IID(nsIDOMDOMConstructor),
PR_FALSE, &v, getter_AddRefs(holder));
sDoSecurityCheckInAddProperty = doSecurityCheckInAddProperty;
@ -5832,8 +5841,8 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
jsval v;
rv = WrapNative(cx, obj, constructor, &NS_GET_IID(nsIDOMDOMConstructor), &v,
getter_AddRefs(holder));
rv = WrapNative(cx, obj, constructor, &NS_GET_IID(nsIDOMDOMConstructor),
PR_FALSE, &v, getter_AddRefs(holder));
sDoSecurityCheckInAddProperty = doSecurityCheckInAddProperty;
@ -5875,7 +5884,7 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
jsval val;
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv = WrapNative(cx, obj, constructor, &NS_GET_IID(nsIDOMDOMConstructor),
&val, getter_AddRefs(holder));
PR_FALSE, &val, getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv);
rv = constructor->Install(cx, obj, val);
@ -5922,7 +5931,8 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
scope = aWin->GetGlobalJSObject();
}
rv = WrapNative(cx, scope, native, &prop_val, getter_AddRefs(holder));
rv = WrapNative(cx, scope, native, PR_TRUE, &prop_val,
getter_AddRefs(holder));
}
NS_ENSURE_SUCCESS(rv, rv);
@ -6213,10 +6223,19 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
jsval v;
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv = WrapNative(cx, wrapperObj, child_win,
&NS_GET_IID(nsIDOMWindowInternal), &v,
&NS_GET_IID(nsIDOMWindowInternal), PR_TRUE, &v,
getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv);
#ifdef DEBUG
if (!win->IsChromeWindow()) {
NS_ASSERTION(JSVAL_IS_OBJECT(v) &&
!strcmp(STOBJ_GET_CLASS(JSVAL_TO_OBJECT(v))->name,
"XPCCrossOriginWrapper"),
"Didn't wrap a window!");
}
#endif
// Script is accessing a child frame and this access can
// potentially come from a context from a different domain.
// ::JS_DefineUCProperty() will call
@ -6229,12 +6248,6 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
// property is 'ok' in this case, even if the call comes from
// a different context.
if (!win->IsChromeWindow()) {
rv = sXPConnect->GetXOWForObject(cx, win->GetGlobalJSObject(),
JSVAL_TO_OBJECT(v), &v);
NS_ENSURE_SUCCESS(rv, rv);
}
JSAutoRequest ar(cx);
PRBool ok = ::JS_DefineUCProperty(cx, obj, chars,
@ -6335,18 +6348,22 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
jsval v;
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv = WrapNative(cx, scope, location, &NS_GET_IID(nsIDOMLocation), &v,
getter_AddRefs(holder));
rv = WrapNative(cx, scope, location, &NS_GET_IID(nsIDOMLocation), PR_TRUE,
&v, getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv);
#ifdef DEBUG
if (!win->IsChromeWindow()) {
NS_ASSERTION(JSVAL_IS_OBJECT(v) &&
!strcmp(STOBJ_GET_CLASS(JSVAL_TO_OBJECT(v))->name,
"XPCCrossOriginWrapper"),
"Didn't wrap a location object!");
}
#endif
PRBool doSecurityCheckInAddProperty = sDoSecurityCheckInAddProperty;
sDoSecurityCheckInAddProperty = PR_FALSE;
if (!win->IsChromeWindow()) {
rv = sXPConnect->GetXOWForObject(cx, scope, JSVAL_TO_OBJECT(v), &v);
NS_ENSURE_SUCCESS(rv, rv);
}
JSAutoRequest ar(cx);
JSBool ok = ::JS_DefineUCProperty(cx, obj, ::JS_GetStringChars(str),
@ -6392,8 +6409,8 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
jsval v;
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv = WrapNative(cx, obj, navigator, &NS_GET_IID(nsIDOMNavigator), &v,
getter_AddRefs(holder));
rv = WrapNative(cx, obj, navigator, &NS_GET_IID(nsIDOMNavigator), PR_TRUE,
&v, getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv);
JSAutoRequest ar(cx);
@ -6416,8 +6433,8 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
jsval v;
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv = WrapNative(cx, obj, document, &NS_GET_IID(nsIDOMDocument), &v,
getter_AddRefs(holder));
rv = WrapNative(cx, obj, document, &NS_GET_IID(nsIDOMDocument), PR_FALSE,
&v, getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv);
// The PostCreate hook for the document will handle defining the
@ -6999,7 +7016,7 @@ nsNodeSH::PreCreate(nsISupports *nativeObj, JSContext *cx, JSObject *globalObj,
jsval v;
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
nsresult rv = WrapNative(cx, globalObj, native_parent, &v,
nsresult rv = WrapNative(cx, globalObj, native_parent, PR_FALSE, &v,
getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv);
@ -7058,7 +7075,7 @@ nsNodeSH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
}
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
nsresult rv = WrapNative(cx, obj, uri, &NS_GET_IID(nsIURI), vp,
nsresult rv = WrapNative(cx, obj, uri, &NS_GET_IID(nsIURI), PR_TRUE, vp,
getter_AddRefs(holder));
return NS_FAILED(rv) ? rv : NS_SUCCESS_I_DID_SOMETHING;
}
@ -7069,7 +7086,7 @@ nsNodeSH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
nsresult rv = WrapNative(cx, obj, node->NodePrincipal(),
&NS_GET_IID(nsIPrincipal), vp,
&NS_GET_IID(nsIPrincipal), PR_TRUE, vp,
getter_AddRefs(holder));
return NS_FAILED(rv) ? rv : NS_SUCCESS_I_DID_SOMETHING;
}
@ -7748,7 +7765,7 @@ nsArraySH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
NS_ENSURE_SUCCESS(rv, rv);
if (array_item) {
rv = WrapNative(cx, obj, array_item, vp);
rv = WrapNative(cx, obj, array_item, PR_TRUE, vp);
NS_ENSURE_SUCCESS(rv, rv);
rv = NS_SUCCESS_I_DID_SOMETHING;
@ -7782,7 +7799,7 @@ nsNodeListSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
jsval v;
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
nsresult rv = WrapNative(cx, globalObj, native_parent, &v,
nsresult rv = WrapNative(cx, globalObj, native_parent, PR_FALSE, &v,
getter_AddRefs(holder));
*parentObj = JSVAL_TO_OBJECT(v);
@ -7856,7 +7873,7 @@ nsNamedArraySH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
NS_ENSURE_SUCCESS(rv, rv);
if (item) {
rv = WrapNative(cx, obj, item, vp);
rv = WrapNative(cx, obj, item, PR_TRUE, vp);
NS_ENSURE_SUCCESS(rv, rv);
rv = NS_SUCCESS_I_DID_SOMETHING;
@ -7968,7 +7985,7 @@ nsContentListSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
jsval v;
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
nsresult rv = WrapNative(cx, globalObj, native_parent, &v,
nsresult rv = WrapNative(cx, globalObj, native_parent, PR_FALSE, &v,
getter_AddRefs(holder));
*parentObj = JSVAL_TO_OBJECT(v);
@ -8064,8 +8081,8 @@ nsDocumentSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
jsval v;
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv = WrapNative(cx, obj, location, &NS_GET_IID(nsIDOMLocation), &v,
getter_AddRefs(holder));
rv = WrapNative(cx, obj, location, &NS_GET_IID(nsIDOMLocation), PR_TRUE,
&v, getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv);
PRBool doSecurityCheckInAddProperty = sDoSecurityCheckInAddProperty;
@ -8108,7 +8125,7 @@ nsDocumentSH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
NS_ENSURE_TRUE(uri, NS_ERROR_NOT_AVAILABLE);
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
nsresult rv = WrapNative(cx, obj, uri, &NS_GET_IID(nsIURI), vp,
nsresult rv = WrapNative(cx, obj, uri, &NS_GET_IID(nsIURI), PR_TRUE, vp,
getter_AddRefs(holder));
return NS_FAILED(rv) ? rv : NS_SUCCESS_I_DID_SOMETHING;
@ -8140,8 +8157,8 @@ nsDocumentSH::SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv = WrapNative(cx, obj, location, &NS_GET_IID(nsIDOMLocation), vp,
getter_AddRefs(holder));
rv = WrapNative(cx, obj, location, &NS_GET_IID(nsIDOMLocation), PR_TRUE,
vp, getter_AddRefs(holder));
return NS_FAILED(rv) ? rv : NS_SUCCESS_I_DID_SOMETHING;
}
}
@ -8194,7 +8211,7 @@ nsDocumentSH::PostCreate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
jsval winVal;
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv = WrapNative(cx, obj, win, &NS_GET_IID(nsIDOMWindow), &winVal,
rv = WrapNative(cx, obj, win, &NS_GET_IID(nsIDOMWindow), PR_FALSE, &winVal,
getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv);
@ -8300,7 +8317,7 @@ nsHTMLDocumentSH::DocumentOpen(JSContext *cx, JSObject *obj, uintN argc,
}
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv = WrapNative(cx, obj, retval, &NS_GET_IID(nsIDOMDocument), rval,
rv = WrapNative(cx, obj, retval, &NS_GET_IID(nsIDOMDocument), PR_FALSE, rval,
getter_AddRefs(holder));
NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to wrap native!");
@ -8375,7 +8392,7 @@ nsHTMLDocumentSH::GetDocumentAllNodeList(JSContext *cx, JSObject *obj,
rv |= domdoc->GetElementsByTagName(NS_LITERAL_STRING("*"), nodeList);
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv |= nsDOMClassInfo::WrapNative(cx, obj, *nodeList, &collection,
rv |= nsDOMClassInfo::WrapNative(cx, obj, *nodeList, PR_FALSE, &collection,
getter_AddRefs(holder));
// ... and store it in our reserved slot.
@ -8472,7 +8489,7 @@ nsHTMLDocumentSH::DocumentAllGetProperty(JSContext *cx, JSObject *obj,
}
if (result) {
rv = WrapNative(cx, obj, result, vp);
rv = WrapNative(cx, obj, result, PR_TRUE, vp);
if (NS_FAILED(rv)) {
nsDOMClassInfo::ThrowJSException(cx, rv);
@ -8744,7 +8761,7 @@ nsHTMLDocumentSH::DocumentAllTagsNewResolve(JSContext *cx, JSObject *obj,
if (tags) {
jsval v;
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
nsresult rv = nsDOMClassInfo::WrapNative(cx, obj, tags, &v,
nsresult rv = nsDOMClassInfo::WrapNative(cx, obj, tags, PR_TRUE, &v,
getter_AddRefs(holder));
if (NS_FAILED(rv)) {
nsDOMClassInfo::ThrowJSException(cx, rv);
@ -8903,7 +8920,7 @@ nsHTMLDocumentSH::GetProperty(nsIXPConnectWrappedNative *wrapper,
NS_ENSURE_SUCCESS(rv, rv);
if (result) {
rv = WrapNative(cx, obj, result, vp);
rv = WrapNative(cx, obj, result, PR_TRUE, vp);
if (NS_SUCCEEDED(rv)) {
rv = NS_SUCCESS_I_DID_SOMETHING;
}
@ -9043,7 +9060,7 @@ nsHTMLFormElementSH::GetProperty(nsIXPConnectWrappedNative *wrapper,
if (result) {
// Wrap result, result can be either an element or a list of
// elements
nsresult rv = WrapNative(cx, obj, result, vp);
nsresult rv = WrapNative(cx, obj, result, PR_TRUE, vp);
return NS_FAILED(rv) ? rv : NS_SUCCESS_I_DID_SOMETHING;
}
}
@ -9055,7 +9072,7 @@ nsHTMLFormElementSH::GetProperty(nsIXPConnectWrappedNative *wrapper,
form->GetElementAt(n, getter_AddRefs(control));
if (control) {
nsresult rv = WrapNative(cx, obj, control, vp);
nsresult rv = WrapNative(cx, obj, control, PR_TRUE, vp);
return NS_FAILED(rv) ? rv : NS_SUCCESS_I_DID_SOMETHING;
}
}
@ -9162,7 +9179,7 @@ nsHTMLSelectElementSH::GetProperty(nsIXPConnectWrappedNative *wrapper,
options->Item(n, getter_AddRefs(node));
rv = WrapNative(cx, obj, node, &NS_GET_IID(nsIDOMNode), vp);
rv = WrapNative(cx, obj, node, &NS_GET_IID(nsIDOMNode), PR_TRUE, vp);
if (NS_SUCCEEDED(rv)) {
rv = NS_SUCCESS_I_DID_SOMETHING;
}
@ -9810,12 +9827,11 @@ nsHTMLPluginObjElementSH::NewResolve(nsIXPConnectWrappedNative *wrapper,
}
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv = sXPConnect->WrapNative(cx, obj, pi, *iid, getter_AddRefs(holder));
jsval v;
rv = WrapNative(cx, obj, pi, iid, PR_TRUE, &v, getter_AddRefs(holder));
if (NS_SUCCEEDED(rv)) {
JSObject* ifaceObj;
rv = holder->GetJSObject(&ifaceObj);
JSObject* ifaceObj = JSVAL_TO_OBJECT(v);
if (NS_SUCCEEDED(rv)) {
nsMemory::Free(iid);

View File

@ -131,19 +131,20 @@ public:
static nsresult WrapNative(JSContext *cx, JSObject *scope,
nsISupports *native, const nsIID* aIID,
jsval *vp,
PRBool aAllowWrapping, jsval *vp,
// If non-null aHolder will keep the jsval alive
// while there's a ref to it
nsIXPConnectJSObjectHolder** aHolder = nsnull);
// Same as the WrapNative above, but use this one if aIID is nsISupports' IID.
static nsresult WrapNative(JSContext *cx, JSObject *scope,
nsISupports *native, jsval *vp,
nsISupports *native, PRBool aAllowWrapping,
jsval *vp,
// If non-null aHolder will keep the jsval alive
// while there's a ref to it
nsIXPConnectJSObjectHolder** aHolder = nsnull)
{
return WrapNative(cx, scope, native, nsnull, vp, aHolder);
return WrapNative(cx, scope, native, nsnull, aAllowWrapping, vp, aHolder);
}
static nsresult ThrowJSException(JSContext *cx, nsresult aResult);

View File

@ -405,7 +405,7 @@ interface nsIXPCFunctionThisTranslator : nsISupports
{ 0xbd, 0xd6, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } }
%}
[uuid(b2ddc328-194b-45d6-95c6-52e487438096)]
[uuid(b76828b8-3ac5-469e-946d-3401c6a2104d)]
interface nsIXPConnect : nsISupports
{
%{ C++
@ -476,12 +476,15 @@ interface nsIXPConnect : nsISupports
* &NS_GET_IID(nsISupports) but when passing in null certain shortcuts
* can be taken because we know without comparing IIDs that the caller is
* asking for an nsISupports wrapper.
* If aAllowWrapper, then the returned value will be wrapped in the proper
* type of security wrapper on top of the XPCWrappedNative (if needed).
*/
void
wrapNativeToJSVal(in JSContextPtr aJSContext,
in JSObjectPtr aScope,
in nsISupports aCOMObj,
in nsIIDPtr aIID,
in boolean aAllowWrapper,
out JSVal aVal,
out nsIXPConnectJSObjectHolder aHolder);
@ -705,6 +708,16 @@ interface nsIXPConnect : nsISupports
in JSObjectPtr aParent,
in JSObjectPtr aWrappedObj);
/**
* Wrap a jsval in a chrome object wrapper.
* @param aJSContext A context to use to create objects.
* @param aParent The parent to create the wrapper with.
* @param aWrappedObj The object to wrap.
*/
[noscript] JSVal getCOWForObject(in JSContextPtr aJSContext,
in JSObjectPtr aParent,
in JSObjectPtr aWrappedObj);
/**
* Tells updateXOWs to clear the scope of all of the XOWs it finds.
*/

View File

@ -109,6 +109,7 @@ CPPSRCS = \
xpcJSWeakReference.cpp \
XPCSafeJSObjectWrapper.cpp \
XPCCrossOriginWrapper.cpp \
XPCChromeObjectWrapper.cpp \
XPCSystemOnlyWrapper.cpp \
XPCWrapper.cpp \
xpcquickstubs.cpp \

View File

@ -0,0 +1,674 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 sw=2 et tw=78 sts=2: */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* The Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Blake Kaplan <mrbkap@gmail.com> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "xpcprivate.h"
#include "nsDOMError.h"
#include "jsdbgapi.h"
#include "jscntxt.h" // For JSAutoTempValueRooter.
#include "jsobj.h"
#include "XPCNativeWrapper.h"
#include "XPCWrapper.h"
// This file implements a wrapper around trusted objects that allows them to
// be safely injected into untrusted code.
static JSBool
XPC_COW_AddProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
static JSBool
XPC_COW_DelProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
static JSBool
XPC_COW_GetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
static JSBool
XPC_COW_SetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
static JSBool
XPC_COW_Enumerate(JSContext *cx, JSObject *obj);
static JSBool
XPC_COW_NewResolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
JSObject **objp);
static JSBool
XPC_COW_Convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp);
static JSBool
XPC_COW_CheckAccess(JSContext *cx, JSObject *obj, jsval id, JSAccessMode mode,
jsval *vp);
static JSBool
XPC_COW_Equality(JSContext *cx, JSObject *obj, jsval v, JSBool *bp);
static JSObject *
XPC_COW_Iterator(JSContext *cx, JSObject *obj, JSBool keysonly);
static JSObject *
XPC_COW_WrappedObject(JSContext *cx, JSObject *obj);
JSExtendedClass sXPC_COW_JSClass = {
// JSClass (JSExtendedClass.base) initialization
{ "ChromeObjectWrapper",
JSCLASS_NEW_RESOLVE | JSCLASS_IS_EXTENDED |
JSCLASS_HAS_RESERVED_SLOTS(XPCWrapper::sNumSlots),
XPC_COW_AddProperty, XPC_COW_DelProperty,
XPC_COW_GetProperty, XPC_COW_SetProperty,
XPC_COW_Enumerate, (JSResolveOp)XPC_COW_NewResolve,
XPC_COW_Convert, JS_FinalizeStub,
nsnull, XPC_COW_CheckAccess,
nsnull, nsnull,
nsnull, nsnull,
nsnull, nsnull
},
// JSExtendedClass initialization
XPC_COW_Equality,
nsnull, // outerObject
nsnull, // innerObject
XPC_COW_Iterator,
XPC_COW_WrappedObject,
JSCLASS_NO_RESERVED_MEMBERS
};
static JSBool
XPC_COW_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
jsval *rval);
// Throws an exception on context |cx|.
static inline JSBool
ThrowException(nsresult rv, JSContext *cx)
{
return XPCWrapper::ThrowException(rv, cx);
}
// Like GetWrappedObject, but works on other types of wrappers, too.
// See also js_GetWrappedObject in jsobj.h.
// TODO Move to XPCWrapper?
static inline JSObject *
GetWrappedJSObject(JSContext *cx, JSObject *obj)
{
JSClass *clasp = STOBJ_GET_CLASS(obj);
if (!(clasp->flags & JSCLASS_IS_EXTENDED)) {
return obj;
}
JSExtendedClass *xclasp = (JSExtendedClass *)clasp;
if (!xclasp->wrappedObject) {
if (XPCNativeWrapper::IsNativeWrapper(obj)) {
XPCWrappedNative *wn = XPCNativeWrapper::SafeGetWrappedNative(obj);
return wn ? wn->GetFlatJSObject() : nsnull;
}
return obj;
}
return xclasp->wrappedObject(cx, obj);
}
// Get the (possibly non-existant) COW off of an object
// TODO Move to XPCWrapper and share with other wrappers.
static inline
JSObject *
GetWrapper(JSObject *obj)
{
while (STOBJ_GET_CLASS(obj) != &sXPC_COW_JSClass.base) {
obj = STOBJ_GET_PROTO(obj);
if (!obj) {
break;
}
}
return obj;
}
// TODO Templatize, move to XPCWrapper and share with other wrappers!
static inline
JSObject *
GetWrappedObject(JSContext *cx, JSObject *wrapper)
{
if (STOBJ_GET_CLASS(wrapper) != &sXPC_COW_JSClass.base) {
return nsnull;
}
jsval v;
if (!JS_GetReservedSlot(cx, wrapper, XPCWrapper::sWrappedObjSlot, &v)) {
JS_ClearPendingException(cx);
return nsnull;
}
if (!JSVAL_IS_OBJECT(v)) {
return nsnull;
}
return JSVAL_TO_OBJECT(v);
}
// Forward declaration for the function wrapper.
JSBool
XPC_COW_RewrapForChrome(JSContext *cx, JSObject *wrapperObj, jsval *vp);
JSBool
XPC_COW_RewrapForContent(JSContext *cx, JSObject *wrapperObj, jsval *vp);
// This function wrapper calls a function from untrusted content into chrome.
static JSBool
XPC_COW_FunctionWrapper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
jsval *rval)
{
JSObject *wrappedObj;
// Allow 'this' to be either a COW, in which case we unwrap it or something
// that isn't a COW. We disallow invalid COWs that have no wrapped object.
wrappedObj = GetWrapper(obj);
if (wrappedObj) {
wrappedObj = GetWrappedObject(cx, wrappedObj);
if (!wrappedObj) {
return ThrowException(NS_ERROR_ILLEGAL_VALUE, cx);
}
} else {
wrappedObj = obj;
}
JSObject *funObj = JSVAL_TO_OBJECT(argv[-2]);
jsval funToCall;
if (!JS_GetReservedSlot(cx, funObj, XPCWrapper::eWrappedFunctionSlot,
&funToCall)) {
return JS_FALSE;
}
JSFunction *fun = JS_ValueToFunction(cx, funToCall);
if (!fun) {
return ThrowException(NS_ERROR_ILLEGAL_VALUE, cx);
}
for (uintN i = 0; i < argc; ++i) {
if (!XPC_COW_RewrapForChrome(cx, obj, &argv[i])) {
return JS_FALSE;
}
}
XPCCallContext ccx(JS_CALLER, cx);
if (!ccx.IsValid()) {
return ThrowException(NS_ERROR_FAILURE, cx);
}
JSNative native = JS_GetFunctionNative(cx, fun);
NS_ASSERTION(native, "How'd we get here with a scripted function?");
// A trick! Calling the native directly doesn't push the native onto the
// JS stack, so interested onlookers will only see us, meaning that they
// will compute *our* subject principal.
argv[-2] = funToCall;
argv[-1] = OBJECT_TO_JSVAL(wrappedObj);
if (!native(cx, wrappedObj, argc, argv, rval)) {
return JS_FALSE;
}
return XPC_COW_RewrapForContent(cx, obj, rval);
}
JSBool
XPC_COW_WrapFunction(JSContext *cx, JSObject *outerObj, JSObject *funobj,
jsval *rval)
{
jsval funobjVal = OBJECT_TO_JSVAL(funobj);
JSFunction *wrappedFun =
reinterpret_cast<JSFunction *>(xpc_GetJSPrivate(funobj));
JSNative native = JS_GetFunctionNative(cx, wrappedFun);
if (!native || native == XPC_COW_FunctionWrapper) {
*rval = funobjVal;
return JS_TRUE;
}
JSFunction *funWrapper =
JS_NewFunction(cx, XPC_COW_FunctionWrapper,
JS_GetFunctionArity(wrappedFun), 0,
JS_GetGlobalForObject(cx, outerObj),
JS_GetFunctionName(wrappedFun));
if (!funWrapper) {
return JS_FALSE;
}
JSObject *funWrapperObj = JS_GetFunctionObject(funWrapper);
*rval = OBJECT_TO_JSVAL(funWrapperObj);
return JS_SetReservedSlot(cx, funWrapperObj,
XPCWrapper::eWrappedFunctionSlot,
funobjVal);
}
JSBool
XPC_COW_RewrapForChrome(JSContext *cx, JSObject *wrapperObj, jsval *vp)
{
jsval v = *vp;
if (JSVAL_IS_PRIMITIVE(v)) {
return JS_TRUE;
}
// We're rewrapping for chrome, so this is safe.
JSObject *obj = GetWrappedJSObject(cx, JSVAL_TO_OBJECT(v));
if (!obj) {
*vp = JSVAL_NULL;
return JS_TRUE;
}
XPCWrappedNative *wn;
if (IS_WRAPPER_CLASS(STOBJ_GET_CLASS(obj)) &&
(wn = XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj))) {
// Return an explicit XPCNativeWrapper in case "chrome" code happens to be
// XBL code cloned into an untrusted context.
return XPCNativeWrapperCtor(cx, obj, 1, vp, vp);
}
return XPC_SJOW_Construct(cx, obj, 1, vp, vp);
}
JSBool
XPC_COW_RewrapForContent(JSContext *cx, JSObject *wrapperObj, jsval *vp)
{
jsval v = *vp;
if (JSVAL_IS_PRIMITIVE(v)) {
return JS_TRUE;
}
JSObject *obj = GetWrappedJSObject(cx, JSVAL_TO_OBJECT(v));
if (!obj) {
*vp = JSVAL_NULL;
return JS_TRUE;
}
if (JS_ObjectIsFunction(cx, obj)) {
return XPC_COW_WrapFunction(cx, wrapperObj, obj, vp);
}
return XPC_COW_WrapObject(cx, JS_GetScopeChain(cx), OBJECT_TO_JSVAL(obj),
vp);
}
static JSBool
XPC_COW_AddProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{
obj = GetWrapper(obj);
jsval resolving;
if (!JS_GetReservedSlot(cx, obj, XPCWrapper::sFlagsSlot, &resolving)) {
return JS_FALSE;
}
if (HAS_FLAGS(resolving, FLAG_RESOLVING)) {
// Allow us to define a property on ourselves.
return JS_TRUE;
}
// Someone's adding a property to us. We need to protect ourselves from
// getters and setters.
JSObject *wrappedObj = GetWrappedObject(cx, obj);
if (!wrappedObj) {
return ThrowException(NS_ERROR_ILLEGAL_VALUE, cx);
}
jsid interned_id;
JSPropertyDescriptor desc;
if (!JS_ValueToId(cx, id, &interned_id) ||
!XPCWrapper::GetPropertyAttrs(cx, obj, interned_id, JSRESOLVE_QUALIFIED,
JS_TRUE, &desc)) {
return JS_FALSE;
}
NS_ASSERTION(desc.obj == obj, "The JS engine lies!");
if (desc.attrs & (JSPROP_GETTER | JSPROP_SETTER)) {
// Only chrome is allowed to add getters or setters to our object.
if (!AllowedToAct(cx, id)) {
return JS_FALSE;
}
}
return XPC_COW_RewrapForChrome(cx, obj, vp) &&
JS_DefinePropertyById(cx, wrappedObj, interned_id, *vp,
desc.getter, desc.setter, desc.attrs);
}
static JSBool
XPC_COW_DelProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{
JSObject *wrappedObj = GetWrappedObject(cx, obj);
if (!wrappedObj) {
return ThrowException(NS_ERROR_ILLEGAL_VALUE, cx);
}
XPCCallContext ccx(JS_CALLER, cx);
if (!ccx.IsValid()) {
return ThrowException(NS_ERROR_FAILURE, cx);
}
// Deleting a property is safe.
return XPCWrapper::DelProperty(cx, wrappedObj, id, vp);
}
static JSBool
XPC_COW_GetOrSetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp,
JSBool isSet)
{
if (id == GetRTStringByIndex(cx, XPCJSRuntime::IDX_TO_STRING)) {
return JS_TRUE;
}
obj = GetWrapper(obj);
if (!obj) {
return ThrowException(NS_ERROR_ILLEGAL_VALUE, cx);
}
XPCCallContext ccx(JS_CALLER, cx);
if (!ccx.IsValid()) {
return ThrowException(NS_ERROR_FAILURE, cx);
}
AUTO_MARK_JSVAL(ccx, vp);
JSObject *wrappedObj = GetWrappedObject(cx, obj);
if (!wrappedObj) {
return ThrowException(NS_ERROR_ILLEGAL_VALUE, cx);
}
if (id == GetRTStringByIndex(cx, XPCJSRuntime::IDX_PROTO) ||
id == GetRTStringByIndex(cx, XPCJSRuntime::IDX_PARENT)) {
// No getting or setting __proto__ or __parent__ on my object.
return ThrowException(NS_ERROR_INVALID_ARG, cx); // XXX better error message
}
if (!XPC_COW_RewrapForChrome(cx, obj, vp)) {
return JS_FALSE;
}
jsid interned_id;
if (!JS_ValueToId(cx, id, &interned_id)) {
return JS_FALSE;
}
JSBool ok = isSet
? JS_SetPropertyById(cx, wrappedObj, interned_id, vp)
: JS_GetPropertyById(cx, wrappedObj, interned_id, vp);
if (!ok) {
return JS_FALSE;
}
return XPC_COW_RewrapForContent(cx, obj, vp);
}
static JSBool
XPC_COW_GetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{
return XPC_COW_GetOrSetProperty(cx, obj, id, vp, JS_FALSE);
}
static JSBool
XPC_COW_SetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{
return XPC_COW_GetOrSetProperty(cx, obj, id, vp, JS_TRUE);
}
static JSBool
XPC_COW_Enumerate(JSContext *cx, JSObject *obj)
{
obj = GetWrapper(obj);
JSObject *wrappedObj = GetWrappedObject(cx, obj);
if (!wrappedObj) {
// Nothing to enumerate.
return JS_TRUE;
}
XPCCallContext ccx(JS_CALLER, cx);
if (!ccx.IsValid()) {
return ThrowException(NS_ERROR_FAILURE, cx);
}
return XPCWrapper::Enumerate(cx, obj, wrappedObj);
}
static JSBool
XPC_COW_NewResolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
JSObject **objp)
{
obj = GetWrapper(obj);
JSObject *wrappedObj = GetWrappedObject(cx, obj);
if (!wrappedObj) {
// No wrappedObj means that this is probably the prototype.
*objp = nsnull;
return JS_TRUE;
}
XPCCallContext ccx(JS_CALLER, cx);
if (!ccx.IsValid()) {
return ThrowException(NS_ERROR_FAILURE, cx);
}
if (id == GetRTStringByIndex(cx, XPCJSRuntime::IDX_TO_STRING)) {
jsval oldSlotVal;
if (!::JS_GetReservedSlot(cx, obj, XPCWrapper::sFlagsSlot, &oldSlotVal) ||
!::JS_SetReservedSlot(cx, obj, XPCWrapper::sFlagsSlot,
INT_TO_JSVAL(JSVAL_TO_INT(oldSlotVal) |
FLAG_RESOLVING))) {
return JS_FALSE;
}
JSBool ok = JS_DefineFunction(cx, obj, "toString",
XPC_COW_toString, 0, 0) != nsnull;
if (ok && (ok = ::JS_SetReservedSlot(cx, obj, XPCWrapper::sFlagsSlot,
oldSlotVal))) {
*objp = obj;
}
return ok;
}
return XPCWrapper::NewResolve(cx, obj, JS_TRUE, wrappedObj, id, flags, objp);
}
static JSBool
XPC_COW_Convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
{
// Don't do any work to convert to object.
if (type == JSTYPE_OBJECT) {
*vp = OBJECT_TO_JSVAL(obj);
return JS_TRUE;
}
JSObject *wrappedObj = GetWrappedObject(cx, obj);
if (!wrappedObj) {
// Converting the prototype to something.
if (type == JSTYPE_STRING || type == JSTYPE_VOID) {
return XPC_COW_toString(cx, obj, 0, nsnull, vp);
}
*vp = OBJECT_TO_JSVAL(obj);
return JS_TRUE;
}
XPCCallContext ccx(JS_CALLER, cx);
if (!ccx.IsValid()) {
return ThrowException(NS_ERROR_FAILURE, cx);
}
if (!STOBJ_GET_CLASS(wrappedObj)->convert(cx, wrappedObj, type, vp)) {
return JS_FALSE;
}
return XPC_COW_RewrapForContent(cx, obj, vp);
}
static JSBool
XPC_COW_CheckAccess(JSContext *cx, JSObject *obj, jsval prop, JSAccessMode mode,
jsval *vp)
{
// Simply forward checkAccess to our wrapped object. It's already expecting
// untrusted things to ask it about accesses.
uintN junk;
jsid id;
return JS_ValueToId(cx, prop, &id) &&
JS_CheckAccess(cx, GetWrappedObject(cx, obj), id, mode, vp, &junk);
}
static JSBool
XPC_COW_Equality(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
{
// Convert both sides to XPCWrappedNative and see if they match.
if (JSVAL_IS_PRIMITIVE(v)) {
*bp = JS_FALSE;
return JS_TRUE;
}
JSObject *test = GetWrappedJSObject(cx, JSVAL_TO_OBJECT(v));
obj = GetWrappedObject(cx, obj);
if (!obj) {
return ThrowException(NS_ERROR_ILLEGAL_VALUE, cx);
}
XPCWrappedNative *other =
XPCWrappedNative::GetWrappedNativeOfJSObject(cx, test);
if (!other) {
*bp = JS_FALSE;
return JS_TRUE;
}
XPCWrappedNative *me = XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj);
obj = me->GetFlatJSObject();
test = other->GetFlatJSObject();
return ((JSExtendedClass *)STOBJ_GET_CLASS(obj))->
equality(cx, obj, OBJECT_TO_JSVAL(test), bp);
}
static JSObject *
XPC_COW_Iterator(JSContext *cx, JSObject *obj, JSBool keysonly)
{
JSObject *wrappedObj = GetWrappedObject(cx, obj);
if (!wrappedObj) {
ThrowException(NS_ERROR_INVALID_ARG, cx);
return nsnull;
}
XPCCallContext ccx(JS_CALLER, cx);
if (!ccx.IsValid()) {
ThrowException(NS_ERROR_FAILURE, cx);
return nsnull;
}
JSObject *wrapperIter = JS_NewObject(cx, &sXPC_COW_JSClass.base, nsnull,
JS_GetGlobalForObject(cx, obj));
if (!wrapperIter) {
return nsnull;
}
JSAutoTempValueRooter tvr(cx, OBJECT_TO_JSVAL(wrapperIter));
// Initialize our COW.
jsval v = OBJECT_TO_JSVAL(wrappedObj);
if (!JS_SetReservedSlot(cx, wrapperIter, XPCWrapper::sWrappedObjSlot, v) ||
!JS_SetReservedSlot(cx, wrapperIter, XPCWrapper::sFlagsSlot,
JSVAL_ZERO)) {
return nsnull;
}
return XPCWrapper::CreateIteratorObj(cx, wrapperIter, obj, wrappedObj,
keysonly);
}
static JSObject *
XPC_COW_WrappedObject(JSContext *cx, JSObject *obj)
{
return GetWrappedObject(cx, obj);
}
static JSBool
XPC_COW_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
jsval *rval)
{
obj = GetWrapper(obj);
if (!obj) {
return ThrowException(NS_ERROR_UNEXPECTED, cx);
}
JSObject *wrappedObj = GetWrappedObject(cx, obj);
if (!wrappedObj) {
// Someone's calling toString on our prototype.
NS_NAMED_LITERAL_CSTRING(protoString, "[object XPCCrossOriginWrapper]");
JSString *str =
JS_NewStringCopyN(cx, protoString.get(), protoString.Length());
if (!str) {
return JS_FALSE;
}
*rval = STRING_TO_JSVAL(str);
return JS_TRUE;
}
XPCCallContext ccx(JS_CALLER, cx);
if (!ccx.IsValid()) {
return ThrowException(NS_ERROR_FAILURE, cx);
}
XPCWrappedNative *wn =
XPCWrappedNative::GetWrappedNativeOfJSObject(cx, wrappedObj);
return XPCWrapper::NativeToString(cx, wn, argc, argv, rval, JS_FALSE);
}
JSBool
XPC_COW_WrapObject(JSContext *cx, JSObject *parent, jsval v, jsval *vp)
{
JSObject *wrapperObj =
JS_NewObjectWithGivenProto(cx, &sXPC_COW_JSClass.base, NULL, parent);
if (!wrapperObj) {
return JS_FALSE;
}
*vp = OBJECT_TO_JSVAL(wrapperObj);
if (!JS_SetReservedSlot(cx, wrapperObj, XPCWrapper::sWrappedObjSlot, v) ||
!JS_SetReservedSlot(cx, wrapperObj, XPCWrapper::sFlagsSlot,
JSVAL_ZERO)) {
return JS_FALSE;
}
return JS_TRUE;
}

View File

@ -111,6 +111,7 @@ XPC_XOW_ClassNeedsXOW(const char *name)
return JS_FALSE;
}
extern JSExtendedClass sXPC_COW_JSClass;
extern JSExtendedClass sXPC_SJOW_JSClass;
extern JSExtendedClass sXPC_SOW_JSClass;
extern JSExtendedClass sXPC_XOW_JSClass;
@ -377,7 +378,6 @@ public:
uintN argc, jsval *argv, jsval *rval,
JSBool isNativeWrapper);
private:
/**
* Looks up a property on obj. If it exists, then the parameters are filled
* in with useful values.

View File

@ -1200,7 +1200,8 @@ nsXPConnect::WrapNative(JSContext * aJSContext,
NS_ASSERTION(aHolder, "bad param");
jsval v;
return WrapNativeToJSVal(aJSContext, aScope, aCOMObj, &aIID, &v, aHolder);
return WrapNativeToJSVal(aJSContext, aScope, aCOMObj, &aIID, PR_FALSE,
&v, aHolder);
}
/* void wrapNativeToJSVal (in JSContextPtr aJSContext, in JSObjectPtr aScope, in nsISupports aCOMObj, in nsIIDPtr aIID, out JSVal aVal, out nsIXPConnectJSObjectHolder aHolder); */
@ -1209,6 +1210,7 @@ nsXPConnect::WrapNativeToJSVal(JSContext * aJSContext,
JSObject * aScope,
nsISupports *aCOMObj,
const nsIID * aIID,
PRBool aAllowWrapping,
jsval *aVal,
nsIXPConnectJSObjectHolder **aHolder)
{
@ -1225,7 +1227,7 @@ nsXPConnect::WrapNativeToJSVal(JSContext * aJSContext,
nsresult rv;
if(!XPCConvert::NativeInterface2JSObject(ccx, aVal, aHolder, aCOMObj, aIID,
nsnull, nsnull, aScope, PR_FALSE,
nsnull, nsnull, aScope, aAllowWrapping,
OBJ_IS_NOT_GLOBAL, &rv))
return rv;
@ -1949,6 +1951,17 @@ nsXPConnect::GetXOWForObject(JSContext * aJSContext,
? NS_OK : NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsXPConnect::GetCOWForObject(JSContext * aJSContext,
JSObject * aParent,
JSObject * aWrappedObj,
jsval * rval)
{
*rval = OBJECT_TO_JSVAL(aWrappedObj);
return XPC_COW_WrapObject(aJSContext, aParent, *rval, rval)
? NS_OK : NS_ERROR_FAILURE;
}
static inline PRBool
PerformOp(JSContext *cx, PRUint32 aWay, JSObject *obj)
{

View File

@ -1320,14 +1320,15 @@ XPCConvert::NativeInterface2JSObject(XPCCallContext& ccx,
CreateHolderIfNeeded(ccx, JSVAL_TO_OBJECT(v), d, dest);
}
if(allowNativeWrapper && wrapper->NeedsChromeWrapper())
*d = v;
if(allowNativeWrapper)
{
if(!XPC_SOW_WrapObject(ccx, xpcscope->GetGlobalJSObject(), v, d))
return JS_FALSE;
}
else
{
*d = v;
if(wrapper->NeedsChromeWrapper())
if(!XPC_SOW_WrapObject(ccx, xpcscope->GetGlobalJSObject(), v, d))
return JS_FALSE;
if(wrapper->IsDoubleWrapper())
if(!XPC_COW_WrapObject(ccx, xpcscope->GetGlobalJSObject(), v, d))
return JS_FALSE;
}
if(dest)
*dest = strongWrapper.forget().get();

View File

@ -61,7 +61,8 @@ const char* XPCJSRuntime::mStrings[] = {
"createInstance", // IDX_CREATE_INSTANCE
"item", // IDX_ITEM
"__proto__", // IDX_PROTO
"__iterator__" // IDX_ITERATOR
"__iterator__", // IDX_ITERATOR
"__parent__" // IDX_PARENT
#ifdef XPC_IDISPATCH_SUPPORT
, "GeckoActiveXObject" // IDX_ACTIVEX_OBJECT
, "COMObject" // IDX_COMOBJECT

View File

@ -688,6 +688,7 @@ public:
IDX_ITEM ,
IDX_PROTO ,
IDX_ITERATOR ,
IDX_PARENT ,
#ifdef XPC_IDISPATCH_SUPPORT
IDX_ACTIVEX_OBJECT ,
IDX_COM_OBJECT ,
@ -2381,16 +2382,20 @@ public:
JSBool HasExternalReference() const {return mRefCnt > 1;}
JSBool NeedsChromeWrapper() { return !!(mWrapper & 1); }
void SetNeedsChromeWrapper() { mWrapper |= 1; }
JSBool NeedsChromeWrapper() { return !!(mWrapperWord & CHROME_ONLY); }
void SetNeedsChromeWrapper() { mWrapperWord |= CHROME_ONLY; }
JSBool IsDoubleWrapper() { return !!(mWrapperWord & DOUBLE_WRAPPER); }
void SetIsDoubleWrapper() { mWrapperWord |= DOUBLE_WRAPPER; }
JSObject* GetWrapper()
{
return (JSObject *)(mWrapper & ~1);
return (JSObject *) JSVAL_CLRTAG(mWrapperWord);
}
void SetWrapper(JSObject *obj)
{
JSBool reset = NeedsChromeWrapper();
mWrapper = PRWord(obj) | reset;
JSBool needsChrome = NeedsChromeWrapper();
JSBool doubleWrapper = IsDoubleWrapper();
mWrapperWord = PRWord(obj) | doubleWrapper | needsChrome;
}
void NoteTearoffs(nsCycleCollectionTraversalCallback& cb);
@ -2426,6 +2431,8 @@ protected:
virtual ~XPCWrappedNative();
private:
enum { CHROME_ONLY = JS_BIT(0), DOUBLE_WRAPPER = JS_BIT(1) };
void TraceOtherWrapper(JSTracer* trc);
JSBool Init(XPCCallContext& ccx, JSObject* parent, JSBool isGlobal,
const XPCNativeScriptableCreateInfo* sci);
@ -2457,7 +2464,7 @@ private:
JSObject* mFlatJSObject;
XPCNativeScriptableInfo* mScriptableInfo;
XPCWrappedNativeTearOffChunk mFirstChunk;
PRWord mWrapper;
PRWord mWrapperWord;
#ifdef XPC_CHECK_WRAPPER_THREADSAFETY
public:
@ -4088,6 +4095,8 @@ XPC_XOW_WrapObject(JSContext *cx, JSObject *parent, jsval *vp,
JSBool
XPC_SOW_WrapObject(JSContext *cx, JSObject *parent, jsval v,
jsval *vp);
JSBool
XPC_COW_WrapObject(JSContext *cx, JSObject *parent, jsval v, jsval *vp);
#ifdef XPC_IDISPATCH_SUPPORT
// IDispatch specific classes

View File

@ -420,6 +420,7 @@ XPCWrappedNative::GetNewOrUsed(XPCCallContext& ccx,
XPCMarkableJSVal newParentVal_markable(&newParentVal);
AutoMarkingJSVal newParentVal_automarker(ccx, &newParentVal_markable);
JSBool chromeOnly = JS_FALSE;
JSBool crossDoubleWrapped = JS_FALSE;
if(sciWrapper.GetFlags().WantPreCreate())
{
@ -477,6 +478,21 @@ XPCWrappedNative::GetNewOrUsed(XPCCallContext& ccx,
return NS_OK;
}
}
else
{
if(nsXPCWrappedJSClass::IsWrappedJS(Object))
{
nsCOMPtr<nsIXPConnectWrappedJS> wrappedjs(do_QueryInterface(Object));
JSObject *obj;
wrappedjs->GetJSObject(&obj);
if((STOBJ_IS_SYSTEM(obj) ||
STOBJ_IS_SYSTEM(JS_GetGlobalForObject(ccx, obj))) &&
!STOBJ_IS_SYSTEM(Scope->GetGlobalJSObject()))
{
crossDoubleWrapped = JS_TRUE;
}
}
}
AutoMarkingWrappedNativeProtoPtr proto(ccx);
@ -540,7 +556,8 @@ XPCWrappedNative::GetNewOrUsed(XPCCallContext& ccx,
if(chromeOnly)
wrapper->SetNeedsChromeWrapper();
if(crossDoubleWrapped)
wrapper->SetIsDoubleWrapper();
#if DEBUG_xpc_leaks
{
@ -705,7 +722,7 @@ XPCWrappedNative::XPCWrappedNative(already_AddRefed<nsISupports> aIdentity,
mSet(aProto->GetSet()),
mFlatJSObject((JSObject*)JSVAL_ONE), // non-null to pass IsValid() test
mScriptableInfo(nsnull),
mWrapper(nsnull)
mWrapperWord(0)
{
mIdentity = aIdentity.get();
@ -724,7 +741,7 @@ XPCWrappedNative::XPCWrappedNative(already_AddRefed<nsISupports> aIdentity,
mSet(aSet),
mFlatJSObject((JSObject*)JSVAL_ONE), // non-null to pass IsValid() test
mScriptableInfo(nsnull),
mWrapper(nsnull)
mWrapperWord(0)
{
mIdentity = aIdentity.get();