mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-24 02:35:41 +00:00
Bug 734475 - Take the full union of native sets when bringing non-PreCreate XPWNs across compartments. r=mrbkap
This commit is contained in:
parent
aaaa3c0e75
commit
e2e6e39b20
@ -665,6 +665,54 @@ XPCNativeSet::GetNewOrUsed(XPCCallContext& ccx,
|
||||
return set;
|
||||
}
|
||||
|
||||
// static
|
||||
XPCNativeSet*
|
||||
XPCNativeSet::GetNewOrUsed(XPCCallContext& ccx,
|
||||
XPCNativeSet* firstSet,
|
||||
XPCNativeSet* secondSet,
|
||||
bool preserveFirstSetOrder)
|
||||
{
|
||||
// Figure out how many interfaces we'll need in the new set.
|
||||
PRUint32 uniqueCount = firstSet->mInterfaceCount;
|
||||
for (PRUint32 i = 0; i < secondSet->mInterfaceCount; ++i) {
|
||||
if (!firstSet->HasInterface(secondSet->mInterfaces[i]))
|
||||
uniqueCount++;
|
||||
}
|
||||
|
||||
// If everything in secondSet was a duplicate, we can just use the first
|
||||
// set.
|
||||
if (uniqueCount == firstSet->mInterfaceCount)
|
||||
return firstSet;
|
||||
|
||||
// If the secondSet is just a superset of the first, we can use it provided
|
||||
// that the caller doesn't care about ordering.
|
||||
if (!preserveFirstSetOrder && uniqueCount == secondSet->mInterfaceCount)
|
||||
return secondSet;
|
||||
|
||||
// Ok, darn. Now we have to make a new set.
|
||||
//
|
||||
// It would be faster to just create the new set all at once, but that
|
||||
// would involve wrangling with some pretty hairy code - especially since
|
||||
// a lot of stuff assumes that sets are created by adding one interface to an
|
||||
// existing set. So let's just do the slow and easy thing and hope that the
|
||||
// above optimizations handle the common cases.
|
||||
XPCNativeSet* currentSet = firstSet;
|
||||
for (PRUint32 i = 0; i < secondSet->mInterfaceCount; ++i) {
|
||||
XPCNativeInterface* iface = secondSet->mInterfaces[i];
|
||||
if (!currentSet->HasInterface(iface)) {
|
||||
// Create a new augmented set, inserting this interface at the end.
|
||||
PRUint32 pos = currentSet->mInterfaceCount;
|
||||
currentSet = XPCNativeSet::GetNewOrUsed(ccx, currentSet, iface, pos);
|
||||
if (!currentSet)
|
||||
return nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
// We've got the union set. Hand it back to the caller.
|
||||
MOZ_ASSERT(currentSet->mInterfaceCount == uniqueCount);
|
||||
return currentSet;
|
||||
}
|
||||
|
||||
// static
|
||||
XPCNativeSet*
|
||||
XPCNativeSet::NewInstance(XPCCallContext& ccx,
|
||||
|
@ -1882,6 +1882,18 @@ public:
|
||||
XPCNativeInterface* newInterface,
|
||||
PRUint16 position);
|
||||
|
||||
// This generates a union set.
|
||||
//
|
||||
// If preserveFirstSetOrder is true, the elements from |firstSet| come first,
|
||||
// followed by any non-duplicate items from |secondSet|. If false, the same
|
||||
// algorithm is applied; but if we detect that |secondSet| is a superset of
|
||||
// |firstSet|, we return |secondSet| without worrying about whether the
|
||||
// ordering might differ from |firstSet|.
|
||||
static XPCNativeSet* GetNewOrUsed(XPCCallContext& ccx,
|
||||
XPCNativeSet* firstSet,
|
||||
XPCNativeSet* secondSet,
|
||||
bool preserveFirstSetOrder);
|
||||
|
||||
static void ClearCacheEntryForClassInfo(nsIClassInfo* classInfo);
|
||||
|
||||
inline JSBool FindMember(jsid name, XPCNativeMember** pMember,
|
||||
|
@ -236,9 +236,21 @@ WrapperFactory::PrepareForWrapping(JSContext *cx, JSObject *scope, JSObject *obj
|
||||
obj = JSVAL_TO_OBJECT(v);
|
||||
NS_ASSERTION(IS_WN_WRAPPER(obj), "bad object");
|
||||
|
||||
// Because the underlying native didn't have a PreCreate hook, we had
|
||||
// to a new (or possibly pre-existing) XPCWN in our compartment.
|
||||
// This could be a problem for chrome code that passes XPCOM objects
|
||||
// across compartments, because the effects of QI would disappear across
|
||||
// compartments.
|
||||
//
|
||||
// So whenever we pull an XPCWN across compartments in this manner, we
|
||||
// give the destination object the union of the two native sets. We try
|
||||
// to do this cleverly in the common case to avoid too much overhead.
|
||||
XPCWrappedNative *newwn = static_cast<XPCWrappedNative *>(xpc_GetJSPrivate(obj));
|
||||
if (newwn->GetSet()->GetInterfaceCount() < wn->GetSet()->GetInterfaceCount())
|
||||
newwn->SetSet(wn->GetSet());
|
||||
XPCNativeSet *unionSet = XPCNativeSet::GetNewOrUsed(ccx, newwn->GetSet(),
|
||||
wn->GetSet(), false);
|
||||
if (!unionSet)
|
||||
return nsnull;
|
||||
newwn->SetSet(unionSet);
|
||||
}
|
||||
|
||||
return DoubleWrap(cx, obj, flags);
|
||||
|
Loading…
Reference in New Issue
Block a user