Bug 507991. Store an alternate URI on the first binding and use that to compare binding URIs. r=sicking

--HG--
extra : rebase_source : 47c46b906039ef6b5e3cb176c6fc6c62018d587d
This commit is contained in:
Timothy Nikkel 2009-11-03 15:45:10 -06:00
parent 23405eac2b
commit 8eba2d79ca
5 changed files with 38 additions and 51 deletions

View File

@ -883,12 +883,7 @@ nsBindingManager::RemoveLayeredBinding(nsIContent* aContent, nsIURI* aURL)
NS_ENSURE_FALSE(binding->GetBaseBinding(), NS_ERROR_FAILURE);
// Make sure that the binding has the URI that is requested to be removed
nsIURI* bindingUri = binding->PrototypeBinding()->BindingURI();
PRBool equalUri;
nsresult rv = aURL->Equals(bindingUri, &equalUri);
NS_ENSURE_SUCCESS(rv, rv);
if (!equalUri) {
if (!binding->PrototypeBinding()->CompareBindingURI(aURL)) {
return NS_OK;
}

View File

@ -566,7 +566,7 @@ nsXBLContentSink::ConstructBinding()
if (!mBinding)
return NS_ERROR_OUT_OF_MEMORY;
rv = mBinding->Init(cid, mDocInfo, binding);
rv = mBinding->Init(cid, mDocInfo, binding, !mFoundFirstBinding);
if (NS_SUCCEEDED(rv) &&
NS_SUCCEEDED(mDocInfo->SetPrototypeBinding(cid, mBinding))) {
if (!mFoundFirstBinding) {

View File

@ -313,7 +313,8 @@ nsXBLPrototypeBinding::nsXBLPrototypeBinding()
nsresult
nsXBLPrototypeBinding::Init(const nsACString& aID,
nsIXBLDocumentInfo* aInfo,
nsIContent* aElement)
nsIContent* aElement,
PRBool aFirstBinding)
{
if (!kAttrPool || !nsXBLInsertionPointEntry::PoolInited()) {
return NS_ERROR_OUT_OF_MEMORY;
@ -325,8 +326,13 @@ nsXBLPrototypeBinding::Init(const nsACString& aID,
// The binding URI might not be a nsIURL (e.g. for data: URIs). In that case,
// we always use the first binding, so we don't need to keep track of the ID.
nsCOMPtr<nsIURL> bindingURL = do_QueryInterface(mBindingURI);
if (bindingURL)
if (bindingURL) {
if (aFirstBinding) {
rv = mBindingURI->Clone(getter_AddRefs(mAlternateBindingURI));
NS_ENSURE_SUCCESS(rv, rv);
}
bindingURL->SetRef(aID);
}
mXBLDocInfoWeak = aInfo;
@ -334,6 +340,16 @@ nsXBLPrototypeBinding::Init(const nsACString& aID,
return NS_OK;
}
PRBool nsXBLPrototypeBinding::CompareBindingURI(nsIURI* aURI) const
{
PRBool equal;
mBindingURI->Equals(aURI, &equal);
if (!equal && mAlternateBindingURI) {
mAlternateBindingURI->Equals(aURI, &equal);
}
return equal;
}
static PRIntn
TraverseInsertionPoint(nsHashKey* aKey, void* aData, void* aClosure)
{

View File

@ -74,8 +74,13 @@ public:
void SetBindingElement(nsIContent* aElement);
nsIURI* BindingURI() const { return mBindingURI; }
nsIURI* AlternateBindingURI() const { return mAlternateBindingURI; }
nsIURI* DocURI() const { return mXBLDocInfoWeak->DocumentURI(); }
// Checks if aURI refers to this binding by comparing to both possible
// binding URIs.
PRBool CompareBindingURI(nsIURI* aURI) const;
nsresult GetAllowScripts(PRBool* aResult);
nsresult BindingAttached(nsIContent* aBoundElement);
@ -195,7 +200,8 @@ public:
// binding's handlers, properties, etc are all set.
nsresult Init(const nsACString& aRef,
nsIXBLDocumentInfo* aInfo,
nsIContent* aElement);
nsIContent* aElement,
PRBool aFirstBinding = PR_FALSE);
void Traverse(nsCycleCollectionTraversalCallback &cb) const;
void UnlinkJSObjects();
@ -256,6 +262,7 @@ protected:
// MEMBER VARIABLES
protected:
nsCOMPtr<nsIURI> mBindingURI;
nsCOMPtr<nsIURI> mAlternateBindingURI; // Alternate id-less URI that is only non-null on the first binding.
nsCOMPtr<nsIContent> mBinding; // Strong. We own a ref to our content element in the binding doc.
nsAutoPtr<nsXBLPrototypeHandler> mPrototypeHandler; // Strong. DocInfo owns us, and we own the handlers.

View File

@ -119,43 +119,8 @@ IsAncestorBinding(nsIDocument* aDocument,
if (!binding) {
continue;
}
PRBool equal;
nsresult rv;
nsCOMPtr<nsIURL> childBindingURL = do_QueryInterface(aChildBindingURI);
nsCAutoString childRef;
if (childBindingURL &&
NS_SUCCEEDED(childBindingURL->GetRef(childRef)) &&
childRef.IsEmpty()) {
// If the child URL has no ref, we need to strip away the ref from the
// URI we're comparing it to, since the child URL will end up pointing
// to the first binding defined at its URI, and that could be the same
// binding that's referred to more specifically by the already attached
// binding's URI via its ref.
// This means we'll get false positives if someone refers to the first
// binding at a given URI without a ref and also binds a parent or child
// to a different binding at that URI *with* a ref, but that shouldn't
// ever be necessary so we don't need to support it.
nsCOMPtr<nsIURI> compareURI;
rv = binding->PrototypeBinding()->BindingURI()->Clone(getter_AddRefs(compareURI));
NS_ENSURE_SUCCESS(rv, PR_TRUE); // assume the worst
nsCOMPtr<nsIURL> compareURL = do_QueryInterface(compareURI, &rv);
NS_ENSURE_SUCCESS(rv, PR_TRUE); // assume the worst
rv = compareURL->SetRef(EmptyCString());
NS_ENSURE_SUCCESS(rv, PR_TRUE); // assume the worst
rv = compareURL->Equals(aChildBindingURI, &equal);
} else {
// Just compare the URIs
rv = binding->PrototypeBinding()->BindingURI()->Equals(aChildBindingURI,
&equal);
}
NS_ENSURE_SUCCESS(rv, PR_TRUE); // assume the worst
if (equal) {
if (binding->PrototypeBinding()->CompareBindingURI(aChildBindingURI)) {
++bindingRecursion;
if (bindingRecursion < NS_MAX_XBL_BINDING_RECURSION) {
continue;
@ -599,9 +564,7 @@ nsXBLService::LoadBindings(nsIContent* aContent, nsIURI* aURL,
}
else {
// See if the URIs match.
nsIURI* uri = styleBinding->PrototypeBinding()->BindingURI();
PRBool equal;
if (NS_SUCCEEDED(uri->Equals(aURL, &equal)) && equal)
if (styleBinding->PrototypeBinding()->CompareBindingURI(aURL))
return NS_OK;
FlushStyleBindings(aContent);
binding = nsnull;
@ -883,8 +846,6 @@ nsXBLService::GetBinding(nsIContent* aBoundElement, nsIURI* aURI,
if (!aURI)
return NS_ERROR_FAILURE;
NS_ENSURE_TRUE(aDontExtendURIs.AppendElement(aURI), NS_ERROR_OUT_OF_MEMORY);
nsCAutoString ref;
nsCOMPtr<nsIURL> url(do_QueryInterface(aURI));
if (url)
@ -914,6 +875,14 @@ nsXBLService::GetBinding(nsIContent* aBoundElement, nsIURI* aURI,
if (!protoBinding)
return NS_ERROR_FAILURE;
NS_ENSURE_TRUE(aDontExtendURIs.AppendElement(protoBinding->BindingURI()),
NS_ERROR_OUT_OF_MEMORY);
nsCOMPtr<nsIURI> altBindingURI = protoBinding->AlternateBindingURI();
if (altBindingURI) {
NS_ENSURE_TRUE(aDontExtendURIs.AppendElement(altBindingURI),
NS_ERROR_OUT_OF_MEMORY);
}
nsCOMPtr<nsIContent> child = protoBinding->GetBindingElement();
// Our prototype binding must have all its resources loaded.