mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 475864 - Move native anonymous content checks into a wrapper so that quickstubs don't sidestep them. r=jst sr=bzbarsky
This commit is contained in:
parent
7b5c2380ff
commit
54734b9d0b
@ -250,11 +250,6 @@ public:
|
||||
return !!(GetFlags() & nsIClassInfo::DOM_OBJECT);
|
||||
}
|
||||
|
||||
PRBool IsContentNode()
|
||||
{
|
||||
return !!(GetFlags() & nsIClassInfo::CONTENT_NODE);
|
||||
}
|
||||
|
||||
const char* GetName()
|
||||
{
|
||||
if (!mName) {
|
||||
@ -744,15 +739,6 @@ nsScriptSecurityManager::CheckPropertyAccessImpl(PRUint32 aAction,
|
||||
rv = NS_OK;
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv) && classInfoData.IsContentNode())
|
||||
{
|
||||
// No access to anonymous content from the web! (bug 164086)
|
||||
nsIContent *content = static_cast<nsIContent*>(aObj);
|
||||
if (content->IsInNativeAnonymousSubtree()) {
|
||||
rv = NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
#ifdef DEBUG_CAPS_CheckPropertyAccessImpl
|
||||
|
@ -173,29 +173,6 @@ public:
|
||||
*/
|
||||
virtual nsIContent* FindFirstNonNativeAnonymous() const;
|
||||
|
||||
/**
|
||||
* Returns PR_TRUE if |this| or any of its ancestors is native anonymous.
|
||||
*/
|
||||
PRBool IsInNativeAnonymousSubtree() const
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (HasFlag(NODE_IS_IN_ANONYMOUS_SUBTREE)) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
nsIContent* content = GetBindingParent();
|
||||
while (content) {
|
||||
if (content->IsRootOfNativeAnonymousSubtree()) {
|
||||
NS_ERROR("Element not marked to be in native anonymous subtree!");
|
||||
break;
|
||||
}
|
||||
content = content->GetBindingParent();
|
||||
}
|
||||
return PR_FALSE;
|
||||
#else
|
||||
return HasFlag(NODE_IS_IN_ANONYMOUS_SUBTREE);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if and only if this node has a parent, but is not in
|
||||
* its parent's child list.
|
||||
|
@ -770,6 +770,22 @@ public:
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns PR_TRUE if |this| or any of its ancestors is native anonymous.
|
||||
*/
|
||||
PRBool IsInNativeAnonymousSubtree() const
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (HasFlag(NODE_IS_IN_ANONYMOUS_SUBTREE)) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
CheckNotNativeAnonymous();
|
||||
return PR_FALSE;
|
||||
#else
|
||||
return HasFlag(NODE_IS_IN_ANONYMOUS_SUBTREE);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the root content of an editor. So, this node must be a descendant of
|
||||
* an editor. Note that this should be only used for getting input or textarea
|
||||
@ -892,6 +908,12 @@ protected:
|
||||
return IsEditableInternal();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
// Note: virtual so that IsInNativeAnonymousSubtree can be called accross
|
||||
// module boundaries.
|
||||
virtual void CheckNotNativeAnonymous() const;
|
||||
#endif
|
||||
|
||||
nsresult GetParentNode(nsIDOMNode** aParentNode);
|
||||
nsresult GetChildNodes(nsIDOMNodeList** aChildNodes);
|
||||
nsresult GetFirstChild(nsIDOMNode** aFirstChild);
|
||||
|
@ -1,4 +1,5 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 sw=2 et tw=79: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
@ -446,6 +447,23 @@ nsINode::GetChildNodesList()
|
||||
return slots->mChildNodes;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void
|
||||
nsINode::CheckNotNativeAnonymous() const
|
||||
{
|
||||
if (!IsNodeOfType(eCONTENT))
|
||||
return;
|
||||
nsIContent* content = static_cast<const nsIContent *>(this)->GetBindingParent();
|
||||
while (content) {
|
||||
if (content->IsRootOfNativeAnonymousSubtree()) {
|
||||
NS_ERROR("Element not marked to be in native anonymous subtree!");
|
||||
break;
|
||||
}
|
||||
content = content->GetBindingParent();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
nsresult
|
||||
nsINode::GetParentNode(nsIDOMNode** aParentNode)
|
||||
{
|
||||
|
@ -6922,7 +6922,8 @@ nsNodeSH::PreCreate(nsISupports *nativeObj, JSContext *cx, JSObject *globalObj,
|
||||
|
||||
*parentObj = globalObj;
|
||||
|
||||
return NS_OK;
|
||||
return node->IsInNativeAnonymousSubtree() ?
|
||||
NS_SUCCESS_CHROME_ACCESS_ONLY : NS_OK;
|
||||
}
|
||||
|
||||
// If we have a document, make sure one of these is true
|
||||
@ -6983,7 +6984,8 @@ nsNodeSH::PreCreate(nsISupports *nativeObj, JSContext *cx, JSObject *globalObj,
|
||||
|
||||
*parentObj = globalObj;
|
||||
|
||||
return NS_OK;
|
||||
return node->IsInNativeAnonymousSubtree() ?
|
||||
NS_SUCCESS_CHROME_ACCESS_ONLY : NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
@ -6997,7 +6999,8 @@ nsNodeSH::PreCreate(nsISupports *nativeObj, JSContext *cx, JSObject *globalObj,
|
||||
(wrapper = static_cast<nsIXPConnectJSObjectHolder*>(doc->GetWrapper()))) {
|
||||
wrapper->GetJSObject(parentObj);
|
||||
if(*parentObj) {
|
||||
return NS_OK;
|
||||
return node->IsInNativeAnonymousSubtree() ?
|
||||
NS_SUCCESS_CHROME_ACCESS_ONLY : NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
@ -7005,10 +7008,12 @@ nsNodeSH::PreCreate(nsISupports *nativeObj, JSContext *cx, JSObject *globalObj,
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
|
||||
nsresult rv = WrapNative(cx, globalObj, native_parent, &v,
|
||||
getter_AddRefs(holder));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
*parentObj = JSVAL_TO_OBJECT(v);
|
||||
|
||||
return rv;
|
||||
return node->IsInNativeAnonymousSubtree() ?
|
||||
NS_SUCCESS_CHROME_ACCESS_ONLY : NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -46,6 +46,8 @@
|
||||
%{ C++
|
||||
#define NS_SUCCESS_I_DID_SOMETHING \
|
||||
(NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_XPCONNECT,1))
|
||||
#define NS_SUCCESS_CHROME_ACCESS_ONLY \
|
||||
(NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_XPCONNECT,2))
|
||||
%}
|
||||
|
||||
/**
|
||||
|
@ -791,6 +791,8 @@ interface nsIXPConnect : nsISupports
|
||||
* XPCCrossOriginWrapper for the given object based on the principal, scope,
|
||||
* and filename flags that are passed in.
|
||||
*
|
||||
* Note: In C++, the out jsval parameter must already be a strong GC root.
|
||||
*
|
||||
* @param aJSContext
|
||||
* A JSContext.
|
||||
* @param aObject
|
||||
|
@ -109,6 +109,7 @@ CPPSRCS = \
|
||||
xpcJSWeakReference.cpp \
|
||||
XPCSafeJSObjectWrapper.cpp \
|
||||
XPCCrossOriginWrapper.cpp \
|
||||
XPCSystemOnlyWrapper.cpp \
|
||||
XPCWrapper.cpp \
|
||||
xpcquickstubs.cpp \
|
||||
dom_quickstubs.cpp \
|
||||
|
@ -164,21 +164,7 @@ static inline
|
||||
JSObject *
|
||||
GetWrappedObject(JSContext *cx, JSObject *wrapper)
|
||||
{
|
||||
if (STOBJ_GET_CLASS(wrapper) != &sXPC_XOW_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);
|
||||
return XPCWrapper::UnwrapGeneric(cx, &sXPC_XOW_JSClass, wrapper);
|
||||
}
|
||||
|
||||
JSBool
|
||||
@ -343,7 +329,8 @@ XPC_XOW_FunctionWrapper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
|
||||
JSObject *funObj = JSVAL_TO_OBJECT(argv[-2]);
|
||||
jsval funToCall;
|
||||
if (!JS_GetReservedSlot(cx, funObj, 0, &funToCall)) {
|
||||
if (!JS_GetReservedSlot(cx, funObj, XPCWrapper::eWrappedFunctionSlot,
|
||||
&funToCall)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
@ -433,8 +420,10 @@ XPC_XOW_WrapFunction(JSContext *cx, JSObject *outerObj, JSObject *funobj,
|
||||
JSObject *funWrapperObj = JS_GetFunctionObject(funWrapper);
|
||||
*rval = OBJECT_TO_JSVAL(funWrapperObj);
|
||||
|
||||
if (!JS_SetReservedSlot(cx, funWrapperObj, XPCWrapper::eXOWWrappedFunctionSlot, funobjVal) ||
|
||||
!JS_SetReservedSlot(cx, funWrapperObj, XPCWrapper::eAllAccessSlot, JSVAL_FALSE)) {
|
||||
if (!JS_SetReservedSlot(cx, funWrapperObj, XPCWrapper::eWrappedFunctionSlot,
|
||||
funobjVal) ||
|
||||
!JS_SetReservedSlot(cx, funWrapperObj, XPCWrapper::eAllAccessSlot,
|
||||
JSVAL_FALSE)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
@ -535,8 +524,8 @@ XPC_XOW_WrapObject(JSContext *cx, JSObject *parent, jsval *vp,
|
||||
}
|
||||
|
||||
if (!JS_SetReservedSlot(cx, outerObj, XPCWrapper::sWrappedObjSlot, *vp) ||
|
||||
!JS_SetReservedSlot(cx, outerObj, XPCWrapper::sResolvingSlot,
|
||||
JSVAL_FALSE) ||
|
||||
!JS_SetReservedSlot(cx, outerObj, XPCWrapper::sFlagsSlot,
|
||||
JSVAL_ZERO) ||
|
||||
!JS_SetReservedSlot(cx, outerObj, XPC_XOW_ScopeSlot,
|
||||
PRIVATE_TO_JSVAL(parentScope))) {
|
||||
return JS_FALSE;
|
||||
@ -557,11 +546,11 @@ XPC_XOW_AddProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
|
||||
obj = GetWrapper(obj);
|
||||
jsval resolving;
|
||||
if (!JS_GetReservedSlot(cx, obj, XPCWrapper::sResolvingSlot, &resolving)) {
|
||||
if (!JS_GetReservedSlot(cx, obj, XPCWrapper::sFlagsSlot, &resolving)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if (JSVAL_TO_BOOLEAN(resolving)) {
|
||||
if (HAS_FLAGS(resolving, FLAG_RESOLVING)) {
|
||||
// Allow us to define a property on ourselves.
|
||||
return JS_TRUE;
|
||||
}
|
||||
@ -586,7 +575,7 @@ XPC_XOW_AddProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
}
|
||||
|
||||
// Same origin, pass this request along.
|
||||
return XPCWrapper::AddProperty(cx, obj, wrappedObj, id, vp);
|
||||
return XPCWrapper::AddProperty(cx, obj, JS_TRUE, wrappedObj, id, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
@ -838,23 +827,26 @@ XPC_XOW_NewResolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
|
||||
|
||||
if (id == GetRTStringByIndex(cx, XPCJSRuntime::IDX_TO_STRING)) {
|
||||
jsval oldSlotVal;
|
||||
if (!::JS_GetReservedSlot(cx, obj, XPCWrapper::sResolvingSlot, &oldSlotVal) ||
|
||||
!::JS_SetReservedSlot(cx, obj, XPCWrapper::sResolvingSlot, JSVAL_TRUE)) {
|
||||
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_XOW_toString, 0, 0) != nsnull;
|
||||
|
||||
if (ok && (ok = ::JS_SetReservedSlot(cx, obj, XPCWrapper::sResolvingSlot,
|
||||
oldSlotVal))) {
|
||||
JS_SetReservedSlot(cx, obj, XPCWrapper::sFlagsSlot, oldSlotVal);
|
||||
|
||||
if (ok) {
|
||||
*objp = obj;
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
return XPCWrapper::NewResolve(cx, obj, wrappedObj, id, flags, objp);
|
||||
return XPCWrapper::NewResolve(cx, obj, JS_TRUE, wrappedObj, id, flags, objp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
@ -1131,8 +1123,8 @@ XPC_XOW_Iterator(JSContext *cx, JSObject *obj, JSBool keysonly)
|
||||
// Initialize our XOW.
|
||||
jsval v = OBJECT_TO_JSVAL(wrappedObj);
|
||||
if (!JS_SetReservedSlot(cx, wrapperIter, XPCWrapper::sWrappedObjSlot, v) ||
|
||||
!JS_SetReservedSlot(cx, wrapperIter, XPCWrapper::sResolvingSlot,
|
||||
JSVAL_FALSE) ||
|
||||
!JS_SetReservedSlot(cx, wrapperIter, XPCWrapper::sFlagsSlot,
|
||||
JSVAL_ZERO) ||
|
||||
!JS_SetReservedSlot(cx, wrapperIter, XPC_XOW_ScopeSlot,
|
||||
PRIVATE_TO_JSVAL(nsnull))) {
|
||||
return nsnull;
|
||||
|
@ -488,7 +488,7 @@ XPC_SJOW_AddProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
jsval isResolving;
|
||||
JSBool ok = ::JS_GetReservedSlot(cx, obj, XPC_SJOW_SLOT_IS_RESOLVING,
|
||||
&isResolving);
|
||||
if (!ok || JSVAL_TO_BOOLEAN(isResolving)) {
|
||||
if (!ok || HAS_FLAGS(isResolving, FLAG_RESOLVING)) {
|
||||
return ok;
|
||||
}
|
||||
|
||||
@ -503,7 +503,7 @@ XPC_SJOW_AddProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
return XPCWrapper::AddProperty(cx, obj, unsafeObj, id, vp);
|
||||
return XPCWrapper::AddProperty(cx, obj, JS_FALSE, unsafeObj, id, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
@ -678,7 +678,7 @@ XPC_SJOW_NewResolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
|
||||
XPC_SJOW_toString, 0, 0) != nsnull;
|
||||
}
|
||||
|
||||
return XPCWrapper::NewResolve(cx, obj, unsafeObj, id, flags, objp);
|
||||
return XPCWrapper::NewResolve(cx, obj, JS_FALSE, unsafeObj, id, flags, objp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
@ -956,7 +956,7 @@ XPC_SJOW_Construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
}
|
||||
|
||||
if (!::JS_SetReservedSlot(cx, wrapperObj, XPC_SJOW_SLOT_IS_RESOLVING,
|
||||
BOOLEAN_TO_JSVAL(JS_FALSE))) {
|
||||
JSVAL_ZERO)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
@ -1043,7 +1043,7 @@ XPC_SJOW_Iterator(JSContext *cx, JSObject *obj, JSBool keysonly)
|
||||
}
|
||||
|
||||
if (!::JS_SetReservedSlot(cx, wrapperIter, XPC_SJOW_SLOT_IS_RESOLVING,
|
||||
BOOLEAN_TO_JSVAL(JS_FALSE))) {
|
||||
JSVAL_ZERO)) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
|
638
js/src/xpconnect/src/XPCSystemOnlyWrapper.cpp
Normal file
638
js/src/xpconnect/src/XPCSystemOnlyWrapper.cpp
Normal file
@ -0,0 +1,638 @@
|
||||
/* -*- 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) 2009
|
||||
* 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 "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_SOW_AddProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
|
||||
|
||||
static JSBool
|
||||
XPC_SOW_DelProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
|
||||
|
||||
static JSBool
|
||||
XPC_SOW_GetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
|
||||
|
||||
static JSBool
|
||||
XPC_SOW_SetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
|
||||
|
||||
static JSBool
|
||||
XPC_SOW_Enumerate(JSContext *cx, JSObject *obj);
|
||||
|
||||
static JSBool
|
||||
XPC_SOW_NewResolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
|
||||
JSObject **objp);
|
||||
|
||||
static JSBool
|
||||
XPC_SOW_Convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp);
|
||||
|
||||
static JSBool
|
||||
XPC_SOW_CheckAccess(JSContext *cx, JSObject *obj, jsval id, JSAccessMode mode,
|
||||
jsval *vp);
|
||||
|
||||
static JSBool
|
||||
XPC_SOW_HasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp);
|
||||
|
||||
static JSBool
|
||||
XPC_SOW_Equality(JSContext *cx, JSObject *obj, jsval v, JSBool *bp);
|
||||
|
||||
static JSObject *
|
||||
XPC_SOW_Iterator(JSContext *cx, JSObject *obj, JSBool keysonly);
|
||||
|
||||
static JSObject *
|
||||
XPC_SOW_WrappedObject(JSContext *cx, JSObject *obj);
|
||||
|
||||
JSExtendedClass sXPC_SOW_JSClass = {
|
||||
// JSClass (JSExtendedClass.base) initialization
|
||||
{ "SystemOnlyWrapper",
|
||||
JSCLASS_NEW_RESOLVE | JSCLASS_IS_EXTENDED |
|
||||
JSCLASS_HAS_RESERVED_SLOTS(XPCWrapper::sNumSlots),
|
||||
XPC_SOW_AddProperty, XPC_SOW_DelProperty,
|
||||
XPC_SOW_GetProperty, XPC_SOW_SetProperty,
|
||||
XPC_SOW_Enumerate, (JSResolveOp)XPC_SOW_NewResolve,
|
||||
XPC_SOW_Convert, JS_FinalizeStub,
|
||||
nsnull, XPC_SOW_CheckAccess,
|
||||
nsnull, nsnull,
|
||||
nsnull, XPC_SOW_HasInstance,
|
||||
nsnull, nsnull
|
||||
},
|
||||
|
||||
// JSExtendedClass initialization
|
||||
XPC_SOW_Equality,
|
||||
nsnull, // outerObject
|
||||
nsnull, // innerObject
|
||||
XPC_SOW_Iterator,
|
||||
XPC_SOW_WrappedObject,
|
||||
JSCLASS_NO_RESERVED_MEMBERS
|
||||
};
|
||||
|
||||
static JSBool
|
||||
XPC_SOW_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.
|
||||
// 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) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
return xclasp->wrappedObject(cx, obj);
|
||||
}
|
||||
|
||||
// Get the (possibly non-existant) SOW off of an object
|
||||
static inline
|
||||
JSObject *
|
||||
GetWrapper(JSObject *obj)
|
||||
{
|
||||
while (STOBJ_GET_CLASS(obj) != &sXPC_SOW_JSClass.base) {
|
||||
obj = STOBJ_GET_PROTO(obj);
|
||||
if (!obj) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
static inline
|
||||
JSObject *
|
||||
GetWrappedObject(JSContext *cx, JSObject *wrapper)
|
||||
{
|
||||
return XPCWrapper::UnwrapGeneric(cx, &sXPC_SOW_JSClass, wrapper);
|
||||
}
|
||||
|
||||
JSBool
|
||||
AllowedToAct(JSContext *cx, jsval idval)
|
||||
{
|
||||
nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
|
||||
if (!ssm) {
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSStackFrame *fp;
|
||||
nsIPrincipal *principal = ssm->GetCxSubjectPrincipalAndFrame(cx, &fp);
|
||||
if (!principal) {
|
||||
return ThrowException(NS_ERROR_UNEXPECTED, cx);
|
||||
}
|
||||
|
||||
void *annotation = JS_GetFrameAnnotation(cx, fp);
|
||||
PRBool privileged;
|
||||
if (fp &&
|
||||
NS_SUCCEEDED(principal->IsCapabilityEnabled("UniversalXPConnect",
|
||||
annotation,
|
||||
&privileged)) &&
|
||||
privileged) {
|
||||
// UniversalXPConnect things are allowed to touch us.
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
// XXX HACK EWW! Allow chrome://global/ access to these things, even
|
||||
// if they've been cloned into less privileged contexts.
|
||||
static const char prefix[] = "chrome://global/";
|
||||
const char *filename = fp->script->filename;
|
||||
if (filename && !strncmp(filename, prefix, NS_ARRAY_LENGTH(prefix) - 1)) {
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
if (JSVAL_IS_VOID(idval)) {
|
||||
ThrowException(NS_ERROR_XPC_SECURITY_MANAGER_VETO, cx);
|
||||
} else {
|
||||
// TODO Localize me?
|
||||
JSString *str = JS_ValueToString(cx, idval);
|
||||
if (str) {
|
||||
JS_ReportError(cx, "Permission denied to access property '%hs' from a non-chrome context",
|
||||
JS_GetStringChars(str));
|
||||
}
|
||||
}
|
||||
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
XPC_SOW_FunctionWrapper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
{
|
||||
if (!AllowedToAct(cx, JSVAL_VOID)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
JSObject *wrappedObj;
|
||||
|
||||
// Allow 'this' to be either a SOW, in which case we unwrap it or something
|
||||
// that isn't a SOW. We disallow invalid SOWs that have no wrapped object.
|
||||
// We do this so that it's possible to use this function with .call on
|
||||
// related objects that are not system only.
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
return JS_CallFunctionValue(cx, wrappedObj, funToCall, argc, argv, rval);
|
||||
}
|
||||
|
||||
JSBool
|
||||
XPC_SOW_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_SOW_FunctionWrapper) {
|
||||
*rval = funobjVal;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSFunction *funWrapper =
|
||||
JS_NewFunction(cx, XPC_SOW_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);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
XPC_SOW_AddProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
{
|
||||
NS_ASSERTION(STOBJ_GET_CLASS(obj) == &sXPC_SOW_JSClass.base, "Wrong object");
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (!AllowedToAct(cx, id)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
JSObject *wrappedObj = GetWrappedObject(cx, obj);
|
||||
if (!wrappedObj) {
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
return XPCWrapper::AddProperty(cx, obj, JS_TRUE, wrappedObj, id, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
XPC_SOW_DelProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
{
|
||||
JSObject *wrappedObj = GetWrappedObject(cx, obj);
|
||||
if (!wrappedObj) {
|
||||
return ThrowException(NS_ERROR_ILLEGAL_VALUE, cx);
|
||||
}
|
||||
|
||||
if (!AllowedToAct(cx, id)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
return XPCWrapper::DelProperty(cx, wrappedObj, id, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
XPC_SOW_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);
|
||||
}
|
||||
|
||||
if (!AllowedToAct(cx, id)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
JSAutoTempValueRooter tvr(cx, 1, vp);
|
||||
|
||||
JSObject *wrappedObj = GetWrappedObject(cx, obj);
|
||||
if (!wrappedObj) {
|
||||
return ThrowException(NS_ERROR_ILLEGAL_VALUE, cx);
|
||||
}
|
||||
|
||||
if (isSet && id == GetRTStringByIndex(cx, XPCJSRuntime::IDX_PROTO)) {
|
||||
// No setting __proto__ on my object.
|
||||
return ThrowException(NS_ERROR_INVALID_ARG, cx); // XXX better error message
|
||||
}
|
||||
|
||||
jsid interned_id;
|
||||
if (!JS_ValueToId(cx, id, &interned_id)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
return isSet
|
||||
? JS_SetPropertyById(cx, wrappedObj, interned_id, vp)
|
||||
: JS_GetPropertyById(cx, wrappedObj, interned_id, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
XPC_SOW_GetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
{
|
||||
return XPC_SOW_GetOrSetProperty(cx, obj, id, vp, JS_FALSE);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
XPC_SOW_SetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
{
|
||||
return XPC_SOW_GetOrSetProperty(cx, obj, id, vp, JS_TRUE);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
XPC_SOW_Enumerate(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
obj = GetWrapper(obj);
|
||||
JSObject *wrappedObj = GetWrappedObject(cx, obj);
|
||||
if (!wrappedObj) {
|
||||
// Nothing to enumerate.
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
if (!AllowedToAct(cx, JSVAL_VOID)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
return XPCWrapper::Enumerate(cx, obj, wrappedObj);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
XPC_SOW_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;
|
||||
}
|
||||
|
||||
if (!AllowedToAct(cx, id)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
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_SOW_toString, 0, 0) != nsnull;
|
||||
|
||||
JS_SetReservedSlot(cx, obj, XPCWrapper::sFlagsSlot, oldSlotVal);
|
||||
|
||||
if (ok) {
|
||||
*objp = obj;
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
return XPCWrapper::NewResolve(cx, obj, JS_TRUE, wrappedObj, id, flags, objp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
XPC_SOW_Convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
|
||||
{
|
||||
if (!AllowedToAct(cx, JSVAL_VOID)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
// 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_SOW_toString(cx, obj, 0, nsnull, vp);
|
||||
}
|
||||
|
||||
*vp = OBJECT_TO_JSVAL(obj);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
return STOBJ_GET_CLASS(wrappedObj)->convert(cx, wrappedObj, type, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
XPC_SOW_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.
|
||||
|
||||
JSObject *wrappedObj = GetWrappedObject(cx, obj);
|
||||
if (!wrappedObj) {
|
||||
*vp = JSVAL_VOID;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
uintN junk;
|
||||
jsid id;
|
||||
return JS_ValueToId(cx, prop, &id) &&
|
||||
JS_CheckAccess(cx, wrappedObj, id, mode, vp, &junk);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
XPC_SOW_HasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
|
||||
{
|
||||
if (!AllowedToAct(cx, JSVAL_VOID)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
JSObject *iface = GetWrappedObject(cx, obj);
|
||||
if (!iface) {
|
||||
*bp = JS_FALSE;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSClass *clasp = STOBJ_GET_CLASS(iface);
|
||||
|
||||
*bp = JS_FALSE;
|
||||
if (!clasp->hasInstance) {
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
// Prematurely unwrap the left hand side. This isn't necessary, but could be
|
||||
// faster than waiting until XPCWrappedNative::GetWrappedNativeOfJSObject to
|
||||
// do it.
|
||||
if (!JSVAL_IS_PRIMITIVE(v)) {
|
||||
JSObject *test = JSVAL_TO_OBJECT(v);
|
||||
|
||||
// GetWrappedObject does a class check.
|
||||
test = GetWrappedObject(cx, test);
|
||||
if (test) {
|
||||
v = OBJECT_TO_JSVAL(test);
|
||||
}
|
||||
}
|
||||
|
||||
return clasp->hasInstance(cx, iface, v, bp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
XPC_SOW_Equality(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
|
||||
{
|
||||
// Delegate to our wrapped object.
|
||||
if (JSVAL_IS_PRIMITIVE(v)) {
|
||||
*bp = JS_FALSE;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
if (obj == JSVAL_TO_OBJECT(v)) {
|
||||
*bp = JS_TRUE;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSObject *lhs = GetWrappedObject(cx, obj);
|
||||
JSObject *rhs = GetWrappedJSObject(cx, JSVAL_TO_OBJECT(v));
|
||||
if (lhs == rhs) {
|
||||
*bp = JS_TRUE;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
if (lhs) {
|
||||
// Delegate to our wrapped object if we can.
|
||||
JSClass *clasp = STOBJ_GET_CLASS(lhs);
|
||||
if (clasp->flags & JSCLASS_IS_EXTENDED) {
|
||||
JSExtendedClass *xclasp = (JSExtendedClass *) clasp;
|
||||
// NB: JSExtendedClass.equality is a required field.
|
||||
return xclasp->equality(cx, lhs, OBJECT_TO_JSVAL(rhs), bp);
|
||||
}
|
||||
}
|
||||
|
||||
// We know rhs is non-null.
|
||||
JSClass *clasp = STOBJ_GET_CLASS(rhs);
|
||||
if (clasp->flags & JSCLASS_IS_EXTENDED) {
|
||||
JSExtendedClass *xclasp = (JSExtendedClass *) clasp;
|
||||
// NB: JSExtendedClass.equality is a required field.
|
||||
return xclasp->equality(cx, rhs, OBJECT_TO_JSVAL(lhs), bp);
|
||||
}
|
||||
|
||||
*bp = JS_FALSE;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSObject *
|
||||
XPC_SOW_Iterator(JSContext *cx, JSObject *obj, JSBool keysonly)
|
||||
{
|
||||
JSObject *wrappedObj = GetWrappedObject(cx, obj);
|
||||
if (!wrappedObj) {
|
||||
ThrowException(NS_ERROR_INVALID_ARG, cx);
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
JSObject *wrapperIter = JS_NewObject(cx, &sXPC_SOW_JSClass.base, nsnull,
|
||||
JS_GetGlobalForObject(cx, obj));
|
||||
if (!wrapperIter) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
JSAutoTempValueRooter tvr(cx, OBJECT_TO_JSVAL(wrapperIter));
|
||||
|
||||
// Initialize our SOW.
|
||||
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_SOW_WrappedObject(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
return GetWrappedObject(cx, obj);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
XPC_SOW_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
{
|
||||
if (!AllowedToAct(cx, JSVAL_VOID)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
XPCWrappedNative *wn =
|
||||
XPCWrappedNative::GetWrappedNativeOfJSObject(cx, wrappedObj);
|
||||
return XPCWrapper::NativeToString(cx, wn, argc, argv, rval, JS_FALSE);
|
||||
}
|
||||
|
||||
JSBool
|
||||
XPC_SOW_WrapObject(JSContext *cx, JSObject *parent, jsval v,
|
||||
jsval *vp)
|
||||
{
|
||||
JSObject *wrapperObj =
|
||||
JS_NewObjectWithGivenProto(cx, &sXPC_SOW_JSClass.base, NULL, parent);
|
||||
if (!wrapperObj) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
*vp = OBJECT_TO_JSVAL(wrapperObj);
|
||||
JSAutoTempValueRooter tvr(cx, *vp);
|
||||
|
||||
if (!JS_SetReservedSlot(cx, wrapperObj, XPCWrapper::sWrappedObjSlot, v) ||
|
||||
!JS_SetReservedSlot(cx, wrapperObj, XPCWrapper::sFlagsSlot,
|
||||
JSVAL_ZERO)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
@ -41,12 +41,13 @@
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "XPCWrapper.h"
|
||||
#include "XPCNativeWrapper.h"
|
||||
|
||||
const PRUint32
|
||||
XPCWrapper::sWrappedObjSlot = 1;
|
||||
|
||||
const PRUint32
|
||||
XPCWrapper::sResolvingSlot = 0;
|
||||
XPCWrapper::sFlagsSlot = 0;
|
||||
|
||||
const PRUint32
|
||||
XPCWrapper::sNumSlots = 2;
|
||||
@ -59,6 +60,44 @@ XPCWrapper::sSecMgrSetProp = nsIXPCSecurityManager::ACCESS_SET_PROPERTY;
|
||||
const PRUint32
|
||||
XPCWrapper::sSecMgrGetProp = nsIXPCSecurityManager::ACCESS_GET_PROPERTY;
|
||||
|
||||
// static
|
||||
JSObject *
|
||||
XPCWrapper::Unwrap(JSContext *cx, JSObject *wrapper)
|
||||
{
|
||||
JSClass *clasp = STOBJ_GET_CLASS(wrapper);
|
||||
if (clasp == &sXPC_XOW_JSClass.base) {
|
||||
return UnwrapXOW(cx, wrapper);
|
||||
}
|
||||
|
||||
if (XPCNativeWrapper::IsNativeWrapperClass(clasp)) {
|
||||
XPCWrappedNative *wrappedObj;
|
||||
if (!XPCNativeWrapper::GetWrappedNative(cx, wrapper, &wrappedObj) ||
|
||||
!wrappedObj) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
return wrappedObj->GetFlatJSObject();
|
||||
}
|
||||
|
||||
if (clasp == &sXPC_SJOW_JSClass.base) {
|
||||
JSObject *wrappedObj = STOBJ_GET_PARENT(wrapper);
|
||||
|
||||
if (NS_FAILED(CanAccessWrapper(cx, wrappedObj))) {
|
||||
JS_ClearPendingException(cx);
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
return wrappedObj;
|
||||
}
|
||||
|
||||
if (clasp == &sXPC_SOW_JSClass.base) {
|
||||
return UnwrapSOW(cx, wrapper);
|
||||
}
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
static void
|
||||
IteratorFinalize(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
@ -197,18 +236,17 @@ XPCWrapper::CreateIteratorObj(JSContext *cx, JSObject *tempWrapper,
|
||||
// static
|
||||
JSBool
|
||||
XPCWrapper::AddProperty(JSContext *cx, JSObject *wrapperObj,
|
||||
JSObject *innerObj, jsval id, jsval *vp)
|
||||
JSBool wantGetterSetter, JSObject *innerObj, jsval id,
|
||||
jsval *vp)
|
||||
{
|
||||
jsid interned_id;
|
||||
if (!::JS_ValueToId(cx, id, &interned_id)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
JSBool isXOW = (STOBJ_GET_CLASS(wrapperObj) == &sXPC_XOW_JSClass.base);
|
||||
|
||||
JSPropertyDescriptor desc;
|
||||
if (!GetPropertyAttrs(cx, wrapperObj, interned_id, JSRESOLVE_QUALIFIED,
|
||||
isXOW, &desc)) {
|
||||
wantGetterSetter, &desc)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
@ -289,18 +327,16 @@ XPCWrapper::Enumerate(JSContext *cx, JSObject *wrapperObj, JSObject *innerObj)
|
||||
// static
|
||||
JSBool
|
||||
XPCWrapper::NewResolve(JSContext *cx, JSObject *wrapperObj,
|
||||
JSObject *innerObj, jsval id, uintN flags,
|
||||
JSObject **objp, JSBool preserveVal)
|
||||
JSBool wantDetails, JSObject *innerObj, jsval id,
|
||||
uintN flags, JSObject **objp)
|
||||
{
|
||||
jsid interned_id;
|
||||
if (!::JS_ValueToId(cx, id, &interned_id)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
JSBool isXOW = (STOBJ_GET_CLASS(wrapperObj) == &sXPC_XOW_JSClass.base);
|
||||
|
||||
JSPropertyDescriptor desc;
|
||||
if (!GetPropertyAttrs(cx, innerObj, interned_id, flags, isXOW, &desc)) {
|
||||
if (!GetPropertyAttrs(cx, innerObj, interned_id, flags, wantDetails, &desc)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
@ -309,21 +345,22 @@ XPCWrapper::NewResolve(JSContext *cx, JSObject *wrapperObj,
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
if (!preserveVal) {
|
||||
desc.value = JSVAL_VOID;
|
||||
}
|
||||
desc.value = JSVAL_VOID;
|
||||
|
||||
jsval oldSlotVal;
|
||||
if (!::JS_GetReservedSlot(cx, wrapperObj, sResolvingSlot, &oldSlotVal) ||
|
||||
!::JS_SetReservedSlot(cx, wrapperObj, sResolvingSlot, JSVAL_TRUE)) {
|
||||
jsval oldFlags;
|
||||
if (!::JS_GetReservedSlot(cx, wrapperObj, sFlagsSlot, &oldFlags) ||
|
||||
!::JS_SetReservedSlot(cx, wrapperObj, sFlagsSlot,
|
||||
INT_TO_JSVAL(JSVAL_TO_INT(oldFlags) |
|
||||
FLAG_RESOLVING))) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
JSBool ok = JS_DefinePropertyById(cx, wrapperObj, interned_id, desc.value,
|
||||
desc.getter, desc.setter, desc.attrs);
|
||||
|
||||
if (ok && (ok = ::JS_SetReservedSlot(cx, wrapperObj, sResolvingSlot,
|
||||
oldSlotVal))) {
|
||||
JS_SetReservedSlot(cx, wrapperObj, sFlagsSlot, oldFlags);
|
||||
|
||||
if (ok) {
|
||||
*objp = wrapperObj;
|
||||
}
|
||||
|
||||
@ -348,18 +385,11 @@ XPCWrapper::ResolveNativeProperty(JSContext *cx, JSObject *wrapperObj,
|
||||
// Mark ourselves as resolving so our AddProperty hook can do the
|
||||
// right thing here.
|
||||
jsval oldFlags;
|
||||
if (isNativeWrapper) {
|
||||
if (!::JS_GetReservedSlot(cx, wrapperObj, 0, &oldFlags) ||
|
||||
!::JS_SetReservedSlot(cx, wrapperObj, 0,
|
||||
INT_TO_JSVAL(JSVAL_TO_INT(oldFlags) |
|
||||
FLAG_RESOLVING))) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
} else {
|
||||
if (!::JS_GetReservedSlot(cx, wrapperObj, sResolvingSlot, &oldFlags) ||
|
||||
!::JS_SetReservedSlot(cx, wrapperObj, sResolvingSlot, JSVAL_TRUE)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
if (!::JS_GetReservedSlot(cx, wrapperObj, sFlagsSlot, &oldFlags) ||
|
||||
!::JS_SetReservedSlot(cx, wrapperObj, sFlagsSlot,
|
||||
INT_TO_JSVAL(JSVAL_TO_INT(oldFlags) |
|
||||
FLAG_RESOLVING))) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
XPCWrappedNative* oldResolvingWrapper = nsnull;
|
||||
@ -379,9 +409,7 @@ XPCWrapper::ResolveNativeProperty(JSContext *cx, JSObject *wrapperObj,
|
||||
ccx.SetResolvingWrapper(oldResolvingWrapper);
|
||||
}
|
||||
|
||||
if (!::JS_SetReservedSlot(cx, wrapperObj,
|
||||
isNativeWrapper ? 0 : sResolvingSlot,
|
||||
oldFlags)) {
|
||||
if (!::JS_SetReservedSlot(cx, wrapperObj, sFlagsSlot, oldFlags)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
@ -405,7 +433,13 @@ XPCWrapper::ResolveNativeProperty(JSContext *cx, JSObject *wrapperObj,
|
||||
return retval;
|
||||
}
|
||||
|
||||
return NewResolve(cx, wrapperObj, innerObj, id, flags, objp, JS_TRUE);
|
||||
// The scriptable helper resolved this property to a *different* object.
|
||||
// We don't know what to do for now (this can't currently happen in
|
||||
// Mozilla) so throw.
|
||||
// I suspect that we'd need to redo the security check on the new object
|
||||
// (if it has a different class than the original object) and then call
|
||||
// ResolveNativeProperty with *that* as the inner object.
|
||||
return ThrowException(NS_ERROR_NOT_IMPLEMENTED, cx);
|
||||
}
|
||||
}
|
||||
|
||||
@ -507,8 +541,10 @@ XPCWrapper::ResolveNativeProperty(JSContext *cx, JSObject *wrapperObj,
|
||||
// XPCNativeWrapper doesn't need to do this.
|
||||
jsval oldFlags;
|
||||
if (!isNativeWrapper &&
|
||||
(!::JS_GetReservedSlot(cx, wrapperObj, sResolvingSlot, &oldFlags) ||
|
||||
!::JS_SetReservedSlot(cx, wrapperObj, sResolvingSlot, JSVAL_TRUE))) {
|
||||
(!::JS_GetReservedSlot(cx, wrapperObj, sFlagsSlot, &oldFlags) ||
|
||||
!::JS_SetReservedSlot(cx, wrapperObj, sFlagsSlot,
|
||||
INT_TO_JSVAL(JSVAL_TO_INT(oldFlags) |
|
||||
FLAG_RESOLVING)))) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
@ -519,7 +555,7 @@ XPCWrapper::ResolveNativeProperty(JSContext *cx, JSObject *wrapperObj,
|
||||
}
|
||||
|
||||
if (!isNativeWrapper &&
|
||||
!::JS_SetReservedSlot(cx, wrapperObj, sResolvingSlot, oldFlags)) {
|
||||
!::JS_SetReservedSlot(cx, wrapperObj, sFlagsSlot, oldFlags)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
|
@ -81,6 +81,10 @@ XPC_XOW_WrapperMoved(JSContext *cx, XPCWrappedNative *innerObj,
|
||||
nsresult
|
||||
CanAccessWrapper(JSContext *cx, JSObject *wrappedObj);
|
||||
|
||||
// Used by UnwrapSOW below.
|
||||
JSBool
|
||||
AllowedToAct(JSContext *cx, jsval idval);
|
||||
|
||||
JSBool
|
||||
XPCNativeWrapperCtor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval);
|
||||
@ -107,8 +111,9 @@ XPC_XOW_ClassNeedsXOW(const char *name)
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
extern JSExtendedClass sXPC_XOW_JSClass;
|
||||
extern JSExtendedClass sXPC_SJOW_JSClass;
|
||||
extern JSExtendedClass sXPC_SOW_JSClass;
|
||||
extern JSExtendedClass sXPC_XOW_JSClass;
|
||||
|
||||
// This class wraps some common functionality between the three existing
|
||||
// wrappers. Its main purpose is to allow XPCCrossOriginWrapper to act both
|
||||
@ -125,11 +130,11 @@ public:
|
||||
static const PRUint32 sWrappedObjSlot;
|
||||
|
||||
/**
|
||||
* Used by the cross origin and safe wrappers: the slot that tells the
|
||||
* AddProperty code that we're resolving a property, and therefore to not do
|
||||
* a security check.
|
||||
* Used by all wrappers to store flags about their state. For example,
|
||||
* it is used when resolving a property to tell to the addProperty hook
|
||||
* that it shouldn't perform any security checks.
|
||||
*/
|
||||
static const PRUint32 sResolvingSlot;
|
||||
static const PRUint32 sFlagsSlot;
|
||||
|
||||
/**
|
||||
* The base number of slots needed by code using the above constants.
|
||||
@ -143,7 +148,7 @@ public:
|
||||
static JSNative sEvalNative;
|
||||
|
||||
typedef enum FunctionObjectSlot {
|
||||
eXOWWrappedFunctionSlot = 0,
|
||||
eWrappedFunctionSlot = 0,
|
||||
eAllAccessSlot = 1
|
||||
};
|
||||
|
||||
@ -214,10 +219,24 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* Unwraps a XPCCrossOriginWrapper into its wrapped native.
|
||||
* Given an arbitrary object, Unwrap will return the wrapped object if the
|
||||
* passed-in object is a wrapper that Unwrap knows about *and* the
|
||||
* currently running code has permission to access both the wrapper and
|
||||
* wrapped object.
|
||||
*
|
||||
* Since this is meant to be called from functions like
|
||||
* XPCWrappedNative::GetWrappedNativeOfJSObject, it does not set an
|
||||
* exception on |cx|.
|
||||
*/
|
||||
static JSObject *Unwrap(JSContext *cx, JSObject *wrapper) {
|
||||
if (STOBJ_GET_CLASS(wrapper) != &sXPC_XOW_JSClass.base) {
|
||||
static JSObject *Unwrap(JSContext *cx, JSObject *wrapper);
|
||||
|
||||
/**
|
||||
* Unwraps objects whose class is |xclasp|.
|
||||
*/
|
||||
static JSObject *UnwrapGeneric(JSContext *cx, const JSExtendedClass *xclasp,
|
||||
JSObject *wrapper)
|
||||
{
|
||||
if (STOBJ_GET_CLASS(wrapper) != &xclasp->base) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
@ -231,14 +250,39 @@ public:
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
JSObject *wrappedObj = JSVAL_TO_OBJECT(v);
|
||||
nsresult rv = CanAccessWrapper(cx, wrappedObj);
|
||||
if (NS_FAILED(rv)) {
|
||||
JS_ClearPendingException(cx);
|
||||
return JSVAL_TO_OBJECT(v);
|
||||
}
|
||||
|
||||
static JSObject *UnwrapSOW(JSContext *cx, JSObject *wrapper) {
|
||||
wrapper = UnwrapGeneric(cx, &sXPC_SOW_JSClass, wrapper);
|
||||
if (!wrapper) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
return wrappedObj;
|
||||
if (!AllowedToAct(cx, JSVAL_VOID)) {
|
||||
JS_ClearPendingException(cx);
|
||||
wrapper = nsnull;
|
||||
}
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unwraps a XOW into its wrapped native.
|
||||
*/
|
||||
static JSObject *UnwrapXOW(JSContext *cx, JSObject *wrapper) {
|
||||
wrapper = UnwrapGeneric(cx, &sXPC_XOW_JSClass, wrapper);
|
||||
if (!wrapper) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsresult rv = CanAccessWrapper(cx, wrapper);
|
||||
if (NS_FAILED(rv)) {
|
||||
JS_ClearPendingException(cx);
|
||||
wrapper = nsnull;
|
||||
}
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -283,7 +327,8 @@ public:
|
||||
* Called for the common part of adding a property to obj.
|
||||
*/
|
||||
static JSBool AddProperty(JSContext *cx, JSObject *wrapperObj,
|
||||
JSObject *innerObj, jsval id, jsval *vp);
|
||||
JSBool wantGetterSetter, JSObject *innerObj,
|
||||
jsval id, jsval *vp);
|
||||
|
||||
/**
|
||||
* Called for the common part of deleting a property from obj.
|
||||
@ -302,8 +347,8 @@ public:
|
||||
* and is therefore unsuitable for cross-origin resolution.
|
||||
*/
|
||||
static JSBool NewResolve(JSContext *cx, JSObject *wrapperObj,
|
||||
JSObject *innerObj, jsval id, uintN flags,
|
||||
JSObject **objp, JSBool preserveVal = JS_FALSE);
|
||||
JSBool preserveVal, JSObject *innerObj,
|
||||
jsval id, uintN flags, JSObject **objp);
|
||||
|
||||
/**
|
||||
* Resolve a native property named id from innerObj onto wrapperObj. The
|
||||
|
@ -2406,6 +2406,9 @@ nsXPConnect::GetWrapperForObject(JSContext* aJSContext,
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
*_retval = OBJECT_TO_JSVAL(wrappedObj);
|
||||
if(wrapper->NeedsChromeWrapper() &&
|
||||
!XPC_SOW_WrapObject(aJSContext, aScope, *_retval, _retval))
|
||||
return NS_ERROR_FAILURE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1281,8 +1281,23 @@ XPCConvert::NativeInterface2JSObject(XPCCallContext& ccx,
|
||||
}
|
||||
|
||||
if(triedWrapping)
|
||||
return destObj &&
|
||||
CreateHolderIfNeeded(ccx, destObj, d, dest);
|
||||
{
|
||||
if(!destObj)
|
||||
return JS_FALSE;
|
||||
|
||||
jsval wrappedObjVal = OBJECT_TO_JSVAL(destObj);
|
||||
AUTO_MARK_JSVAL(ccx, &wrappedObjVal);
|
||||
if(wrapper->NeedsChromeWrapper())
|
||||
{
|
||||
if(!XPC_SOW_WrapObject(ccx, xpcscope->GetGlobalJSObject(),
|
||||
OBJECT_TO_JSVAL(destObj),
|
||||
&wrappedObjVal))
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
return CreateHolderIfNeeded(ccx, JSVAL_TO_OBJECT(wrappedObjVal),
|
||||
d, dest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1297,11 +1312,23 @@ XPCConvert::NativeInterface2JSObject(XPCCallContext& ccx,
|
||||
if(!strongWrapper)
|
||||
strongWrapper = wrapper;
|
||||
|
||||
AUTO_MARK_JSVAL(ccx, &v);
|
||||
return XPC_XOW_WrapObject(ccx, scope, &v) &&
|
||||
(!wrapper->NeedsChromeWrapper() ||
|
||||
XPC_SOW_WrapObject(ccx, xpcscope->GetGlobalJSObject(),
|
||||
v, &v)) &&
|
||||
CreateHolderIfNeeded(ccx, JSVAL_TO_OBJECT(v), d, dest);
|
||||
}
|
||||
|
||||
*d = v;
|
||||
if(allowNativeWrapper && wrapper->NeedsChromeWrapper())
|
||||
{
|
||||
if(!XPC_SOW_WrapObject(ccx, xpcscope->GetGlobalJSObject(), v, d))
|
||||
return JS_FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
*d = v;
|
||||
}
|
||||
if(dest)
|
||||
*dest = strongWrapper.forget().get();
|
||||
return JS_TRUE;
|
||||
|
@ -2346,8 +2346,9 @@ public:
|
||||
if(mScriptableInfo && JS_IsGCMarkingTracer(trc))
|
||||
mScriptableInfo->Mark();
|
||||
if(HasProto()) GetProto()->TraceJS(trc);
|
||||
if(mWrapper)
|
||||
JS_CALL_OBJECT_TRACER(trc, mWrapper, "XPCWrappedNative::mWrapper");
|
||||
JSObject* wrapper = GetWrapper();
|
||||
if(wrapper)
|
||||
JS_CALL_OBJECT_TRACER(trc, wrapper, "XPCWrappedNative::mWrapper");
|
||||
TraceOtherWrapper(trc);
|
||||
}
|
||||
|
||||
@ -2387,8 +2388,17 @@ public:
|
||||
|
||||
JSBool HasExternalReference() const {return mRefCnt > 1;}
|
||||
|
||||
JSObject* GetWrapper() { return mWrapper; }
|
||||
void SetWrapper(JSObject *obj) { mWrapper = obj; }
|
||||
JSBool NeedsChromeWrapper() { return !!(mWrapper & 1); }
|
||||
void SetNeedsChromeWrapper() { mWrapper |= 1; }
|
||||
JSObject* GetWrapper()
|
||||
{
|
||||
return (JSObject *)(mWrapper & ~1);
|
||||
}
|
||||
void SetWrapper(JSObject *obj)
|
||||
{
|
||||
JSBool reset = NeedsChromeWrapper();
|
||||
mWrapper = PRWord(obj) | reset;
|
||||
}
|
||||
|
||||
void NoteTearoffs(nsCycleCollectionTraversalCallback& cb);
|
||||
|
||||
@ -2454,7 +2464,7 @@ private:
|
||||
JSObject* mFlatJSObject;
|
||||
XPCNativeScriptableInfo* mScriptableInfo;
|
||||
XPCWrappedNativeTearOffChunk mFirstChunk;
|
||||
JSObject* mWrapper;
|
||||
PRWord mWrapper;
|
||||
|
||||
#ifdef XPC_CHECK_WRAPPER_THREADSAFETY
|
||||
public:
|
||||
@ -4082,6 +4092,10 @@ JSBool
|
||||
XPC_XOW_WrapObject(JSContext *cx, JSObject *parent, jsval *vp,
|
||||
XPCWrappedNative *wn = nsnull);
|
||||
|
||||
JSBool
|
||||
XPC_SOW_WrapObject(JSContext *cx, JSObject *parent, jsval v,
|
||||
jsval *vp);
|
||||
|
||||
#ifdef XPC_IDISPATCH_SUPPORT
|
||||
// IDispatch specific classes
|
||||
#include "XPCDispPrivate.h"
|
||||
|
@ -829,7 +829,7 @@ xpc_qsUnwrapThisImpl(JSContext *cx,
|
||||
wrapper = (XPCWrappedNative*) xpc_GetJSPrivate(STOBJ_GET_PARENT(cur));
|
||||
NS_ASSERTION(wrapper, "XPCWN wrapping nothing");
|
||||
}
|
||||
else if(clazz == &sXPC_XOW_JSClass.base)
|
||||
else
|
||||
{
|
||||
JSObject *unsafeObj = XPCWrapper::Unwrap(cx, cur);
|
||||
if(unsafeObj)
|
||||
@ -842,21 +842,6 @@ xpc_qsUnwrapThisImpl(JSContext *cx,
|
||||
// XPCWrappedNative::GetWrappedNativeOfJSObject.
|
||||
goto next;
|
||||
}
|
||||
else if(XPCNativeWrapper::IsNativeWrapperClass(clazz))
|
||||
{
|
||||
if(!XPCNativeWrapper::GetWrappedNative(cx, cur, &wrapper) ||
|
||||
!wrapper)
|
||||
goto next;
|
||||
}
|
||||
else if(IsXPCSafeJSObjectWrapperClass(clazz))
|
||||
{
|
||||
cur = STOBJ_GET_PARENT(cur);
|
||||
NS_ASSERTION(cur, "SJOW wrapping nothing");
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
goto next;
|
||||
}
|
||||
|
||||
rv = getNativeFromWrapper(wrapper, iid, ppThis, pThisRef, vp);
|
||||
if(NS_SUCCEEDED(rv))
|
||||
|
@ -44,6 +44,7 @@
|
||||
#include "xpcprivate.h"
|
||||
#include "nsArrayEnumerator.h"
|
||||
#include "nsWrapperCache.h"
|
||||
#include "XPCWrapper.h"
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(nsXPCWrappedJSClass, nsIXPCWrappedJSClass)
|
||||
|
||||
@ -736,7 +737,12 @@ nsXPCWrappedJSClass::GetRootJSObject(XPCCallContext& ccx, JSObject* aJSObj)
|
||||
{
|
||||
JSObject* result = CallQueryInterfaceOnJSObject(ccx, aJSObj,
|
||||
NS_GET_IID(nsISupports));
|
||||
return result ? result : aJSObj;
|
||||
if(!result)
|
||||
return aJSObj;
|
||||
JSObject* inner = XPCWrapper::Unwrap(ccx, result);
|
||||
if (inner)
|
||||
return inner;
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -419,6 +419,7 @@ XPCWrappedNative::GetNewOrUsed(XPCCallContext& ccx,
|
||||
jsval newParentVal = JSVAL_NULL;
|
||||
XPCMarkableJSVal newParentVal_markable(&newParentVal);
|
||||
AutoMarkingJSVal newParentVal_automarker(ccx, &newParentVal_markable);
|
||||
JSBool chromeOnly = JS_FALSE;
|
||||
|
||||
if(sciWrapper.GetFlags().WantPreCreate())
|
||||
{
|
||||
@ -428,6 +429,9 @@ XPCWrappedNative::GetNewOrUsed(XPCCallContext& ccx,
|
||||
if(NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
chromeOnly = (rv == NS_SUCCESS_CHROME_ACCESS_ONLY);
|
||||
rv = NS_OK;
|
||||
|
||||
NS_ASSERTION(!XPCNativeWrapper::IsNativeWrapper(parent),
|
||||
"Parent should never be an XPCNativeWrapper here");
|
||||
|
||||
@ -519,7 +523,7 @@ XPCWrappedNative::GetNewOrUsed(XPCCallContext& ccx,
|
||||
|
||||
NS_ASSERTION(!XPCNativeWrapper::IsNativeWrapper(parent),
|
||||
"XPCNativeWrapper being used to parent XPCWrappedNative?");
|
||||
|
||||
|
||||
if(!wrapper->Init(ccx, parent, isGlobal, &sciWrapper))
|
||||
{
|
||||
NS_RELEASE(wrapper);
|
||||
@ -534,6 +538,10 @@ XPCWrappedNative::GetNewOrUsed(XPCCallContext& ccx,
|
||||
return rv;
|
||||
}
|
||||
|
||||
if(chromeOnly)
|
||||
wrapper->SetNeedsChromeWrapper();
|
||||
|
||||
|
||||
#if DEBUG_xpc_leaks
|
||||
{
|
||||
char* s = wrapper->ToString(ccx);
|
||||
@ -1491,23 +1499,9 @@ return_tearoff:
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
// Unwrap any XPCCrossOriginWrappers and SafeJSObjectWrappers.
|
||||
// Unwrap any wrapper wrappers.
|
||||
JSObject *unsafeObj;
|
||||
if(clazz == &sXPC_XOW_JSClass.base &&
|
||||
(unsafeObj = XPCWrapper::Unwrap(cx, cur)))
|
||||
return GetWrappedNativeOfJSObject(cx, unsafeObj, funobj, pobj2,
|
||||
pTearOff);
|
||||
|
||||
if(XPCNativeWrapper::IsNativeWrapperClass(clazz))
|
||||
{
|
||||
XPCWrappedNative* wrapper;
|
||||
if(XPCNativeWrapper::GetWrappedNative(cx, cur, &wrapper) && wrapper)
|
||||
return GetWrappedNativeOfJSObject(cx, wrapper->GetFlatJSObject(),
|
||||
funobj, pobj2, pTearOff);
|
||||
}
|
||||
|
||||
if(IsXPCSafeJSObjectWrapperClass(clazz) &&
|
||||
(unsafeObj = STOBJ_GET_PARENT(cur)))
|
||||
if((unsafeObj = XPCWrapper::Unwrap(cx, cur)))
|
||||
return GetWrappedNativeOfJSObject(cx, unsafeObj, funobj, pobj2,
|
||||
pTearOff);
|
||||
}
|
||||
@ -1526,7 +1520,7 @@ return_tearoff:
|
||||
JSObject *unsafeObj;
|
||||
clazz = STOBJ_GET_CLASS(outer);
|
||||
if(clazz == &sXPC_XOW_JSClass.base &&
|
||||
(unsafeObj = XPCWrapper::Unwrap(cx, outer)))
|
||||
(unsafeObj = XPCWrapper::UnwrapXOW(cx, outer)))
|
||||
{
|
||||
outer = unsafeObj;
|
||||
}
|
||||
|
@ -742,11 +742,14 @@ MochiKit.Base.update(MochiKit.Base, {
|
||||
}
|
||||
return MochiKit.Base.reprRegistry.match(o);
|
||||
} catch (e) {
|
||||
if (typeof(o.NAME) == 'string' && (
|
||||
o.toString == Function.prototype.toString ||
|
||||
o.toString == Object.prototype.toString
|
||||
)) {
|
||||
return o.NAME;
|
||||
try {
|
||||
if (typeof(o.NAME) == 'string' && (
|
||||
o.toString == Function.prototype.toString ||
|
||||
o.toString == Object.prototype.toString
|
||||
)) {
|
||||
return o.NAME;
|
||||
}
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
try {
|
||||
|
Loading…
Reference in New Issue
Block a user