Backout bug 658909 for Marionette bustage.

This commit is contained in:
Ms2ger 2013-03-17 10:44:33 +01:00
parent 5bc91d7db4
commit d8a7fada3c
23 changed files with 316 additions and 502 deletions

View File

@ -3196,8 +3196,8 @@ nsDOMClassInfo::ResolveConstructor(JSContext *cx, JSObject *obj,
// window.classname, just fall through and let the JS engine
// return the Object constructor.
if (!::JS_DefinePropertyById(cx, obj, sConstructor_id, val, JS_PropertyStub,
JS_StrictPropertyStub, JSPROP_ENUMERATE)) {
if (!::JS_DefinePropertyById(cx, obj, sConstructor_id, val, nullptr, nullptr,
JSPROP_ENUMERATE)) {
return NS_ERROR_UNEXPECTED;
}
@ -3757,7 +3757,7 @@ nsWindowSH::GlobalScopePolluterNewResolve(JSContext *cx, JSHandleObject obj,
NS_ENSURE_SUCCESS(rv, JS_FALSE);
if (!JS_WrapValue(cx, &v) ||
!JS_DefinePropertyById(cx, obj, id, v, JS_PropertyStub, JS_StrictPropertyStub, 0)) {
!JS_DefinePropertyById(cx, obj, id, v, nullptr, nullptr, 0)) {
return JS_FALSE;
}
@ -4099,8 +4099,7 @@ DefineInterfaceConstants(JSContext *cx, JSObject *obj, const nsIID *aIID)
}
}
if (!::JS_DefineProperty(cx, obj, c->GetName(), v,
JS_PropertyStub, JS_StrictPropertyStub,
if (!::JS_DefineProperty(cx, obj, c->GetName(), v, nullptr, nullptr,
JSPROP_ENUMERATE | JSPROP_READONLY |
JSPROP_PERMANENT)) {
return NS_ERROR_UNEXPECTED;
@ -4209,8 +4208,7 @@ IDBConstantGetter(JSContext *cx, JSHandleObject obj, JSHandleId id, JSMutableHan
if (!xpc::StringToJsval(cx, valStr, &value)) {
return JS_FALSE;
}
if (!::JS_DefineProperty(cx, obj, c.name, value,
JS_PropertyStub, JS_StrictPropertyStub,
if (!::JS_DefineProperty(cx, obj, c.name, value, nullptr, nullptr,
JSPROP_ENUMERATE)) {
return JS_FALSE;
}
@ -4244,7 +4242,7 @@ DefineIDBInterfaceConstants(JSContext *cx, JSObject *obj, const nsIID *aIID)
}
if (!JS_DefineProperty(cx, obj, c.name, JSVAL_VOID,
IDBConstantGetter, JS_StrictPropertyStub,
IDBConstantGetter, nullptr,
JSPROP_ENUMERATE)) {
return NS_ERROR_UNEXPECTED;
}
@ -4292,8 +4290,8 @@ public:
JSBool ok = JS_WrapValue(cx, &thisAsVal) &&
::JS_DefineUCProperty(cx, target,
reinterpret_cast<const jschar *>(mClassName),
NS_strlen(mClassName), thisAsVal, JS_PropertyStub,
JS_StrictPropertyStub, 0);
NS_strlen(mClassName), thisAsVal, nullptr,
nullptr, 0);
return ok ? NS_OK : NS_ERROR_UNEXPECTED;
}
@ -4901,8 +4899,7 @@ ResolvePrototype(nsIXPConnect *aXPConnect, nsGlobalWindow *aWin, JSContext *cx,
// Per ECMA, the prototype property is {DontEnum, DontDelete, ReadOnly}
if (!JS_WrapValue(cx, &v) ||
!JS_DefineProperty(cx, class_obj, "prototype", v,
JS_PropertyStub, JS_StrictPropertyStub,
!JS_DefineProperty(cx, class_obj, "prototype", v, nullptr, nullptr,
JSPROP_PERMANENT | JSPROP_READONLY)) {
return NS_ERROR_UNEXPECTED;
}
@ -5016,8 +5013,8 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
ac.destroy();
if (!JS_WrapObject(cx, &interfaceObject) ||
!JS_DefinePropertyById(cx, obj, id,
JS::ObjectValue(*interfaceObject), JS_PropertyStub,
JS_StrictPropertyStub, 0)) {
JS::ObjectValue(*interfaceObject), nullptr,
nullptr, 0)) {
return NS_ERROR_FAILURE;
}
}
@ -5201,8 +5198,7 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
return NS_ERROR_UNEXPECTED;
}
JSBool ok = ::JS_DefinePropertyById(cx, obj, id, prop_val,
JS_PropertyStub, JS_StrictPropertyStub,
JSBool ok = ::JS_DefinePropertyById(cx, obj, id, prop_val, nullptr, nullptr,
JSPROP_ENUMERATE);
*did_resolve = true;
@ -5243,10 +5239,8 @@ static nsresult
LocationSetterGuts(JSContext *cx, JSObject *obj, jsval *vp)
{
// This function duplicates some of the logic in XPC_WN_HelperSetProperty
obj = js::UnwrapObjectChecked(obj, /* stopAtOuter = */ false);
if (!IS_WN_WRAPPER(obj))
return NS_ERROR_XPC_BAD_CONVERT_JS;
XPCWrappedNative *wrapper = XPCWrappedNative::Get(obj);
XPCWrappedNative *wrapper =
XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj);
// The error checks duplicate code in THROW_AND_RETURN_IF_BAD_WRAPPER
NS_ENSURE_TRUE(!wrapper || wrapper->IsValid(), NS_ERROR_XPC_HAS_BEEN_SHUTDOWN);
@ -5426,7 +5420,7 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
NS_ENSURE_SUCCESS(rv, rv);
JSBool ok = JS_WrapValue(cx, &v) &&
JS_DefinePropertyById(cx, obj, id, v, JS_PropertyStub,
JS_DefinePropertyById(cx, obj, id, v, nullptr,
LocationSetterUnwrapper,
JSPROP_PERMANENT | JSPROP_ENUMERATE);
@ -5452,7 +5446,7 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
// Hold on to the top window object as a global property so we
// don't need to worry about losing expando properties etc.
if (!JS_DefinePropertyById(cx, obj, id, v, JS_PropertyStub, JS_StrictPropertyStub,
if (!JS_DefinePropertyById(cx, obj, id, v, nullptr, nullptr,
JSPROP_READONLY | JSPROP_PERMANENT |
JSPROP_ENUMERATE)) {
return NS_ERROR_FAILURE;
@ -5506,7 +5500,7 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
if (!::JS_DefinePropertyById(cx, windowObj, id, JSVAL_VOID,
JS_DATA_TO_FUNC_PTR(JSPropertyOp, funObj),
JS_StrictPropertyStub,
nullptr,
JSPROP_ENUMERATE | JSPROP_GETTER |
JSPROP_SHARED)) {
return NS_ERROR_FAILURE;
@ -5547,8 +5541,7 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
// Hold on to the navigator object as a global property so we
// don't need to worry about losing expando properties etc.
if (!::JS_DefinePropertyById(cx, obj, id, v,
JS_PropertyStub, JS_StrictPropertyStub,
if (!::JS_DefinePropertyById(cx, obj, id, v, nullptr, nullptr,
JSPROP_READONLY | JSPROP_PERMANENT |
JSPROP_ENUMERATE)) {
return NS_ERROR_FAILURE;
@ -5577,8 +5570,7 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
// define it ourselves.
*_retval = JS_WrapValue(cx, &v) &&
JS_DefineProperty(cx, obj, "document", v,
JS_PropertyStub, JS_StrictPropertyStub,
JS_DefineProperty(cx, obj, "document", v, NULL, NULL,
JSPROP_READONLY | JSPROP_ENUMERATE);
if (!*_retval) {
return NS_ERROR_UNEXPECTED;
@ -5846,8 +5838,7 @@ nsNavigatorSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
return NS_ERROR_UNEXPECTED;
}
JSBool ok = ::JS_DefinePropertyById(cx, obj, id, prop_val,
JS_PropertyStub, JS_StrictPropertyStub,
JSBool ok = ::JS_DefinePropertyById(cx, obj, id, prop_val, nullptr, nullptr,
JSPROP_ENUMERATE);
*_retval = true;
@ -6657,7 +6648,7 @@ nsDocumentSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv);
JSBool ok = ::JS_DefinePropertyById(cx, obj, id, v, JS_PropertyStub,
JSBool ok = ::JS_DefinePropertyById(cx, obj, id, v, nullptr,
LocationSetter<nsIDOMDocument>,
JSPROP_PERMANENT | JSPROP_ENUMERATE);

View File

@ -46,7 +46,7 @@ class JS_FRIEND_API(Wrapper) : public DirectProxyHandler
* object (via UnwrapObjectChecked) will throw. Otherwise, they will succeed.
*/
void setSafeToUnwrap(bool safe) { mSafeToUnwrap = safe; }
virtual bool isSafeToUnwrap() { return mSafeToUnwrap; }
bool isSafeToUnwrap() { return mSafeToUnwrap; }
static JSObject *New(JSContext *cx, JSObject *obj, JSObject *proto,
JSObject *parent, Wrapper *handler);

View File

@ -7,12 +7,10 @@
/* Call context. */
#include "mozilla/Util.h"
#include "AccessCheck.h"
#include "xpcprivate.h"
using namespace mozilla;
using namespace xpc;
XPCCallContext::XPCCallContext(XPCContext::LangType callerLanguage,
JSContext* cx /* = nullptr */,
@ -28,10 +26,7 @@ XPCCallContext::XPCCallContext(XPCContext::LangType callerLanguage,
mJSContext(cx),
mContextPopRequired(false),
mDestroyJSContextInDestructor(false),
mCallerLanguage(callerLanguage),
mFlattenedJSObject(nullptr),
mWrapper(nullptr),
mTearOff(nullptr)
mCallerLanguage(callerLanguage)
{
Init(callerLanguage, callerLanguage == NATIVE_CALLER, obj, funobj,
INIT_SHOULD_LOOKUP_WRAPPER, name, argc, argv, rval);
@ -60,8 +55,6 @@ XPCCallContext::XPCCallContext(XPCContext::LangType callerLanguage,
nullptr, nullptr);
}
#define IS_TEAROFF_CLASS(clazz) ((clazz) == &XPC_WN_Tearoff_JSClass)
void
XPCCallContext::Init(XPCContext::LangType callerLanguage,
JSBool callBeginRequest,
@ -146,28 +139,10 @@ XPCCallContext::Init(XPCContext::LangType callerLanguage,
mTearOff = nullptr;
if (wrapperInitOptions == INIT_SHOULD_LOOKUP_WRAPPER) {
// If the object is a security wrapper, GetWrappedNativeOfJSObject can't
// handle it. Do special handling here to make cross-origin Xrays work.
JSObject *unwrapped = js::UnwrapObjectChecked(obj, /* stopAtOuter = */ false);
if (!unwrapped) {
mWrapper = UnwrapThisIfAllowed(obj, funobj, argc);
if (!mWrapper) {
JS_ReportError(mJSContext, "Permission denied to call method on |this|");
mState = INIT_FAILED;
return;
}
} else {
js::Class *clasp = js::GetObjectClass(unwrapped);
if (IS_WRAPPER_CLASS(clasp)) {
if (IS_SLIM_WRAPPER_OBJECT(unwrapped))
mFlattenedJSObject = unwrapped;
else
mWrapper = XPCWrappedNative::Get(unwrapped);
} else if (IS_TEAROFF_CLASS(clasp)) {
mTearOff = (XPCWrappedNativeTearOff*)js::GetObjectPrivate(unwrapped);
mWrapper = XPCWrappedNative::Get(js::GetObjectParent(unwrapped));
}
}
mWrapper = XPCWrappedNative::GetWrappedNativeOfJSObject(mJSContext, obj,
funobj,
&mFlattenedJSObject,
&mTearOff);
if (mWrapper) {
mFlattenedJSObject = mWrapper->GetFlatJSObject();
@ -453,58 +428,3 @@ XPCLazyCallContext::AssertContextIsTopOfStack(JSContext* cx)
NS_ASSERTION(cx == topJSContext, "wrong context on XPCJSContextStack!");
}
#endif
XPCWrappedNative*
XPCCallContext::UnwrapThisIfAllowed(JSObject *obj, JSObject *fun, unsigned argc)
{
// We should only get here for objects that aren't safe to unwrap.
MOZ_ASSERT(!js::UnwrapObjectChecked(obj));
MOZ_ASSERT(js::IsObjectInContextCompartment(obj, mJSContext));
// Determine if we're allowed to unwrap the security wrapper to invoke the
// method.
//
// We have the Interface and Member that this corresponds to, but
// unfortunately our access checks are based on the object class name and
// property name. So we cheat a little bit here - we verify that the object
// does indeed implement the method's Interface, and then just check that we
// can successfully access property with method's name from the object.
// First, get the XPCWN out of the underlying object. We should have a wrapper
// here, potentially an outer window proxy, and then an XPCWN.
MOZ_ASSERT(js::IsWrapper(obj));
JSObject *unwrapped = js::UnwrapObject(obj, /* stopAtOuter = */ false);
MOZ_ASSERT(unwrapped == JS_ObjectToInnerObject(mJSContext, js::Wrapper::wrappedObject(obj)));
// Make sure we have an XPCWN, and grab it.
MOZ_ASSERT(!IS_SLIM_WRAPPER(unwrapped), "security wrapping morphs slim wrappers");
if (!IS_WRAPPER_CLASS(js::GetObjectClass(unwrapped)))
return nullptr;
XPCWrappedNative *wn = (XPCWrappedNative*)js::GetObjectPrivate(unwrapped);
// Next, get the call info off the function object.
XPCNativeInterface *interface;
XPCNativeMember *member;
XPCNativeMember::GetCallInfo(fun, &interface, &member);
// To be extra safe, make sure that the underlying native implements the
// interface before unwrapping. Even if we didn't check this, we'd still
// theoretically fail during tearoff lookup for mismatched methods.
if (!wn->HasInterfaceNoQI(*interface->GetIID()))
return nullptr;
// See if the access is permitted.
//
// NB: This calculation of SET vs GET is a bit wonky, but that's what
// XPC_WN_GetterSetter does.
bool set = argc && argc != NO_ARGS && member->IsWritableAttribute();
js::Wrapper::Action act = set ? js::Wrapper::SET : js::Wrapper::GET;
js::Wrapper *handler = js::Wrapper::wrapperHandler(obj);
bool ignored;
if (!handler->enter(mJSContext, obj, member->GetName(), act, &ignored))
return nullptr;
// Ok, this call is safe.
return wn;
}

View File

@ -3064,37 +3064,12 @@ xpc::SandboxCallableProxyHandler::call(JSContext *cx, JSObject *proxy,
MOZ_ASSERT(js::GetObjectJSClass(sandboxGlobal) == &SandboxClass);
// If our this object is the sandbox global, we call with this set to the
// original proto instead.
//
// There are two different ways we can compute |this|. If we use
// JS_THIS_VALUE, we'll get the bonafide |this| value as passed by the
// caller, which may be undefined if a global function was invoked without
// an explicit invocant. If we use JS_THIS or JS_THIS_OBJECT, the |this|
// in |vp| will be coerced to the global, which is not the correct
// behavior in ES5 strict mode. And we have no way to compute strictness
// here.
//
// The naive approach is simply to use JS_THIS_VALUE here. If |this| was
// explicit, we can remap it appropriately. If it was implicit, then we
// leave it as undefined, and let the callee sort it out. Since the callee
// is generally in the same compartment as its global (eg the Window's
// compartment, not the Sandbox's), the callee will generally compute the
// correct |this|.
//
// However, this breaks down in the Xray case. If the sandboxPrototype
// is an Xray wrapper, then we'll end up reifying the native methods in
// the Sandbox's scope, which means that they'll compute |this| to be the
// Sandbox, breaking old-style XPC_WN_CallMethod methods.
//
// Luckily, the intent of Xrays is to provide a vanilla view of a foreign
// DOM interface, which means that we don't care about script-enacted
// strictness in the prototype's home compartment. Indeed, since DOM
// methods are always non-strict, we can just assume non-strict semantics
// if the sandboxPrototype is an Xray Wrapper, which lets us appropriately
// remap |this|.
JS::Value thisVal =
WrapperFactory::IsXrayWrapper(sandboxProxy) ? JS_THIS(cx, vp)
: JS_THIS_VALUE(cx, vp);
// original proto instead. Note that we very carefully avoid using JS_THIS
// or JS_THIS_OBJECT here, because we do NOT want to box undefined into the
// global. Instead, we just pass it through to our callable, and it will
// compute the global based on its own scope chain, which will do the right
// thing.
JS::Value thisVal = JS_THIS_VALUE(cx, vp);
if (thisVal == ObjectValue(*sandboxGlobal)) {
thisVal = ObjectValue(*js::GetProxyTargetObject(sandboxProxy));
}

View File

@ -1032,25 +1032,22 @@ XPCConvert::JSObject2NativeInterface(JSContext* cx,
// If we're looking at a security wrapper, see now if we're allowed to
// pass it to C++. If we are, then fall through to the code below. If
// we aren't, throw an exception eagerly.
JSObject* inner = js::UnwrapObjectChecked(src, /* stopAtOuter = */ false);
// Hack - For historical reasons, wrapped chrome JS objects have been
// passable as native interfaces. We'd like to fix this, but it
// involves fixing the contacts API and PeerConnection to stop using
// COWs. This needs to happen, but for now just preserve the old
// behavior.
if (!inner && MOZ_UNLIKELY(xpc::WrapperFactory::IsCOW(src)))
inner = js::UnwrapObject(src);
if (!inner) {
if (pErr)
*pErr = NS_ERROR_XPC_SECURITY_MANAGER_VETO;
return false;
JSObject* inner = nullptr;
if (XPCWrapper::IsSecurityWrapper(src)) {
inner = XPCWrapper::Unwrap(cx, src, false);
if (!inner) {
if (pErr)
*pErr = NS_ERROR_XPC_SECURITY_MANAGER_VETO;
return false;
}
}
// Is this really a native xpcom object with a wrapper?
XPCWrappedNative* wrappedNative = nullptr;
if (IS_WN_WRAPPER(inner))
wrappedNative = XPCWrappedNative::Get(inner);
XPCWrappedNative* wrappedNative =
XPCWrappedNative::GetWrappedNativeOfJSObject(cx,
inner
? inner
: src);
if (wrappedNative) {
iface = wrappedNative->GetIdentityObject();
return NS_SUCCEEDED(iface->QueryInterface(*iid, dest));
@ -1177,12 +1174,9 @@ XPCConvert::JSValToXPCException(XPCCallContext& ccx,
}
// is this really a native xpcom object with a wrapper?
JSObject *unwrapped = js::UnwrapObjectChecked(obj, /* stopAtOuter = */ false);
if (!unwrapped)
return NS_ERROR_XPC_SECURITY_MANAGER_VETO;
XPCWrappedNative* wrapper = IS_WN_WRAPPER(unwrapped) ? XPCWrappedNative::Get(unwrapped)
: nullptr;
if (wrapper) {
XPCWrappedNative* wrapper;
if (nullptr != (wrapper =
XPCWrappedNative::GetWrappedNativeOfJSObject(cx,obj))) {
nsISupports* supports = wrapper->GetIdentityObject();
nsCOMPtr<nsIException> iface = do_QueryInterface(supports);
if (iface) {

View File

@ -447,41 +447,6 @@ nsJSIID::Enumerate(nsIXPConnectWrappedNative *wrapper,
return NS_OK;
}
/*
* HasInstance hooks need to find an appropriate reflector in order to function
* properly. There are two complexities that we need to handle:
*
* 1 - Cross-compartment wrappers. Chrome uses over 100 compartments, all with
* system principal. The success of an instanceof check should not depend
* on which compartment an object comes from. At the same time, we want to
* make sure we don't unwrap important security wrappers.
* UnwrapObjectChecked does the right thing here.
*
* 2 - Prototype chains. Suppose someone creates a vanilla JS object |a| and
* sets its __proto__ to some WN |b|. If |b instanceof nsIFoo| returns true,
* one would expect |a instanceof nsIFoo| to return true as well, since
* instanceof is transitive up the prototype chain in ECMAScript. Moreover,
* there's chrome code that relies on this.
*
* This static method handles both complexities, returning either an XPCWN, a
* slim wrapper, a DOM object, or null. The object may well be cross-compartment
* from |cx|.
*/
static JSObject *
FindObjectForHasInstance(JSContext *cx, JSObject *obj)
{
while (obj && !IS_WRAPPER_CLASS(js::GetObjectClass(obj)) &&
!mozilla::dom::IsDOMObject(obj))
{
if (js::IsWrapper(obj))
obj = js::UnwrapObjectChecked(obj, /* stopAtOuter = */ false);
else if (!js::GetObjectProto(cx, obj, &obj))
return nullptr;
}
return obj;
}
/* bool hasInstance (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval val, out bool bp); */
NS_IMETHODIMP
nsJSIID::HasInstance(nsIXPConnectWrappedNative *wrapper,
@ -497,15 +462,10 @@ nsJSIID::HasInstance(nsIXPConnectWrappedNative *wrapper,
NS_ASSERTION(obj, "when is an object not an object?");
nsISupports *identity = nullptr;
// is this really a native xpcom object with a wrapper?
const nsIID* iid;
mInfo->GetIIDShared(&iid);
obj = FindObjectForHasInstance(cx, obj);
if (!obj)
return NS_OK;
if (IS_SLIM_WRAPPER(obj)) {
XPCWrappedNativeProto* proto = GetSlimWrapperProto(obj);
if (proto->GetSet()->HasInterfaceWithAncestor(iid)) {
@ -520,15 +480,22 @@ nsJSIID::HasInstance(nsIXPConnectWrappedNative *wrapper,
#endif
if (!MorphSlimWrapper(cx, obj))
return NS_ERROR_FAILURE;
} else if (mozilla::dom::UnwrapDOMObjectToISupports(obj, identity)) {
nsCOMPtr<nsISupports> supp;
identity->QueryInterface(*iid, getter_AddRefs(supp));
*bp = supp;
return NS_OK;
} else {
JSObject* unsafeObj =
XPCWrapper::Unwrap(cx, obj, /* stopAtOuter = */ false);
JSObject* cur = unsafeObj ? unsafeObj : obj;
nsISupports *identity;
if (mozilla::dom::UnwrapDOMObjectToISupports(cur, identity)) {
nsCOMPtr<nsISupports> supp;
identity->QueryInterface(*iid, getter_AddRefs(supp));
*bp = supp;
return NS_OK;
}
}
MOZ_ASSERT(IS_WN_WRAPPER(obj));
XPCWrappedNative* other_wrapper = XPCWrappedNative::Get(obj);
XPCWrappedNative* other_wrapper =
XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj);
if (!other_wrapper)
return NS_OK;
@ -849,14 +816,16 @@ nsJSCID::HasInstance(nsIXPConnectWrappedNative *wrapper,
NS_ASSERTION(obj, "when is an object not an object?");
// is this really a native xpcom object with a wrapper?
nsIClassInfo* ci = nullptr;
obj = FindObjectForHasInstance(cx, obj);
if (!obj || !IS_WRAPPER_CLASS(js::GetObjectClass(obj)))
return rv;
if (IS_SLIM_WRAPPER_OBJECT(obj))
ci = GetSlimWrapperProto(obj)->GetClassInfo();
else if (XPCWrappedNative* other_wrapper = XPCWrappedNative::Get(obj))
ci = other_wrapper->GetClassInfo();
JSObject* obj2;
XPCWrappedNative* other_wrapper =
XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj, nullptr, &obj2);
if (!other_wrapper && !obj2)
return NS_OK;
nsIClassInfo* ci = other_wrapper ?
other_wrapper->GetClassInfo() :
GetSlimWrapperProto(obj2)->GetClassInfo();
// We consider CID equality to be the thing that matters here.
// This is perhaps debatable.
@ -903,10 +872,8 @@ xpc_JSObjectToID(JSContext *cx, JSObject* obj)
return nullptr;
// NOTE: this call does NOT addref
XPCWrappedNative* wrapper = nullptr;
obj = js::UnwrapObjectChecked(obj);
if (obj && IS_WN_WRAPPER(obj))
wrapper = XPCWrappedNative::Get(obj);
XPCWrappedNative* wrapper =
XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj);
if (wrapper &&
(wrapper->HasInterfaceNoQI(NS_GET_IID(nsIJSID)) ||
wrapper->HasInterfaceNoQI(NS_GET_IID(nsIJSIID)) ||
@ -921,10 +888,8 @@ xpc_JSObjectIsID(JSContext *cx, JSObject* obj)
{
NS_ASSERTION(cx && obj, "bad param");
// NOTE: this call does NOT addref
XPCWrappedNative* wrapper = nullptr;
obj = js::UnwrapObjectChecked(obj);
if (obj && IS_WN_WRAPPER(obj))
wrapper = XPCWrappedNative::Get(obj);
XPCWrappedNative* wrapper =
XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj);
return wrapper &&
(wrapper->HasInterfaceNoQI(NS_GET_IID(nsIJSID)) ||
wrapper->HasInterfaceNoQI(NS_GET_IID(nsIJSIID)) ||

View File

@ -2427,21 +2427,27 @@ PreserveWrapper(JSContext *cx, JSObject *obj)
if (!ccx.IsValid())
return false;
if (!IS_WRAPPER_CLASS(js::GetObjectClass(obj)))
return mozilla::dom::TryPreserveWrapper(obj);
JSObject *obj2 = nullptr;
nsIXPConnectWrappedNative *wrapper =
XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj, nullptr, &obj2);
nsISupports *supports = nullptr;
if (IS_WN_WRAPPER_OBJECT(obj))
supports = XPCWrappedNative::Get(obj)->Native();
else
supports = static_cast<nsISupports*>(xpc_GetJSPrivate(obj));
// For pre-Paris DOM bindings objects, we only support Node.
if (nsCOMPtr<nsINode> node = do_QueryInterface(supports)) {
nsContentUtils::PreserveWrapper(supports, node);
return true;
if (wrapper) {
supports = wrapper->Native();
} else if (obj2) {
supports = static_cast<nsISupports*>(xpc_GetJSPrivate(obj2));
}
return false;
if (supports) {
// For pre-Paris DOM bindings objects, we only support Node.
if (nsCOMPtr<nsINode> node = do_QueryInterface(supports)) {
nsContentUtils::PreserveWrapper(supports, node);
return true;
}
return false;
}
return mozilla::dom::TryPreserveWrapper(obj);
}
static nsresult

View File

@ -28,20 +28,21 @@ XPCVariant::XPCVariant(JSContext* cx, jsval aJSVal)
{
nsVariant::Initialize(&mData);
if (!JSVAL_IS_PRIMITIVE(mJSVal)) {
// XXXbholley - The innerization here was from bug 638026. Blake says
// the basic problem was that we were storing the C++ inner but the JS
// outer, which meant that, after navigation, the JS inner could be
// collected, which would cause us to try to recreate the JS inner at
// some later point after teardown, which would crash. This is shouldn't
// be a problem anymore because SetParentToWindow will do the right
// thing, but I'm saving the cleanup here for another day. Blake thinks
// that we should just not store the WN if we're creating a variant for
// an outer window.
JSObject *obj = JS_ObjectToInnerObject(cx, JSVAL_TO_OBJECT(mJSVal));
mJSVal = OBJECT_TO_JSVAL(obj);
JSObject *unwrapped = js::UnwrapObjectChecked(obj, /* stopAtOuter = */ false);
mReturnRawObject = !(unwrapped && IS_WN_WRAPPER(unwrapped));
// If the incoming object is an XPCWrappedNative, then it could be a
// double-wrapped object, and we should return the double-wrapped
// object back out to script.
JSObject* proto;
XPCWrappedNative* wn =
XPCWrappedNative::GetWrappedNativeOfJSObject(cx,
JSVAL_TO_OBJECT(mJSVal),
nullptr,
&proto);
mReturnRawObject = !wn && !proto;
} else
mReturnRawObject = false;
}

View File

@ -1751,6 +1751,134 @@ XPCWrappedNative::RescueOrphans(XPCCallContext& ccx)
return ::RescueOrphans(ccx, mFlatJSObject);
}
#define IS_TEAROFF_CLASS(clazz) \
((clazz) == &XPC_WN_Tearoff_JSClass)
// static
XPCWrappedNative*
XPCWrappedNative::GetWrappedNativeOfJSObject(JSContext* cx,
JSObject* obj,
JSObject* funobj,
JSObject** pobj2,
XPCWrappedNativeTearOff** pTearOff)
{
NS_PRECONDITION(obj, "bad param");
// fubobj must be null if called without cx.
NS_PRECONDITION(cx || !funobj, "bad param");
// *pTeaorOff must be null if pTearOff is given
NS_PRECONDITION(!pTearOff || !*pTearOff, "bad param");
JSObject* cur;
XPCWrappedNativeProto* proto = nullptr;
nsIClassInfo* protoClassInfo = nullptr;
// When an object is unwrapped (near the bottom of this function), we need
// to enter its compartment. Unfortunately, given the crazy usage of gotos,
// scoped JSAutoCompartments are pretty much impossible. So instead, we use
// a single Maybe<JSAutoCompartment>, and let anyone who wants to enter a
// compartment destroy and then reconstruct it.
Maybe<JSAutoCompartment> mac;
if (cx)
mac.construct(cx, obj);
// If we were passed a function object then we need to find the correct
// wrapper out of those that might be in the callee obj's proto chain.
if (funobj) {
JSObject* funObjParent = js::UnwrapObject(js::GetObjectParent(funobj));
funObjParent = JS_ObjectToInnerObject(cx, funObjParent);
NS_ASSERTION(funObjParent, "funobj has no parent");
js::Class* funObjParentClass = js::GetObjectClass(funObjParent);
if (IS_PROTO_CLASS(funObjParentClass)) {
NS_ASSERTION(js::GetObjectParent(funObjParent), "funobj's parent (proto) is global");
proto = (XPCWrappedNativeProto*) js::GetObjectPrivate(funObjParent);
if (proto)
protoClassInfo = proto->GetClassInfo();
} else if (IS_WRAPPER_CLASS(funObjParentClass)) {
cur = funObjParent;
goto return_wrapper;
} else if (IS_TEAROFF_CLASS(funObjParentClass)) {
NS_ASSERTION(js::GetObjectParent(funObjParent), "funobj's parent (tearoff) is global");
cur = funObjParent;
goto return_tearoff;
} else {
NS_ERROR("function object has parent of unknown class!");
return nullptr;
}
}
restart:
if (cx) {
mac.destroy();
mac.construct(cx, obj);
}
for (cur = obj; cur; ) {
// this is on two lines to make the compiler happy given the goto.
js::Class* clazz;
clazz = js::GetObjectClass(cur);
if (IS_WRAPPER_CLASS(clazz)) {
return_wrapper:
JSBool isWN = IS_WN_WRAPPER_OBJECT(cur);
XPCWrappedNative* wrapper =
isWN ? (XPCWrappedNative*) js::GetObjectPrivate(cur) : nullptr;
if (proto) {
XPCWrappedNativeProto* wrapper_proto =
isWN ? wrapper->GetProto() : GetSlimWrapperProto(cur);
if (proto != wrapper_proto &&
(!protoClassInfo || !wrapper_proto ||
protoClassInfo != wrapper_proto->GetClassInfo()))
goto next;
}
if (pobj2)
*pobj2 = isWN ? nullptr : cur;
return wrapper;
}
if (IS_TEAROFF_CLASS(clazz)) {
return_tearoff:
XPCWrappedNative* wrapper =
(XPCWrappedNative*) js::GetObjectPrivate(js::GetObjectParent(cur));
if (proto && proto != wrapper->GetProto() &&
(proto->GetScope() != wrapper->GetScope() ||
!protoClassInfo || !wrapper->GetProto() ||
protoClassInfo != wrapper->GetProto()->GetClassInfo()))
goto next;
if (pobj2)
*pobj2 = nullptr;
XPCWrappedNativeTearOff* to = (XPCWrappedNativeTearOff*) js::GetObjectPrivate(cur);
if (!to)
return nullptr;
if (pTearOff)
*pTearOff = to;
return wrapper;
}
// Unwrap any wrapper wrappers.
JSObject *unsafeObj;
unsafeObj = cx
? XPCWrapper::Unwrap(cx, cur, /* stopAtOuter = */ false)
: js::UnwrapObject(cur, /* stopAtOuter = */ false);
if (unsafeObj) {
obj = unsafeObj;
goto restart;
}
next:
if (!js::GetObjectProto(cx, cur, &cur))
return nullptr;
}
if (pobj2)
*pobj2 = nullptr;
return nullptr;
}
JSBool
XPCWrappedNative::ExtendSet(XPCCallContext& ccx, XPCNativeInterface* aInterface)
{

View File

@ -14,7 +14,8 @@
// static
JSBool
XPCNativeMember::GetCallInfo(JSObject* funobj,
XPCNativeMember::GetCallInfo(XPCCallContext& ccx,
JSObject* funobj,
XPCNativeInterface** pInterface,
XPCNativeMember** pMember)
{

View File

@ -9,7 +9,6 @@
#include "xpcprivate.h"
#include "XPCWrapper.h"
#include "AccessCheck.h"
#include "nsWrapperCacheInlines.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/Preferences.h"
@ -664,17 +663,19 @@ MarkWrappedNative(JSTracer *trc, JSObject *obj)
if (clazz->flags & JSCLASS_DOM_GLOBAL) {
mozilla::dom::TraceProtoAndIfaceCache(trc, obj);
}
MOZ_ASSERT(IS_WRAPPER_CLASS(clazz));
if (IS_WN_WRAPPER_OBJECT(obj)) {
XPCWrappedNative *wrapper = XPCWrappedNative::Get(obj);
if (wrapper) {
if (wrapper->IsValid())
wrapper->TraceInside(trc);
}
} else {
MOZ_ASSERT(IS_SLIM_WRAPPER_OBJECT(obj));
TraceInsideSlimWrapper(trc, obj);
JSObject *obj2;
// Pass null for the first JSContext* parameter to skip any security
// checks and to avoid potential state change there.
XPCWrappedNative* wrapper =
XPCWrappedNative::GetWrappedNativeOfJSObject(nullptr, obj, nullptr, &obj2);
if (wrapper) {
if (wrapper->IsValid())
wrapper->TraceInside(trc);
} else if (obj2) {
TraceInsideSlimWrapper(trc, obj2);
}
}
@ -848,21 +849,13 @@ XPC_WN_MaybeResolvingStrictPropertyStub(JSContext *cx, JSHandleObject obj, JSHan
#define PRE_HELPER_STUB \
XPCWrappedNative* wrapper; \
nsIXPCScriptable* si; \
JSObject *unwrapped = js::UnwrapObjectChecked(obj, false); \
if (!unwrapped) { \
JS_ReportError(cx, "Permission denied to operate on object."); \
return false; \
if (IS_SLIM_WRAPPER(obj)) { \
wrapper = nullptr; \
si = GetSlimWrapperProto(obj)->GetScriptableInfo()->GetCallback(); \
} \
if (!IS_WRAPPER_CLASS(js::GetObjectClass(unwrapped))) { \
return Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO, cx); \
} \
if (IS_SLIM_WRAPPER_OBJECT(unwrapped)) { \
wrapper = nullptr; \
si = GetSlimWrapperProto(unwrapped)->GetScriptableInfo() \
->GetCallback(); \
} else { \
MOZ_ASSERT(IS_WN_WRAPPER_OBJECT(unwrapped)); \
wrapper = XPCWrappedNative::Get(unwrapped); \
else \
{ \
wrapper = XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj); \
THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper); \
si = wrapper->GetScriptableCallback(); \
} \
@ -1357,6 +1350,11 @@ XPCNativeScriptableShared::PopulateJSClass()
if (mFlags.WantCheckAccess())
mJSClass.base.checkAccess = XPC_WN_Helper_CheckAccess;
// Note that we *must* set the ObjectOps (even for the cases were it does
// not do much) because with these dynamically generated JSClasses, the
// code in XPCWrappedNative::GetWrappedNativeOfJSObject() needs to look
// for that these callback pointers in order to identify that a given
// JSObject represents a wrapper.
js::ObjectOps *ops = &mJSClass.base.ops;
ops->enumerate = XPC_WN_JSOp_Enumerate;
ops->thisObject = XPC_WN_JSOp_ThisObject;
@ -1384,33 +1382,6 @@ XPCNativeScriptableShared::PopulateJSClass()
/***************************************************************************/
/***************************************************************************/
// Compatibility hack.
//
// XPConnect used to do all sorts of funny tricks to find the "correct"
// |this| object for a given method (often to the detriment of proper
// call/apply). When these tricks were removed, a fair amount of chrome
// code broke, because it was relying on being able to grab methods off
// some XPCOM object (like the nsITelemetry service) and invoke them without
// a proper |this|. So, if it's quite clear that we're in this situation and
// about to use a |this| argument that just won't work, fix things up.
//
// This hack is only useful for getters/setters if someone sets an XPCOM object
// as the prototype for a vanilla JS object and expects the XPCOM attributes to
// work on the derived object, which we really don't want to support. But we
// handle it anyway, for now, to minimize regression risk on an already-risky
// landing.
MOZ_ALWAYS_INLINE JSObject*
FixUpThisIfBroken(JSObject *obj, JSObject *funobj)
{
if (MOZ_UNLIKELY(funobj &&
(js::GetObjectClass(js::GetObjectParent(funobj)) == &XPC_WN_NoHelper_JSClass.base) &&
(js::GetObjectClass(obj) != &XPC_WN_NoHelper_JSClass.base)))
{
return js::GetObjectParent(funobj);
}
return obj;
}
JSBool
XPC_WN_CallMethod(JSContext *cx, unsigned argc, jsval *vp)
{
@ -1433,7 +1404,6 @@ XPC_WN_CallMethod(JSContext *cx, unsigned argc, jsval *vp)
if (IS_SLIM_WRAPPER(obj) && !MorphSlimWrapper(cx, obj))
return Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO, cx);
obj = FixUpThisIfBroken(obj, funobj);
XPCCallContext ccx(JS_CALLER, cx, obj, funobj, JSID_VOID, argc, JS_ARGV(cx, vp), vp);
XPCWrappedNative* wrapper = ccx.GetWrapper();
THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
@ -1441,7 +1411,7 @@ XPC_WN_CallMethod(JSContext *cx, unsigned argc, jsval *vp)
XPCNativeInterface* iface;
XPCNativeMember* member;
if (!XPCNativeMember::GetCallInfo(funobj, &iface, &member))
if (!XPCNativeMember::GetCallInfo(ccx, funobj, &iface, &member))
return Throw(NS_ERROR_XPC_CANT_GET_METHOD_INFO, cx);
ccx.SetCallInfo(iface, member, false);
return XPCWrappedNative::CallMethod(ccx);
@ -1471,18 +1441,17 @@ XPC_WN_GetterSetter(JSContext *cx, unsigned argc, jsval *vp)
if (IS_SLIM_WRAPPER(obj) && !MorphSlimWrapper(cx, obj))
return Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO, cx);
obj = FixUpThisIfBroken(obj, funobj);
XPCCallContext ccx(JS_CALLER, cx, obj, funobj, JSID_VOID, argc, JS_ARGV(cx, vp), vp);
XPCCallContext ccx(JS_CALLER, cx, obj, funobj);
XPCWrappedNative* wrapper = ccx.GetWrapper();
THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
XPCNativeInterface* iface;
XPCNativeMember* member;
if (!XPCNativeMember::GetCallInfo(funobj, &iface, &member))
if (!XPCNativeMember::GetCallInfo(ccx, funobj, &iface, &member))
return Throw(NS_ERROR_XPC_CANT_GET_METHOD_INFO, cx);
ccx.SetArgsAndResultPtr(argc, JS_ARGV(cx, vp), vp);
if (argc && member->IsWritableAttribute()) {
ccx.SetCallInfo(iface, member, true);
JSBool retval = XPCWrappedNative::SetAttribute(ccx);

View File

@ -1332,18 +1332,15 @@ nsXPConnect::GetNativeOfWrapper(JSContext * aJSContext,
return nullptr;
}
aJSObj = js::UnwrapObjectChecked(aJSObj, /* stopAtOuter = */ false);
if (!aJSObj) {
JS_ReportError(aJSContext, "Permission denied to get native of security wrapper");
return nullptr;
}
if (IS_WRAPPER_CLASS(js::GetObjectClass(aJSObj))) {
if (IS_SLIM_WRAPPER_OBJECT(aJSObj))
return (nsISupports*)xpc_GetJSPrivate(aJSObj);
else if (XPCWrappedNative *wn = XPCWrappedNative::Get(aJSObj))
return wn->Native();
return nullptr;
}
JSObject* obj2 = nullptr;
nsIXPConnectWrappedNative* wrapper =
XPCWrappedNative::GetWrappedNativeOfJSObject(aJSContext, aJSObj, nullptr,
&obj2);
if (wrapper)
return wrapper->Native();
if (obj2)
return (nsISupports*)xpc_GetJSPrivate(obj2);
JSObject* unsafeObj =
XPCWrapper::Unwrap(aJSContext, aJSObj, /* stopAtOuter = */ false);

View File

@ -1248,9 +1248,6 @@ private:
jsval *argv,
jsval *rval);
XPCWrappedNative* UnwrapThisIfAllowed(JSObject *obj, JSObject *fun,
unsigned argc);
private:
// posible values for mState
enum State {
@ -1753,7 +1750,8 @@ private:
class XPCNativeMember
{
public:
static JSBool GetCallInfo(JSObject* funobj,
static JSBool GetCallInfo(XPCCallContext& ccx,
JSObject* funobj,
XPCNativeInterface** pInterface,
XPCNativeMember** pMember);
@ -2687,11 +2685,6 @@ public:
void
SetSet(XPCNativeSet* set) {XPCAutoLock al(GetLock()); mSet = set;}
static XPCWrappedNative* Get(JSObject *obj) {
MOZ_ASSERT(IS_WN_WRAPPER(obj));
return (XPCWrappedNative*)js::GetObjectPrivate(obj);
}
private:
inline void
ExpireWrapper()
@ -2751,19 +2744,30 @@ public:
XPCNativeInterface* Interface,
XPCWrappedNative** wrapper);
// If pobj2 is not null and *pobj2 is not null after the call then *pobj2
// points to an object for which IS_SLIM_WRAPPER_OBJECT is true.
// cx is null when invoked from the marking phase of the GC. In this case
// fubobj must be null as well.
static XPCWrappedNative*
GetWrappedNativeOfJSObject(JSContext* cx, JSObject* obj,
JSObject* funobj = nullptr,
JSObject** pobj2 = nullptr,
XPCWrappedNativeTearOff** pTearOff = nullptr);
static XPCWrappedNative*
GetAndMorphWrappedNativeOfJSObject(JSContext* cx, JSObject* obj)
{
obj = js::UnwrapObjectChecked(obj, /* stopAtOuter = */ false);
if (!obj)
return nullptr;
if (!IS_WRAPPER_CLASS(js::GetObjectClass(obj)))
return nullptr;
JSObject *obj2 = nullptr;
XPCWrappedNative* wrapper =
GetWrappedNativeOfJSObject(cx, obj, nullptr, &obj2);
if (wrapper || !obj2)
return wrapper;
if (IS_SLIM_WRAPPER_OBJECT(obj) && !MorphSlimWrapper(cx, obj))
return nullptr;
MOZ_ASSERT(IS_WN_WRAPPER(obj));
return XPCWrappedNative::Get(obj);
NS_ASSERTION(IS_SLIM_WRAPPER(obj2),
"Hmm, someone changed GetWrappedNativeOfJSObject?");
SLIM_LOG_WILL_MORPH(cx, obj2);
return MorphSlimWrapper(cx, obj2) ?
(XPCWrappedNative*)xpc_GetJSPrivate(obj2) :
nullptr;
}
static nsresult

View File

@ -29,7 +29,6 @@ MOCHITEST_CHROME_FILES = \
file_bug618176.xul \
test_bug654370.xul \
test_bug658560.xul \
test_bug658909.xul \
test_bug664689.xul \
test_bug679861.xul \
test_bug706301.xul \

View File

@ -1,92 +0,0 @@
<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=658909
-->
<window title="Mozilla Bug 658909"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<!-- test results are displayed in the html:body -->
<body xmlns="http://www.w3.org/1999/xhtml">
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=658909"
target="_blank">Mozilla Bug 658909</a>
</body>
<!-- test code goes here -->
<script type="application/javascript">
<![CDATA[
/** Test for call/apply-ing Xray methods.**/
SimpleTest.waitForExplicitFinish();
gLoadCount = 0;
function frameLoaded() {
if (++gLoadCount == frames.length)
go();
}
function msg(a, b, testName) {
return "(" + a.name + ", " + b.name + "): " + testName;
}
var testFunctions = {
testDocumentElement: function(a, b, name) {
var getter = Object.prototype.__lookupGetter__.call(a.document, 'documentElement');
is(getter.call(b.document), b.document.documentElement, msg(a, b, name));
},
testInvalidCall: function(a, b, name) {
var getter = Object.prototype.__lookupGetter__.call(a.document, 'documentElement');
var threw = false;
try { getter.call(b.document.body); } catch (e) { threw = true; };
ok(threw, msg(a, b, name));
},
testStatus: function(a, b, name) {
var setter = Object.prototype.__lookupSetter__.call(a, 'status');
is(b.status, "", "Empty status");
setter.call(b, "foopy");
is(b.status, "foopy", msg(a, b, name));
b.status = "";
},
testCreateElement: function(a, b, name) {
is(a.document.createElement.call(b.document, 'div').ownerDocument, b.document, msg(a, b, name));
},
testWindowName: function(a, b, name) {
var getter = Object.prototype.__lookupGetter__.call(a, 'name');
is(getter.call(b), b.name, msg(a, b, name));
},
testCanvas: function(a, b, name) {
var canvasA = a.document.createElement('canvas');
var canvasB = b.document.createElement('canvas');
var contextA = canvasA.getContext('2d');
var contextB = canvasB.getContext('2d');
var getter = Object.prototype.__lookupGetter__.call(contextA, 'canvas');
is(getter.call(contextB), canvasB, msg(a, b, name));
}
};
function go() {
for (var i = 0; i < frames.length; ++i)
frames[i].name = 'frame' + i;
for (var i = 0; i < frames.length; ++i) {
for (var j = 0; j < frames.length; ++j) {
for (var k in testFunctions)
testFunctions[k](frames[i], frames[j], k);
}
}
SimpleTest.finish();
}
]]>
</script>
<iframe id="frame1" onload="frameLoaded();" type="content" src="http://example.org/tests/js/xpconnect/tests/mochitest/file_empty.html" />
<iframe id="frame2" onload="frameLoaded();" type="content" src="http://example.org/tests/js/xpconnect/tests/mochitest/file_empty.html" />
<iframe id="frame3" onload="frameLoaded();" type="content" src="http://example.com/tests/js/xpconnect/tests/mochitest/file_empty.html" />
</window>

View File

@ -55,10 +55,18 @@ function mergeObjects(a, b) {
function getAllTests() {
var innerTests = getTests(false);
var outerTests = getTests(true);
outerTests.getLocationApply1.skipMessageCheck = true;
outerTests.getLocationApply2.skipMessageCheck = true;
outerTests.getLocationApply3.skipMessageCheck = true;
outerTests.getLocationViaPrototype.skipMessageCheck = true;
outerTests.getHrefViaApply.skipMessageCheck = true;
outerTests.getHrefViaPrototype.skipMessageCheck = true;
return mergeObjects(mungeNames(innerTests, '_inner'),
mungeNames(outerTests, '_outer'));
}
</script>
</head>
<body>

View File

@ -13,13 +13,17 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=802557
/** Test for Bug 802557 **/
SimpleTest.waitForExplicitFinish();
function checkThrows(fun, desc) {
// In the case of apply()ing on a Location object that's script access only,
// we just throw a very bland XPConnect message. In other cases though, we want
// to check the message to make sure we're throwing a security exception and not
// something else.
function checkThrows(fun, desc, skipMessageCheck) {
try {
fun();
ok(false, "Didn't throw when " + desc);
} catch(e) {
ok(true, "Threw when " + desc + " " + e);
ok(/denied|insecure/.exec(e), "Should be security exception");
(skipMessageCheck ? todo : ok)(/denied|insecure/.exec(e), "Should be security exception");
}
}
@ -55,7 +59,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=802557
else if (loadCount == 2) {
gGetters.forEach(function(item) {
checkThrows(function() { item[0].call(gLoc); },
'call()ing ' + item[1] + ' after navigation cross-origin');
'call()ing ' + item[1] + ' after navigation cross-origin',
/* skipMessageCheck = */ false);
});
ifr.src = 'http://mochi.test:8888/tests/js/xpconnect/tests/mochitest/file_bug802557.html';
}
@ -69,7 +74,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=802557
else if (loadCount == 4) {
for (fun in gTestFunctions) {
var f = gTestFunctions[fun];
checkThrows(f, "calling " + fun);
checkThrows(f, "calling " + fun, f.skipMessageCheck);
}
SimpleTest.finish();
}

View File

@ -166,10 +166,7 @@ IsPermitted(const char *name, JSFlatString *prop, bool set)
static bool
IsFrameId(JSContext *cx, JSObject *obj, jsid id)
{
obj = JS_ObjectToInnerObject(cx, obj);
MOZ_ASSERT(!js::IsWrapper(obj));
XPCWrappedNative *wn = IS_WN_WRAPPER(obj) ? XPCWrappedNative::Get(obj)
: nullptr;
XPCWrappedNative *wn = XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj);
if (!wn) {
return false;
}
@ -270,19 +267,6 @@ AccessCheck::isScriptAccessOnly(JSContext *cx, JSObject *wrapper)
return false;
}
bool
OnlyIfSubjectIsSystem::isSafeToUnwrap()
{
if (XPCJSRuntime::Get()->XBLScopesEnabled())
return false;
// It's nasty to use the context stack here, but the alternative is passing cx all
// the way down through UnwrapObjectChecked, which we just undid in a 100k patch. :-(
JSContext *cx = nsContentUtils::GetCurrentJSContext();
if (!cx)
return true;
return AccessCheck::isSystemOnlyAccessPermitted(cx);
}
enum Access { READ = (1<<0), WRITE = (1<<1), NO_ACCESS = 0 };
static bool

View File

@ -50,9 +50,6 @@ struct Opaque : public Policy {
{
return false;
}
static bool isSafeToUnwrap() {
return false;
}
};
// This policy only permits access to the object if the subject can touch
@ -70,8 +67,6 @@ struct OnlyIfSubjectIsSystem : public Policy {
{
return AccessCheck::isSystemOnlyAccessPermitted(cx);
}
static bool isSafeToUnwrap();
};
// This policy only permits access to properties that are safe to be used
@ -87,10 +82,6 @@ struct CrossOriginAccessiblePropertiesOnly : public Policy {
{
return false;
}
static bool isSafeToUnwrap() {
return false;
}
};
// This policy only permits access to properties if they appear in the
@ -103,10 +94,6 @@ struct ExposedPropertiesOnly : public Policy {
return act == js::Wrapper::GET;
}
static bool allowNativeCall(JSContext *cx, JS::IsAcceptableThis test, JS::NativeImpl impl);
static bool isSafeToUnwrap() {
return false;
}
};
// Components specific policy
@ -119,10 +106,6 @@ struct ComponentsObjectPolicy : public Policy {
static bool allowNativeCall(JSContext *cx, JS::IsAcceptableThis test, JS::NativeImpl impl) {
return false;
}
static bool isSafeToUnwrap() {
return false;
}
};
}

View File

@ -29,13 +29,6 @@ FilteringWrapper<Base, Policy>::~FilteringWrapper()
{
}
template <typename Base, typename Policy>
bool
FilteringWrapper<Base, Policy>::isSafeToUnwrap()
{
return Policy::isSafeToUnwrap();
}
template <typename Policy>
static bool
Filter(JSContext *cx, JSObject *wrapper, AutoIdVector &props)

View File

@ -19,9 +19,6 @@ class FilteringWrapper : public Base {
FilteringWrapper(unsigned flags);
virtual ~FilteringWrapper();
// This is potentially dynamic until XBL scopes are no longer behind a pref.
virtual bool isSafeToUnwrap();
virtual bool getPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id, js::PropertyDescriptor *desc, unsigned flags) MOZ_OVERRIDE;
virtual bool getOwnPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id, js::PropertyDescriptor *desc, unsigned flags) MOZ_OVERRIDE;
virtual bool getOwnPropertyNames(JSContext *cx, JSObject *wrapper, js::AutoIdVector &props) MOZ_OVERRIDE;

View File

@ -39,13 +39,6 @@ Wrapper XrayWaiver(WrapperFactory::WAIVE_XRAY_WRAPPER_FLAG);
// off it.
WaiveXrayWrapper WaiveXrayWrapper::singleton(0);
bool
WrapperFactory::IsCOW(JSObject *obj)
{
return IsWrapper(obj) &&
Wrapper::wrapperHandler(obj) == &ChromeObjectWrapper::singleton;
}
JSObject *
WrapperFactory::GetXrayWaiver(JSObject *obj)
{
@ -291,8 +284,8 @@ DEBUG_CheckUnwrapSafety(JSObject *obj, js::Wrapper *handler,
// The Components object that is restricted regardless of origin.
MOZ_ASSERT(!handler->isSafeToUnwrap());
} else if (AccessCheck::needsSystemOnlyWrapper(obj)) {
// SOWs have a dynamic unwrap check, so we can't really say anything useful
// about them here :-(
// SOWs are opaque to everyone but Chrome and XBL scopes.
MOZ_ASSERT(handler->isSafeToUnwrap() == nsContentUtils::CanAccessNativeAnon());
} else {
// Otherwise, it should depend on whether the target subsumes the origin.
MOZ_ASSERT(handler->isSafeToUnwrap() == AccessCheck::subsumes(target, origin));
@ -506,8 +499,7 @@ WrapperFactory::WrapForSameCompartment(JSContext *cx, JSObject *obj)
// The WN knows what to do.
JSObject *wrapper = wn->GetSameCompartmentSecurityWrapper(cx);
MOZ_ASSERT_IF(wrapper != obj && IsComponentsObject(js::UnwrapObject(obj)),
!Wrapper::wrapperHandler(wrapper)->isSafeToUnwrap());
MOZ_ASSERT_IF(wrapper != obj, !Wrapper::wrapperHandler(wrapper)->isSafeToUnwrap());
return wrapper;
}

View File

@ -35,12 +35,6 @@ class WrapperFactory {
return HasWrapperFlag(wrapper, WAIVE_XRAY_WRAPPER_FLAG);
}
static bool IsSecurityWrapper(JSObject *obj) {
return !js::UnwrapObjectChecked(obj);
}
static bool IsCOW(JSObject *wrapper);
static JSObject *GetXrayWaiver(JSObject *obj);
static JSObject *CreateXrayWaiver(JSContext *cx, JSObject *obj);
static JSObject *WaiveXray(JSContext *cx, JSObject *obj);