mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-30 00:01:50 +00:00
Work on 48150 and XBL performance (async and arenas).
This commit is contained in:
parent
75afe2361d
commit
a489c05fae
@ -74,6 +74,7 @@
|
|||||||
#include "nsLayoutCID.h"
|
#include "nsLayoutCID.h"
|
||||||
#include "nsGfxCIID.h"
|
#include "nsGfxCIID.h"
|
||||||
#include "nsIImageManager.h"
|
#include "nsIImageManager.h"
|
||||||
|
#include "nsIBindingManager.h"
|
||||||
#include "prio.h"
|
#include "prio.h"
|
||||||
|
|
||||||
static char kChromePrefix[] = "chrome://";
|
static char kChromePrefix[] = "chrome://";
|
||||||
@ -1044,6 +1045,11 @@ NS_IMETHODIMP nsChromeRegistry::RefreshWindow(nsIDOMWindow* aWindow)
|
|||||||
if (!document)
|
if (!document)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
||||||
|
// Annihilate all XBL bindings.
|
||||||
|
nsCOMPtr<nsIBindingManager> bindingManager;
|
||||||
|
document->GetBindingManager(getter_AddRefs(bindingManager));
|
||||||
|
bindingManager->FlushChromeBindings();
|
||||||
|
|
||||||
nsCOMPtr<nsIXULDocument> xulDoc = do_QueryInterface(domDocument);
|
nsCOMPtr<nsIXULDocument> xulDoc = do_QueryInterface(domDocument);
|
||||||
if (xulDoc) {
|
if (xulDoc) {
|
||||||
// Deal with the backstop sheets first.
|
// Deal with the backstop sheets first.
|
||||||
|
@ -74,6 +74,7 @@ public:
|
|||||||
NS_IMETHOD RemoveLoadingDocListener(const nsCString& aURL)=0;
|
NS_IMETHOD RemoveLoadingDocListener(const nsCString& aURL)=0;
|
||||||
|
|
||||||
NS_IMETHOD InheritsStyle(nsIContent* aContent, PRBool* aResult) = 0;
|
NS_IMETHOD InheritsStyle(nsIContent* aContent, PRBool* aResult) = 0;
|
||||||
|
NS_IMETHOD FlushChromeBindings() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // nsIBinding_Manager_h__
|
#endif // nsIBinding_Manager_h__
|
||||||
|
@ -91,6 +91,9 @@ public:
|
|||||||
NS_IMETHOD WalkRules(nsISupportsArrayEnumFunc aFunc, void* aData)=0;
|
NS_IMETHOD WalkRules(nsISupportsArrayEnumFunc aFunc, void* aData)=0;
|
||||||
|
|
||||||
NS_IMETHOD SetAllowScripts(PRBool aFlag)=0;
|
NS_IMETHOD SetAllowScripts(PRBool aFlag)=0;
|
||||||
|
|
||||||
|
NS_IMETHOD MarkForDeath()=0;
|
||||||
|
NS_IMETHOD MarkedForDeath(PRBool* aResult)=0;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern nsresult
|
extern nsresult
|
||||||
|
@ -59,6 +59,9 @@ public:
|
|||||||
// This method loads a binding doc and then builds the specific binding required.
|
// This method loads a binding doc and then builds the specific binding required.
|
||||||
NS_IMETHOD GetBinding(nsIContent* aBoundElement, const nsCString& aURLStr, nsIXBLBinding** aResult) = 0;
|
NS_IMETHOD GetBinding(nsIContent* aBoundElement, const nsCString& aURLStr, nsIXBLBinding** aResult) = 0;
|
||||||
|
|
||||||
|
// Indicates whether or not a binding is fully loaded.
|
||||||
|
NS_IMETHOD BindingReady(nsIContent* aBoundElement, const nsCString& aURLStr, PRBool* aIsReady) = 0;
|
||||||
|
|
||||||
// For a given element, returns a flat list of all the anonymous children that need
|
// For a given element, returns a flat list of all the anonymous children that need
|
||||||
// frames built.
|
// frames built.
|
||||||
NS_IMETHOD GetContentList(nsIContent* aContent, nsISupportsArray** aResult, nsIContent** aChildElement,
|
NS_IMETHOD GetContentList(nsIContent* aContent, nsISupportsArray** aResult, nsIContent** aChildElement,
|
||||||
|
@ -178,6 +178,7 @@ public:
|
|||||||
NS_IMETHOD RemoveLoadingDocListener(const nsCString& aURL);
|
NS_IMETHOD RemoveLoadingDocListener(const nsCString& aURL);
|
||||||
|
|
||||||
NS_IMETHOD InheritsStyle(nsIContent* aContent, PRBool* aResult);
|
NS_IMETHOD InheritsStyle(nsIContent* aContent, PRBool* aResult);
|
||||||
|
NS_IMETHOD FlushChromeBindings();
|
||||||
|
|
||||||
// nsIStyleRuleSupplier
|
// nsIStyleRuleSupplier
|
||||||
NS_IMETHOD UseDocumentRules(nsIContent* aContent, PRBool* aResult);
|
NS_IMETHOD UseDocumentRules(nsIContent* aContent, PRBool* aResult);
|
||||||
@ -252,8 +253,13 @@ nsBindingManager::SetBinding(nsIContent* aContent, nsIXBLBinding* aBinding )
|
|||||||
mBindingTable = new nsSupportsHashtable;
|
mBindingTable = new nsSupportsHashtable;
|
||||||
|
|
||||||
nsISupportsKey key(aContent);
|
nsISupportsKey key(aContent);
|
||||||
|
|
||||||
|
nsCOMPtr<nsISupports> old = getter_AddRefs(mBindingTable->Get(&key));
|
||||||
|
if (old && aBinding)
|
||||||
|
NS_ERROR("Binding already installed!");
|
||||||
|
|
||||||
if (aBinding) {
|
if (aBinding) {
|
||||||
mBindingTable->Put (&key, aBinding);
|
mBindingTable->Put(&key, aBinding);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
mBindingTable->Remove(&key);
|
mBindingTable->Remove(&key);
|
||||||
@ -468,6 +474,23 @@ nsBindingManager::RemoveLoadingDocListener(const nsCString& aURL)
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PRBool PR_CALLBACK MarkForDeath(nsHashKey* aKey, void* aData, void* aClosure)
|
||||||
|
{
|
||||||
|
nsIXBLBinding* binding = (nsIXBLBinding*)aData;
|
||||||
|
nsCAutoString docURI;
|
||||||
|
binding->GetDocURI(docURI);
|
||||||
|
if (!docURI.CompareWithConversion("chrome", PR_FALSE, 6))
|
||||||
|
binding->MarkForDeath();
|
||||||
|
return PR_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsBindingManager::FlushChromeBindings()
|
||||||
|
{
|
||||||
|
mBindingTable->Enumerate(MarkForDeath);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsBindingManager::InheritsStyle(nsIContent* aContent, PRBool* aResult)
|
nsBindingManager::InheritsStyle(nsIContent* aContent, PRBool* aResult)
|
||||||
{
|
{
|
||||||
|
@ -252,11 +252,14 @@ nsXBLBinding::nsXBLBinding(const nsCString& aDocURI, const nsCString& aID)
|
|||||||
mIsStyleBinding(PR_TRUE),
|
mIsStyleBinding(PR_TRUE),
|
||||||
mAllowScripts(PR_TRUE),
|
mAllowScripts(PR_TRUE),
|
||||||
mInheritStyle(PR_TRUE),
|
mInheritStyle(PR_TRUE),
|
||||||
|
mMarkedForDeath(PR_FALSE),
|
||||||
mAttributeTable(nsnull),
|
mAttributeTable(nsnull),
|
||||||
mInsertionPointTable(nsnull)
|
mInsertionPointTable(nsnull)
|
||||||
{
|
{
|
||||||
NS_INIT_REFCNT();
|
NS_INIT_REFCNT();
|
||||||
gRefCnt++;
|
gRefCnt++;
|
||||||
|
// printf("REF COUNT UP: %d %s\n", gRefCnt, (const char*)mID);
|
||||||
|
|
||||||
if (gRefCnt == 1) {
|
if (gRefCnt == 1) {
|
||||||
kContentAtom = NS_NewAtom("content");
|
kContentAtom = NS_NewAtom("content");
|
||||||
kInterfaceAtom = NS_NewAtom("interface");
|
kInterfaceAtom = NS_NewAtom("interface");
|
||||||
@ -303,6 +306,8 @@ nsXBLBinding::~nsXBLBinding(void)
|
|||||||
delete mInsertionPointTable;
|
delete mInsertionPointTable;
|
||||||
|
|
||||||
gRefCnt--;
|
gRefCnt--;
|
||||||
|
// printf("REF COUNT DOWN: %d %s\n", gRefCnt, (const char*)mID);
|
||||||
|
|
||||||
if (gRefCnt == 0) {
|
if (gRefCnt == 0) {
|
||||||
NS_RELEASE(kContentAtom);
|
NS_RELEASE(kContentAtom);
|
||||||
NS_RELEASE(kInterfaceAtom);
|
NS_RELEASE(kInterfaceAtom);
|
||||||
@ -354,6 +359,11 @@ nsXBLBinding::GetBaseBinding(nsIXBLBinding** aResult)
|
|||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsXBLBinding::SetBaseBinding(nsIXBLBinding* aBinding)
|
nsXBLBinding::SetBaseBinding(nsIXBLBinding* aBinding)
|
||||||
{
|
{
|
||||||
|
if (mNextBinding) {
|
||||||
|
NS_ERROR("Base XBL binding is already defined!");
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
mNextBinding = aBinding; // Comptr handles rel/add
|
mNextBinding = aBinding; // Comptr handles rel/add
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
@ -1454,8 +1464,6 @@ nsXBLBinding::IsInExcludesList(nsIAtom* aTag, const nsString& aList)
|
|||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsXBLBinding::ConstructAttributeTable(nsIContent* aElement)
|
nsXBLBinding::ConstructAttributeTable(nsIContent* aElement)
|
||||||
{
|
{
|
||||||
// XXX This function still needs to deal with the
|
|
||||||
// ability to map one attribute to another.
|
|
||||||
nsAutoString inherits;
|
nsAutoString inherits;
|
||||||
aElement->GetAttribute(kNameSpaceID_None, kInheritsAtom, inherits);
|
aElement->GetAttribute(kNameSpaceID_None, kInheritsAtom, inherits);
|
||||||
if (!inherits.IsEmpty()) {
|
if (!inherits.IsEmpty()) {
|
||||||
@ -1745,7 +1753,19 @@ nsXBLBinding::GetFirstStyleBinding(nsIXBLBinding** aResult)
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsXBLBinding::MarkForDeath()
|
||||||
|
{
|
||||||
|
mMarkedForDeath = PR_TRUE;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsXBLBinding::MarkedForDeath(PRBool* aResult)
|
||||||
|
{
|
||||||
|
*aResult = mMarkedForDeath;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
// Creation Routine ///////////////////////////////////////////////////////////////////////
|
// Creation Routine ///////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ -85,6 +85,9 @@ class nsXBLBinding: public nsIXBLBinding
|
|||||||
|
|
||||||
NS_IMETHOD SetAllowScripts(PRBool aFlag) { mAllowScripts = aFlag; return NS_OK; };
|
NS_IMETHOD SetAllowScripts(PRBool aFlag) { mAllowScripts = aFlag; return NS_OK; };
|
||||||
|
|
||||||
|
NS_IMETHOD MarkForDeath();
|
||||||
|
NS_IMETHOD MarkedForDeath(PRBool* aResult);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
nsXBLBinding(const nsCString& aDocURI, const nsCString& aRef);
|
nsXBLBinding(const nsCString& aDocURI, const nsCString& aRef);
|
||||||
virtual ~nsXBLBinding();
|
virtual ~nsXBLBinding();
|
||||||
@ -172,9 +175,10 @@ protected:
|
|||||||
|
|
||||||
nsIContent* mBoundElement; // [WEAK] We have a reference, but we don't own it.
|
nsIContent* mBoundElement; // [WEAK] We have a reference, but we don't own it.
|
||||||
|
|
||||||
PRBool mIsStyleBinding;
|
PRPackedBool mIsStyleBinding;
|
||||||
PRBool mAllowScripts;
|
PRPackedBool mAllowScripts;
|
||||||
PRBool mInheritStyle;
|
PRPackedBool mInheritStyle;
|
||||||
|
PRPackedBool mMarkedForDeath;
|
||||||
|
|
||||||
nsSupportsHashtable* mAttributeTable; // A table for attribute entries.
|
nsSupportsHashtable* mAttributeTable; // A table for attribute entries.
|
||||||
nsSupportsHashtable* mInsertionPointTable; // A table of insertion points.
|
nsSupportsHashtable* mInsertionPointTable; // A table of insertion points.
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "nsXBLService.h"
|
#include "nsXBLService.h"
|
||||||
#include "nsIInputStream.h"
|
#include "nsIInputStream.h"
|
||||||
|
#include "nsINameSpace.h"
|
||||||
#include "nsINameSpaceManager.h"
|
#include "nsINameSpaceManager.h"
|
||||||
#include "nsHashtable.h"
|
#include "nsHashtable.h"
|
||||||
#include "nsIURI.h"
|
#include "nsIURI.h"
|
||||||
@ -37,6 +38,7 @@
|
|||||||
#include "nsNetUtil.h"
|
#include "nsNetUtil.h"
|
||||||
#include "plstr.h"
|
#include "plstr.h"
|
||||||
#include "nsIContent.h"
|
#include "nsIContent.h"
|
||||||
|
#include "nsIXMLContent.h"
|
||||||
#include "nsIDOMElement.h"
|
#include "nsIDOMElement.h"
|
||||||
#include "nsIDocument.h"
|
#include "nsIDocument.h"
|
||||||
#include "nsIXMLContentSink.h"
|
#include "nsIXMLContentSink.h"
|
||||||
@ -52,6 +54,9 @@
|
|||||||
#include "nsIChromeRegistry.h"
|
#include "nsIChromeRegistry.h"
|
||||||
#include "nsIPref.h"
|
#include "nsIPref.h"
|
||||||
|
|
||||||
|
#include "nsIPresShell.h"
|
||||||
|
#include "nsIDocumentObserver.h"
|
||||||
|
|
||||||
#include "nsIXULContentUtils.h"
|
#include "nsIXULContentUtils.h"
|
||||||
#include "nsIXULPrototypeCache.h"
|
#include "nsIXULPrototypeCache.h"
|
||||||
#include "nsIDOMLoadListener.h"
|
#include "nsIDOMLoadListener.h"
|
||||||
@ -104,55 +109,56 @@ struct nsXBLBindingRequest
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void* operator new(size_t aSize, nsFixedSizeAllocator& aAllocator) {
|
||||||
|
return aAllocator.Alloc(aSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void operator delete(void* aPtr, size_t aSize) {
|
||||||
|
nsFixedSizeAllocator::Free(aPtr, aSize);
|
||||||
|
}
|
||||||
|
|
||||||
void DocumentLoaded(nsIDocument* aBindingDoc)
|
void DocumentLoaded(nsIDocument* aBindingDoc)
|
||||||
{
|
{
|
||||||
// Get the binding.
|
|
||||||
nsCOMPtr<nsIXBLBinding> newBinding;
|
|
||||||
gXBLService->GetBinding(mBoundElement, mBindingURL, getter_AddRefs(newBinding));
|
|
||||||
|
|
||||||
// XXX Deal with layered bindings.
|
|
||||||
// XXX Deal with cross-site inheritance (e.g., http://a/a.xml inheriting from http://b/b.xml)
|
|
||||||
// Install the binding on the content node.
|
|
||||||
nsCOMPtr<nsIDocument> doc;
|
nsCOMPtr<nsIDocument> doc;
|
||||||
mBoundElement->GetDocument(*getter_AddRefs(doc));
|
mBoundElement->GetDocument(*getter_AddRefs(doc));
|
||||||
if (!doc)
|
if (!doc)
|
||||||
return;
|
return;
|
||||||
nsCOMPtr<nsIBindingManager> bindingManager;
|
|
||||||
doc->GetBindingManager(getter_AddRefs(bindingManager));
|
|
||||||
bindingManager->SetBinding(mBoundElement, newBinding);
|
|
||||||
|
|
||||||
// Set the binding's bound element.
|
// Get the binding.
|
||||||
newBinding->SetBoundElement(mBoundElement);
|
PRBool ready = PR_FALSE;
|
||||||
|
gXBLService->BindingReady(mBoundElement, mBindingURL, &ready);
|
||||||
|
|
||||||
// Tell the binding to build the anonymous content.
|
if (!ready)
|
||||||
newBinding->GenerateAnonymousContent(mBoundElement);
|
return;
|
||||||
|
|
||||||
// Tell the binding to install event handlers
|
|
||||||
nsCOMPtr<nsIXBLBinding> attachReq;
|
|
||||||
newBinding->InstallEventHandlers(mBoundElement, getter_AddRefs(attachReq));
|
|
||||||
|
|
||||||
// Set up our properties
|
|
||||||
newBinding->InstallProperties(mBoundElement);
|
|
||||||
|
|
||||||
if (attachReq) {
|
|
||||||
attachReq->ExecuteAttachedHandler();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// XXX Deal with layered bindings.
|
||||||
// Now do a ContentInserted notification to cause the frames to get installed finally,
|
// Now do a ContentInserted notification to cause the frames to get installed finally,
|
||||||
nsCOMPtr<nsIContent> parent;
|
nsCOMPtr<nsIContent> parent;
|
||||||
mBoundElement->GetParent(*getter_AddRefs(parent));
|
mBoundElement->GetParent(*getter_AddRefs(parent));
|
||||||
PRInt32 index = 0;
|
PRInt32 index = 0;
|
||||||
if (parent)
|
if (parent)
|
||||||
parent->IndexOf(mBoundElement, index);
|
parent->IndexOf(mBoundElement, index);
|
||||||
if (index == -1)
|
|
||||||
return;
|
nsCOMPtr<nsIPresShell> shell = getter_AddRefs(doc->GetShellAt(0));
|
||||||
doc->ContentInserted(parent, mBoundElement, index);
|
if (shell) {
|
||||||
|
nsCOMPtr<nsIDocumentObserver> obs(do_QueryInterface(shell));
|
||||||
|
obs->ContentRemoved(doc, parent, mBoundElement, index);
|
||||||
|
obs->ContentInserted(doc, parent, mBoundElement, index);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static nsIXBLService* gXBLService;
|
static nsIXBLService* gXBLService;
|
||||||
static int gRefCnt;
|
static int gRefCnt;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const size_t kBucketSizes[] = {
|
||||||
|
sizeof(nsXBLBindingRequest)
|
||||||
|
};
|
||||||
|
|
||||||
|
static const PRInt32 kNumBuckets = sizeof(kBucketSizes)/sizeof(size_t);
|
||||||
|
static const PRInt32 kNumElements = 64;
|
||||||
|
static const PRInt32 kInitialSize = (NS_SIZE_IN_HEAP(sizeof(nsXBLBindingRequest))) * kNumElements;
|
||||||
|
|
||||||
nsIXBLService* nsXBLBindingRequest::gXBLService = nsnull;
|
nsIXBLService* nsXBLBindingRequest::gXBLService = nsnull;
|
||||||
int nsXBLBindingRequest::gRefCnt = 0;
|
int nsXBLBindingRequest::gRefCnt = 0;
|
||||||
|
|
||||||
@ -180,12 +186,13 @@ public:
|
|||||||
virtual ~nsXBLStreamListener();
|
virtual ~nsXBLStreamListener();
|
||||||
|
|
||||||
void AddRequest(nsXBLBindingRequest* aRequest) { mBindingRequests.AppendElement(aRequest); };
|
void AddRequest(nsXBLBindingRequest* aRequest) { mBindingRequests.AppendElement(aRequest); };
|
||||||
|
PRBool HasRequest(const nsCString& aURI, nsIContent* aBoundElement);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
nsCOMPtr<nsIStreamListener> mInner;
|
nsCOMPtr<nsIStreamListener> mInner;
|
||||||
nsVoidArray mBindingRequests;
|
nsVoidArray mBindingRequests;
|
||||||
|
|
||||||
nsCOMPtr<nsIDocument> mDocument;
|
nsIDocument* mDocument;
|
||||||
nsCOMPtr<nsIDocument> mBindingDocument;
|
nsCOMPtr<nsIDocument> mBindingDocument;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -264,17 +271,34 @@ nsXBLStreamListener::OnStopRequest(nsIChannel* aChannel, nsISupports* aCtxt, nsr
|
|||||||
rv = mInner->OnStopRequest(aChannel, aCtxt, aStatus, aStatusArg);
|
rv = mInner->OnStopRequest(aChannel, aCtxt, aStatus, aStatusArg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv) || NS_FAILED(aStatus)) {
|
||||||
PRUint32 count = mBindingRequests.Count();
|
PRUint32 count = mBindingRequests.Count();
|
||||||
for (PRUint32 i = 0; i < count; i++) {
|
for (PRUint32 i = 0; i < count; i++) {
|
||||||
nsXBLBindingRequest* req = (nsXBLBindingRequest*)mBindingRequests.ElementAt(i);
|
nsXBLBindingRequest* req = (nsXBLBindingRequest*)mBindingRequests.ElementAt(i);
|
||||||
delete req;
|
delete req;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mDocument = nsnull;
|
||||||
|
mBindingDocument = nsnull;
|
||||||
}
|
}
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PRBool
|
||||||
|
nsXBLStreamListener::HasRequest(const nsCString& aURI, nsIContent* aElt)
|
||||||
|
{
|
||||||
|
// XXX Could be more efficient.
|
||||||
|
PRUint32 count = mBindingRequests.Count();
|
||||||
|
for (PRUint32 i = 0; i < count; i++) {
|
||||||
|
nsXBLBindingRequest* req = (nsXBLBindingRequest*)mBindingRequests.ElementAt(i);
|
||||||
|
if (req->mBindingURL.Equals(aURI) && req->mBoundElement.get() == aElt)
|
||||||
|
return PR_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return PR_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsXBLStreamListener::Load(nsIDOMEvent* aEvent)
|
nsXBLStreamListener::Load(nsIDOMEvent* aEvent)
|
||||||
{
|
{
|
||||||
@ -313,6 +337,7 @@ nsXBLStreamListener::Load(nsIDOMEvent* aEvent)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!cached)
|
||||||
bindingManager->PutXBLDocumentInfo(info);
|
bindingManager->PutXBLDocumentInfo(info);
|
||||||
|
|
||||||
// Notify all pending requests that their bindings are
|
// Notify all pending requests that their bindings are
|
||||||
@ -328,9 +353,12 @@ nsXBLStreamListener::Load(nsIDOMEvent* aEvent)
|
|||||||
delete req;
|
delete req;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMEventReceiver> rec(do_QueryInterface(mDocument));
|
nsCOMPtr<nsIDOMEventReceiver> rec(do_QueryInterface(mBindingDocument));
|
||||||
rec->RemoveEventListener(NS_ConvertASCIItoUCS2("load"), (nsIDOMLoadListener*)this, PR_FALSE);
|
rec->RemoveEventListener(NS_ConvertASCIItoUCS2("load"), (nsIDOMLoadListener*)this, PR_FALSE);
|
||||||
|
|
||||||
|
mDocument = nsnull;
|
||||||
|
mBindingDocument = nsnull;
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -406,7 +434,7 @@ PRUint32 nsXBLService::gClassLRUListLength = 0;
|
|||||||
PRUint32 nsXBLService::gClassLRUListQuota = 64;
|
PRUint32 nsXBLService::gClassLRUListQuota = 64;
|
||||||
|
|
||||||
nsIAtom* nsXBLService::kExtendsAtom = nsnull;
|
nsIAtom* nsXBLService::kExtendsAtom = nsnull;
|
||||||
nsIAtom* nsXBLService::kHasChildrenAtom = nsnull;
|
nsIAtom* nsXBLService::kScrollbarAtom = nsnull;
|
||||||
|
|
||||||
// Enabled by default. Must be over-ridden to disable
|
// Enabled by default. Must be over-ridden to disable
|
||||||
PRBool nsXBLService::gDisableChromeCache = PR_FALSE;
|
PRBool nsXBLService::gDisableChromeCache = PR_FALSE;
|
||||||
@ -421,6 +449,8 @@ NS_IMPL_ISUPPORTS2(nsXBLService, nsIXBLService, nsIMemoryPressureObserver)
|
|||||||
nsXBLService::nsXBLService(void)
|
nsXBLService::nsXBLService(void)
|
||||||
{
|
{
|
||||||
NS_INIT_REFCNT();
|
NS_INIT_REFCNT();
|
||||||
|
mPool.Init("XBL Binding Requests", kBucketSizes, kNumBuckets, kInitialSize);
|
||||||
|
|
||||||
gRefCnt++;
|
gRefCnt++;
|
||||||
if (gRefCnt == 1) {
|
if (gRefCnt == 1) {
|
||||||
|
|
||||||
@ -442,7 +472,7 @@ nsXBLService::nsXBLService(void)
|
|||||||
|
|
||||||
// Create our atoms
|
// Create our atoms
|
||||||
kExtendsAtom = NS_NewAtom("extends");
|
kExtendsAtom = NS_NewAtom("extends");
|
||||||
kHasChildrenAtom = NS_NewAtom("haschildren");
|
kScrollbarAtom = NS_NewAtom("scrollbar");
|
||||||
|
|
||||||
// Find out if the XUL cache is on or off
|
// Find out if the XUL cache is on or off
|
||||||
NS_WITH_SERVICE(nsIPref, prefs, NS_PREF_PROGID, &rv);
|
NS_WITH_SERVICE(nsIPref, prefs, NS_PREF_PROGID, &rv);
|
||||||
@ -476,7 +506,7 @@ nsXBLService::~nsXBLService(void)
|
|||||||
|
|
||||||
// Release our atoms
|
// Release our atoms
|
||||||
NS_RELEASE(kExtendsAtom);
|
NS_RELEASE(kExtendsAtom);
|
||||||
NS_RELEASE(kHasChildrenAtom);
|
NS_RELEASE(kScrollbarAtom);
|
||||||
|
|
||||||
// Walk the LRU list removing and deleting the nsXBLJSClasses.
|
// Walk the LRU list removing and deleting the nsXBLJSClasses.
|
||||||
FlushMemory(REASON_HEAP_MINIMIZE, 0);
|
FlushMemory(REASON_HEAP_MINIMIZE, 0);
|
||||||
@ -526,6 +556,13 @@ nsXBLService::LoadBindings(nsIContent* aContent, const nsString& aURL, PRBool aA
|
|||||||
nsCOMPtr<nsIXBLBinding> styleBinding;
|
nsCOMPtr<nsIXBLBinding> styleBinding;
|
||||||
binding->GetFirstStyleBinding(getter_AddRefs(styleBinding));
|
binding->GetFirstStyleBinding(getter_AddRefs(styleBinding));
|
||||||
if (styleBinding) {
|
if (styleBinding) {
|
||||||
|
PRBool marked = PR_FALSE;
|
||||||
|
binding->MarkedForDeath(&marked);
|
||||||
|
if (marked) {
|
||||||
|
FlushStyleBindings(aContent);
|
||||||
|
binding = nsnull;
|
||||||
|
}
|
||||||
|
else {
|
||||||
// See if the URIs match.
|
// See if the URIs match.
|
||||||
nsCAutoString uri;
|
nsCAutoString uri;
|
||||||
styleBinding->GetBindingURI(uri);
|
styleBinding->GetBindingURI(uri);
|
||||||
@ -537,6 +574,7 @@ nsXBLService::LoadBindings(nsIContent* aContent, const nsString& aURL, PRBool aA
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsIXBLBinding> newBinding;
|
nsCOMPtr<nsIXBLBinding> newBinding;
|
||||||
nsCAutoString url; url.AssignWithConversion(aURL);
|
nsCAutoString url; url.AssignWithConversion(aURL);
|
||||||
@ -736,8 +774,28 @@ nsXBLService::FlushMemory(PRUint32 reason, size_t requestedAmount)
|
|||||||
|
|
||||||
// Internal helper methods ////////////////////////////////////////////////////////////////
|
// Internal helper methods ////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
NS_IMETHODIMP nsXBLService::GetBinding(nsIContent* aBoundElement, const nsCString& aURLStr, nsIXBLBinding** aResult)
|
NS_IMETHODIMP nsXBLService::GetBinding(nsIContent* aBoundElement,
|
||||||
|
const nsCString& aURLStr,
|
||||||
|
nsIXBLBinding** aResult)
|
||||||
{
|
{
|
||||||
|
PRBool dummy;
|
||||||
|
return GetBindingInternal(aBoundElement, aURLStr, PR_FALSE, &dummy, aResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP nsXBLService::BindingReady(nsIContent* aBoundElement,
|
||||||
|
const nsCString& aURLStr,
|
||||||
|
PRBool* aIsReady)
|
||||||
|
{
|
||||||
|
return GetBindingInternal(aBoundElement, aURLStr, PR_TRUE, aIsReady, nsnull);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP nsXBLService::GetBindingInternal(nsIContent* aBoundElement,
|
||||||
|
const nsCString& aURLStr,
|
||||||
|
PRBool aPeekOnly,
|
||||||
|
PRBool* aIsReady,
|
||||||
|
nsIXBLBinding** aResult)
|
||||||
|
{
|
||||||
|
if (aResult)
|
||||||
*aResult = nsnull;
|
*aResult = nsnull;
|
||||||
|
|
||||||
if (aURLStr.IsEmpty())
|
if (aURLStr.IsEmpty())
|
||||||
@ -782,6 +840,42 @@ NS_IMETHODIMP nsXBLService::GetBinding(nsIContent* aBoundElement, const nsCStrin
|
|||||||
|
|
||||||
// If no ref is specified just use this.
|
// If no ref is specified just use this.
|
||||||
if ((bindingName.IsEmpty()) || (bindingName == value)) {
|
if ((bindingName.IsEmpty()) || (bindingName == value)) {
|
||||||
|
// Check for the presence of an extends attribute
|
||||||
|
nsAutoString extends;
|
||||||
|
nsCOMPtr<nsIXBLBinding> baseBinding;
|
||||||
|
child->GetAttribute(kNameSpaceID_None, kExtendsAtom, extends);
|
||||||
|
value = extends;
|
||||||
|
if (!extends.IsEmpty()) {
|
||||||
|
nsAutoString prefix;
|
||||||
|
PRInt32 offset = extends.FindChar(':');
|
||||||
|
if (-1 != offset) {
|
||||||
|
extends.Left(prefix, offset);
|
||||||
|
extends.Cut(0, offset+1);
|
||||||
|
}
|
||||||
|
if (prefix.Length() > 0) {
|
||||||
|
// Look up the prefix.
|
||||||
|
nsCOMPtr<nsIAtom> prefixAtom = getter_AddRefs(NS_NewAtom(prefix));
|
||||||
|
nsCOMPtr<nsINameSpace> nameSpace;
|
||||||
|
nsCOMPtr<nsIXMLContent> xmlContent(do_QueryInterface(child));
|
||||||
|
if (xmlContent) {
|
||||||
|
xmlContent->GetContainingNameSpace(*getter_AddRefs(nameSpace));
|
||||||
|
if (nameSpace) {
|
||||||
|
nsCOMPtr<nsINameSpace> tagSpace;
|
||||||
|
nameSpace->FindNameSpace(prefixAtom, *getter_AddRefs(tagSpace));
|
||||||
|
if (!tagSpace) {
|
||||||
|
// We have a base class binding. Load it right now.
|
||||||
|
nsCAutoString urlCString; urlCString.AssignWithConversion(value);
|
||||||
|
GetBindingInternal(aBoundElement, urlCString, aPeekOnly, aIsReady, getter_AddRefs(baseBinding));
|
||||||
|
if (!*aIsReady)
|
||||||
|
return NS_ERROR_FAILURE; // Binding not yet ready or an error occurred.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*aIsReady = PR_TRUE;
|
||||||
|
if (!aPeekOnly) {
|
||||||
// Make a new binding
|
// Make a new binding
|
||||||
NS_NewXBLBinding(uri, ref, aResult);
|
NS_NewXBLBinding(uri, ref, aResult);
|
||||||
|
|
||||||
@ -789,24 +883,9 @@ NS_IMETHODIMP nsXBLService::GetBinding(nsIContent* aBoundElement, const nsCStrin
|
|||||||
(*aResult)->SetBindingElement(child);
|
(*aResult)->SetBindingElement(child);
|
||||||
(*aResult)->SetAllowScripts(allowScripts);
|
(*aResult)->SetAllowScripts(allowScripts);
|
||||||
|
|
||||||
// Check for the presence of an extends attribute
|
if (baseBinding)
|
||||||
child->GetAttribute(kNameSpaceID_None, kExtendsAtom, value);
|
|
||||||
if (!value.IsEmpty()) {
|
|
||||||
// See if we are extending a builtin tag.
|
|
||||||
nsCOMPtr<nsIAtom> tag;
|
|
||||||
PRInt32 dummy;
|
|
||||||
(*aResult)->GetBaseTag(&dummy, getter_AddRefs(tag));
|
|
||||||
if (!tag) {
|
|
||||||
// We have a base class binding. Load it right now.
|
|
||||||
nsCOMPtr<nsIXBLBinding> baseBinding;
|
|
||||||
nsCAutoString urlCString; urlCString.AssignWithConversion(value);
|
|
||||||
GetBinding(aBoundElement, urlCString, getter_AddRefs(baseBinding));
|
|
||||||
if (!baseBinding)
|
|
||||||
return NS_OK; // At least we got the derived class binding loaded.
|
|
||||||
(*aResult)->SetBaseBinding(baseBinding);
|
(*aResult)->SetBaseBinding(baseBinding);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -839,7 +918,9 @@ nsXBLService::GetBindingDocumentInfo(nsIContent* aBoundElement, const nsCString&
|
|||||||
boundDocument->GetBindingManager(getter_AddRefs(bindingManager));
|
boundDocument->GetBindingManager(getter_AddRefs(bindingManager));
|
||||||
bindingManager->GetXBLDocumentInfo(aURLStr, getter_AddRefs(info));
|
bindingManager->GetXBLDocumentInfo(aURLStr, getter_AddRefs(info));
|
||||||
|
|
||||||
if (!info) {
|
nsCOMPtr<nsIAtom> tagName;
|
||||||
|
aBoundElement->GetTag(*getter_AddRefs(tagName));
|
||||||
|
if (!info && (tagName.get() != kScrollbarAtom)) {
|
||||||
// The third line of defense is to investigate whether or not the
|
// The third line of defense is to investigate whether or not the
|
||||||
// document is currently being loaded asynchronously. If so, there's no
|
// document is currently being loaded asynchronously. If so, there's no
|
||||||
// document yet, but we need to glom on our request so that it will be
|
// document yet, but we need to glom on our request so that it will be
|
||||||
@ -847,14 +928,16 @@ nsXBLService::GetBindingDocumentInfo(nsIContent* aBoundElement, const nsCString&
|
|||||||
nsCOMPtr<nsIStreamListener> listener;
|
nsCOMPtr<nsIStreamListener> listener;
|
||||||
bindingManager->GetLoadingDocListener(aURLStr, getter_AddRefs(listener));
|
bindingManager->GetLoadingDocListener(aURLStr, getter_AddRefs(listener));
|
||||||
if (listener) {
|
if (listener) {
|
||||||
|
nsIStreamListener* ilist = listener.get();
|
||||||
|
nsXBLStreamListener* xblListener = NS_STATIC_CAST(nsXBLStreamListener*, ilist);
|
||||||
// Create a new load observer.
|
// Create a new load observer.
|
||||||
nsCAutoString bindingURI(aURLStr);
|
nsCAutoString bindingURI(aURLStr);
|
||||||
bindingURI += "#";
|
bindingURI += "#";
|
||||||
bindingURI += aRef;
|
bindingURI += aRef;
|
||||||
nsXBLBindingRequest* req = new nsXBLBindingRequest(aRef, aBoundElement);
|
if (!xblListener->HasRequest(bindingURI, aBoundElement)) {
|
||||||
nsIStreamListener* ilist = listener.get();
|
nsXBLBindingRequest* req = new (mPool) nsXBLBindingRequest(bindingURI, aBoundElement);
|
||||||
nsXBLStreamListener* xblListener = NS_STATIC_CAST(nsXBLStreamListener*, ilist);
|
|
||||||
xblListener->AddRequest(req);
|
xblListener->AddRequest(req);
|
||||||
|
}
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -947,10 +1030,11 @@ nsXBLService::FetchBindingDocument(nsIContent* aBoundElement, nsIURI* aURI, cons
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsChromeURI(aURI)) {
|
nsCOMPtr<nsIAtom> tagName;
|
||||||
|
aBoundElement->GetTag(*getter_AddRefs(tagName));
|
||||||
|
if (tagName != kScrollbarAtom) {
|
||||||
// We can be asynchronous
|
// We can be asynchronous
|
||||||
nsXBLStreamListener* xblListener = new nsXBLStreamListener(listener, boundDoc, doc);
|
nsXBLStreamListener* xblListener = new nsXBLStreamListener(listener, boundDoc, doc);
|
||||||
NS_ADDREF(xblListener);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMEventReceiver> rec(do_QueryInterface(doc));
|
nsCOMPtr<nsIDOMEventReceiver> rec(do_QueryInterface(doc));
|
||||||
rec->AddEventListener(NS_ConvertASCIItoUCS2("load"), (nsIDOMLoadListener*)xblListener, PR_FALSE);
|
rec->AddEventListener(NS_ConvertASCIItoUCS2("load"), (nsIDOMLoadListener*)xblListener, PR_FALSE);
|
||||||
@ -968,7 +1052,7 @@ nsXBLService::FetchBindingDocument(nsIContent* aBoundElement, nsIURI* aURI, cons
|
|||||||
nsCAutoString bindingURI(uri);
|
nsCAutoString bindingURI(uri);
|
||||||
bindingURI += "#";
|
bindingURI += "#";
|
||||||
bindingURI += aRef;
|
bindingURI += aRef;
|
||||||
nsXBLBindingRequest* req = new nsXBLBindingRequest(bindingURI, aBoundElement);
|
nsXBLBindingRequest* req = new (mPool) nsXBLBindingRequest(bindingURI, aBoundElement);
|
||||||
xblListener->AddRequest(req);
|
xblListener->AddRequest(req);
|
||||||
|
|
||||||
// Now kick off the async read.
|
// Now kick off the async read.
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include "nsIMemory.h"
|
#include "nsIMemory.h"
|
||||||
#include "jsapi.h" // nsXBLJSClass derives from JSClass
|
#include "jsapi.h" // nsXBLJSClass derives from JSClass
|
||||||
#include "jsclist.h" // nsXBLJSClass derives from JSCList
|
#include "jsclist.h" // nsXBLJSClass derives from JSCList
|
||||||
|
#include "nsFixedSizeAllocator.h"
|
||||||
|
|
||||||
class nsIXBLBinding;
|
class nsIXBLBinding;
|
||||||
class nsIXBLDocumentInfo;
|
class nsIXBLDocumentInfo;
|
||||||
@ -54,6 +55,9 @@ class nsXBLService : public nsIXBLService, public nsIMemoryPressureObserver
|
|||||||
// This method loads a binding doc and then builds the specific binding required.
|
// This method loads a binding doc and then builds the specific binding required.
|
||||||
NS_IMETHOD GetBinding(nsIContent* aBoundElement, const nsCString& aURLStr, nsIXBLBinding** aResult);
|
NS_IMETHOD GetBinding(nsIContent* aBoundElement, const nsCString& aURLStr, nsIXBLBinding** aResult);
|
||||||
|
|
||||||
|
// Indicates whether or not a binding is fully loaded.
|
||||||
|
NS_IMETHOD BindingReady(nsIContent* aBoundElement, const nsCString& aURLStr, PRBool* aIsReady);
|
||||||
|
|
||||||
// This function clears out the bindings on a given content node.
|
// This function clears out the bindings on a given content node.
|
||||||
NS_IMETHOD FlushStyleBindings(nsIContent* aContent);
|
NS_IMETHOD FlushStyleBindings(nsIContent* aContent);
|
||||||
|
|
||||||
@ -80,6 +84,11 @@ public:
|
|||||||
// This method synchronously loads and parses an XBL file.
|
// This method synchronously loads and parses an XBL file.
|
||||||
NS_IMETHOD FetchBindingDocument(nsIContent* aBoundElement, nsIURI* aURI, const nsCString& aRef, nsIDocument** aResult);
|
NS_IMETHOD FetchBindingDocument(nsIContent* aBoundElement, nsIURI* aURI, const nsCString& aRef, nsIDocument** aResult);
|
||||||
|
|
||||||
|
// This method loads a binding doc and then builds the specific binding required. It
|
||||||
|
// can also peek without building.
|
||||||
|
NS_IMETHOD GetBindingInternal(nsIContent* aBoundElement, const nsCString& aURLStr,
|
||||||
|
PRBool aPeekFlag, PRBool* aIsReady, nsIXBLBinding** aResult);
|
||||||
|
|
||||||
// This method walks a binding document and removes any text nodes
|
// This method walks a binding document and removes any text nodes
|
||||||
// that contain only whitespace.
|
// that contain only whitespace.
|
||||||
static nsresult StripWhitespaceNodes(nsIContent* aContent);
|
static nsresult StripWhitespaceNodes(nsIContent* aContent);
|
||||||
@ -104,7 +113,10 @@ public:
|
|||||||
|
|
||||||
// XBL Atoms
|
// XBL Atoms
|
||||||
static nsIAtom* kExtendsAtom;
|
static nsIAtom* kExtendsAtom;
|
||||||
static nsIAtom* kHasChildrenAtom;
|
|
||||||
|
static nsIAtom* kScrollbarAtom;
|
||||||
|
|
||||||
|
nsFixedSizeAllocator mPool;
|
||||||
};
|
};
|
||||||
|
|
||||||
class nsXBLJSClass : public JSCList, public JSClass
|
class nsXBLJSClass : public JSCList, public JSClass
|
||||||
|
@ -5235,7 +5235,9 @@ nsCSSFrameConstructor::CreateAnonymousFrames(nsIPresShell* aPresShell,
|
|||||||
|
|
||||||
// Load the bindings.
|
// Load the bindings.
|
||||||
nsCOMPtr<nsIXBLBinding> binding;
|
nsCOMPtr<nsIXBLBinding> binding;
|
||||||
xblService->LoadBindings(aParent, ui->mBehavior, PR_FALSE, getter_AddRefs(binding));
|
rv = xblService->LoadBindings(aParent, ui->mBehavior, PR_FALSE, getter_AddRefs(binding));
|
||||||
|
if (NS_FAILED(rv))
|
||||||
|
return NS_OK;
|
||||||
|
|
||||||
// Retrieve the anonymous content that we should build.
|
// Retrieve the anonymous content that we should build.
|
||||||
nsCOMPtr<nsISupportsArray> anonymousItems;
|
nsCOMPtr<nsISupportsArray> anonymousItems;
|
||||||
@ -5467,7 +5469,9 @@ nsCSSFrameConstructor::CreateAnonymousTableCellFrames(nsIPresShell* aPres
|
|||||||
|
|
||||||
// Load the bindings.
|
// Load the bindings.
|
||||||
nsCOMPtr<nsIXBLBinding> binding;
|
nsCOMPtr<nsIXBLBinding> binding;
|
||||||
xblService->LoadBindings(aParent, ui->mBehavior, PR_FALSE, getter_AddRefs(binding));
|
rv = xblService->LoadBindings(aParent, ui->mBehavior, PR_FALSE, getter_AddRefs(binding));
|
||||||
|
if (NS_FAILED(rv))
|
||||||
|
return NS_OK;
|
||||||
|
|
||||||
// Retrieve the anonymous content that we should build.
|
// Retrieve the anonymous content that we should build.
|
||||||
nsCOMPtr<nsIContent> childElement;
|
nsCOMPtr<nsIContent> childElement;
|
||||||
|
@ -5235,7 +5235,9 @@ nsCSSFrameConstructor::CreateAnonymousFrames(nsIPresShell* aPresShell,
|
|||||||
|
|
||||||
// Load the bindings.
|
// Load the bindings.
|
||||||
nsCOMPtr<nsIXBLBinding> binding;
|
nsCOMPtr<nsIXBLBinding> binding;
|
||||||
xblService->LoadBindings(aParent, ui->mBehavior, PR_FALSE, getter_AddRefs(binding));
|
rv = xblService->LoadBindings(aParent, ui->mBehavior, PR_FALSE, getter_AddRefs(binding));
|
||||||
|
if (NS_FAILED(rv))
|
||||||
|
return NS_OK;
|
||||||
|
|
||||||
// Retrieve the anonymous content that we should build.
|
// Retrieve the anonymous content that we should build.
|
||||||
nsCOMPtr<nsISupportsArray> anonymousItems;
|
nsCOMPtr<nsISupportsArray> anonymousItems;
|
||||||
@ -5467,7 +5469,9 @@ nsCSSFrameConstructor::CreateAnonymousTableCellFrames(nsIPresShell* aPres
|
|||||||
|
|
||||||
// Load the bindings.
|
// Load the bindings.
|
||||||
nsCOMPtr<nsIXBLBinding> binding;
|
nsCOMPtr<nsIXBLBinding> binding;
|
||||||
xblService->LoadBindings(aParent, ui->mBehavior, PR_FALSE, getter_AddRefs(binding));
|
rv = xblService->LoadBindings(aParent, ui->mBehavior, PR_FALSE, getter_AddRefs(binding));
|
||||||
|
if (NS_FAILED(rv))
|
||||||
|
return NS_OK;
|
||||||
|
|
||||||
// Retrieve the anonymous content that we should build.
|
// Retrieve the anonymous content that we should build.
|
||||||
nsCOMPtr<nsIContent> childElement;
|
nsCOMPtr<nsIContent> childElement;
|
||||||
|
@ -74,6 +74,7 @@ public:
|
|||||||
NS_IMETHOD RemoveLoadingDocListener(const nsCString& aURL)=0;
|
NS_IMETHOD RemoveLoadingDocListener(const nsCString& aURL)=0;
|
||||||
|
|
||||||
NS_IMETHOD InheritsStyle(nsIContent* aContent, PRBool* aResult) = 0;
|
NS_IMETHOD InheritsStyle(nsIContent* aContent, PRBool* aResult) = 0;
|
||||||
|
NS_IMETHOD FlushChromeBindings() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // nsIBinding_Manager_h__
|
#endif // nsIBinding_Manager_h__
|
||||||
|
@ -91,6 +91,9 @@ public:
|
|||||||
NS_IMETHOD WalkRules(nsISupportsArrayEnumFunc aFunc, void* aData)=0;
|
NS_IMETHOD WalkRules(nsISupportsArrayEnumFunc aFunc, void* aData)=0;
|
||||||
|
|
||||||
NS_IMETHOD SetAllowScripts(PRBool aFlag)=0;
|
NS_IMETHOD SetAllowScripts(PRBool aFlag)=0;
|
||||||
|
|
||||||
|
NS_IMETHOD MarkForDeath()=0;
|
||||||
|
NS_IMETHOD MarkedForDeath(PRBool* aResult)=0;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern nsresult
|
extern nsresult
|
||||||
|
@ -59,6 +59,9 @@ public:
|
|||||||
// This method loads a binding doc and then builds the specific binding required.
|
// This method loads a binding doc and then builds the specific binding required.
|
||||||
NS_IMETHOD GetBinding(nsIContent* aBoundElement, const nsCString& aURLStr, nsIXBLBinding** aResult) = 0;
|
NS_IMETHOD GetBinding(nsIContent* aBoundElement, const nsCString& aURLStr, nsIXBLBinding** aResult) = 0;
|
||||||
|
|
||||||
|
// Indicates whether or not a binding is fully loaded.
|
||||||
|
NS_IMETHOD BindingReady(nsIContent* aBoundElement, const nsCString& aURLStr, PRBool* aIsReady) = 0;
|
||||||
|
|
||||||
// For a given element, returns a flat list of all the anonymous children that need
|
// For a given element, returns a flat list of all the anonymous children that need
|
||||||
// frames built.
|
// frames built.
|
||||||
NS_IMETHOD GetContentList(nsIContent* aContent, nsISupportsArray** aResult, nsIContent** aChildElement,
|
NS_IMETHOD GetContentList(nsIContent* aContent, nsISupportsArray** aResult, nsIContent** aChildElement,
|
||||||
|
@ -178,6 +178,7 @@ public:
|
|||||||
NS_IMETHOD RemoveLoadingDocListener(const nsCString& aURL);
|
NS_IMETHOD RemoveLoadingDocListener(const nsCString& aURL);
|
||||||
|
|
||||||
NS_IMETHOD InheritsStyle(nsIContent* aContent, PRBool* aResult);
|
NS_IMETHOD InheritsStyle(nsIContent* aContent, PRBool* aResult);
|
||||||
|
NS_IMETHOD FlushChromeBindings();
|
||||||
|
|
||||||
// nsIStyleRuleSupplier
|
// nsIStyleRuleSupplier
|
||||||
NS_IMETHOD UseDocumentRules(nsIContent* aContent, PRBool* aResult);
|
NS_IMETHOD UseDocumentRules(nsIContent* aContent, PRBool* aResult);
|
||||||
@ -252,8 +253,13 @@ nsBindingManager::SetBinding(nsIContent* aContent, nsIXBLBinding* aBinding )
|
|||||||
mBindingTable = new nsSupportsHashtable;
|
mBindingTable = new nsSupportsHashtable;
|
||||||
|
|
||||||
nsISupportsKey key(aContent);
|
nsISupportsKey key(aContent);
|
||||||
|
|
||||||
|
nsCOMPtr<nsISupports> old = getter_AddRefs(mBindingTable->Get(&key));
|
||||||
|
if (old && aBinding)
|
||||||
|
NS_ERROR("Binding already installed!");
|
||||||
|
|
||||||
if (aBinding) {
|
if (aBinding) {
|
||||||
mBindingTable->Put (&key, aBinding);
|
mBindingTable->Put(&key, aBinding);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
mBindingTable->Remove(&key);
|
mBindingTable->Remove(&key);
|
||||||
@ -468,6 +474,23 @@ nsBindingManager::RemoveLoadingDocListener(const nsCString& aURL)
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PRBool PR_CALLBACK MarkForDeath(nsHashKey* aKey, void* aData, void* aClosure)
|
||||||
|
{
|
||||||
|
nsIXBLBinding* binding = (nsIXBLBinding*)aData;
|
||||||
|
nsCAutoString docURI;
|
||||||
|
binding->GetDocURI(docURI);
|
||||||
|
if (!docURI.CompareWithConversion("chrome", PR_FALSE, 6))
|
||||||
|
binding->MarkForDeath();
|
||||||
|
return PR_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsBindingManager::FlushChromeBindings()
|
||||||
|
{
|
||||||
|
mBindingTable->Enumerate(MarkForDeath);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsBindingManager::InheritsStyle(nsIContent* aContent, PRBool* aResult)
|
nsBindingManager::InheritsStyle(nsIContent* aContent, PRBool* aResult)
|
||||||
{
|
{
|
||||||
|
@ -252,11 +252,14 @@ nsXBLBinding::nsXBLBinding(const nsCString& aDocURI, const nsCString& aID)
|
|||||||
mIsStyleBinding(PR_TRUE),
|
mIsStyleBinding(PR_TRUE),
|
||||||
mAllowScripts(PR_TRUE),
|
mAllowScripts(PR_TRUE),
|
||||||
mInheritStyle(PR_TRUE),
|
mInheritStyle(PR_TRUE),
|
||||||
|
mMarkedForDeath(PR_FALSE),
|
||||||
mAttributeTable(nsnull),
|
mAttributeTable(nsnull),
|
||||||
mInsertionPointTable(nsnull)
|
mInsertionPointTable(nsnull)
|
||||||
{
|
{
|
||||||
NS_INIT_REFCNT();
|
NS_INIT_REFCNT();
|
||||||
gRefCnt++;
|
gRefCnt++;
|
||||||
|
// printf("REF COUNT UP: %d %s\n", gRefCnt, (const char*)mID);
|
||||||
|
|
||||||
if (gRefCnt == 1) {
|
if (gRefCnt == 1) {
|
||||||
kContentAtom = NS_NewAtom("content");
|
kContentAtom = NS_NewAtom("content");
|
||||||
kInterfaceAtom = NS_NewAtom("interface");
|
kInterfaceAtom = NS_NewAtom("interface");
|
||||||
@ -303,6 +306,8 @@ nsXBLBinding::~nsXBLBinding(void)
|
|||||||
delete mInsertionPointTable;
|
delete mInsertionPointTable;
|
||||||
|
|
||||||
gRefCnt--;
|
gRefCnt--;
|
||||||
|
// printf("REF COUNT DOWN: %d %s\n", gRefCnt, (const char*)mID);
|
||||||
|
|
||||||
if (gRefCnt == 0) {
|
if (gRefCnt == 0) {
|
||||||
NS_RELEASE(kContentAtom);
|
NS_RELEASE(kContentAtom);
|
||||||
NS_RELEASE(kInterfaceAtom);
|
NS_RELEASE(kInterfaceAtom);
|
||||||
@ -354,6 +359,11 @@ nsXBLBinding::GetBaseBinding(nsIXBLBinding** aResult)
|
|||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsXBLBinding::SetBaseBinding(nsIXBLBinding* aBinding)
|
nsXBLBinding::SetBaseBinding(nsIXBLBinding* aBinding)
|
||||||
{
|
{
|
||||||
|
if (mNextBinding) {
|
||||||
|
NS_ERROR("Base XBL binding is already defined!");
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
mNextBinding = aBinding; // Comptr handles rel/add
|
mNextBinding = aBinding; // Comptr handles rel/add
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
@ -1454,8 +1464,6 @@ nsXBLBinding::IsInExcludesList(nsIAtom* aTag, const nsString& aList)
|
|||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsXBLBinding::ConstructAttributeTable(nsIContent* aElement)
|
nsXBLBinding::ConstructAttributeTable(nsIContent* aElement)
|
||||||
{
|
{
|
||||||
// XXX This function still needs to deal with the
|
|
||||||
// ability to map one attribute to another.
|
|
||||||
nsAutoString inherits;
|
nsAutoString inherits;
|
||||||
aElement->GetAttribute(kNameSpaceID_None, kInheritsAtom, inherits);
|
aElement->GetAttribute(kNameSpaceID_None, kInheritsAtom, inherits);
|
||||||
if (!inherits.IsEmpty()) {
|
if (!inherits.IsEmpty()) {
|
||||||
@ -1745,7 +1753,19 @@ nsXBLBinding::GetFirstStyleBinding(nsIXBLBinding** aResult)
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsXBLBinding::MarkForDeath()
|
||||||
|
{
|
||||||
|
mMarkedForDeath = PR_TRUE;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsXBLBinding::MarkedForDeath(PRBool* aResult)
|
||||||
|
{
|
||||||
|
*aResult = mMarkedForDeath;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
// Creation Routine ///////////////////////////////////////////////////////////////////////
|
// Creation Routine ///////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ -85,6 +85,9 @@ class nsXBLBinding: public nsIXBLBinding
|
|||||||
|
|
||||||
NS_IMETHOD SetAllowScripts(PRBool aFlag) { mAllowScripts = aFlag; return NS_OK; };
|
NS_IMETHOD SetAllowScripts(PRBool aFlag) { mAllowScripts = aFlag; return NS_OK; };
|
||||||
|
|
||||||
|
NS_IMETHOD MarkForDeath();
|
||||||
|
NS_IMETHOD MarkedForDeath(PRBool* aResult);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
nsXBLBinding(const nsCString& aDocURI, const nsCString& aRef);
|
nsXBLBinding(const nsCString& aDocURI, const nsCString& aRef);
|
||||||
virtual ~nsXBLBinding();
|
virtual ~nsXBLBinding();
|
||||||
@ -172,9 +175,10 @@ protected:
|
|||||||
|
|
||||||
nsIContent* mBoundElement; // [WEAK] We have a reference, but we don't own it.
|
nsIContent* mBoundElement; // [WEAK] We have a reference, but we don't own it.
|
||||||
|
|
||||||
PRBool mIsStyleBinding;
|
PRPackedBool mIsStyleBinding;
|
||||||
PRBool mAllowScripts;
|
PRPackedBool mAllowScripts;
|
||||||
PRBool mInheritStyle;
|
PRPackedBool mInheritStyle;
|
||||||
|
PRPackedBool mMarkedForDeath;
|
||||||
|
|
||||||
nsSupportsHashtable* mAttributeTable; // A table for attribute entries.
|
nsSupportsHashtable* mAttributeTable; // A table for attribute entries.
|
||||||
nsSupportsHashtable* mInsertionPointTable; // A table of insertion points.
|
nsSupportsHashtable* mInsertionPointTable; // A table of insertion points.
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "nsXBLService.h"
|
#include "nsXBLService.h"
|
||||||
#include "nsIInputStream.h"
|
#include "nsIInputStream.h"
|
||||||
|
#include "nsINameSpace.h"
|
||||||
#include "nsINameSpaceManager.h"
|
#include "nsINameSpaceManager.h"
|
||||||
#include "nsHashtable.h"
|
#include "nsHashtable.h"
|
||||||
#include "nsIURI.h"
|
#include "nsIURI.h"
|
||||||
@ -37,6 +38,7 @@
|
|||||||
#include "nsNetUtil.h"
|
#include "nsNetUtil.h"
|
||||||
#include "plstr.h"
|
#include "plstr.h"
|
||||||
#include "nsIContent.h"
|
#include "nsIContent.h"
|
||||||
|
#include "nsIXMLContent.h"
|
||||||
#include "nsIDOMElement.h"
|
#include "nsIDOMElement.h"
|
||||||
#include "nsIDocument.h"
|
#include "nsIDocument.h"
|
||||||
#include "nsIXMLContentSink.h"
|
#include "nsIXMLContentSink.h"
|
||||||
@ -52,6 +54,9 @@
|
|||||||
#include "nsIChromeRegistry.h"
|
#include "nsIChromeRegistry.h"
|
||||||
#include "nsIPref.h"
|
#include "nsIPref.h"
|
||||||
|
|
||||||
|
#include "nsIPresShell.h"
|
||||||
|
#include "nsIDocumentObserver.h"
|
||||||
|
|
||||||
#include "nsIXULContentUtils.h"
|
#include "nsIXULContentUtils.h"
|
||||||
#include "nsIXULPrototypeCache.h"
|
#include "nsIXULPrototypeCache.h"
|
||||||
#include "nsIDOMLoadListener.h"
|
#include "nsIDOMLoadListener.h"
|
||||||
@ -104,55 +109,56 @@ struct nsXBLBindingRequest
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void* operator new(size_t aSize, nsFixedSizeAllocator& aAllocator) {
|
||||||
|
return aAllocator.Alloc(aSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void operator delete(void* aPtr, size_t aSize) {
|
||||||
|
nsFixedSizeAllocator::Free(aPtr, aSize);
|
||||||
|
}
|
||||||
|
|
||||||
void DocumentLoaded(nsIDocument* aBindingDoc)
|
void DocumentLoaded(nsIDocument* aBindingDoc)
|
||||||
{
|
{
|
||||||
// Get the binding.
|
|
||||||
nsCOMPtr<nsIXBLBinding> newBinding;
|
|
||||||
gXBLService->GetBinding(mBoundElement, mBindingURL, getter_AddRefs(newBinding));
|
|
||||||
|
|
||||||
// XXX Deal with layered bindings.
|
|
||||||
// XXX Deal with cross-site inheritance (e.g., http://a/a.xml inheriting from http://b/b.xml)
|
|
||||||
// Install the binding on the content node.
|
|
||||||
nsCOMPtr<nsIDocument> doc;
|
nsCOMPtr<nsIDocument> doc;
|
||||||
mBoundElement->GetDocument(*getter_AddRefs(doc));
|
mBoundElement->GetDocument(*getter_AddRefs(doc));
|
||||||
if (!doc)
|
if (!doc)
|
||||||
return;
|
return;
|
||||||
nsCOMPtr<nsIBindingManager> bindingManager;
|
|
||||||
doc->GetBindingManager(getter_AddRefs(bindingManager));
|
|
||||||
bindingManager->SetBinding(mBoundElement, newBinding);
|
|
||||||
|
|
||||||
// Set the binding's bound element.
|
// Get the binding.
|
||||||
newBinding->SetBoundElement(mBoundElement);
|
PRBool ready = PR_FALSE;
|
||||||
|
gXBLService->BindingReady(mBoundElement, mBindingURL, &ready);
|
||||||
|
|
||||||
// Tell the binding to build the anonymous content.
|
if (!ready)
|
||||||
newBinding->GenerateAnonymousContent(mBoundElement);
|
return;
|
||||||
|
|
||||||
// Tell the binding to install event handlers
|
|
||||||
nsCOMPtr<nsIXBLBinding> attachReq;
|
|
||||||
newBinding->InstallEventHandlers(mBoundElement, getter_AddRefs(attachReq));
|
|
||||||
|
|
||||||
// Set up our properties
|
|
||||||
newBinding->InstallProperties(mBoundElement);
|
|
||||||
|
|
||||||
if (attachReq) {
|
|
||||||
attachReq->ExecuteAttachedHandler();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// XXX Deal with layered bindings.
|
||||||
// Now do a ContentInserted notification to cause the frames to get installed finally,
|
// Now do a ContentInserted notification to cause the frames to get installed finally,
|
||||||
nsCOMPtr<nsIContent> parent;
|
nsCOMPtr<nsIContent> parent;
|
||||||
mBoundElement->GetParent(*getter_AddRefs(parent));
|
mBoundElement->GetParent(*getter_AddRefs(parent));
|
||||||
PRInt32 index = 0;
|
PRInt32 index = 0;
|
||||||
if (parent)
|
if (parent)
|
||||||
parent->IndexOf(mBoundElement, index);
|
parent->IndexOf(mBoundElement, index);
|
||||||
if (index == -1)
|
|
||||||
return;
|
nsCOMPtr<nsIPresShell> shell = getter_AddRefs(doc->GetShellAt(0));
|
||||||
doc->ContentInserted(parent, mBoundElement, index);
|
if (shell) {
|
||||||
|
nsCOMPtr<nsIDocumentObserver> obs(do_QueryInterface(shell));
|
||||||
|
obs->ContentRemoved(doc, parent, mBoundElement, index);
|
||||||
|
obs->ContentInserted(doc, parent, mBoundElement, index);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static nsIXBLService* gXBLService;
|
static nsIXBLService* gXBLService;
|
||||||
static int gRefCnt;
|
static int gRefCnt;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const size_t kBucketSizes[] = {
|
||||||
|
sizeof(nsXBLBindingRequest)
|
||||||
|
};
|
||||||
|
|
||||||
|
static const PRInt32 kNumBuckets = sizeof(kBucketSizes)/sizeof(size_t);
|
||||||
|
static const PRInt32 kNumElements = 64;
|
||||||
|
static const PRInt32 kInitialSize = (NS_SIZE_IN_HEAP(sizeof(nsXBLBindingRequest))) * kNumElements;
|
||||||
|
|
||||||
nsIXBLService* nsXBLBindingRequest::gXBLService = nsnull;
|
nsIXBLService* nsXBLBindingRequest::gXBLService = nsnull;
|
||||||
int nsXBLBindingRequest::gRefCnt = 0;
|
int nsXBLBindingRequest::gRefCnt = 0;
|
||||||
|
|
||||||
@ -180,12 +186,13 @@ public:
|
|||||||
virtual ~nsXBLStreamListener();
|
virtual ~nsXBLStreamListener();
|
||||||
|
|
||||||
void AddRequest(nsXBLBindingRequest* aRequest) { mBindingRequests.AppendElement(aRequest); };
|
void AddRequest(nsXBLBindingRequest* aRequest) { mBindingRequests.AppendElement(aRequest); };
|
||||||
|
PRBool HasRequest(const nsCString& aURI, nsIContent* aBoundElement);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
nsCOMPtr<nsIStreamListener> mInner;
|
nsCOMPtr<nsIStreamListener> mInner;
|
||||||
nsVoidArray mBindingRequests;
|
nsVoidArray mBindingRequests;
|
||||||
|
|
||||||
nsCOMPtr<nsIDocument> mDocument;
|
nsIDocument* mDocument;
|
||||||
nsCOMPtr<nsIDocument> mBindingDocument;
|
nsCOMPtr<nsIDocument> mBindingDocument;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -264,17 +271,34 @@ nsXBLStreamListener::OnStopRequest(nsIChannel* aChannel, nsISupports* aCtxt, nsr
|
|||||||
rv = mInner->OnStopRequest(aChannel, aCtxt, aStatus, aStatusArg);
|
rv = mInner->OnStopRequest(aChannel, aCtxt, aStatus, aStatusArg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv) || NS_FAILED(aStatus)) {
|
||||||
PRUint32 count = mBindingRequests.Count();
|
PRUint32 count = mBindingRequests.Count();
|
||||||
for (PRUint32 i = 0; i < count; i++) {
|
for (PRUint32 i = 0; i < count; i++) {
|
||||||
nsXBLBindingRequest* req = (nsXBLBindingRequest*)mBindingRequests.ElementAt(i);
|
nsXBLBindingRequest* req = (nsXBLBindingRequest*)mBindingRequests.ElementAt(i);
|
||||||
delete req;
|
delete req;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mDocument = nsnull;
|
||||||
|
mBindingDocument = nsnull;
|
||||||
}
|
}
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PRBool
|
||||||
|
nsXBLStreamListener::HasRequest(const nsCString& aURI, nsIContent* aElt)
|
||||||
|
{
|
||||||
|
// XXX Could be more efficient.
|
||||||
|
PRUint32 count = mBindingRequests.Count();
|
||||||
|
for (PRUint32 i = 0; i < count; i++) {
|
||||||
|
nsXBLBindingRequest* req = (nsXBLBindingRequest*)mBindingRequests.ElementAt(i);
|
||||||
|
if (req->mBindingURL.Equals(aURI) && req->mBoundElement.get() == aElt)
|
||||||
|
return PR_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return PR_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsXBLStreamListener::Load(nsIDOMEvent* aEvent)
|
nsXBLStreamListener::Load(nsIDOMEvent* aEvent)
|
||||||
{
|
{
|
||||||
@ -313,6 +337,7 @@ nsXBLStreamListener::Load(nsIDOMEvent* aEvent)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!cached)
|
||||||
bindingManager->PutXBLDocumentInfo(info);
|
bindingManager->PutXBLDocumentInfo(info);
|
||||||
|
|
||||||
// Notify all pending requests that their bindings are
|
// Notify all pending requests that their bindings are
|
||||||
@ -328,9 +353,12 @@ nsXBLStreamListener::Load(nsIDOMEvent* aEvent)
|
|||||||
delete req;
|
delete req;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMEventReceiver> rec(do_QueryInterface(mDocument));
|
nsCOMPtr<nsIDOMEventReceiver> rec(do_QueryInterface(mBindingDocument));
|
||||||
rec->RemoveEventListener(NS_ConvertASCIItoUCS2("load"), (nsIDOMLoadListener*)this, PR_FALSE);
|
rec->RemoveEventListener(NS_ConvertASCIItoUCS2("load"), (nsIDOMLoadListener*)this, PR_FALSE);
|
||||||
|
|
||||||
|
mDocument = nsnull;
|
||||||
|
mBindingDocument = nsnull;
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -406,7 +434,7 @@ PRUint32 nsXBLService::gClassLRUListLength = 0;
|
|||||||
PRUint32 nsXBLService::gClassLRUListQuota = 64;
|
PRUint32 nsXBLService::gClassLRUListQuota = 64;
|
||||||
|
|
||||||
nsIAtom* nsXBLService::kExtendsAtom = nsnull;
|
nsIAtom* nsXBLService::kExtendsAtom = nsnull;
|
||||||
nsIAtom* nsXBLService::kHasChildrenAtom = nsnull;
|
nsIAtom* nsXBLService::kScrollbarAtom = nsnull;
|
||||||
|
|
||||||
// Enabled by default. Must be over-ridden to disable
|
// Enabled by default. Must be over-ridden to disable
|
||||||
PRBool nsXBLService::gDisableChromeCache = PR_FALSE;
|
PRBool nsXBLService::gDisableChromeCache = PR_FALSE;
|
||||||
@ -421,6 +449,8 @@ NS_IMPL_ISUPPORTS2(nsXBLService, nsIXBLService, nsIMemoryPressureObserver)
|
|||||||
nsXBLService::nsXBLService(void)
|
nsXBLService::nsXBLService(void)
|
||||||
{
|
{
|
||||||
NS_INIT_REFCNT();
|
NS_INIT_REFCNT();
|
||||||
|
mPool.Init("XBL Binding Requests", kBucketSizes, kNumBuckets, kInitialSize);
|
||||||
|
|
||||||
gRefCnt++;
|
gRefCnt++;
|
||||||
if (gRefCnt == 1) {
|
if (gRefCnt == 1) {
|
||||||
|
|
||||||
@ -442,7 +472,7 @@ nsXBLService::nsXBLService(void)
|
|||||||
|
|
||||||
// Create our atoms
|
// Create our atoms
|
||||||
kExtendsAtom = NS_NewAtom("extends");
|
kExtendsAtom = NS_NewAtom("extends");
|
||||||
kHasChildrenAtom = NS_NewAtom("haschildren");
|
kScrollbarAtom = NS_NewAtom("scrollbar");
|
||||||
|
|
||||||
// Find out if the XUL cache is on or off
|
// Find out if the XUL cache is on or off
|
||||||
NS_WITH_SERVICE(nsIPref, prefs, NS_PREF_PROGID, &rv);
|
NS_WITH_SERVICE(nsIPref, prefs, NS_PREF_PROGID, &rv);
|
||||||
@ -476,7 +506,7 @@ nsXBLService::~nsXBLService(void)
|
|||||||
|
|
||||||
// Release our atoms
|
// Release our atoms
|
||||||
NS_RELEASE(kExtendsAtom);
|
NS_RELEASE(kExtendsAtom);
|
||||||
NS_RELEASE(kHasChildrenAtom);
|
NS_RELEASE(kScrollbarAtom);
|
||||||
|
|
||||||
// Walk the LRU list removing and deleting the nsXBLJSClasses.
|
// Walk the LRU list removing and deleting the nsXBLJSClasses.
|
||||||
FlushMemory(REASON_HEAP_MINIMIZE, 0);
|
FlushMemory(REASON_HEAP_MINIMIZE, 0);
|
||||||
@ -526,6 +556,13 @@ nsXBLService::LoadBindings(nsIContent* aContent, const nsString& aURL, PRBool aA
|
|||||||
nsCOMPtr<nsIXBLBinding> styleBinding;
|
nsCOMPtr<nsIXBLBinding> styleBinding;
|
||||||
binding->GetFirstStyleBinding(getter_AddRefs(styleBinding));
|
binding->GetFirstStyleBinding(getter_AddRefs(styleBinding));
|
||||||
if (styleBinding) {
|
if (styleBinding) {
|
||||||
|
PRBool marked = PR_FALSE;
|
||||||
|
binding->MarkedForDeath(&marked);
|
||||||
|
if (marked) {
|
||||||
|
FlushStyleBindings(aContent);
|
||||||
|
binding = nsnull;
|
||||||
|
}
|
||||||
|
else {
|
||||||
// See if the URIs match.
|
// See if the URIs match.
|
||||||
nsCAutoString uri;
|
nsCAutoString uri;
|
||||||
styleBinding->GetBindingURI(uri);
|
styleBinding->GetBindingURI(uri);
|
||||||
@ -537,6 +574,7 @@ nsXBLService::LoadBindings(nsIContent* aContent, const nsString& aURL, PRBool aA
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsIXBLBinding> newBinding;
|
nsCOMPtr<nsIXBLBinding> newBinding;
|
||||||
nsCAutoString url; url.AssignWithConversion(aURL);
|
nsCAutoString url; url.AssignWithConversion(aURL);
|
||||||
@ -736,8 +774,28 @@ nsXBLService::FlushMemory(PRUint32 reason, size_t requestedAmount)
|
|||||||
|
|
||||||
// Internal helper methods ////////////////////////////////////////////////////////////////
|
// Internal helper methods ////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
NS_IMETHODIMP nsXBLService::GetBinding(nsIContent* aBoundElement, const nsCString& aURLStr, nsIXBLBinding** aResult)
|
NS_IMETHODIMP nsXBLService::GetBinding(nsIContent* aBoundElement,
|
||||||
|
const nsCString& aURLStr,
|
||||||
|
nsIXBLBinding** aResult)
|
||||||
{
|
{
|
||||||
|
PRBool dummy;
|
||||||
|
return GetBindingInternal(aBoundElement, aURLStr, PR_FALSE, &dummy, aResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP nsXBLService::BindingReady(nsIContent* aBoundElement,
|
||||||
|
const nsCString& aURLStr,
|
||||||
|
PRBool* aIsReady)
|
||||||
|
{
|
||||||
|
return GetBindingInternal(aBoundElement, aURLStr, PR_TRUE, aIsReady, nsnull);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP nsXBLService::GetBindingInternal(nsIContent* aBoundElement,
|
||||||
|
const nsCString& aURLStr,
|
||||||
|
PRBool aPeekOnly,
|
||||||
|
PRBool* aIsReady,
|
||||||
|
nsIXBLBinding** aResult)
|
||||||
|
{
|
||||||
|
if (aResult)
|
||||||
*aResult = nsnull;
|
*aResult = nsnull;
|
||||||
|
|
||||||
if (aURLStr.IsEmpty())
|
if (aURLStr.IsEmpty())
|
||||||
@ -782,6 +840,42 @@ NS_IMETHODIMP nsXBLService::GetBinding(nsIContent* aBoundElement, const nsCStrin
|
|||||||
|
|
||||||
// If no ref is specified just use this.
|
// If no ref is specified just use this.
|
||||||
if ((bindingName.IsEmpty()) || (bindingName == value)) {
|
if ((bindingName.IsEmpty()) || (bindingName == value)) {
|
||||||
|
// Check for the presence of an extends attribute
|
||||||
|
nsAutoString extends;
|
||||||
|
nsCOMPtr<nsIXBLBinding> baseBinding;
|
||||||
|
child->GetAttribute(kNameSpaceID_None, kExtendsAtom, extends);
|
||||||
|
value = extends;
|
||||||
|
if (!extends.IsEmpty()) {
|
||||||
|
nsAutoString prefix;
|
||||||
|
PRInt32 offset = extends.FindChar(':');
|
||||||
|
if (-1 != offset) {
|
||||||
|
extends.Left(prefix, offset);
|
||||||
|
extends.Cut(0, offset+1);
|
||||||
|
}
|
||||||
|
if (prefix.Length() > 0) {
|
||||||
|
// Look up the prefix.
|
||||||
|
nsCOMPtr<nsIAtom> prefixAtom = getter_AddRefs(NS_NewAtom(prefix));
|
||||||
|
nsCOMPtr<nsINameSpace> nameSpace;
|
||||||
|
nsCOMPtr<nsIXMLContent> xmlContent(do_QueryInterface(child));
|
||||||
|
if (xmlContent) {
|
||||||
|
xmlContent->GetContainingNameSpace(*getter_AddRefs(nameSpace));
|
||||||
|
if (nameSpace) {
|
||||||
|
nsCOMPtr<nsINameSpace> tagSpace;
|
||||||
|
nameSpace->FindNameSpace(prefixAtom, *getter_AddRefs(tagSpace));
|
||||||
|
if (!tagSpace) {
|
||||||
|
// We have a base class binding. Load it right now.
|
||||||
|
nsCAutoString urlCString; urlCString.AssignWithConversion(value);
|
||||||
|
GetBindingInternal(aBoundElement, urlCString, aPeekOnly, aIsReady, getter_AddRefs(baseBinding));
|
||||||
|
if (!*aIsReady)
|
||||||
|
return NS_ERROR_FAILURE; // Binding not yet ready or an error occurred.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*aIsReady = PR_TRUE;
|
||||||
|
if (!aPeekOnly) {
|
||||||
// Make a new binding
|
// Make a new binding
|
||||||
NS_NewXBLBinding(uri, ref, aResult);
|
NS_NewXBLBinding(uri, ref, aResult);
|
||||||
|
|
||||||
@ -789,24 +883,9 @@ NS_IMETHODIMP nsXBLService::GetBinding(nsIContent* aBoundElement, const nsCStrin
|
|||||||
(*aResult)->SetBindingElement(child);
|
(*aResult)->SetBindingElement(child);
|
||||||
(*aResult)->SetAllowScripts(allowScripts);
|
(*aResult)->SetAllowScripts(allowScripts);
|
||||||
|
|
||||||
// Check for the presence of an extends attribute
|
if (baseBinding)
|
||||||
child->GetAttribute(kNameSpaceID_None, kExtendsAtom, value);
|
|
||||||
if (!value.IsEmpty()) {
|
|
||||||
// See if we are extending a builtin tag.
|
|
||||||
nsCOMPtr<nsIAtom> tag;
|
|
||||||
PRInt32 dummy;
|
|
||||||
(*aResult)->GetBaseTag(&dummy, getter_AddRefs(tag));
|
|
||||||
if (!tag) {
|
|
||||||
// We have a base class binding. Load it right now.
|
|
||||||
nsCOMPtr<nsIXBLBinding> baseBinding;
|
|
||||||
nsCAutoString urlCString; urlCString.AssignWithConversion(value);
|
|
||||||
GetBinding(aBoundElement, urlCString, getter_AddRefs(baseBinding));
|
|
||||||
if (!baseBinding)
|
|
||||||
return NS_OK; // At least we got the derived class binding loaded.
|
|
||||||
(*aResult)->SetBaseBinding(baseBinding);
|
(*aResult)->SetBaseBinding(baseBinding);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -839,7 +918,9 @@ nsXBLService::GetBindingDocumentInfo(nsIContent* aBoundElement, const nsCString&
|
|||||||
boundDocument->GetBindingManager(getter_AddRefs(bindingManager));
|
boundDocument->GetBindingManager(getter_AddRefs(bindingManager));
|
||||||
bindingManager->GetXBLDocumentInfo(aURLStr, getter_AddRefs(info));
|
bindingManager->GetXBLDocumentInfo(aURLStr, getter_AddRefs(info));
|
||||||
|
|
||||||
if (!info) {
|
nsCOMPtr<nsIAtom> tagName;
|
||||||
|
aBoundElement->GetTag(*getter_AddRefs(tagName));
|
||||||
|
if (!info && (tagName.get() != kScrollbarAtom)) {
|
||||||
// The third line of defense is to investigate whether or not the
|
// The third line of defense is to investigate whether or not the
|
||||||
// document is currently being loaded asynchronously. If so, there's no
|
// document is currently being loaded asynchronously. If so, there's no
|
||||||
// document yet, but we need to glom on our request so that it will be
|
// document yet, but we need to glom on our request so that it will be
|
||||||
@ -847,14 +928,16 @@ nsXBLService::GetBindingDocumentInfo(nsIContent* aBoundElement, const nsCString&
|
|||||||
nsCOMPtr<nsIStreamListener> listener;
|
nsCOMPtr<nsIStreamListener> listener;
|
||||||
bindingManager->GetLoadingDocListener(aURLStr, getter_AddRefs(listener));
|
bindingManager->GetLoadingDocListener(aURLStr, getter_AddRefs(listener));
|
||||||
if (listener) {
|
if (listener) {
|
||||||
|
nsIStreamListener* ilist = listener.get();
|
||||||
|
nsXBLStreamListener* xblListener = NS_STATIC_CAST(nsXBLStreamListener*, ilist);
|
||||||
// Create a new load observer.
|
// Create a new load observer.
|
||||||
nsCAutoString bindingURI(aURLStr);
|
nsCAutoString bindingURI(aURLStr);
|
||||||
bindingURI += "#";
|
bindingURI += "#";
|
||||||
bindingURI += aRef;
|
bindingURI += aRef;
|
||||||
nsXBLBindingRequest* req = new nsXBLBindingRequest(aRef, aBoundElement);
|
if (!xblListener->HasRequest(bindingURI, aBoundElement)) {
|
||||||
nsIStreamListener* ilist = listener.get();
|
nsXBLBindingRequest* req = new (mPool) nsXBLBindingRequest(bindingURI, aBoundElement);
|
||||||
nsXBLStreamListener* xblListener = NS_STATIC_CAST(nsXBLStreamListener*, ilist);
|
|
||||||
xblListener->AddRequest(req);
|
xblListener->AddRequest(req);
|
||||||
|
}
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -947,10 +1030,11 @@ nsXBLService::FetchBindingDocument(nsIContent* aBoundElement, nsIURI* aURI, cons
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsChromeURI(aURI)) {
|
nsCOMPtr<nsIAtom> tagName;
|
||||||
|
aBoundElement->GetTag(*getter_AddRefs(tagName));
|
||||||
|
if (tagName != kScrollbarAtom) {
|
||||||
// We can be asynchronous
|
// We can be asynchronous
|
||||||
nsXBLStreamListener* xblListener = new nsXBLStreamListener(listener, boundDoc, doc);
|
nsXBLStreamListener* xblListener = new nsXBLStreamListener(listener, boundDoc, doc);
|
||||||
NS_ADDREF(xblListener);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMEventReceiver> rec(do_QueryInterface(doc));
|
nsCOMPtr<nsIDOMEventReceiver> rec(do_QueryInterface(doc));
|
||||||
rec->AddEventListener(NS_ConvertASCIItoUCS2("load"), (nsIDOMLoadListener*)xblListener, PR_FALSE);
|
rec->AddEventListener(NS_ConvertASCIItoUCS2("load"), (nsIDOMLoadListener*)xblListener, PR_FALSE);
|
||||||
@ -968,7 +1052,7 @@ nsXBLService::FetchBindingDocument(nsIContent* aBoundElement, nsIURI* aURI, cons
|
|||||||
nsCAutoString bindingURI(uri);
|
nsCAutoString bindingURI(uri);
|
||||||
bindingURI += "#";
|
bindingURI += "#";
|
||||||
bindingURI += aRef;
|
bindingURI += aRef;
|
||||||
nsXBLBindingRequest* req = new nsXBLBindingRequest(bindingURI, aBoundElement);
|
nsXBLBindingRequest* req = new (mPool) nsXBLBindingRequest(bindingURI, aBoundElement);
|
||||||
xblListener->AddRequest(req);
|
xblListener->AddRequest(req);
|
||||||
|
|
||||||
// Now kick off the async read.
|
// Now kick off the async read.
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include "nsIMemory.h"
|
#include "nsIMemory.h"
|
||||||
#include "jsapi.h" // nsXBLJSClass derives from JSClass
|
#include "jsapi.h" // nsXBLJSClass derives from JSClass
|
||||||
#include "jsclist.h" // nsXBLJSClass derives from JSCList
|
#include "jsclist.h" // nsXBLJSClass derives from JSCList
|
||||||
|
#include "nsFixedSizeAllocator.h"
|
||||||
|
|
||||||
class nsIXBLBinding;
|
class nsIXBLBinding;
|
||||||
class nsIXBLDocumentInfo;
|
class nsIXBLDocumentInfo;
|
||||||
@ -54,6 +55,9 @@ class nsXBLService : public nsIXBLService, public nsIMemoryPressureObserver
|
|||||||
// This method loads a binding doc and then builds the specific binding required.
|
// This method loads a binding doc and then builds the specific binding required.
|
||||||
NS_IMETHOD GetBinding(nsIContent* aBoundElement, const nsCString& aURLStr, nsIXBLBinding** aResult);
|
NS_IMETHOD GetBinding(nsIContent* aBoundElement, const nsCString& aURLStr, nsIXBLBinding** aResult);
|
||||||
|
|
||||||
|
// Indicates whether or not a binding is fully loaded.
|
||||||
|
NS_IMETHOD BindingReady(nsIContent* aBoundElement, const nsCString& aURLStr, PRBool* aIsReady);
|
||||||
|
|
||||||
// This function clears out the bindings on a given content node.
|
// This function clears out the bindings on a given content node.
|
||||||
NS_IMETHOD FlushStyleBindings(nsIContent* aContent);
|
NS_IMETHOD FlushStyleBindings(nsIContent* aContent);
|
||||||
|
|
||||||
@ -80,6 +84,11 @@ public:
|
|||||||
// This method synchronously loads and parses an XBL file.
|
// This method synchronously loads and parses an XBL file.
|
||||||
NS_IMETHOD FetchBindingDocument(nsIContent* aBoundElement, nsIURI* aURI, const nsCString& aRef, nsIDocument** aResult);
|
NS_IMETHOD FetchBindingDocument(nsIContent* aBoundElement, nsIURI* aURI, const nsCString& aRef, nsIDocument** aResult);
|
||||||
|
|
||||||
|
// This method loads a binding doc and then builds the specific binding required. It
|
||||||
|
// can also peek without building.
|
||||||
|
NS_IMETHOD GetBindingInternal(nsIContent* aBoundElement, const nsCString& aURLStr,
|
||||||
|
PRBool aPeekFlag, PRBool* aIsReady, nsIXBLBinding** aResult);
|
||||||
|
|
||||||
// This method walks a binding document and removes any text nodes
|
// This method walks a binding document and removes any text nodes
|
||||||
// that contain only whitespace.
|
// that contain only whitespace.
|
||||||
static nsresult StripWhitespaceNodes(nsIContent* aContent);
|
static nsresult StripWhitespaceNodes(nsIContent* aContent);
|
||||||
@ -104,7 +113,10 @@ public:
|
|||||||
|
|
||||||
// XBL Atoms
|
// XBL Atoms
|
||||||
static nsIAtom* kExtendsAtom;
|
static nsIAtom* kExtendsAtom;
|
||||||
static nsIAtom* kHasChildrenAtom;
|
|
||||||
|
static nsIAtom* kScrollbarAtom;
|
||||||
|
|
||||||
|
nsFixedSizeAllocator mPool;
|
||||||
};
|
};
|
||||||
|
|
||||||
class nsXBLJSClass : public JSCList, public JSClass
|
class nsXBLJSClass : public JSCList, public JSClass
|
||||||
|
@ -74,6 +74,7 @@
|
|||||||
#include "nsLayoutCID.h"
|
#include "nsLayoutCID.h"
|
||||||
#include "nsGfxCIID.h"
|
#include "nsGfxCIID.h"
|
||||||
#include "nsIImageManager.h"
|
#include "nsIImageManager.h"
|
||||||
|
#include "nsIBindingManager.h"
|
||||||
#include "prio.h"
|
#include "prio.h"
|
||||||
|
|
||||||
static char kChromePrefix[] = "chrome://";
|
static char kChromePrefix[] = "chrome://";
|
||||||
@ -1044,6 +1045,11 @@ NS_IMETHODIMP nsChromeRegistry::RefreshWindow(nsIDOMWindow* aWindow)
|
|||||||
if (!document)
|
if (!document)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
||||||
|
// Annihilate all XBL bindings.
|
||||||
|
nsCOMPtr<nsIBindingManager> bindingManager;
|
||||||
|
document->GetBindingManager(getter_AddRefs(bindingManager));
|
||||||
|
bindingManager->FlushChromeBindings();
|
||||||
|
|
||||||
nsCOMPtr<nsIXULDocument> xulDoc = do_QueryInterface(domDocument);
|
nsCOMPtr<nsIXULDocument> xulDoc = do_QueryInterface(domDocument);
|
||||||
if (xulDoc) {
|
if (xulDoc) {
|
||||||
// Deal with the backstop sheets first.
|
// Deal with the backstop sheets first.
|
||||||
|
Loading…
Reference in New Issue
Block a user