Bug 366770: use the first binding in the file if no fragment identifier is present in a binding's URI, r+sr=bzbarsky

This commit is contained in:
gavin%gavinsharp.com 2007-02-24 16:27:51 +00:00
Родитель 90d1fd161d
Коммит d2dae6875b
11 изменённых файлов: 66 добавлений и 59 удалений

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

@ -44,5 +44,9 @@ include $(DEPTH)/config/autoconf.mk
DIRS = public src builtin
ifdef MOZ_MOCHITEST
DIRS += test
endif
include $(topsrcdir)/config/rules.mk

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

@ -54,9 +54,9 @@ class nsXBLPrototypeBinding;
class nsIURI;
class nsACString;
// 3eedb7ff-d51d-4461-8162-a192b93216de
// 2d8334b0-e0b8-4a23-9153-dc89ac275894
#define NS_IXBLDOCUMENTINFO_IID \
{ 0x3eedb7ff, 0xd51d, 0x4461, { 0x81, 0x62, 0xa1, 0x92, 0xb9, 0x32, 0x16, 0xde } }
{ 0x2d8334b0, 0xe0b8, 0x4a23, { 0x91, 0x52, 0xdc, 0x89, 0xac, 0x27, 0x58, 0x94 } }
class nsIXBLDocumentInfo : public nsISupports
{
@ -73,6 +73,8 @@ public:
NS_IMETHOD GetPrototypeBinding(const nsACString& aRef, nsXBLPrototypeBinding** aResult)=0;
NS_IMETHOD SetPrototypeBinding(const nsACString& aRef, nsXBLPrototypeBinding* aBinding)=0;
NS_IMETHOD SetFirstPrototypeBinding(nsXBLPrototypeBinding* aBinding)=0;
NS_IMETHOD FlushSkinStylesheets()=0;
// Tells whether the scheme of the document URI is "chrome".

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

@ -460,13 +460,9 @@ nsXBLBinding::GenerateAnonymousContent()
// See if there's an includes attribute.
if (nsContentUtils::HasNonEmptyAttr(content, kNameSpaceID_None,
nsGkAtoms::includes)) {
nsCAutoString id;
mPrototypeBinding->GetID(id);
nsCAutoString message("An XBL Binding with an id of ");
message += id;
message += " and found in the file ";
nsCAutoString message("An XBL Binding with URI ");
nsCAutoString uri;
mPrototypeBinding->DocURI()->GetSpec(uri);
mPrototypeBinding->BindingURI()->GetSpec(uri);
message += uri;
message += " is still using the deprecated\n<content includes=\"\"> syntax! Use <children> instead!\n";
NS_WARNING(message.get());

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

@ -83,6 +83,7 @@ nsXBLContentSink::nsXBLContentSink()
: mState(eXBL_InDocument),
mSecondaryState(eXBL_None),
mDocInfo(nsnull),
mFoundFirstBinding(PR_FALSE),
mIsChromeOrResource(PR_FALSE),
mBinding(nsnull),
mHandler(nsnull),
@ -563,6 +564,10 @@ nsXBLContentSink::ConstructBinding()
rv = mBinding->Init(cid, mDocInfo, binding);
if (NS_SUCCEEDED(rv)) {
if (!mFoundFirstBinding) {
mFoundFirstBinding = PR_TRUE;
mDocInfo->SetFirstPrototypeBinding(mBinding);
}
mDocInfo->SetPrototypeBinding(cid, mBinding);
binding->UnsetAttr(kNameSpaceID_None, nsGkAtoms::id, PR_FALSE);
} else {

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

@ -162,7 +162,8 @@ protected:
XBLPrimaryState mState;
XBLSecondaryState mSecondaryState;
nsIXBLDocumentInfo* mDocInfo;
PRBool mIsChromeOrResource; // For bug #45989
PRPackedBool mIsChromeOrResource; // For bug #45989
PRPackedBool mFoundFirstBinding;
nsXBLPrototypeBinding* mBinding;
nsXBLPrototypeHandler* mHandler; // current handler, owned by its PrototypeBinding

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

@ -444,7 +444,8 @@ nsXBLDocumentInfo::nsXBLDocumentInfo(nsIDocument* aDocument)
: mDocument(aDocument),
mScriptAccess(PR_TRUE),
mIsChrome(PR_FALSE),
mBindingTable(nsnull)
mBindingTable(nsnull),
mFirstBinding(nsnull)
{
nsIURI* uri = aDocument->GetDocumentURI();
if (IsChromeURI(uri)) {
@ -477,6 +478,12 @@ nsXBLDocumentInfo::GetPrototypeBinding(const nsACString& aRef, nsXBLPrototypeBin
if (!mBindingTable)
return NS_OK;
if (aRef.IsEmpty()) {
// Return our first binding
*aResult = mFirstBinding;
return NS_OK;
}
const nsPromiseFlatCString& flat = PromiseFlatCString(aRef);
nsCStringKey key(flat.get());
*aResult = NS_STATIC_CAST(nsXBLPrototypeBinding*, mBindingTable->Get(&key));
@ -505,6 +512,14 @@ nsXBLDocumentInfo::SetPrototypeBinding(const nsACString& aRef, nsXBLPrototypeBin
return NS_OK;
}
NS_IMETHODIMP
nsXBLDocumentInfo::SetFirstPrototypeBinding(nsXBLPrototypeBinding* aBinding)
{
mFirstBinding = aBinding;
return NS_OK;
}
PRBool PR_CALLBACK FlushScopedSkinSheets(nsHashKey* aKey, void* aData, void* aClosure)
{
nsXBLPrototypeBinding* proto = (nsXBLPrototypeBinding*)aData;

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

@ -61,6 +61,8 @@ public:
NS_IMETHOD GetPrototypeBinding(const nsACString& aRef, nsXBLPrototypeBinding** aResult);
NS_IMETHOD SetPrototypeBinding(const nsACString& aRef, nsXBLPrototypeBinding* aBinding);
NS_IMETHOD SetFirstPrototypeBinding(nsXBLPrototypeBinding* aBinding);
NS_IMETHOD FlushSkinStylesheets();
NS_IMETHOD_(PRBool) IsChrome() { return mIsChrome; }
@ -77,6 +79,8 @@ private:
PRPackedBool mIsChrome;
// the binding table owns each nsXBLPrototypeBinding
nsObjectHashtable* mBindingTable;
// non-owning pointer to the first binding in the table
nsXBLPrototypeBinding* mFirstBinding;
nsCOMPtr<nsIScriptGlobalObject> mGlobalObject;
};

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

@ -263,16 +263,15 @@ nsXBLPrototypeBinding::Init(const nsACString& aID,
return NS_ERROR_OUT_OF_MEMORY;
}
nsCOMPtr<nsIURI> uri;
nsresult rv = NS_NewURI(getter_AddRefs(uri),
NS_LITERAL_CSTRING("#") + aID,
nsnull,
aInfo->DocumentURI());
nsresult rv = aInfo->DocumentURI()->Clone(getter_AddRefs(mBindingURI));
NS_ENSURE_SUCCESS(rv, rv);
mBindingURI = do_QueryInterface(uri, &rv);
NS_ENSURE_SUCCESS(rv, rv);
// 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)
bindingURL->SetRef(aID);
mXBLDocInfoWeak = aInfo;
SetBindingElement(aElement);

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

@ -50,7 +50,6 @@
#include "nsHashtable.h"
#include "nsIXBLDocumentInfo.h"
#include "nsCOMArray.h"
#include "nsIURL.h"
class nsIAtom;
class nsIDocument;
@ -76,7 +75,6 @@ public:
nsIURI* BindingURI() const { return mBindingURI; }
nsIURI* DocURI() const { return mXBLDocInfoWeak->DocumentURI(); }
nsresult GetID(nsACString& aResult) const { return mBindingURI->GetRef(aResult); }
nsresult GetAllowScripts(PRBool* aResult);
@ -230,7 +228,7 @@ protected:
// MEMBER VARIABLES
protected:
nsCOMPtr<nsIURL> mBindingURI;
nsCOMPtr<nsIURI> mBindingURI;
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.

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

@ -144,13 +144,13 @@ IsAncestorBinding(nsIDocument* aDocument,
class nsXBLBindingRequest
{
public:
nsCOMPtr<nsIURL> mBindingURL;
nsCOMPtr<nsIURI> mBindingURI;
nsCOMPtr<nsIContent> mBoundElement;
static nsXBLBindingRequest*
Create(nsFixedSizeAllocator& aPool, nsIURL* aURL, nsIContent* aBoundElement) {
Create(nsFixedSizeAllocator& aPool, nsIURI* aURI, nsIContent* aBoundElement) {
void* place = aPool.Alloc(sizeof(nsXBLBindingRequest));
return place ? ::new (place) nsXBLBindingRequest(aURL, aBoundElement) : nsnull;
return place ? ::new (place) nsXBLBindingRequest(aURI, aBoundElement) : nsnull;
}
static void
@ -169,7 +169,7 @@ public:
// Get the binding.
PRBool ready = PR_FALSE;
gXBLService->BindingReady(mBoundElement, mBindingURL, &ready);
gXBLService->BindingReady(mBoundElement, mBindingURI, &ready);
if (!ready)
return;
@ -202,8 +202,8 @@ public:
static int gRefCnt;
protected:
nsXBLBindingRequest(nsIURL* aURL, nsIContent* aBoundElement)
: mBindingURL(aURL),
nsXBLBindingRequest(nsIURI* aURI, nsIContent* aBoundElement)
: mBindingURI(aURI),
mBoundElement(aBoundElement)
{
gRefCnt++;
@ -375,7 +375,7 @@ nsXBLStreamListener::HasRequest(nsIURI* aURI, nsIContent* aElt)
nsXBLBindingRequest* req = (nsXBLBindingRequest*)mBindingRequests.ElementAt(i);
PRBool eq;
if (req->mBoundElement == aElt &&
NS_SUCCEEDED(req->mBindingURL->Equals(aURI, &eq)) && eq)
NS_SUCCEEDED(req->mBindingURI->Equals(aURI, &eq)) && eq)
return PR_TRUE;
}
@ -854,23 +854,11 @@ nsXBLService::GetBinding(nsIContent* aBoundElement, nsIURI* aURI,
NS_ENSURE_TRUE(aDontExtendURIs.AppendElement(aURI), NS_ERROR_OUT_OF_MEMORY);
nsCOMPtr<nsIURL> url(do_QueryInterface(aURI));
if (!url) {
#ifdef DEBUG
NS_ERROR("Binding load from a non-URL URI not allowed.");
nsCAutoString spec;
aURI->GetSpec(spec);
fprintf(stderr, "Spec of non-URL URI is: '%s'\n", spec.get());
#endif
return NS_ERROR_FAILURE;
}
nsCAutoString ref;
url->GetRef(ref);
NS_ASSERTION(!ref.IsEmpty(), "Incorrect syntax for an XBL binding");
if (ref.IsEmpty())
return NS_ERROR_FAILURE;
nsCOMPtr<nsIURL> url(do_QueryInterface(aURI));
if (url)
url->GetRef(ref);
nsCOMPtr<nsIDocument> boundDocument = aBoundElement->GetOwnerDoc();
nsCOMPtr<nsIXBLDocumentInfo> docInfo;
@ -1048,14 +1036,13 @@ nsXBLService::LoadBindingDocumentInfo(nsIContent* aBoundElement,
*aResult = nsnull;
nsCOMPtr<nsIXBLDocumentInfo> info;
nsCOMPtr<nsIURI> uriClone;
rv = aBindingURI->Clone(getter_AddRefs(uriClone));
nsCOMPtr<nsIURI> documentURI;
rv = aBindingURI->Clone(getter_AddRefs(documentURI));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIURL> documentURI(do_QueryInterface(uriClone, &rv));
NS_ENSURE_TRUE(documentURI, rv);
documentURI->SetRef(EmptyCString());
nsCOMPtr<nsIURL> documentURL(do_QueryInterface(documentURI));
if (documentURL)
documentURL->SetRef(EmptyCString());
#ifdef MOZ_XUL
// We've got a file. Check our XBL document cache.
@ -1074,9 +1061,6 @@ nsXBLService::LoadBindingDocumentInfo(nsIContent* aBoundElement,
// The second line of defense is the binding manager's document table.
nsBindingManager *bindingManager = nsnull;
nsCOMPtr<nsIURL> bindingURL(do_QueryInterface(aBindingURI, &rv));
NS_ENSURE_SUCCESS(rv, rv);
if (aBoundDocument) {
bindingManager = aBoundDocument->BindingManager();
bindingManager->GetXBLDocumentInfo(documentURI, getter_AddRefs(info));
@ -1105,7 +1089,7 @@ nsXBLService::LoadBindingDocumentInfo(nsIContent* aBoundElement,
nsXBLStreamListener* xblListener = NS_STATIC_CAST(nsXBLStreamListener*, ilist);
// Create a new load observer.
if (!xblListener->HasRequest(aBindingURI, aBoundElement)) {
nsXBLBindingRequest* req = nsXBLBindingRequest::Create(mPool, bindingURL, aBoundElement);
nsXBLBindingRequest* req = nsXBLBindingRequest::Create(mPool, aBindingURI, aBoundElement);
xblListener->AddRequest(req);
}
return NS_OK;
@ -1123,7 +1107,7 @@ nsXBLService::LoadBindingDocumentInfo(nsIContent* aBoundElement,
nsCOMPtr<nsIDocument> document;
FetchBindingDocument(aBoundElement, aBoundDocument, documentURI,
bindingURL, aForceSyncLoad, getter_AddRefs(document));
aBindingURI, aForceSyncLoad, getter_AddRefs(document));
if (document) {
nsBindingManager *xblDocBindingManager = document->BindingManager();
@ -1161,7 +1145,7 @@ nsXBLService::LoadBindingDocumentInfo(nsIContent* aBoundElement,
nsresult
nsXBLService::FetchBindingDocument(nsIContent* aBoundElement, nsIDocument* aBoundDocument,
nsIURI* aDocumentURI, nsIURL* aBindingURL,
nsIURI* aDocumentURI, nsIURI* aBindingURI,
PRBool aForceSyncLoad, nsIDocument** aResult)
{
nsresult rv = NS_OK;
@ -1223,7 +1207,7 @@ nsXBLService::FetchBindingDocument(nsIContent* aBoundElement, nsIDocument* aBoun
// Add our request.
nsXBLBindingRequest* req = nsXBLBindingRequest::Create(mPool,
aBindingURL,
aBindingURI,
aBoundElement);
xblListener->AddRequest(req);

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

@ -55,7 +55,6 @@ class nsIDocument;
class nsIAtom;
class nsString;
class nsIURI;
class nsIURL;
class nsSupportsHashtable;
class nsHashtable;
class nsIXULPrototypeCache;
@ -100,7 +99,7 @@ protected:
// This method synchronously loads and parses an XBL file.
nsresult FetchBindingDocument(nsIContent* aBoundElement, nsIDocument* aBoundDocument,
nsIURI* aDocumentURI, nsIURL* aBindingURL,
nsIURI* aDocumentURI, nsIURI* aBindingURI,
PRBool aForceSyncLoad, nsIDocument** aResult);
nsresult GetXBLDocumentInfo(nsIURI* aURI, nsIContent* aBoundElement, nsIXBLDocumentInfo** aResult);