fix hashtable lookup for xbl binding files to remove 15% of time paging up/down in mailnews r=waterson,hyatt

stop creating nsISupportsArrays and instead chain nsIXBLAttributeEntrys r=hyatt
remove unnecessary creation of atoms r=hyatt
(around 20% speedup to mailnews tree scrolling)
This commit is contained in:
pavlov%netscape.com 2000-04-26 00:50:48 +00:00
parent c06efd2fc4
commit f3b435d030
4 changed files with 178 additions and 212 deletions

View File

@ -81,6 +81,8 @@ public:
NS_IMETHOD GetAttribute(nsIAtom** aResult) = 0;
NS_IMETHOD GetElement(nsIContent** aResult) = 0;
NS_IMETHOD GetNext(nsIXBLAttributeEntry** aResult) = 0;
NS_IMETHOD SetNext(nsIXBLAttributeEntry* aEntry) = 0;
};
@ -89,8 +91,12 @@ public:
NS_IMETHOD GetAttribute(nsIAtom** aResult) { *aResult = mAttribute; NS_IF_ADDREF(*aResult); return NS_OK; };
NS_IMETHOD GetElement(nsIContent** aResult) { *aResult = mElement; NS_IF_ADDREF(*aResult); return NS_OK; };
NS_IMETHOD GetNext(nsIXBLAttributeEntry** aResult) { NS_IF_ADDREF(*aResult = mNext); return NS_OK; }
NS_IMETHOD SetNext(nsIXBLAttributeEntry* aEntry) { mNext = aEntry; return NS_OK; }
nsCOMPtr<nsIContent> mElement;
nsCOMPtr<nsIAtom> mAttribute;
nsCOMPtr<nsIXBLAttributeEntry> mNext;
nsXBLAttributeEntry(nsIAtom* aAtom, nsIContent* aContent) {
NS_INIT_REFCNT(); mAttribute = aAtom; mElement = aContent;
@ -910,64 +916,59 @@ nsXBLBinding::AttributeChanged(nsIAtom* aAttribute, PRInt32 aNameSpaceID, PRBool
nsCOMPtr<nsISupports> supports = getter_AddRefs(NS_STATIC_CAST(nsISupports*,
mAttributeTable->Get(&key)));
nsCOMPtr<nsISupportsArray> entry = do_QueryInterface(supports);
if (!entry)
nsCOMPtr<nsIXBLAttributeEntry> xblAttr = do_QueryInterface(supports);
if (!xblAttr)
return NS_OK;
// Iterate over the elements in the array.
PRUint32 count;
entry->Count(&count);
for (PRUint32 i=0; i<count; i++) {
nsCOMPtr<nsISupports> item;
entry->GetElementAt(i, getter_AddRefs(item));
nsCOMPtr<nsIXBLAttributeEntry> xblAttr = do_QueryInterface(item);
if (xblAttr) {
nsCOMPtr<nsIContent> element;
nsCOMPtr<nsIAtom> setAttr;
xblAttr->GetElement(getter_AddRefs(element));
xblAttr->GetAttribute(getter_AddRefs(setAttr));
while (xblAttr) {
nsCOMPtr<nsIContent> element;
nsCOMPtr<nsIAtom> setAttr;
xblAttr->GetElement(getter_AddRefs(element));
xblAttr->GetAttribute(getter_AddRefs(setAttr));
if (aRemoveFlag)
element->UnsetAttribute(aNameSpaceID, setAttr, PR_TRUE);
else {
if (aRemoveFlag)
element->UnsetAttribute(aNameSpaceID, setAttr, PR_TRUE);
else {
nsAutoString value;
nsresult result = mBoundElement->GetAttribute(aNameSpaceID, aAttribute, value);
PRBool attrPresent = (result == NS_CONTENT_ATTR_NO_VALUE ||
result == NS_CONTENT_ATTR_HAS_VALUE);
if (attrPresent)
element->SetAttribute(aNameSpaceID, setAttr, value, PR_TRUE);
}
// See if we're the <html> tag in XUL, and see if value is being
// set or unset on us.
nsCOMPtr<nsIAtom> tag;
element->GetTag(*getter_AddRefs(tag));
if ((tag.get() == kHTMLAtom) && (setAttr.get() == kValueAtom)) {
// Flush out all our kids.
PRInt32 childCount;
element->ChildCount(childCount);
if (childCount > 0)
element->RemoveChildAt(0, PR_TRUE);
if (!aRemoveFlag) {
// Construct a new text node and insert it.
nsAutoString value;
nsresult result = mBoundElement->GetAttribute(aNameSpaceID, aAttribute, value);
PRBool attrPresent = (result == NS_CONTENT_ATTR_NO_VALUE ||
result == NS_CONTENT_ATTR_HAS_VALUE);
if (attrPresent)
element->SetAttribute(aNameSpaceID, setAttr, value, PR_TRUE);
}
// See if we're the <html> tag in XUL, and see if value is being
// set or unset on us.
nsCOMPtr<nsIAtom> tag;
element->GetTag(*getter_AddRefs(tag));
if ((tag.get() == kHTMLAtom) && (setAttr.get() == kValueAtom)) {
// Flush out all our kids.
PRInt32 childCount;
element->ChildCount(childCount);
if (childCount > 0)
element->RemoveChildAt(0, PR_TRUE);
if (!aRemoveFlag) {
// Construct a new text node and insert it.
nsAutoString value;
nsresult result = mBoundElement->GetAttribute(aNameSpaceID, aAttribute, value);
if (!value.IsEmpty()) {
nsCOMPtr<nsIDOMText> textNode;
nsCOMPtr<nsIDocument> doc;
mBoundElement->GetDocument(*getter_AddRefs(doc));
nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(doc));
domDoc->CreateTextNode(value, getter_AddRefs(textNode));
nsCOMPtr<nsIDOMNode> dummy;
nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(element));
domElement->AppendChild(textNode, getter_AddRefs(dummy));
}
if (!value.IsEmpty()) {
nsCOMPtr<nsIDOMText> textNode;
nsCOMPtr<nsIDocument> doc;
mBoundElement->GetDocument(*getter_AddRefs(doc));
nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(doc));
domDoc->CreateTextNode(value, getter_AddRefs(textNode));
nsCOMPtr<nsIDOMNode> dummy;
nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(element));
domElement->AppendChild(textNode, getter_AddRefs(dummy));
}
}
}
nsCOMPtr<nsIXBLAttributeEntry> tmpAttr = xblAttr;
tmpAttr->GetNext(getter_AddRefs(xblAttr));
}
return NS_OK;
@ -1173,13 +1174,16 @@ nsXBLBinding::ConstructAttributeTable(nsIContent* aElement)
aElement->GetAttribute(kNameSpaceID_None, kInheritsAtom, inherits);
if (!inherits.IsEmpty()) {
if (!mAttributeTable) {
mAttributeTable = new nsSupportsHashtable(8);
mAttributeTable = new nsSupportsHashtable(4);
}
// The user specified at least one attribute.
char* str = inherits.ToNewCString();
char* newStr;
char* token = nsCRT::strtok( str, ", ", &newStr );
// XXX We should use a strtok function that tokenizes PRUnichar's
// so that we don't have to convert from Unicode to ASCII and then back
char* token = nsCRT::strtok( str, ", ", &newStr );
while( token != NULL ) {
// Build an atom out of this attribute.
nsCOMPtr<nsIAtom> atom;
@ -1194,12 +1198,13 @@ nsXBLBinding::ConstructAttributeTable(nsIContent* aElement)
attr.Left(left, index);
attr.Right(right, attr.Length()-index-1);
atom = getter_AddRefs(NS_NewAtom(left));
attribute = getter_AddRefs(NS_NewAtom(right));
atom = getter_AddRefs(NS_NewAtom(left.GetUnicode()));
attribute = getter_AddRefs(NS_NewAtom(right.GetUnicode()));
}
else {
atom = getter_AddRefs(NS_NewAtom(token));
attribute = getter_AddRefs(NS_NewAtom(token));
nsAutoString tok; tok.AssignWithConversion(token);
atom = getter_AddRefs(NS_NewAtom(tok.GetUnicode()));
attribute = atom;
}
// Create an XBL attribute entry.
@ -1211,18 +1216,20 @@ nsXBLBinding::ConstructAttributeTable(nsIContent* aElement)
nsCOMPtr<nsISupports> supports = getter_AddRefs(NS_STATIC_CAST(nsISupports*,
mAttributeTable->Get(&key)));
nsCOMPtr<nsISupportsArray> entry = do_QueryInterface(supports);
nsCOMPtr<nsIXBLAttributeEntry> entry = do_QueryInterface(supports);
if (!entry) {
// Make a new entry.
NS_NewISupportsArray(getter_AddRefs(entry));
// Put it in the table.
mAttributeTable->Put(&key, entry);
mAttributeTable->Put(&key, xblAttr);
} else {
nsCOMPtr<nsIXBLAttributeEntry> attr = entry;
nsCOMPtr<nsIXBLAttributeEntry> tmpAttr = entry;
do {
attr = tmpAttr;
attr->GetNext(getter_AddRefs(tmpAttr));
} while (tmpAttr);
attr->SetNext(xblAttr);
}
// Append ourselves to our entry.
entry->AppendElement(xblAttr);
// Now make sure that this attribute is initially set.
// XXX How to deal with NAMESPACES!!!?
nsAutoString value;

View File

@ -133,10 +133,10 @@ public:
virtual ~nsXBLService();
// This method loads a binding doc and then builds the specific binding required.
NS_IMETHOD GetBinding(nsCAutoString& aURLStr, nsIXBLBinding** aResult);
NS_IMETHOD GetBinding(const nsCString& aURLStr, nsIXBLBinding** aResult);
// This method checks the hashtable and then calls FetchBindingDocument on a miss.
NS_IMETHOD GetBindingDocument(nsIURL* aURI, nsIDocument** aResult);
NS_IMETHOD GetBindingDocument(const nsCString& aURI, nsIDocument** aResult);
// This method synchronously loads and parses an XBL file.
NS_IMETHOD FetchBindingDocument(nsIURI* aURI, nsIDocument** aResult);
@ -145,34 +145,6 @@ public:
// that contain only whitespace.
NS_IMETHOD StripWhitespaceNodes(nsIContent* aContent);
protected:
// This URIkey class is used to hash URLs into an XBL binding
// cache.
class nsIURIKey : public nsHashKey {
protected:
nsCOMPtr<nsIURI> mKey;
public:
nsIURIKey(nsIURI* key) : mKey(key) {}
~nsIURIKey(void) {}
PRUint32 HashValue(void) const {
nsXPIDLCString spec;
mKey->GetSpec(getter_Copies(spec));
return (PRUint32) PL_HashString(spec);
}
PRBool Equals(const nsHashKey *aKey) const {
PRBool eq;
mKey->Equals( ((nsIURIKey*) aKey)->mKey, &eq );
return eq;
}
nsHashKey *Clone(void) const {
return new nsIURIKey(mKey);
}
};
// MEMBER VARIABLES
protected:
static nsSupportsHashtable* mBindingTable; // This is a table of all the bindings files
@ -378,26 +350,22 @@ nsXBLService::GetBaseTag(nsIContent* aContent, nsIAtom** aResult)
// Internal helper methods ////////////////////////////////////////////////////////////////
NS_IMETHODIMP nsXBLService::GetBinding(nsCAutoString& aURLStr, nsIXBLBinding** aResult)
NS_IMETHODIMP nsXBLService::GetBinding(const nsCString& aURLStr, nsIXBLBinding** aResult)
{
*aResult = nsnull;
if (aURLStr.IsEmpty())
return NS_ERROR_FAILURE;
nsCOMPtr<nsIURL> uri;
nsComponentManager::CreateInstance("component://netscape/network/standard-url",
nsnull,
NS_GET_IID(nsIURL),
getter_AddRefs(uri));
uri->SetSpec(aURLStr);
// XXX Obtain the # marker and remove it from the URL.
nsXPIDLCString ref;
uri->GetRef(getter_Copies(ref));
uri->SetRef("");
nsCAutoString uri(aURLStr);
PRInt32 indx = uri.RFindChar('#');
nsCAutoString ref;
uri.Right(ref, uri.Length() - (indx + 1));
uri.Truncate(indx);
nsCOMPtr<nsIDocument> doc;
GetBindingDocument(uri, getter_AddRefs(doc));
if (!doc)
return NS_ERROR_FAILURE;
@ -454,17 +422,25 @@ NS_IMETHODIMP nsXBLService::GetBinding(nsCAutoString& aURLStr, nsIXBLBinding** a
NS_IMETHODIMP
nsXBLService::GetBindingDocument(nsIURL* aURI, nsIDocument** aResult)
nsXBLService::GetBindingDocument(const nsCString& aURLStr, nsIDocument** aResult)
{
*aResult = nsnull;
// We've got a file. Check our key binding file cache.
nsIURIKey key(aURI);
nsStringKey key(aURLStr);
nsCOMPtr<nsIDocument> document;
document = dont_AddRef(NS_STATIC_CAST(nsIDocument*, mBindingTable->Get(&key)));
if (!document) {
FetchBindingDocument(aURI, getter_AddRefs(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) {
// Put the key binding doc into our table.
mBindingTable->Put(&key, document);

View File

@ -81,6 +81,8 @@ public:
NS_IMETHOD GetAttribute(nsIAtom** aResult) = 0;
NS_IMETHOD GetElement(nsIContent** aResult) = 0;
NS_IMETHOD GetNext(nsIXBLAttributeEntry** aResult) = 0;
NS_IMETHOD SetNext(nsIXBLAttributeEntry* aEntry) = 0;
};
@ -89,8 +91,12 @@ public:
NS_IMETHOD GetAttribute(nsIAtom** aResult) { *aResult = mAttribute; NS_IF_ADDREF(*aResult); return NS_OK; };
NS_IMETHOD GetElement(nsIContent** aResult) { *aResult = mElement; NS_IF_ADDREF(*aResult); return NS_OK; };
NS_IMETHOD GetNext(nsIXBLAttributeEntry** aResult) { NS_IF_ADDREF(*aResult = mNext); return NS_OK; }
NS_IMETHOD SetNext(nsIXBLAttributeEntry* aEntry) { mNext = aEntry; return NS_OK; }
nsCOMPtr<nsIContent> mElement;
nsCOMPtr<nsIAtom> mAttribute;
nsCOMPtr<nsIXBLAttributeEntry> mNext;
nsXBLAttributeEntry(nsIAtom* aAtom, nsIContent* aContent) {
NS_INIT_REFCNT(); mAttribute = aAtom; mElement = aContent;
@ -910,64 +916,59 @@ nsXBLBinding::AttributeChanged(nsIAtom* aAttribute, PRInt32 aNameSpaceID, PRBool
nsCOMPtr<nsISupports> supports = getter_AddRefs(NS_STATIC_CAST(nsISupports*,
mAttributeTable->Get(&key)));
nsCOMPtr<nsISupportsArray> entry = do_QueryInterface(supports);
if (!entry)
nsCOMPtr<nsIXBLAttributeEntry> xblAttr = do_QueryInterface(supports);
if (!xblAttr)
return NS_OK;
// Iterate over the elements in the array.
PRUint32 count;
entry->Count(&count);
for (PRUint32 i=0; i<count; i++) {
nsCOMPtr<nsISupports> item;
entry->GetElementAt(i, getter_AddRefs(item));
nsCOMPtr<nsIXBLAttributeEntry> xblAttr = do_QueryInterface(item);
if (xblAttr) {
nsCOMPtr<nsIContent> element;
nsCOMPtr<nsIAtom> setAttr;
xblAttr->GetElement(getter_AddRefs(element));
xblAttr->GetAttribute(getter_AddRefs(setAttr));
while (xblAttr) {
nsCOMPtr<nsIContent> element;
nsCOMPtr<nsIAtom> setAttr;
xblAttr->GetElement(getter_AddRefs(element));
xblAttr->GetAttribute(getter_AddRefs(setAttr));
if (aRemoveFlag)
element->UnsetAttribute(aNameSpaceID, setAttr, PR_TRUE);
else {
if (aRemoveFlag)
element->UnsetAttribute(aNameSpaceID, setAttr, PR_TRUE);
else {
nsAutoString value;
nsresult result = mBoundElement->GetAttribute(aNameSpaceID, aAttribute, value);
PRBool attrPresent = (result == NS_CONTENT_ATTR_NO_VALUE ||
result == NS_CONTENT_ATTR_HAS_VALUE);
if (attrPresent)
element->SetAttribute(aNameSpaceID, setAttr, value, PR_TRUE);
}
// See if we're the <html> tag in XUL, and see if value is being
// set or unset on us.
nsCOMPtr<nsIAtom> tag;
element->GetTag(*getter_AddRefs(tag));
if ((tag.get() == kHTMLAtom) && (setAttr.get() == kValueAtom)) {
// Flush out all our kids.
PRInt32 childCount;
element->ChildCount(childCount);
if (childCount > 0)
element->RemoveChildAt(0, PR_TRUE);
if (!aRemoveFlag) {
// Construct a new text node and insert it.
nsAutoString value;
nsresult result = mBoundElement->GetAttribute(aNameSpaceID, aAttribute, value);
PRBool attrPresent = (result == NS_CONTENT_ATTR_NO_VALUE ||
result == NS_CONTENT_ATTR_HAS_VALUE);
if (attrPresent)
element->SetAttribute(aNameSpaceID, setAttr, value, PR_TRUE);
}
// See if we're the <html> tag in XUL, and see if value is being
// set or unset on us.
nsCOMPtr<nsIAtom> tag;
element->GetTag(*getter_AddRefs(tag));
if ((tag.get() == kHTMLAtom) && (setAttr.get() == kValueAtom)) {
// Flush out all our kids.
PRInt32 childCount;
element->ChildCount(childCount);
if (childCount > 0)
element->RemoveChildAt(0, PR_TRUE);
if (!aRemoveFlag) {
// Construct a new text node and insert it.
nsAutoString value;
nsresult result = mBoundElement->GetAttribute(aNameSpaceID, aAttribute, value);
if (!value.IsEmpty()) {
nsCOMPtr<nsIDOMText> textNode;
nsCOMPtr<nsIDocument> doc;
mBoundElement->GetDocument(*getter_AddRefs(doc));
nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(doc));
domDoc->CreateTextNode(value, getter_AddRefs(textNode));
nsCOMPtr<nsIDOMNode> dummy;
nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(element));
domElement->AppendChild(textNode, getter_AddRefs(dummy));
}
if (!value.IsEmpty()) {
nsCOMPtr<nsIDOMText> textNode;
nsCOMPtr<nsIDocument> doc;
mBoundElement->GetDocument(*getter_AddRefs(doc));
nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(doc));
domDoc->CreateTextNode(value, getter_AddRefs(textNode));
nsCOMPtr<nsIDOMNode> dummy;
nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(element));
domElement->AppendChild(textNode, getter_AddRefs(dummy));
}
}
}
nsCOMPtr<nsIXBLAttributeEntry> tmpAttr = xblAttr;
tmpAttr->GetNext(getter_AddRefs(xblAttr));
}
return NS_OK;
@ -1173,13 +1174,16 @@ nsXBLBinding::ConstructAttributeTable(nsIContent* aElement)
aElement->GetAttribute(kNameSpaceID_None, kInheritsAtom, inherits);
if (!inherits.IsEmpty()) {
if (!mAttributeTable) {
mAttributeTable = new nsSupportsHashtable(8);
mAttributeTable = new nsSupportsHashtable(4);
}
// The user specified at least one attribute.
char* str = inherits.ToNewCString();
char* newStr;
char* token = nsCRT::strtok( str, ", ", &newStr );
// XXX We should use a strtok function that tokenizes PRUnichar's
// so that we don't have to convert from Unicode to ASCII and then back
char* token = nsCRT::strtok( str, ", ", &newStr );
while( token != NULL ) {
// Build an atom out of this attribute.
nsCOMPtr<nsIAtom> atom;
@ -1194,12 +1198,13 @@ nsXBLBinding::ConstructAttributeTable(nsIContent* aElement)
attr.Left(left, index);
attr.Right(right, attr.Length()-index-1);
atom = getter_AddRefs(NS_NewAtom(left));
attribute = getter_AddRefs(NS_NewAtom(right));
atom = getter_AddRefs(NS_NewAtom(left.GetUnicode()));
attribute = getter_AddRefs(NS_NewAtom(right.GetUnicode()));
}
else {
atom = getter_AddRefs(NS_NewAtom(token));
attribute = getter_AddRefs(NS_NewAtom(token));
nsAutoString tok; tok.AssignWithConversion(token);
atom = getter_AddRefs(NS_NewAtom(tok.GetUnicode()));
attribute = atom;
}
// Create an XBL attribute entry.
@ -1211,18 +1216,20 @@ nsXBLBinding::ConstructAttributeTable(nsIContent* aElement)
nsCOMPtr<nsISupports> supports = getter_AddRefs(NS_STATIC_CAST(nsISupports*,
mAttributeTable->Get(&key)));
nsCOMPtr<nsISupportsArray> entry = do_QueryInterface(supports);
nsCOMPtr<nsIXBLAttributeEntry> entry = do_QueryInterface(supports);
if (!entry) {
// Make a new entry.
NS_NewISupportsArray(getter_AddRefs(entry));
// Put it in the table.
mAttributeTable->Put(&key, entry);
mAttributeTable->Put(&key, xblAttr);
} else {
nsCOMPtr<nsIXBLAttributeEntry> attr = entry;
nsCOMPtr<nsIXBLAttributeEntry> tmpAttr = entry;
do {
attr = tmpAttr;
attr->GetNext(getter_AddRefs(tmpAttr));
} while (tmpAttr);
attr->SetNext(xblAttr);
}
// Append ourselves to our entry.
entry->AppendElement(xblAttr);
// Now make sure that this attribute is initially set.
// XXX How to deal with NAMESPACES!!!?
nsAutoString value;

View File

@ -133,10 +133,10 @@ public:
virtual ~nsXBLService();
// This method loads a binding doc and then builds the specific binding required.
NS_IMETHOD GetBinding(nsCAutoString& aURLStr, nsIXBLBinding** aResult);
NS_IMETHOD GetBinding(const nsCString& aURLStr, nsIXBLBinding** aResult);
// This method checks the hashtable and then calls FetchBindingDocument on a miss.
NS_IMETHOD GetBindingDocument(nsIURL* aURI, nsIDocument** aResult);
NS_IMETHOD GetBindingDocument(const nsCString& aURI, nsIDocument** aResult);
// This method synchronously loads and parses an XBL file.
NS_IMETHOD FetchBindingDocument(nsIURI* aURI, nsIDocument** aResult);
@ -145,34 +145,6 @@ public:
// that contain only whitespace.
NS_IMETHOD StripWhitespaceNodes(nsIContent* aContent);
protected:
// This URIkey class is used to hash URLs into an XBL binding
// cache.
class nsIURIKey : public nsHashKey {
protected:
nsCOMPtr<nsIURI> mKey;
public:
nsIURIKey(nsIURI* key) : mKey(key) {}
~nsIURIKey(void) {}
PRUint32 HashValue(void) const {
nsXPIDLCString spec;
mKey->GetSpec(getter_Copies(spec));
return (PRUint32) PL_HashString(spec);
}
PRBool Equals(const nsHashKey *aKey) const {
PRBool eq;
mKey->Equals( ((nsIURIKey*) aKey)->mKey, &eq );
return eq;
}
nsHashKey *Clone(void) const {
return new nsIURIKey(mKey);
}
};
// MEMBER VARIABLES
protected:
static nsSupportsHashtable* mBindingTable; // This is a table of all the bindings files
@ -378,26 +350,22 @@ nsXBLService::GetBaseTag(nsIContent* aContent, nsIAtom** aResult)
// Internal helper methods ////////////////////////////////////////////////////////////////
NS_IMETHODIMP nsXBLService::GetBinding(nsCAutoString& aURLStr, nsIXBLBinding** aResult)
NS_IMETHODIMP nsXBLService::GetBinding(const nsCString& aURLStr, nsIXBLBinding** aResult)
{
*aResult = nsnull;
if (aURLStr.IsEmpty())
return NS_ERROR_FAILURE;
nsCOMPtr<nsIURL> uri;
nsComponentManager::CreateInstance("component://netscape/network/standard-url",
nsnull,
NS_GET_IID(nsIURL),
getter_AddRefs(uri));
uri->SetSpec(aURLStr);
// XXX Obtain the # marker and remove it from the URL.
nsXPIDLCString ref;
uri->GetRef(getter_Copies(ref));
uri->SetRef("");
nsCAutoString uri(aURLStr);
PRInt32 indx = uri.RFindChar('#');
nsCAutoString ref;
uri.Right(ref, uri.Length() - (indx + 1));
uri.Truncate(indx);
nsCOMPtr<nsIDocument> doc;
GetBindingDocument(uri, getter_AddRefs(doc));
if (!doc)
return NS_ERROR_FAILURE;
@ -454,17 +422,25 @@ NS_IMETHODIMP nsXBLService::GetBinding(nsCAutoString& aURLStr, nsIXBLBinding** a
NS_IMETHODIMP
nsXBLService::GetBindingDocument(nsIURL* aURI, nsIDocument** aResult)
nsXBLService::GetBindingDocument(const nsCString& aURLStr, nsIDocument** aResult)
{
*aResult = nsnull;
// We've got a file. Check our key binding file cache.
nsIURIKey key(aURI);
nsStringKey key(aURLStr);
nsCOMPtr<nsIDocument> document;
document = dont_AddRef(NS_STATIC_CAST(nsIDocument*, mBindingTable->Get(&key)));
if (!document) {
FetchBindingDocument(aURI, getter_AddRefs(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) {
// Put the key binding doc into our table.
mBindingTable->Put(&key, document);