mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-30 00:01:50 +00:00
Bug 958324 - Remove same-compartment security wrappers for WNs. r=peterv,r=mrbkap
We've fixed Components, and SOWs are new-binding only. Youpie!
This commit is contained in:
parent
06f47384db
commit
44cd3fcb36
@ -28,15 +28,6 @@ using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
using namespace JS;
|
||||
|
||||
bool
|
||||
xpc_OkToHandOutWrapper(nsWrapperCache *cache)
|
||||
{
|
||||
MOZ_ASSERT(cache->GetWrapper(), "Must have wrapper");
|
||||
MOZ_ASSERT(IS_WN_REFLECTOR(cache->GetWrapper()),
|
||||
"Must have XPCWrappedNative wrapper");
|
||||
return !XPCWrappedNative::Get(cache->GetWrapper())->NeedsSOW();
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(XPCWrappedNative)
|
||||
@ -362,8 +353,6 @@ XPCWrappedNative::GetNewOrUsed(xpcObjectHelper& helper,
|
||||
RootedObject parent(cx, Scope->GetGlobalJSObject());
|
||||
|
||||
RootedValue newParentVal(cx, NullValue());
|
||||
bool needsSOW = false;
|
||||
bool needsCOW = false;
|
||||
|
||||
mozilla::Maybe<JSAutoCompartment> ac;
|
||||
|
||||
@ -376,9 +365,6 @@ XPCWrappedNative::GetNewOrUsed(xpcObjectHelper& helper,
|
||||
parent, parent.address());
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
if (rv == NS_SUCCESS_CHROME_ACCESS_ONLY)
|
||||
needsSOW = true;
|
||||
rv = NS_OK;
|
||||
|
||||
MOZ_ASSERT(!xpc::WrapperFactory::IsXrayWrapper(parent),
|
||||
@ -416,15 +402,6 @@ XPCWrappedNative::GetNewOrUsed(xpcObjectHelper& helper,
|
||||
}
|
||||
} else {
|
||||
ac.construct(static_cast<JSContext*>(cx), parent);
|
||||
|
||||
nsISupports *Object = helper.Object();
|
||||
if (nsXPCWrappedJSClass::IsWrappedJS(Object)) {
|
||||
nsCOMPtr<nsIXPConnectWrappedJS> wrappedjs(do_QueryInterface(Object));
|
||||
if (xpc::AccessCheck::isChrome(js::GetObjectCompartment(wrappedjs->GetJSObject())) &&
|
||||
!xpc::AccessCheck::isChrome(js::GetObjectCompartment(Scope->GetGlobalJSObject()))) {
|
||||
needsCOW = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AutoMarkingWrappedNativeProtoPtr proto(cx);
|
||||
@ -473,11 +450,6 @@ XPCWrappedNative::GetNewOrUsed(xpcObjectHelper& helper,
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (needsSOW)
|
||||
wrapper->SetNeedsSOW();
|
||||
if (needsCOW)
|
||||
wrapper->SetNeedsCOW();
|
||||
|
||||
return FinishCreate(Scope, Interface, cache, wrapper, resultWrapper);
|
||||
}
|
||||
|
||||
@ -667,21 +639,6 @@ XPCWrappedNative::Destroy()
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The only time GetRuntime() will be nullptr is if Destroy is called a
|
||||
* second time on a wrapped native. Since we already unregistered the
|
||||
* pointer the first time, there's no need to unregister again.
|
||||
* Unregistration is safe the first time because mWrapper isn't used
|
||||
* afterwards.
|
||||
*/
|
||||
if (XPCJSRuntime *rt = GetRuntime()) {
|
||||
if (IsIncrementalBarrierNeeded(rt->Runtime()))
|
||||
IncrementalObjectBarrier(GetWrapperPreserveColor());
|
||||
mWrapper.setToCrashOnTouch();
|
||||
} else {
|
||||
MOZ_ASSERT(mWrapper.isSetToCrashOnTouch());
|
||||
}
|
||||
|
||||
mMaybeScope = nullptr;
|
||||
}
|
||||
|
||||
@ -1226,15 +1183,6 @@ XPCWrappedNative::ReparentWrapperIfFound(XPCWrappedNativeScope* aOldScope,
|
||||
JS_SetPrivate(flat, nullptr);
|
||||
}
|
||||
|
||||
// Before proceeding, eagerly create any same-compartment security wrappers
|
||||
// that the object might have. This forces us to take the 'WithWrapper' path
|
||||
// while transplanting that handles this stuff correctly.
|
||||
{
|
||||
JSAutoCompartment innerAC(cx, aOldScope->GetGlobalJSObject());
|
||||
if (!wrapper->GetSameCompartmentSecurityWrapper(cx))
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Update scope maps. This section modifies global state, so from
|
||||
// here on out we crash if anything fails.
|
||||
Native2WrappedNativeMap* oldMap = aOldScope->GetWrappedNativeMap();
|
||||
@ -1271,20 +1219,10 @@ XPCWrappedNative::ReparentWrapperIfFound(XPCWrappedNativeScope* aOldScope,
|
||||
if (!newMap->Add(wrapper))
|
||||
MOZ_CRASH();
|
||||
|
||||
RootedObject ww(cx, wrapper->GetWrapper());
|
||||
if (ww) {
|
||||
RootedObject newwrapper(cx);
|
||||
MOZ_ASSERT(wrapper->NeedsSOW(), "weird wrapper wrapper");
|
||||
|
||||
// Oops. We don't support transplanting objects with SOWs anymore.
|
||||
flat = xpc::TransplantObject(cx, flat, newobj);
|
||||
if (!flat)
|
||||
MOZ_CRASH();
|
||||
|
||||
} else {
|
||||
flat = xpc::TransplantObject(cx, flat, newobj);
|
||||
if (!flat)
|
||||
MOZ_CRASH();
|
||||
}
|
||||
|
||||
MOZ_ASSERT(flat);
|
||||
wrapper->mFlatJSObject = flat;
|
||||
wrapper->mFlatJSObject.setFlags(FLAT_JS_OBJECT_VALID);
|
||||
@ -1309,11 +1247,6 @@ XPCWrappedNative::ReparentWrapperIfFound(XPCWrappedNativeScope* aOldScope,
|
||||
if (aNewParent) {
|
||||
if (!JS_SetParent(cx, flat, aNewParent))
|
||||
MOZ_CRASH();
|
||||
|
||||
JSObject *nw = wrapper->GetWrapper();
|
||||
if (nw && !JS_SetParent(cx, nw, JS_GetGlobalForObject(cx, aNewParent))) {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@ -1673,47 +1606,6 @@ XPCWrappedNative::InitTearOffJSObject(XPCWrappedNativeTearOff* to)
|
||||
return true;
|
||||
}
|
||||
|
||||
JSObject*
|
||||
XPCWrappedNative::GetSameCompartmentSecurityWrapper(JSContext *cx)
|
||||
{
|
||||
// Grab the current state of affairs.
|
||||
RootedObject flat(cx, GetFlatJSObject());
|
||||
RootedObject wrapper(cx, GetWrapper());
|
||||
|
||||
// If we already have a wrapper, it must be what we want.
|
||||
if (wrapper)
|
||||
return wrapper;
|
||||
|
||||
// Chrome callers don't need same-compartment security wrappers.
|
||||
JSCompartment *cxCompartment = js::GetContextCompartment(cx);
|
||||
MOZ_ASSERT(cxCompartment == js::GetObjectCompartment(flat));
|
||||
if (xpc::AccessCheck::isChrome(cxCompartment)) {
|
||||
MOZ_ASSERT(wrapper == nullptr);
|
||||
return flat;
|
||||
}
|
||||
|
||||
// Check the possibilities. Note that we need to check for null in each
|
||||
// case in order to distinguish between the 'no need for wrapper' and
|
||||
// 'wrapping failed' cases.
|
||||
//
|
||||
// NB: We don't make SOWs for remote XUL domains where XBL scopes are
|
||||
// disallowed.
|
||||
if (NeedsSOW() && xpc::AllowXBLScope(js::GetContextCompartment(cx))) {
|
||||
wrapper = xpc::WrapperFactory::WrapSOWObject(cx, flat);
|
||||
if (!wrapper)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// If we made a wrapper, cache it and return it.
|
||||
if (wrapper) {
|
||||
SetWrapper(wrapper);
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
// Otherwise, just return the bare JS reflection.
|
||||
return flat;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
static bool Throw(nsresult errNum, XPCCallContext& ccx)
|
||||
|
@ -1029,26 +1029,6 @@ static inline bool IS_PROTO_CLASS(const js::Class *clazz)
|
||||
clazz == &XPC_WN_ModsAllowed_NoCall_Proto_JSClass;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
namespace XPCWrapper {
|
||||
|
||||
enum WrapperType {
|
||||
UNKNOWN = 0,
|
||||
NONE = 0,
|
||||
XPCNW_IMPLICIT = 1 << 0,
|
||||
XPCNW_EXPLICIT = 1 << 1,
|
||||
XPCNW = (XPCNW_IMPLICIT | XPCNW_EXPLICIT),
|
||||
SJOW = 1 << 2,
|
||||
// SJOW must be the last wrapper type that can be returned to chrome.
|
||||
|
||||
XOW = 1 << 3,
|
||||
COW = 1 << 4,
|
||||
SOW = 1 << 5
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
// XPCWrappedNativeScope is one-to-one with a JS global object.
|
||||
|
||||
@ -2189,7 +2169,6 @@ public:
|
||||
GetProto()->TraceSelf(trc);
|
||||
else
|
||||
GetScope()->TraceSelf(trc);
|
||||
TraceWrapper(trc);
|
||||
if (mFlatJSObject && JS_IsGlobalObject(mFlatJSObject))
|
||||
{
|
||||
TraceXPCGlobal(trc, mFlatJSObject);
|
||||
@ -2232,41 +2211,6 @@ public:
|
||||
|
||||
bool HasExternalReference() const {return mRefCnt > 1;}
|
||||
|
||||
bool NeedsSOW() { return mWrapper.hasFlag(WRAPPER_NEEDS_SOW); }
|
||||
void SetNeedsSOW() { mWrapper.setFlags(WRAPPER_NEEDS_SOW); }
|
||||
bool NeedsCOW() { return mWrapper.hasFlag(WRAPPER_NEEDS_COW); }
|
||||
void SetNeedsCOW() { mWrapper.setFlags(WRAPPER_NEEDS_COW); }
|
||||
|
||||
JSObject* GetWrapperPreserveColor() const { return mWrapper.getPtr(); }
|
||||
|
||||
JSObject* GetWrapper()
|
||||
{
|
||||
JSObject* wrapper = GetWrapperPreserveColor();
|
||||
if (wrapper) {
|
||||
JS::ExposeObjectToActiveJS(wrapper);
|
||||
// Call this to unmark mFlatJSObject.
|
||||
GetFlatJSObject();
|
||||
}
|
||||
return wrapper;
|
||||
}
|
||||
void SetWrapper(JSObject *obj)
|
||||
{
|
||||
JS::IncrementalObjectBarrier(GetWrapperPreserveColor());
|
||||
mWrapper.setPtr(obj);
|
||||
}
|
||||
|
||||
void TraceWrapper(JSTracer *trc)
|
||||
{
|
||||
JS_CallTenuredObjectTracer(trc, &mWrapper, "XPCWrappedNative::mWrapper");
|
||||
}
|
||||
|
||||
// Returns the relevant same-compartment security if applicable, or
|
||||
// mFlatJSObject otherwise.
|
||||
//
|
||||
// This takes care of checking mWrapper to see if we already have such
|
||||
// a wrapper.
|
||||
JSObject *GetSameCompartmentSecurityWrapper(JSContext *cx);
|
||||
|
||||
void NoteTearoffs(nsCycleCollectionTraversalCallback& cb);
|
||||
|
||||
// Make ctor and dtor protected (rather than private) to placate nsCOMPtr.
|
||||
@ -2289,10 +2233,6 @@ protected:
|
||||
|
||||
private:
|
||||
enum {
|
||||
// Flags bits for mWrapper:
|
||||
WRAPPER_NEEDS_SOW = JS_BIT(0),
|
||||
WRAPPER_NEEDS_COW = JS_BIT(1),
|
||||
|
||||
// Flags bits for mFlatJSObject:
|
||||
FLAT_JS_OBJECT_VALID = JS_BIT(0)
|
||||
};
|
||||
@ -2326,7 +2266,6 @@ private:
|
||||
JS::TenuredHeap<JSObject*> mFlatJSObject;
|
||||
XPCNativeScriptableInfo* mScriptableInfo;
|
||||
XPCWrappedNativeTearOffChunk mFirstChunk;
|
||||
JS::TenuredHeap<JSObject*> mWrapper;
|
||||
};
|
||||
|
||||
/***************************************************************************
|
||||
|
@ -119,9 +119,6 @@ struct RuntimeStats;
|
||||
|
||||
#define XPCONNECT_GLOBAL_FLAGS XPCONNECT_GLOBAL_FLAGS_WITH_EXTRA_SLOTS(0)
|
||||
|
||||
extern bool
|
||||
xpc_OkToHandOutWrapper(nsWrapperCache *cache);
|
||||
|
||||
inline JSObject*
|
||||
xpc_FastGetCachedWrapper(nsWrapperCache *cache, JSObject *scope, JS::MutableHandleValue vp)
|
||||
{
|
||||
@ -129,8 +126,8 @@ xpc_FastGetCachedWrapper(nsWrapperCache *cache, JSObject *scope, JS::MutableHand
|
||||
JSObject* wrapper = cache->GetWrapper();
|
||||
if (wrapper &&
|
||||
js::GetObjectCompartment(wrapper) == js::GetObjectCompartment(scope) &&
|
||||
(cache->IsDOMBinding() ? !cache->HasSystemOnlyWrapper() :
|
||||
xpc_OkToHandOutWrapper(cache))) {
|
||||
!(cache->IsDOMBinding() && cache->HasSystemOnlyWrapper()))
|
||||
{
|
||||
vp.setObject(*wrapper);
|
||||
return wrapper;
|
||||
}
|
||||
|
@ -263,12 +263,7 @@ AccessCheck::needsSystemOnlyWrapper(JSObject *obj)
|
||||
JSObject* wrapper = obj;
|
||||
if (dom::GetSameCompartmentWrapperForDOMBinding(wrapper))
|
||||
return wrapper != obj;
|
||||
|
||||
if (!IS_WN_REFLECTOR(obj))
|
||||
return false;
|
||||
|
||||
XPCWrappedNative *wn = XPCWrappedNative::Get(obj);
|
||||
return wn->NeedsSOW();
|
||||
return false;
|
||||
}
|
||||
|
||||
enum Access { READ = (1<<0), WRITE = (1<<1), NO_ACCESS = 0 };
|
||||
|
@ -494,22 +494,9 @@ WrapperFactory::WrapForSameCompartment(JSContext *cx, HandleObject objArg)
|
||||
obj = JS_ObjectToOuterObject(cx, obj);
|
||||
NS_ENSURE_TRUE(obj, nullptr);
|
||||
|
||||
if (dom::GetSameCompartmentWrapperForDOMBinding(*obj.address())) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!dom::IsDOMObject(obj));
|
||||
|
||||
if (!IS_WN_REFLECTOR(obj))
|
||||
return obj;
|
||||
|
||||
// Extract the WN. It should exist.
|
||||
XPCWrappedNative *wn = XPCWrappedNative::Get(obj);
|
||||
MOZ_ASSERT(wn, "Trying to wrap a dead WN!");
|
||||
|
||||
// The WN knows what to do.
|
||||
RootedObject wrapper(cx, wn->GetSameCompartmentSecurityWrapper(cx));
|
||||
return wrapper;
|
||||
// The method below is a no-op for non-DOM objects.
|
||||
dom::GetSameCompartmentWrapperForDOMBinding(*obj.address());
|
||||
return obj;
|
||||
}
|
||||
|
||||
// Call WaiveXrayAndWrap when you have a JS object that you don't want to be
|
||||
|
@ -600,10 +600,6 @@
|
||||
/* any new errors here should have an associated entry added in xpc.msg */
|
||||
|
||||
ERROR(NS_SUCCESS_I_DID_SOMETHING, SUCCESS(1)),
|
||||
/* Classes that want to only be touched by chrome (or from code whose
|
||||
* filename begins with chrome://global/) shoudl return this from their
|
||||
* scriptable helper's PreCreate hook. */
|
||||
ERROR(NS_SUCCESS_CHROME_ACCESS_ONLY, SUCCESS(2)),
|
||||
#undef MODULE
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user