mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-12 04:45:45 +00:00
Fix for 42320. r=danm
This commit is contained in:
parent
ed96fc9dc0
commit
1e75026c61
@ -32,6 +32,7 @@ EXPORTS = \
|
||||
nsIBindingManager.h \
|
||||
nsIXBLBinding.h \
|
||||
nsIXBLService.h \
|
||||
nsIXBLStreamListener.h \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))
|
||||
|
@ -1,4 +1,6 @@
|
||||
nsIBindingManager.h
|
||||
nsIXBLBinding.h
|
||||
nsIXBLService.h
|
||||
nsIXBLStreamListener.h
|
||||
|
||||
|
||||
|
@ -25,6 +25,7 @@ EXPORTS = \
|
||||
nsIBindingManager.h \
|
||||
nsIXBLBinding.h \
|
||||
nsIXBLService.h \
|
||||
nsIXBLStreamListener.h \
|
||||
$(NULL)
|
||||
|
||||
MODULE=raptor
|
||||
|
@ -37,6 +37,7 @@
|
||||
class nsIContent;
|
||||
class nsIXBLBinding;
|
||||
class nsIAtom;
|
||||
class nsIXBLStreamListener;
|
||||
|
||||
// {55D70FE0-C8E5-11d3-97FB-00400553EEF0}
|
||||
#define NS_IBINDING_MANAGER_IID \
|
||||
@ -66,6 +67,9 @@ public:
|
||||
NS_IMETHOD PutXBLDocument(nsIDocument* aDocument) = 0;
|
||||
NS_IMETHOD GetXBLDocument(const nsCString& aURL, nsIDocument** aResult) = 0;
|
||||
|
||||
NS_IMETHOD PutLoadingDocListener(const nsCString& aURL, nsIXBLStreamListener* aListener) = 0;
|
||||
NS_IMETHOD GetLoadingDocListener(const nsCString& aURL, nsIXBLStreamListener** aResult) = 0;
|
||||
NS_IMETHOD RemoveLoadingDocListener(const nsCString& aURL)=0;
|
||||
};
|
||||
|
||||
#endif // nsIBinding_Manager_h__
|
||||
|
@ -55,6 +55,9 @@ public:
|
||||
// This function clears out the bindings on a given content node.
|
||||
NS_IMETHOD FlushStyleBindings(nsIContent* aContent) = 0;
|
||||
|
||||
// This method loads a binding doc and then builds the specific binding required.
|
||||
NS_IMETHOD GetBinding(nsIContent* aBoundElement, const nsCString& aURLStr, nsIXBLBinding** aResult) = 0;
|
||||
|
||||
// For a given element, returns a flat list of all the anonymous children that need
|
||||
// frames built.
|
||||
NS_IMETHOD GetContentList(nsIContent* aContent, nsISupportsArray** aResult, nsIContent** aChildElement,
|
||||
|
@ -46,6 +46,7 @@
|
||||
#include "nsITextContent.h"
|
||||
|
||||
#include "nsIXBLBinding.h"
|
||||
#include "nsIXBLStreamListener.h"
|
||||
|
||||
// Static IIDs/CIDs. Try to minimize these.
|
||||
static NS_DEFINE_CID(kNameSpaceManagerCID, NS_NAMESPACEMANAGER_CID);
|
||||
@ -79,10 +80,16 @@ public:
|
||||
NS_IMETHOD PutXBLDocument(nsIDocument* aDocument);
|
||||
NS_IMETHOD GetXBLDocument(const nsCString& aURL, nsIDocument** aResult);
|
||||
|
||||
NS_IMETHOD PutLoadingDocListener(const nsCString& aURL, nsIXBLStreamListener* aListener);
|
||||
NS_IMETHOD GetLoadingDocListener(const nsCString& aURL, nsIXBLStreamListener** aResult);
|
||||
NS_IMETHOD RemoveLoadingDocListener(const nsCString& aURL);
|
||||
|
||||
// MEMBER VARIABLES
|
||||
protected:
|
||||
nsSupportsHashtable* mBindingTable;
|
||||
nsSupportsHashtable* mDocumentTable;
|
||||
nsSupportsHashtable* mLoadingDocTable;
|
||||
|
||||
nsCOMPtr<nsISupportsArray> mAttachedQueue;
|
||||
};
|
||||
|
||||
@ -99,7 +106,10 @@ nsBindingManager::nsBindingManager(void)
|
||||
NS_INIT_REFCNT();
|
||||
|
||||
mBindingTable = nsnull;
|
||||
|
||||
mDocumentTable = nsnull;
|
||||
mLoadingDocTable = nsnull;
|
||||
|
||||
mAttachedQueue = nsnull;
|
||||
}
|
||||
|
||||
@ -107,6 +117,7 @@ nsBindingManager::~nsBindingManager(void)
|
||||
{
|
||||
delete mBindingTable;
|
||||
delete mDocumentTable;
|
||||
delete mLoadingDocTable;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -310,6 +321,41 @@ nsBindingManager::GetXBLDocument(const nsCString& aURL, nsIDocument** aResult)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBindingManager::PutLoadingDocListener(const nsCString& aURL, nsIXBLStreamListener* aListener)
|
||||
{
|
||||
if (!mLoadingDocTable)
|
||||
mLoadingDocTable = new nsSupportsHashtable();
|
||||
|
||||
nsStringKey key(aURL);
|
||||
mLoadingDocTable->Put(&key, aListener);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBindingManager::GetLoadingDocListener(const nsCString& aURL, nsIXBLStreamListener** aResult)
|
||||
{
|
||||
*aResult = nsnull;
|
||||
if (!mLoadingDocTable)
|
||||
return NS_OK;
|
||||
|
||||
nsStringKey key(aURL);
|
||||
*aResult = NS_STATIC_CAST(nsIXBLStreamListener*, mLoadingDocTable->Get(&key)); // Addref happens here.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBindingManager::RemoveLoadingDocListener(const nsCString& aURL)
|
||||
{
|
||||
if (!mLoadingDocTable)
|
||||
return NS_OK;
|
||||
|
||||
nsStringKey key(aURL);
|
||||
mLoadingDocTable->Remove(&key);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Creation Routine ///////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
@ -52,6 +52,7 @@
|
||||
|
||||
#include "nsIXULContentUtils.h"
|
||||
#include "nsIXULPrototypeCache.h"
|
||||
#include "nsIXBLStreamListener.h"
|
||||
|
||||
// Static IIDs/CIDs. Try to minimize these.
|
||||
static NS_DEFINE_CID(kNameSpaceManagerCID, NS_NAMESPACEMANAGER_CID);
|
||||
@ -62,40 +63,118 @@ static NS_DEFINE_CID(kChromeRegistryCID, NS_CHROMEREGISTRY_CID);
|
||||
// Individual binding requests.
|
||||
struct nsXBLBindingRequest
|
||||
{
|
||||
nsCOMPtr<nsIURL> mURL;
|
||||
nsCString mBindingURL;
|
||||
nsCOMPtr<nsIContent> mBoundElement;
|
||||
|
||||
nsXBLBindingRequest(const nsCString& aURL, nsIContent* aBoundElement)
|
||||
{
|
||||
mBindingURL = aURL;
|
||||
mBoundElement = aBoundElement;
|
||||
|
||||
gRefCnt++;
|
||||
if (gRefCnt == 1) {
|
||||
nsServiceManager::GetService("component://netscape/xbl",
|
||||
NS_GET_IID(nsIXBLService),
|
||||
(nsISupports**) &gXBLService);
|
||||
}
|
||||
}
|
||||
|
||||
~nsXBLBindingRequest()
|
||||
{
|
||||
gRefCnt--;
|
||||
if (gRefCnt == 0) {
|
||||
nsServiceManager::ReleaseService("component://netscape/xbl", gXBLService);
|
||||
gXBLService = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
mBoundElement->GetDocument(*getter_AddRefs(doc));
|
||||
if (!doc)
|
||||
return;
|
||||
nsCOMPtr<nsIBindingManager> bindingManager;
|
||||
doc->GetBindingManager(getter_AddRefs(bindingManager));
|
||||
bindingManager->SetBinding(mBoundElement, newBinding);
|
||||
|
||||
// Set the binding's bound element.
|
||||
newBinding->SetBoundElement(mBoundElement);
|
||||
|
||||
// Tell the binding to build the anonymous content.
|
||||
newBinding->GenerateAnonymousContent(mBoundElement);
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
// Now do a ContentInserted notification to cause the frames to get installed finally,
|
||||
nsCOMPtr<nsIContent> parent;
|
||||
mBoundElement->GetParent(*getter_AddRefs(parent));
|
||||
PRInt32 index = 0;
|
||||
if (parent)
|
||||
parent->IndexOf(mBoundElement, index);
|
||||
if (index == -1)
|
||||
return;
|
||||
doc->ContentInserted(parent, mBoundElement, index);
|
||||
}
|
||||
|
||||
static nsIXBLService* gXBLService;
|
||||
static int gRefCnt;
|
||||
};
|
||||
|
||||
nsIXBLService* nsXBLBindingRequest::gXBLService = nsnull;
|
||||
int nsXBLBindingRequest::gRefCnt = 0;
|
||||
|
||||
// nsXBLStreamListener, a helper class used for
|
||||
// asynchronous parsing of URLs
|
||||
/* Header file */
|
||||
class nsXBLStreamListener : public nsIStreamListener
|
||||
class nsXBLStreamListener : public nsIStreamListener, public nsIXBLStreamListener
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSISTREAMLISTENER
|
||||
NS_DECL_NSISTREAMOBSERVER
|
||||
|
||||
nsXBLStreamListener(nsIStreamListener* aInner);
|
||||
nsXBLStreamListener(nsIStreamListener* aInner, nsIDocument* aDocument, nsIDocument* aBindingDocument);
|
||||
virtual ~nsXBLStreamListener();
|
||||
/* additional members */
|
||||
|
||||
void AddRequest(nsXBLBindingRequest* aRequest) { mBindingRequests.AppendElement(aRequest); };
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIStreamListener> mInner;
|
||||
|
||||
nsVoidArray mBindingRequests;
|
||||
|
||||
nsCOMPtr<nsIDocument> mDocument;
|
||||
|
||||
static nsIXBLService* gXBLService;
|
||||
nsCOMPtr<nsIDocument> mBindingDocument;
|
||||
};
|
||||
|
||||
nsIXBLService* nsXBLStreamListener::gXBLService = nsnull;
|
||||
|
||||
/* Implementation file */
|
||||
NS_IMPL_ISUPPORTS2(nsXBLStreamListener, nsIStreamListener, nsIStreamObserver)
|
||||
NS_IMPL_ISUPPORTS3(nsXBLStreamListener, nsIStreamListener, nsIStreamObserver, nsIXBLStreamListener)
|
||||
|
||||
nsXBLStreamListener::nsXBLStreamListener(nsIStreamListener* aInner)
|
||||
nsXBLStreamListener::nsXBLStreamListener(nsIStreamListener* aInner, nsIDocument* aDocument,
|
||||
nsIDocument* aBindingDocument)
|
||||
{
|
||||
NS_INIT_ISUPPORTS();
|
||||
/* member initializers and constructor code */
|
||||
mInner = aInner;
|
||||
mDocument = aDocument;
|
||||
mBindingDocument = aBindingDocument;
|
||||
}
|
||||
|
||||
nsXBLStreamListener::~nsXBLStreamListener()
|
||||
@ -117,16 +196,9 @@ nsXBLStreamListener::OnDataAvailable(nsIChannel* aChannel, nsISupports* aCtxt, n
|
||||
NS_IMETHODIMP
|
||||
nsXBLStreamListener::OnStartRequest(nsIChannel* aChannel, nsISupports* aCtxt)
|
||||
{
|
||||
nsresult rv;
|
||||
if (mInner) {
|
||||
rv = mInner->OnStartRequest(aChannel, aCtxt);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
//
|
||||
|
||||
}
|
||||
|
||||
if (mInner)
|
||||
return mInner->OnStartRequest(aChannel, aCtxt);
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
@ -134,8 +206,39 @@ nsXBLStreamListener::OnStartRequest(nsIChannel* aChannel, nsISupports* aCtxt)
|
||||
NS_IMETHODIMP
|
||||
nsXBLStreamListener::OnStopRequest(nsIChannel* aChannel, nsISupports* aCtxt, nsresult aStatus, const PRUnichar* aStatusArg)
|
||||
{
|
||||
if (mInner)
|
||||
return mInner->OnStopRequest(aChannel, aCtxt, aStatus, aStatusArg);
|
||||
if (mInner) {
|
||||
nsresult rv = mInner->OnStopRequest(aChannel, aCtxt, aStatus, aStatusArg);
|
||||
if (NS_FAILED(rv))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// Remove ourselves from the set of pending docs.
|
||||
nsCOMPtr<nsIBindingManager> bindingManager;
|
||||
mDocument->GetBindingManager(getter_AddRefs(bindingManager));
|
||||
nsCOMPtr<nsIURI> uri(mBindingDocument->GetDocumentURL());
|
||||
nsXPIDLCString str;
|
||||
uri->GetSpec(getter_Copies(str));
|
||||
bindingManager->RemoveLoadingDocListener((const char*)str);
|
||||
|
||||
PRUint32 count = mBindingRequests.Count();
|
||||
|
||||
if (NS_SUCCEEDED(aStatus)) {
|
||||
// Put our doc in the doc table.
|
||||
bindingManager->PutXBLDocument(mBindingDocument);
|
||||
|
||||
// Notify all pending requests that their bindings are
|
||||
// ready and can be installed.
|
||||
for (PRUint32 i = 0; i < count; i++) {
|
||||
nsXBLBindingRequest* req = (nsXBLBindingRequest*)mBindingRequests.ElementAt(i);
|
||||
req->DocumentLoaded(mBindingDocument);
|
||||
}
|
||||
}
|
||||
|
||||
for (PRUint32 i = 0; i < count; i++) {
|
||||
nsXBLBindingRequest* req = (nsXBLBindingRequest*)mBindingRequests.ElementAt(i);
|
||||
delete req;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
@ -560,7 +663,7 @@ NS_IMETHODIMP nsXBLService::GetBinding(nsIContent* aBoundElement, const nsCStrin
|
||||
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
|
||||
GetBindingDocument(aBoundElement, uri, getter_AddRefs(doc));
|
||||
GetBindingDocument(aBoundElement, uri, ref, getter_AddRefs(doc));
|
||||
if (!doc)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
@ -637,7 +740,8 @@ static PRBool IsChromeOrResourceURI(nsIURI* aURI)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLService::GetBindingDocument(nsIContent* aBoundElement, const nsCString& aURLStr, nsIDocument** aResult)
|
||||
nsXBLService::GetBindingDocument(nsIContent* aBoundElement, const nsCString& aURLStr, const nsCString& aRef,
|
||||
nsIDocument** aResult)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
@ -660,53 +764,69 @@ nsXBLService::GetBindingDocument(nsIContent* aBoundElement, const nsCString& aUR
|
||||
nsCOMPtr<nsIBindingManager> bindingManager;
|
||||
boundDocument->GetBindingManager(getter_AddRefs(bindingManager));
|
||||
bindingManager->GetXBLDocument(aURLStr, getter_AddRefs(document));
|
||||
}
|
||||
|
||||
if (!document) {
|
||||
// XXX The third line of defense is to investigate whether or not the
|
||||
// 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
|
||||
// processed whenever the doc does finish loading.
|
||||
|
||||
// Finally, if all lines of defense fail, we go and fetch the binding
|
||||
// document.
|
||||
nsCOMPtr<nsIURL> uri;
|
||||
nsComponentManager::CreateInstance("component://netscape/network/standard-url",
|
||||
nsnull,
|
||||
NS_GET_IID(nsIURL),
|
||||
getter_AddRefs(uri));
|
||||
uri->SetSpec(aURLStr);
|
||||
|
||||
FetchBindingDocument(uri, getter_AddRefs(document));
|
||||
if (document) {
|
||||
// If the doc is a chrome URI, then we put it into the XUL cache.
|
||||
PRBool cached = PR_FALSE;
|
||||
if (IsChromeOrResourceURI(uri) && gXULUtils->UseXULCache()) {
|
||||
cached = PR_TRUE;
|
||||
gXULCache->PutXBLDocument(document);
|
||||
|
||||
// Cache whether or not this chrome XBL can execute scripts.
|
||||
nsCOMPtr<nsIChromeRegistry> reg(do_GetService(kChromeRegistryCID, &rv));
|
||||
if (NS_SUCCEEDED(rv) && reg) {
|
||||
PRBool allow;
|
||||
reg->AllowScriptsForSkin(uri, &allow);
|
||||
if (!allow)
|
||||
gXULCache->PutXBLDocScriptAccess(document);
|
||||
}
|
||||
}
|
||||
|
||||
if (!cached) {
|
||||
// Otherwise we put it in our binding manager's document table.
|
||||
nsCOMPtr<nsIDocument> boundDocument;
|
||||
aBoundElement->GetDocument(*getter_AddRefs(boundDocument));
|
||||
nsCOMPtr<nsIBindingManager> bindingManager;
|
||||
boundDocument->GetBindingManager(getter_AddRefs(bindingManager));
|
||||
bindingManager->PutXBLDocument(document);
|
||||
|
||||
if (!document) {
|
||||
// The third line of defense is to investigate whether or not the
|
||||
// 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
|
||||
// processed whenever the doc does finish loading.
|
||||
nsCOMPtr<nsIXBLStreamListener> listener;
|
||||
bindingManager->GetLoadingDocListener(aURLStr, getter_AddRefs(listener));
|
||||
if (listener) {
|
||||
// Create a new load observer.
|
||||
nsCAutoString bindingURI(aURLStr);
|
||||
bindingURI += "#";
|
||||
bindingURI += aRef;
|
||||
nsXBLBindingRequest* req = new nsXBLBindingRequest(aRef, aBoundElement);
|
||||
nsIXBLStreamListener* ilist = listener.get();
|
||||
nsXBLStreamListener* xblListener = NS_STATIC_CAST(nsXBLStreamListener*, ilist);
|
||||
xblListener->AddRequest(req);
|
||||
}
|
||||
}
|
||||
|
||||
if (!document) {
|
||||
// Finally, if all lines of defense fail, we go and fetch the binding
|
||||
// document.
|
||||
nsCOMPtr<nsIURL> uri;
|
||||
nsComponentManager::CreateInstance("component://netscape/network/standard-url",
|
||||
nsnull,
|
||||
NS_GET_IID(nsIURL),
|
||||
getter_AddRefs(uri));
|
||||
uri->SetSpec(aURLStr);
|
||||
FetchBindingDocument(aBoundElement, uri, aRef, getter_AddRefs(document));
|
||||
|
||||
if (document) {
|
||||
// If the doc is a chrome URI, then we put it into the XUL cache.
|
||||
PRBool cached = PR_FALSE;
|
||||
if (IsChromeOrResourceURI(uri) && gXULUtils->UseXULCache()) {
|
||||
cached = PR_TRUE;
|
||||
gXULCache->PutXBLDocument(document);
|
||||
|
||||
// Cache whether or not this chrome XBL can execute scripts.
|
||||
nsCOMPtr<nsIChromeRegistry> reg(do_GetService(kChromeRegistryCID, &rv));
|
||||
if (NS_SUCCEEDED(rv) && reg) {
|
||||
PRBool allow;
|
||||
reg->AllowScriptsForSkin(uri, &allow);
|
||||
if (!allow)
|
||||
gXULCache->PutXBLDocScriptAccess(document);
|
||||
}
|
||||
}
|
||||
|
||||
if (!cached) {
|
||||
// Otherwise we put it in our binding manager's document table.
|
||||
nsCOMPtr<nsIDocument> boundDocument;
|
||||
aBoundElement->GetDocument(*getter_AddRefs(boundDocument));
|
||||
nsCOMPtr<nsIBindingManager> bindingManager;
|
||||
boundDocument->GetBindingManager(getter_AddRefs(bindingManager));
|
||||
bindingManager->PutXBLDocument(document);
|
||||
}
|
||||
}
|
||||
}
|
||||
else return NS_OK;
|
||||
}
|
||||
|
||||
if (!document)
|
||||
return NS_OK;
|
||||
|
||||
*aResult = document;
|
||||
NS_IF_ADDREF(*aResult);
|
||||
|
||||
@ -714,7 +834,7 @@ nsXBLService::GetBindingDocument(nsIContent* aBoundElement, const nsCString& aUR
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLService::FetchBindingDocument(nsIURI* aURI, nsIDocument** aResult)
|
||||
nsXBLService::FetchBindingDocument(nsIContent* aBoundElement, nsIURI* aURI, const nsCString& aRef, nsIDocument** aResult)
|
||||
{
|
||||
// Initialize our out pointer to nsnull
|
||||
*aResult = nsnull;
|
||||
@ -749,8 +869,28 @@ nsXBLService::FetchBindingDocument(nsIURI* aURI, nsIDocument** aResult)
|
||||
nsCOMPtr<nsIHTTPChannel> http(do_QueryInterface(channel));
|
||||
if (http) {
|
||||
// Need to be asynchronous
|
||||
nsXBLStreamListener* xblListener = new nsXBLStreamListener(listener);
|
||||
nsCOMPtr<nsIDocument> boundDoc;
|
||||
aBoundElement->GetDocument(*getter_AddRefs(boundDoc));
|
||||
nsXBLStreamListener* xblListener = new nsXBLStreamListener(listener, boundDoc, doc);
|
||||
NS_ADDREF(xblListener);
|
||||
|
||||
// Add ourselves to the list of loading docs.
|
||||
nsCOMPtr<nsIDocument> boundDocument;
|
||||
aBoundElement->GetDocument(*getter_AddRefs(boundDocument));
|
||||
nsCOMPtr<nsIBindingManager> bindingManager;
|
||||
boundDocument->GetBindingManager(getter_AddRefs(bindingManager));
|
||||
nsXPIDLCString uri;
|
||||
aURI->GetSpec(getter_Copies(uri));
|
||||
bindingManager->PutLoadingDocListener((const char*)uri, xblListener);
|
||||
|
||||
// Add our request.
|
||||
nsCAutoString bindingURI(uri);
|
||||
bindingURI += "#";
|
||||
bindingURI += aRef;
|
||||
nsXBLBindingRequest* req = new nsXBLBindingRequest(bindingURI, aBoundElement);
|
||||
xblListener->AddRequest(req);
|
||||
|
||||
// Now kick off the async read.
|
||||
http->AsyncRead(xblListener, nsnull);
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -50,6 +50,9 @@ class nsXBLService : public nsIXBLService, public nsIMemoryPressureObserver
|
||||
NS_IMETHOD LoadBindings(nsIContent* aContent, const nsString& aURL, PRBool aAugmentFlag,
|
||||
nsIXBLBinding** aBinding);
|
||||
|
||||
// This method loads a binding doc and then builds the specific binding required.
|
||||
NS_IMETHOD GetBinding(nsIContent* aBoundElement, const nsCString& aURLStr, nsIXBLBinding** aResult);
|
||||
|
||||
// This function clears out the bindings on a given content node.
|
||||
NS_IMETHOD FlushStyleBindings(nsIContent* aContent);
|
||||
|
||||
@ -69,14 +72,12 @@ public:
|
||||
nsXBLService();
|
||||
virtual ~nsXBLService();
|
||||
|
||||
// This method loads a binding doc and then builds the specific binding required.
|
||||
NS_IMETHOD GetBinding(nsIContent* aBoundElement, const nsCString& aURLStr, nsIXBLBinding** aResult);
|
||||
|
||||
// This method checks the hashtable and then calls FetchBindingDocument on a miss.
|
||||
NS_IMETHOD GetBindingDocument(nsIContent* aBoundElement, const nsCString& aURI, nsIDocument** aResult);
|
||||
NS_IMETHOD GetBindingDocument(nsIContent* aBoundElement, const nsCString& aURI, const nsCString& aRef,
|
||||
nsIDocument** aResult);
|
||||
|
||||
// This method synchronously loads and parses an XBL file.
|
||||
NS_IMETHOD FetchBindingDocument(nsIURI* aURI, nsIDocument** aResult);
|
||||
NS_IMETHOD FetchBindingDocument(nsIContent* aBoundElement, nsIURI* aURI, const nsCString& aRef, nsIDocument** aResult);
|
||||
|
||||
// This method walks a binding document and removes any text nodes
|
||||
// that contain only whitespace.
|
||||
|
@ -32,6 +32,7 @@ EXPORTS = \
|
||||
nsIBindingManager.h \
|
||||
nsIXBLBinding.h \
|
||||
nsIXBLService.h \
|
||||
nsIXBLStreamListener.h \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))
|
||||
|
@ -1,4 +1,6 @@
|
||||
nsIBindingManager.h
|
||||
nsIXBLBinding.h
|
||||
nsIXBLService.h
|
||||
nsIXBLStreamListener.h
|
||||
|
||||
|
||||
|
@ -25,6 +25,7 @@ EXPORTS = \
|
||||
nsIBindingManager.h \
|
||||
nsIXBLBinding.h \
|
||||
nsIXBLService.h \
|
||||
nsIXBLStreamListener.h \
|
||||
$(NULL)
|
||||
|
||||
MODULE=raptor
|
||||
|
@ -37,6 +37,7 @@
|
||||
class nsIContent;
|
||||
class nsIXBLBinding;
|
||||
class nsIAtom;
|
||||
class nsIXBLStreamListener;
|
||||
|
||||
// {55D70FE0-C8E5-11d3-97FB-00400553EEF0}
|
||||
#define NS_IBINDING_MANAGER_IID \
|
||||
@ -66,6 +67,9 @@ public:
|
||||
NS_IMETHOD PutXBLDocument(nsIDocument* aDocument) = 0;
|
||||
NS_IMETHOD GetXBLDocument(const nsCString& aURL, nsIDocument** aResult) = 0;
|
||||
|
||||
NS_IMETHOD PutLoadingDocListener(const nsCString& aURL, nsIXBLStreamListener* aListener) = 0;
|
||||
NS_IMETHOD GetLoadingDocListener(const nsCString& aURL, nsIXBLStreamListener** aResult) = 0;
|
||||
NS_IMETHOD RemoveLoadingDocListener(const nsCString& aURL)=0;
|
||||
};
|
||||
|
||||
#endif // nsIBinding_Manager_h__
|
||||
|
@ -55,6 +55,9 @@ public:
|
||||
// This function clears out the bindings on a given content node.
|
||||
NS_IMETHOD FlushStyleBindings(nsIContent* aContent) = 0;
|
||||
|
||||
// This method loads a binding doc and then builds the specific binding required.
|
||||
NS_IMETHOD GetBinding(nsIContent* aBoundElement, const nsCString& aURLStr, nsIXBLBinding** aResult) = 0;
|
||||
|
||||
// For a given element, returns a flat list of all the anonymous children that need
|
||||
// frames built.
|
||||
NS_IMETHOD GetContentList(nsIContent* aContent, nsISupportsArray** aResult, nsIContent** aChildElement,
|
||||
|
@ -46,6 +46,7 @@
|
||||
#include "nsITextContent.h"
|
||||
|
||||
#include "nsIXBLBinding.h"
|
||||
#include "nsIXBLStreamListener.h"
|
||||
|
||||
// Static IIDs/CIDs. Try to minimize these.
|
||||
static NS_DEFINE_CID(kNameSpaceManagerCID, NS_NAMESPACEMANAGER_CID);
|
||||
@ -79,10 +80,16 @@ public:
|
||||
NS_IMETHOD PutXBLDocument(nsIDocument* aDocument);
|
||||
NS_IMETHOD GetXBLDocument(const nsCString& aURL, nsIDocument** aResult);
|
||||
|
||||
NS_IMETHOD PutLoadingDocListener(const nsCString& aURL, nsIXBLStreamListener* aListener);
|
||||
NS_IMETHOD GetLoadingDocListener(const nsCString& aURL, nsIXBLStreamListener** aResult);
|
||||
NS_IMETHOD RemoveLoadingDocListener(const nsCString& aURL);
|
||||
|
||||
// MEMBER VARIABLES
|
||||
protected:
|
||||
nsSupportsHashtable* mBindingTable;
|
||||
nsSupportsHashtable* mDocumentTable;
|
||||
nsSupportsHashtable* mLoadingDocTable;
|
||||
|
||||
nsCOMPtr<nsISupportsArray> mAttachedQueue;
|
||||
};
|
||||
|
||||
@ -99,7 +106,10 @@ nsBindingManager::nsBindingManager(void)
|
||||
NS_INIT_REFCNT();
|
||||
|
||||
mBindingTable = nsnull;
|
||||
|
||||
mDocumentTable = nsnull;
|
||||
mLoadingDocTable = nsnull;
|
||||
|
||||
mAttachedQueue = nsnull;
|
||||
}
|
||||
|
||||
@ -107,6 +117,7 @@ nsBindingManager::~nsBindingManager(void)
|
||||
{
|
||||
delete mBindingTable;
|
||||
delete mDocumentTable;
|
||||
delete mLoadingDocTable;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -310,6 +321,41 @@ nsBindingManager::GetXBLDocument(const nsCString& aURL, nsIDocument** aResult)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBindingManager::PutLoadingDocListener(const nsCString& aURL, nsIXBLStreamListener* aListener)
|
||||
{
|
||||
if (!mLoadingDocTable)
|
||||
mLoadingDocTable = new nsSupportsHashtable();
|
||||
|
||||
nsStringKey key(aURL);
|
||||
mLoadingDocTable->Put(&key, aListener);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBindingManager::GetLoadingDocListener(const nsCString& aURL, nsIXBLStreamListener** aResult)
|
||||
{
|
||||
*aResult = nsnull;
|
||||
if (!mLoadingDocTable)
|
||||
return NS_OK;
|
||||
|
||||
nsStringKey key(aURL);
|
||||
*aResult = NS_STATIC_CAST(nsIXBLStreamListener*, mLoadingDocTable->Get(&key)); // Addref happens here.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBindingManager::RemoveLoadingDocListener(const nsCString& aURL)
|
||||
{
|
||||
if (!mLoadingDocTable)
|
||||
return NS_OK;
|
||||
|
||||
nsStringKey key(aURL);
|
||||
mLoadingDocTable->Remove(&key);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Creation Routine ///////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
@ -52,6 +52,7 @@
|
||||
|
||||
#include "nsIXULContentUtils.h"
|
||||
#include "nsIXULPrototypeCache.h"
|
||||
#include "nsIXBLStreamListener.h"
|
||||
|
||||
// Static IIDs/CIDs. Try to minimize these.
|
||||
static NS_DEFINE_CID(kNameSpaceManagerCID, NS_NAMESPACEMANAGER_CID);
|
||||
@ -62,40 +63,118 @@ static NS_DEFINE_CID(kChromeRegistryCID, NS_CHROMEREGISTRY_CID);
|
||||
// Individual binding requests.
|
||||
struct nsXBLBindingRequest
|
||||
{
|
||||
nsCOMPtr<nsIURL> mURL;
|
||||
nsCString mBindingURL;
|
||||
nsCOMPtr<nsIContent> mBoundElement;
|
||||
|
||||
nsXBLBindingRequest(const nsCString& aURL, nsIContent* aBoundElement)
|
||||
{
|
||||
mBindingURL = aURL;
|
||||
mBoundElement = aBoundElement;
|
||||
|
||||
gRefCnt++;
|
||||
if (gRefCnt == 1) {
|
||||
nsServiceManager::GetService("component://netscape/xbl",
|
||||
NS_GET_IID(nsIXBLService),
|
||||
(nsISupports**) &gXBLService);
|
||||
}
|
||||
}
|
||||
|
||||
~nsXBLBindingRequest()
|
||||
{
|
||||
gRefCnt--;
|
||||
if (gRefCnt == 0) {
|
||||
nsServiceManager::ReleaseService("component://netscape/xbl", gXBLService);
|
||||
gXBLService = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
mBoundElement->GetDocument(*getter_AddRefs(doc));
|
||||
if (!doc)
|
||||
return;
|
||||
nsCOMPtr<nsIBindingManager> bindingManager;
|
||||
doc->GetBindingManager(getter_AddRefs(bindingManager));
|
||||
bindingManager->SetBinding(mBoundElement, newBinding);
|
||||
|
||||
// Set the binding's bound element.
|
||||
newBinding->SetBoundElement(mBoundElement);
|
||||
|
||||
// Tell the binding to build the anonymous content.
|
||||
newBinding->GenerateAnonymousContent(mBoundElement);
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
// Now do a ContentInserted notification to cause the frames to get installed finally,
|
||||
nsCOMPtr<nsIContent> parent;
|
||||
mBoundElement->GetParent(*getter_AddRefs(parent));
|
||||
PRInt32 index = 0;
|
||||
if (parent)
|
||||
parent->IndexOf(mBoundElement, index);
|
||||
if (index == -1)
|
||||
return;
|
||||
doc->ContentInserted(parent, mBoundElement, index);
|
||||
}
|
||||
|
||||
static nsIXBLService* gXBLService;
|
||||
static int gRefCnt;
|
||||
};
|
||||
|
||||
nsIXBLService* nsXBLBindingRequest::gXBLService = nsnull;
|
||||
int nsXBLBindingRequest::gRefCnt = 0;
|
||||
|
||||
// nsXBLStreamListener, a helper class used for
|
||||
// asynchronous parsing of URLs
|
||||
/* Header file */
|
||||
class nsXBLStreamListener : public nsIStreamListener
|
||||
class nsXBLStreamListener : public nsIStreamListener, public nsIXBLStreamListener
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSISTREAMLISTENER
|
||||
NS_DECL_NSISTREAMOBSERVER
|
||||
|
||||
nsXBLStreamListener(nsIStreamListener* aInner);
|
||||
nsXBLStreamListener(nsIStreamListener* aInner, nsIDocument* aDocument, nsIDocument* aBindingDocument);
|
||||
virtual ~nsXBLStreamListener();
|
||||
/* additional members */
|
||||
|
||||
void AddRequest(nsXBLBindingRequest* aRequest) { mBindingRequests.AppendElement(aRequest); };
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIStreamListener> mInner;
|
||||
|
||||
nsVoidArray mBindingRequests;
|
||||
|
||||
nsCOMPtr<nsIDocument> mDocument;
|
||||
|
||||
static nsIXBLService* gXBLService;
|
||||
nsCOMPtr<nsIDocument> mBindingDocument;
|
||||
};
|
||||
|
||||
nsIXBLService* nsXBLStreamListener::gXBLService = nsnull;
|
||||
|
||||
/* Implementation file */
|
||||
NS_IMPL_ISUPPORTS2(nsXBLStreamListener, nsIStreamListener, nsIStreamObserver)
|
||||
NS_IMPL_ISUPPORTS3(nsXBLStreamListener, nsIStreamListener, nsIStreamObserver, nsIXBLStreamListener)
|
||||
|
||||
nsXBLStreamListener::nsXBLStreamListener(nsIStreamListener* aInner)
|
||||
nsXBLStreamListener::nsXBLStreamListener(nsIStreamListener* aInner, nsIDocument* aDocument,
|
||||
nsIDocument* aBindingDocument)
|
||||
{
|
||||
NS_INIT_ISUPPORTS();
|
||||
/* member initializers and constructor code */
|
||||
mInner = aInner;
|
||||
mDocument = aDocument;
|
||||
mBindingDocument = aBindingDocument;
|
||||
}
|
||||
|
||||
nsXBLStreamListener::~nsXBLStreamListener()
|
||||
@ -117,16 +196,9 @@ nsXBLStreamListener::OnDataAvailable(nsIChannel* aChannel, nsISupports* aCtxt, n
|
||||
NS_IMETHODIMP
|
||||
nsXBLStreamListener::OnStartRequest(nsIChannel* aChannel, nsISupports* aCtxt)
|
||||
{
|
||||
nsresult rv;
|
||||
if (mInner) {
|
||||
rv = mInner->OnStartRequest(aChannel, aCtxt);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
//
|
||||
|
||||
}
|
||||
|
||||
if (mInner)
|
||||
return mInner->OnStartRequest(aChannel, aCtxt);
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
@ -134,8 +206,39 @@ nsXBLStreamListener::OnStartRequest(nsIChannel* aChannel, nsISupports* aCtxt)
|
||||
NS_IMETHODIMP
|
||||
nsXBLStreamListener::OnStopRequest(nsIChannel* aChannel, nsISupports* aCtxt, nsresult aStatus, const PRUnichar* aStatusArg)
|
||||
{
|
||||
if (mInner)
|
||||
return mInner->OnStopRequest(aChannel, aCtxt, aStatus, aStatusArg);
|
||||
if (mInner) {
|
||||
nsresult rv = mInner->OnStopRequest(aChannel, aCtxt, aStatus, aStatusArg);
|
||||
if (NS_FAILED(rv))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// Remove ourselves from the set of pending docs.
|
||||
nsCOMPtr<nsIBindingManager> bindingManager;
|
||||
mDocument->GetBindingManager(getter_AddRefs(bindingManager));
|
||||
nsCOMPtr<nsIURI> uri(mBindingDocument->GetDocumentURL());
|
||||
nsXPIDLCString str;
|
||||
uri->GetSpec(getter_Copies(str));
|
||||
bindingManager->RemoveLoadingDocListener((const char*)str);
|
||||
|
||||
PRUint32 count = mBindingRequests.Count();
|
||||
|
||||
if (NS_SUCCEEDED(aStatus)) {
|
||||
// Put our doc in the doc table.
|
||||
bindingManager->PutXBLDocument(mBindingDocument);
|
||||
|
||||
// Notify all pending requests that their bindings are
|
||||
// ready and can be installed.
|
||||
for (PRUint32 i = 0; i < count; i++) {
|
||||
nsXBLBindingRequest* req = (nsXBLBindingRequest*)mBindingRequests.ElementAt(i);
|
||||
req->DocumentLoaded(mBindingDocument);
|
||||
}
|
||||
}
|
||||
|
||||
for (PRUint32 i = 0; i < count; i++) {
|
||||
nsXBLBindingRequest* req = (nsXBLBindingRequest*)mBindingRequests.ElementAt(i);
|
||||
delete req;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
@ -560,7 +663,7 @@ NS_IMETHODIMP nsXBLService::GetBinding(nsIContent* aBoundElement, const nsCStrin
|
||||
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
|
||||
GetBindingDocument(aBoundElement, uri, getter_AddRefs(doc));
|
||||
GetBindingDocument(aBoundElement, uri, ref, getter_AddRefs(doc));
|
||||
if (!doc)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
@ -637,7 +740,8 @@ static PRBool IsChromeOrResourceURI(nsIURI* aURI)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLService::GetBindingDocument(nsIContent* aBoundElement, const nsCString& aURLStr, nsIDocument** aResult)
|
||||
nsXBLService::GetBindingDocument(nsIContent* aBoundElement, const nsCString& aURLStr, const nsCString& aRef,
|
||||
nsIDocument** aResult)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
@ -660,53 +764,69 @@ nsXBLService::GetBindingDocument(nsIContent* aBoundElement, const nsCString& aUR
|
||||
nsCOMPtr<nsIBindingManager> bindingManager;
|
||||
boundDocument->GetBindingManager(getter_AddRefs(bindingManager));
|
||||
bindingManager->GetXBLDocument(aURLStr, getter_AddRefs(document));
|
||||
}
|
||||
|
||||
if (!document) {
|
||||
// XXX The third line of defense is to investigate whether or not the
|
||||
// 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
|
||||
// processed whenever the doc does finish loading.
|
||||
|
||||
// Finally, if all lines of defense fail, we go and fetch the binding
|
||||
// document.
|
||||
nsCOMPtr<nsIURL> uri;
|
||||
nsComponentManager::CreateInstance("component://netscape/network/standard-url",
|
||||
nsnull,
|
||||
NS_GET_IID(nsIURL),
|
||||
getter_AddRefs(uri));
|
||||
uri->SetSpec(aURLStr);
|
||||
|
||||
FetchBindingDocument(uri, getter_AddRefs(document));
|
||||
if (document) {
|
||||
// If the doc is a chrome URI, then we put it into the XUL cache.
|
||||
PRBool cached = PR_FALSE;
|
||||
if (IsChromeOrResourceURI(uri) && gXULUtils->UseXULCache()) {
|
||||
cached = PR_TRUE;
|
||||
gXULCache->PutXBLDocument(document);
|
||||
|
||||
// Cache whether or not this chrome XBL can execute scripts.
|
||||
nsCOMPtr<nsIChromeRegistry> reg(do_GetService(kChromeRegistryCID, &rv));
|
||||
if (NS_SUCCEEDED(rv) && reg) {
|
||||
PRBool allow;
|
||||
reg->AllowScriptsForSkin(uri, &allow);
|
||||
if (!allow)
|
||||
gXULCache->PutXBLDocScriptAccess(document);
|
||||
}
|
||||
}
|
||||
|
||||
if (!cached) {
|
||||
// Otherwise we put it in our binding manager's document table.
|
||||
nsCOMPtr<nsIDocument> boundDocument;
|
||||
aBoundElement->GetDocument(*getter_AddRefs(boundDocument));
|
||||
nsCOMPtr<nsIBindingManager> bindingManager;
|
||||
boundDocument->GetBindingManager(getter_AddRefs(bindingManager));
|
||||
bindingManager->PutXBLDocument(document);
|
||||
|
||||
if (!document) {
|
||||
// The third line of defense is to investigate whether or not the
|
||||
// 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
|
||||
// processed whenever the doc does finish loading.
|
||||
nsCOMPtr<nsIXBLStreamListener> listener;
|
||||
bindingManager->GetLoadingDocListener(aURLStr, getter_AddRefs(listener));
|
||||
if (listener) {
|
||||
// Create a new load observer.
|
||||
nsCAutoString bindingURI(aURLStr);
|
||||
bindingURI += "#";
|
||||
bindingURI += aRef;
|
||||
nsXBLBindingRequest* req = new nsXBLBindingRequest(aRef, aBoundElement);
|
||||
nsIXBLStreamListener* ilist = listener.get();
|
||||
nsXBLStreamListener* xblListener = NS_STATIC_CAST(nsXBLStreamListener*, ilist);
|
||||
xblListener->AddRequest(req);
|
||||
}
|
||||
}
|
||||
|
||||
if (!document) {
|
||||
// Finally, if all lines of defense fail, we go and fetch the binding
|
||||
// document.
|
||||
nsCOMPtr<nsIURL> uri;
|
||||
nsComponentManager::CreateInstance("component://netscape/network/standard-url",
|
||||
nsnull,
|
||||
NS_GET_IID(nsIURL),
|
||||
getter_AddRefs(uri));
|
||||
uri->SetSpec(aURLStr);
|
||||
FetchBindingDocument(aBoundElement, uri, aRef, getter_AddRefs(document));
|
||||
|
||||
if (document) {
|
||||
// If the doc is a chrome URI, then we put it into the XUL cache.
|
||||
PRBool cached = PR_FALSE;
|
||||
if (IsChromeOrResourceURI(uri) && gXULUtils->UseXULCache()) {
|
||||
cached = PR_TRUE;
|
||||
gXULCache->PutXBLDocument(document);
|
||||
|
||||
// Cache whether or not this chrome XBL can execute scripts.
|
||||
nsCOMPtr<nsIChromeRegistry> reg(do_GetService(kChromeRegistryCID, &rv));
|
||||
if (NS_SUCCEEDED(rv) && reg) {
|
||||
PRBool allow;
|
||||
reg->AllowScriptsForSkin(uri, &allow);
|
||||
if (!allow)
|
||||
gXULCache->PutXBLDocScriptAccess(document);
|
||||
}
|
||||
}
|
||||
|
||||
if (!cached) {
|
||||
// Otherwise we put it in our binding manager's document table.
|
||||
nsCOMPtr<nsIDocument> boundDocument;
|
||||
aBoundElement->GetDocument(*getter_AddRefs(boundDocument));
|
||||
nsCOMPtr<nsIBindingManager> bindingManager;
|
||||
boundDocument->GetBindingManager(getter_AddRefs(bindingManager));
|
||||
bindingManager->PutXBLDocument(document);
|
||||
}
|
||||
}
|
||||
}
|
||||
else return NS_OK;
|
||||
}
|
||||
|
||||
if (!document)
|
||||
return NS_OK;
|
||||
|
||||
*aResult = document;
|
||||
NS_IF_ADDREF(*aResult);
|
||||
|
||||
@ -714,7 +834,7 @@ nsXBLService::GetBindingDocument(nsIContent* aBoundElement, const nsCString& aUR
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLService::FetchBindingDocument(nsIURI* aURI, nsIDocument** aResult)
|
||||
nsXBLService::FetchBindingDocument(nsIContent* aBoundElement, nsIURI* aURI, const nsCString& aRef, nsIDocument** aResult)
|
||||
{
|
||||
// Initialize our out pointer to nsnull
|
||||
*aResult = nsnull;
|
||||
@ -749,8 +869,28 @@ nsXBLService::FetchBindingDocument(nsIURI* aURI, nsIDocument** aResult)
|
||||
nsCOMPtr<nsIHTTPChannel> http(do_QueryInterface(channel));
|
||||
if (http) {
|
||||
// Need to be asynchronous
|
||||
nsXBLStreamListener* xblListener = new nsXBLStreamListener(listener);
|
||||
nsCOMPtr<nsIDocument> boundDoc;
|
||||
aBoundElement->GetDocument(*getter_AddRefs(boundDoc));
|
||||
nsXBLStreamListener* xblListener = new nsXBLStreamListener(listener, boundDoc, doc);
|
||||
NS_ADDREF(xblListener);
|
||||
|
||||
// Add ourselves to the list of loading docs.
|
||||
nsCOMPtr<nsIDocument> boundDocument;
|
||||
aBoundElement->GetDocument(*getter_AddRefs(boundDocument));
|
||||
nsCOMPtr<nsIBindingManager> bindingManager;
|
||||
boundDocument->GetBindingManager(getter_AddRefs(bindingManager));
|
||||
nsXPIDLCString uri;
|
||||
aURI->GetSpec(getter_Copies(uri));
|
||||
bindingManager->PutLoadingDocListener((const char*)uri, xblListener);
|
||||
|
||||
// Add our request.
|
||||
nsCAutoString bindingURI(uri);
|
||||
bindingURI += "#";
|
||||
bindingURI += aRef;
|
||||
nsXBLBindingRequest* req = new nsXBLBindingRequest(bindingURI, aBoundElement);
|
||||
xblListener->AddRequest(req);
|
||||
|
||||
// Now kick off the async read.
|
||||
http->AsyncRead(xblListener, nsnull);
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -50,6 +50,9 @@ class nsXBLService : public nsIXBLService, public nsIMemoryPressureObserver
|
||||
NS_IMETHOD LoadBindings(nsIContent* aContent, const nsString& aURL, PRBool aAugmentFlag,
|
||||
nsIXBLBinding** aBinding);
|
||||
|
||||
// This method loads a binding doc and then builds the specific binding required.
|
||||
NS_IMETHOD GetBinding(nsIContent* aBoundElement, const nsCString& aURLStr, nsIXBLBinding** aResult);
|
||||
|
||||
// This function clears out the bindings on a given content node.
|
||||
NS_IMETHOD FlushStyleBindings(nsIContent* aContent);
|
||||
|
||||
@ -69,14 +72,12 @@ public:
|
||||
nsXBLService();
|
||||
virtual ~nsXBLService();
|
||||
|
||||
// This method loads a binding doc and then builds the specific binding required.
|
||||
NS_IMETHOD GetBinding(nsIContent* aBoundElement, const nsCString& aURLStr, nsIXBLBinding** aResult);
|
||||
|
||||
// This method checks the hashtable and then calls FetchBindingDocument on a miss.
|
||||
NS_IMETHOD GetBindingDocument(nsIContent* aBoundElement, const nsCString& aURI, nsIDocument** aResult);
|
||||
NS_IMETHOD GetBindingDocument(nsIContent* aBoundElement, const nsCString& aURI, const nsCString& aRef,
|
||||
nsIDocument** aResult);
|
||||
|
||||
// This method synchronously loads and parses an XBL file.
|
||||
NS_IMETHOD FetchBindingDocument(nsIURI* aURI, nsIDocument** aResult);
|
||||
NS_IMETHOD FetchBindingDocument(nsIContent* aBoundElement, nsIURI* aURI, const nsCString& aRef, nsIDocument** aResult);
|
||||
|
||||
// This method walks a binding document and removes any text nodes
|
||||
// that contain only whitespace.
|
||||
|
Loading…
Reference in New Issue
Block a user