зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
a8b6ee5b62
Коммит
b572a685e7
|
@ -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()));
|
||||
|
|
Загрузка…
Ссылка в новой задаче