Bug 753277 - Assert that all cross-scope wrapper reparenting operations are cross-compartment, and remove the conditional. r=mrbkap

The reindentation is pure. No snakes.
This commit is contained in:
Bobby Holley 2012-05-14 12:52:17 +02:00
Родитель a8b6ee5b62
Коммит b572a685e7
1 изменённых файлов: 88 добавлений и 108 удалений

Просмотреть файл

@ -1557,15 +1557,6 @@ XPCWrappedNative::ReparentWrapperIfFound(XPCCallContext& ccx,
return NS_OK;
}
bool crosscompartment = js::GetObjectCompartment(aOldScope->GetGlobalJSObject()) !=
js::GetObjectCompartment(aNewScope->GetGlobalJSObject());
#ifdef DEBUG
if (crosscompartment) {
NS_ASSERTION(aNewParent, "won't be able to find the new parent");
NS_ASSERTION(wrapper, "can't transplant slim wrappers");
}
#endif
// ReparentWrapperIfFound is really only meant to be called from DOM code
// which must happen only on the main thread. Bail if we're on some other
// thread or have a non-main-thread-only wrapper.
@ -1585,6 +1576,12 @@ XPCWrappedNative::ReparentWrapperIfFound(XPCCallContext& ccx,
AutoMarkingWrappedNativeProtoPtr oldProto(ccx);
AutoMarkingWrappedNativeProtoPtr newProto(ccx);
// Cross-scope means cross-compartment.
MOZ_ASSERT(js::GetObjectCompartment(aOldScope->GetGlobalJSObject()) !=
js::GetObjectCompartment(aNewScope->GetGlobalJSObject()));
NS_ASSERTION(aNewParent, "won't be able to find the new parent");
NS_ASSERTION(wrapper, "can't transplant slim wrappers");
if (!wrapper)
oldProto = GetSlimWrapperProto(flat);
else if (wrapper->HasProto())
@ -1639,108 +1636,91 @@ XPCWrappedNative::ReparentWrapperIfFound(XPCCallContext& ccx,
(void) newMap->Add(wrapper);
}
// We only try to fixup the __proto__ JSObject if the wrapper
// is directly using that of its XPCWrappedNativeProto.
JSObject *newobj = JS_CloneObject(ccx, flat,
newProto->GetJSProtoObject(),
aNewParent);
if (!newobj)
return NS_ERROR_FAILURE;
if (crosscompartment) {
JSObject *newobj = JS_CloneObject(ccx, flat,
newProto->GetJSProtoObject(),
aNewParent);
if (!newobj)
JS_SetPrivate(flat, nsnull);
JSObject *propertyHolder =
JS_NewObjectWithGivenProto(ccx, NULL, NULL, aNewParent);
if (!propertyHolder || !JS_CopyPropertiesFrom(ccx, propertyHolder, flat))
return NS_ERROR_OUT_OF_MEMORY;
// 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.
{
JSAutoEnterCompartment innerAC;
if (!innerAC.enter(ccx, aOldScope->GetGlobalJSObject()) ||
!wrapper->GetSameCompartmentSecurityWrapper(ccx))
return NS_ERROR_FAILURE;
JS_SetPrivate(flat, nsnull);
JSObject *propertyHolder =
JS_NewObjectWithGivenProto(ccx, NULL, NULL, aNewParent);
if (!propertyHolder || !JS_CopyPropertiesFrom(ccx, propertyHolder, flat))
return NS_ERROR_OUT_OF_MEMORY;
// 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.
{
JSAutoEnterCompartment innerAC;
if (!innerAC.enter(ccx, aOldScope->GetGlobalJSObject()) ||
!wrapper->GetSameCompartmentSecurityWrapper(ccx))
return NS_ERROR_FAILURE;
}
JSObject *ww = wrapper->GetWrapper();
if (ww) {
JSObject *newwrapper;
MOZ_ASSERT(!xpc::WrapperFactory::IsComponentsObject(flat),
"Components object should never get here");
if (xpc::WrapperFactory::IsLocationObject(flat)) {
newwrapper = xpc::WrapperFactory::WrapLocationObject(ccx, newobj);
if (!newwrapper)
return NS_ERROR_FAILURE;
} else {
NS_ASSERTION(wrapper->NeedsSOW(), "weird wrapper wrapper");
newwrapper = xpc::WrapperFactory::WrapSOWObject(ccx, newobj);
if (!newwrapper)
return NS_ERROR_FAILURE;
}
// Ok, now we do the special object-plus-wrapper transplant.
//
// This is some pretty serious brain surgery.
//
// In the case where we wrap a Location object from a same-
// origin compartment, we actually want our cross-compartment
// wrapper to point to the same-compartment wrapper in the
// other compartment. This double-wrapping allows expandos to
// be shared. So our wrapping callback (in WrapperFactory.cpp)
// calls XPCWrappedNative::GetSameCompartmentSecurityWrapper
// before wrapping same-origin Location objects.
//
// This normally works fine, but gets tricky here.
// js_TransplantObjectWithWrapper needs to update the old
// same-compartment security wrapper to be a cross-compartment
// wrapper to the newly transplanted object. So it needs to go
// through the aforementioned double-wrapping mechanism.
// But during the call, things aren't really in a consistent
// state, because mFlatJSObject hasn't yet been updated to
// point to the object in the new compartment.
//
// So we need to cache the new same-compartment security
// wrapper on the XPCWN before the call, so that
// GetSameCompartmentSecurityWrapper can return early before
// getting confused. Hold your breath.
JSObject *wwsaved = ww;
wrapper->SetWrapper(newwrapper);
ww = js_TransplantObjectWithWrapper(ccx, flat, ww, newobj,
newwrapper);
if (!ww) {
wrapper->SetWrapper(wwsaved);
return NS_ERROR_FAILURE;
}
flat = newobj;
} else {
flat = JS_TransplantObject(ccx, flat, newobj);
if (!flat)
return NS_ERROR_FAILURE;
}
wrapper->mFlatJSObject = flat;
if (cache)
cache->SetWrapper(flat);
if (!JS_CopyPropertiesFrom(ccx, flat, propertyHolder))
return NS_ERROR_FAILURE;
} else {
if (wrapper->HasProto() &&
js::GetObjectProto(flat) == oldProto->GetJSProtoObject()) {
if (!JS_SetPrototype(ccx, flat, newProto->GetJSProtoObject())) {
// this is bad, very bad
NS_ERROR("JS_SetPrototype failed");
return NS_ERROR_FAILURE;
}
} else {
NS_WARNING("Moving XPConnect wrappedNative to new scope, "
"but can't fixup __proto__");
}
}
JSObject *ww = wrapper->GetWrapper();
if (ww) {
JSObject *newwrapper;
MOZ_ASSERT(!xpc::WrapperFactory::IsComponentsObject(flat),
"Components object should never get here");
if (xpc::WrapperFactory::IsLocationObject(flat)) {
newwrapper = xpc::WrapperFactory::WrapLocationObject(ccx, newobj);
if (!newwrapper)
return NS_ERROR_FAILURE;
} else {
NS_ASSERTION(wrapper->NeedsSOW(), "weird wrapper wrapper");
newwrapper = xpc::WrapperFactory::WrapSOWObject(ccx, newobj);
if (!newwrapper)
return NS_ERROR_FAILURE;
}
// Ok, now we do the special object-plus-wrapper transplant.
//
// This is some pretty serious brain surgery.
//
// In the case where we wrap a Location object from a same-
// origin compartment, we actually want our cross-compartment
// wrapper to point to the same-compartment wrapper in the
// other compartment. This double-wrapping allows expandos to
// be shared. So our wrapping callback (in WrapperFactory.cpp)
// calls XPCWrappedNative::GetSameCompartmentSecurityWrapper
// before wrapping same-origin Location objects.
//
// This normally works fine, but gets tricky here.
// js_TransplantObjectWithWrapper needs to update the old
// same-compartment security wrapper to be a cross-compartment
// wrapper to the newly transplanted object. So it needs to go
// through the aforementioned double-wrapping mechanism.
// But during the call, things aren't really in a consistent
// state, because mFlatJSObject hasn't yet been updated to
// point to the object in the new compartment.
//
// So we need to cache the new same-compartment security
// wrapper on the XPCWN before the call, so that
// GetSameCompartmentSecurityWrapper can return early before
// getting confused. Hold your breath.
JSObject *wwsaved = ww;
wrapper->SetWrapper(newwrapper);
ww = js_TransplantObjectWithWrapper(ccx, flat, ww, newobj,
newwrapper);
if (!ww) {
wrapper->SetWrapper(wwsaved);
return NS_ERROR_FAILURE;
}
flat = newobj;
} else {
flat = JS_TransplantObject(ccx, flat, newobj);
if (!flat)
return NS_ERROR_FAILURE;
}
wrapper->mFlatJSObject = flat;
if (cache)
cache->SetWrapper(flat);
if (!JS_CopyPropertiesFrom(ccx, flat, propertyHolder))
return NS_ERROR_FAILURE;
} else {
JS_SetReservedSlot(flat, 0,
PRIVATE_TO_JSVAL(newProto.get()));