mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-10 09:19:28 +00:00
Big XBL landing. Fixes numerous XBL bugs. a=ben
This commit is contained in:
parent
021da9b1d3
commit
a809cb4755
@ -41,6 +41,7 @@ class nsIXBLBindingAttachedHandler;
|
||||
class nsIXBLDocumentInfo;
|
||||
class nsIAtom;
|
||||
class nsIStreamListener;
|
||||
class nsIXPConnectWrappedJS;
|
||||
|
||||
// {55D70FE0-C8E5-11d3-97FB-00400553EEF0}
|
||||
#define NS_IBINDING_MANAGER_IID \
|
||||
@ -54,6 +55,9 @@ public:
|
||||
NS_IMETHOD GetBinding(nsIContent* aContent, nsIXBLBinding** aResult) = 0;
|
||||
NS_IMETHOD SetBinding(nsIContent* aContent, nsIXBLBinding* aBinding) = 0;
|
||||
|
||||
NS_IMETHOD GetWrappedJS(nsIContent* aContent, nsIXPConnectWrappedJS** aResult) = 0;
|
||||
NS_IMETHOD SetWrappedJS(nsIContent* aContent, nsIXPConnectWrappedJS* aResult) = 0;
|
||||
|
||||
/**
|
||||
* Notify the binding manager that an element
|
||||
* has been moved from one document to another,
|
||||
@ -100,6 +104,10 @@ public:
|
||||
|
||||
NS_IMETHOD InheritsStyle(nsIContent* aContent, PRBool* aResult) = 0;
|
||||
NS_IMETHOD FlushChromeBindings() = 0;
|
||||
|
||||
NS_IMETHOD GetBindingImplementation(nsIContent* aContent, void* aScriptObject, REFNSIID aIID, void** aResult)=0;
|
||||
|
||||
NS_IMETHOD ShouldBuildChildFrames(nsIContent* aContent, PRBool* aResult) = 0;
|
||||
};
|
||||
|
||||
#endif // nsIBinding_Manager_h__
|
||||
|
@ -98,6 +98,10 @@ public:
|
||||
|
||||
NS_IMETHOD MarkForDeath()=0;
|
||||
NS_IMETHOD MarkedForDeath(PRBool* aResult)=0;
|
||||
|
||||
NS_IMETHOD ImplementsInterface(REFNSIID aIID, PRBool* aResult)=0;
|
||||
|
||||
NS_IMETHOD ShouldBuildChildFrames(PRBool* aResult)=0;
|
||||
};
|
||||
|
||||
extern nsresult
|
||||
|
@ -84,6 +84,10 @@ public:
|
||||
|
||||
NS_IMETHOD GetBaseTag(PRInt32* aNamespaceID, nsIAtom** aTag)=0;
|
||||
NS_IMETHOD SetBaseTag(PRInt32 aNamespaceID, nsIAtom* aTag)=0;
|
||||
|
||||
NS_IMETHOD ImplementsInterface(REFNSIID aIID, PRBool* aResult)=0;
|
||||
|
||||
NS_IMETHOD ShouldBuildChildFrames(PRBool* aResult)=0;
|
||||
};
|
||||
|
||||
extern nsresult
|
||||
|
@ -62,6 +62,8 @@
|
||||
#include "nsIXBLPrototypeBinding.h"
|
||||
#include "nsIWeakReference.h"
|
||||
|
||||
#include "nsIXPConnect.h"
|
||||
|
||||
// Static IIDs/CIDs. Try to minimize these.
|
||||
static NS_DEFINE_CID(kNameSpaceManagerCID, NS_NAMESPACEMANAGER_CID);
|
||||
static NS_DEFINE_CID(kXMLDocumentCID, NS_XMLDOCUMENT_CID);
|
||||
@ -203,6 +205,9 @@ public:
|
||||
NS_IMETHOD GetBinding(nsIContent* aContent, nsIXBLBinding** aResult);
|
||||
NS_IMETHOD SetBinding(nsIContent* aContent, nsIXBLBinding* aBinding);
|
||||
|
||||
NS_IMETHOD GetWrappedJS(nsIContent* aContent, nsIXPConnectWrappedJS** aResult);
|
||||
NS_IMETHOD SetWrappedJS(nsIContent* aContent, nsIXPConnectWrappedJS* aResult);
|
||||
|
||||
NS_IMETHOD ChangeDocumentFor(nsIContent* aContent, nsIDocument* aOldDocument,
|
||||
nsIDocument* aNewDocument);
|
||||
|
||||
@ -234,12 +239,16 @@ public:
|
||||
NS_IMETHOD InheritsStyle(nsIContent* aContent, PRBool* aResult);
|
||||
NS_IMETHOD FlushChromeBindings();
|
||||
|
||||
NS_IMETHOD GetBindingImplementation(nsIContent* aContent, void* aScriptObject, REFNSIID aIID, void** aResult);
|
||||
|
||||
// nsIStyleRuleSupplier
|
||||
NS_IMETHOD UseDocumentRules(nsIContent* aContent, PRBool* aResult);
|
||||
NS_IMETHOD WalkRules(nsIStyleSet* aStyleSet,
|
||||
nsISupportsArrayEnumFunc aFunc, void* aData,
|
||||
nsIContent* aContent);
|
||||
|
||||
NS_IMETHOD ShouldBuildChildFrames(nsIContent* aContent, PRBool* aResult);
|
||||
|
||||
protected:
|
||||
void GetEnclosingScope(nsIContent* aContent, nsIContent** aParent);
|
||||
void GetOutermostStyleScope(nsIContent* aContent, nsIContent** aParent);
|
||||
@ -250,6 +259,7 @@ protected:
|
||||
// MEMBER VARIABLES
|
||||
protected:
|
||||
nsSupportsHashtable* mBindingTable;
|
||||
nsSupportsHashtable* mWrapperTable;
|
||||
nsSupportsHashtable* mDocumentTable;
|
||||
nsSupportsHashtable* mLoadingDocTable;
|
||||
|
||||
@ -269,7 +279,7 @@ nsBindingManager::nsBindingManager(void)
|
||||
NS_INIT_REFCNT();
|
||||
|
||||
mBindingTable = nsnull;
|
||||
|
||||
mWrapperTable = nsnull;
|
||||
mDocumentTable = nsnull;
|
||||
mLoadingDocTable = nsnull;
|
||||
|
||||
@ -279,6 +289,7 @@ nsBindingManager::nsBindingManager(void)
|
||||
nsBindingManager::~nsBindingManager(void)
|
||||
{
|
||||
delete mBindingTable;
|
||||
delete mWrapperTable;
|
||||
delete mDocumentTable;
|
||||
delete mLoadingDocTable;
|
||||
}
|
||||
@ -312,9 +323,43 @@ nsBindingManager::SetBinding(nsIContent* aContent, nsIXBLBinding* aBinding )
|
||||
if (aBinding) {
|
||||
mBindingTable->Put(&key, aBinding);
|
||||
}
|
||||
else
|
||||
else {
|
||||
mBindingTable->Remove(&key);
|
||||
|
||||
// The death of the bindings means the death of the JS wrapper.
|
||||
SetWrappedJS(aContent, nsnull);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBindingManager::GetWrappedJS(nsIContent* aContent, nsIXPConnectWrappedJS** aResult)
|
||||
{
|
||||
if (mWrapperTable) {
|
||||
nsISupportsKey key(aContent);
|
||||
*aResult = NS_STATIC_CAST(nsIXPConnectWrappedJS*, mWrapperTable->Get(&key));
|
||||
}
|
||||
else {
|
||||
*aResult = nsnull;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBindingManager::SetWrappedJS(nsIContent* aContent, nsIXPConnectWrappedJS* aWrappedJS)
|
||||
{
|
||||
if (!mWrapperTable)
|
||||
mWrapperTable = new nsSupportsHashtable;
|
||||
|
||||
nsISupportsKey key(aContent);
|
||||
if (aWrappedJS) {
|
||||
mWrapperTable->Put(&key, aWrappedJS);
|
||||
}
|
||||
else
|
||||
mWrapperTable->Remove(&key);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -669,6 +714,69 @@ nsBindingManager::FlushChromeBindings()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBindingManager::GetBindingImplementation(nsIContent* aContent, void* aScriptObject, REFNSIID aIID, void** aResult)
|
||||
{
|
||||
*aResult = nsnull;
|
||||
nsCOMPtr<nsIXBLBinding> binding;
|
||||
GetBinding(aContent, getter_AddRefs(binding));
|
||||
if (binding) {
|
||||
PRBool supportsInterface;
|
||||
binding->ImplementsInterface(aIID, &supportsInterface);
|
||||
if (supportsInterface) {
|
||||
nsCOMPtr<nsIXPConnectWrappedJS> wrappedJS;
|
||||
GetWrappedJS(aContent, getter_AddRefs(wrappedJS));
|
||||
|
||||
if (wrappedJS)
|
||||
return wrappedJS->AggregatedQueryInterface(aIID, aResult);
|
||||
|
||||
// We have never made a wrapper for this implementation.
|
||||
// Create an XPC wrapper for the script object and hand it back.
|
||||
JSObject* jsobj = (JSObject*)aScriptObject;
|
||||
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
aContent->GetDocument(*getter_AddRefs(doc));
|
||||
if (!doc)
|
||||
return NS_NOINTERFACE;
|
||||
|
||||
nsCOMPtr<nsIScriptGlobalObject> global;
|
||||
doc->GetScriptGlobalObject(getter_AddRefs(global));
|
||||
if (!global)
|
||||
return NS_NOINTERFACE;
|
||||
|
||||
nsCOMPtr<nsIScriptContext> context;
|
||||
global->GetContext(getter_AddRefs(context));
|
||||
if (!context)
|
||||
return NS_NOINTERFACE;
|
||||
|
||||
JSContext* jscontext = (JSContext*)context->GetNativeContext();
|
||||
if (!jscontext)
|
||||
return NS_NOINTERFACE;
|
||||
|
||||
nsCOMPtr<nsIXPConnect> xpConnect = do_GetService("@mozilla.org/js/xpc/XPConnect;1");
|
||||
if (!xpConnect)
|
||||
return NS_NOINTERFACE;
|
||||
|
||||
nsISupports* nativeThis = (nsISupports*)JS_GetPrivate(jscontext, jsobj);
|
||||
nsresult rv = xpConnect->WrapJSAggregatedToNative(nativeThis, jscontext, jsobj, aIID, aResult);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// We successfully created a wrapper. We will own this wrapper for as long as the binding remains
|
||||
// alive. At the time the binding is cleared out of the bindingManager, we will remove the wrapper
|
||||
// from the bindingManager as well.
|
||||
nsISupports* supp = NS_STATIC_CAST(nsISupports*, *aResult);
|
||||
wrappedJS = do_QueryInterface(supp);
|
||||
SetWrappedJS(aContent, wrappedJS);
|
||||
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
*aResult = nsnull;
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBindingManager::InheritsStyle(nsIContent* aContent, PRBool* aResult)
|
||||
{
|
||||
@ -781,6 +889,19 @@ nsBindingManager::WalkRules(nsIStyleSet* aStyleSet,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBindingManager::ShouldBuildChildFrames(nsIContent* aContent, PRBool* aResult)
|
||||
{
|
||||
*aResult = PR_TRUE;
|
||||
|
||||
nsCOMPtr<nsIXBLBinding> binding;
|
||||
GetBinding(aContent, getter_AddRefs(binding));
|
||||
|
||||
if (binding)
|
||||
return binding->ShouldBuildChildFrames(aResult);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Creation Routine ///////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
@ -993,9 +993,10 @@ nsXBLBinding::InstallProperties(nsIContent* aBoundElement)
|
||||
NS_IMETHODIMP
|
||||
nsXBLBinding::GetBaseTag(PRInt32* aNameSpaceID, nsIAtom** aResult)
|
||||
{
|
||||
if (mNextBinding)
|
||||
mPrototypeBinding->GetBaseTag(aNameSpaceID, aResult);
|
||||
if (!*aResult && mNextBinding)
|
||||
return mNextBinding->GetBaseTag(aNameSpaceID, aResult);
|
||||
return mPrototypeBinding->GetBaseTag(aNameSpaceID, aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -1467,6 +1468,27 @@ nsXBLBinding::MarkedForDeath(PRBool* aResult)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLBinding::ImplementsInterface(REFNSIID aIID, PRBool* aResult)
|
||||
{
|
||||
mPrototypeBinding->ImplementsInterface(aIID, aResult);
|
||||
if (!*aResult && mNextBinding)
|
||||
return mNextBinding->ImplementsInterface(aIID, aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLBinding::ShouldBuildChildFrames(PRBool* aResult)
|
||||
{
|
||||
*aResult = PR_TRUE;
|
||||
if (mContent)
|
||||
return mPrototypeBinding->ShouldBuildChildFrames(aResult);
|
||||
else if (mNextBinding)
|
||||
return mNextBinding->ShouldBuildChildFrames(aResult);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Creation Routine ///////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsresult
|
||||
|
@ -34,6 +34,7 @@ class nsISupportsArray;
|
||||
class nsSupportsHashtable;
|
||||
class nsIXBLService;
|
||||
class nsFixedSizeAllocator;
|
||||
class nsXBLEventHandler;
|
||||
|
||||
// *********************************************************************/
|
||||
// The XBLBinding class
|
||||
@ -93,6 +94,10 @@ class nsXBLBinding: public nsIXBLBinding
|
||||
NS_IMETHOD MarkForDeath();
|
||||
NS_IMETHOD MarkedForDeath(PRBool* aResult);
|
||||
|
||||
NS_IMETHOD ImplementsInterface(REFNSIID aIID, PRBool* aResult);
|
||||
|
||||
NS_IMETHOD ShouldBuildChildFrames(PRBool* aResult);
|
||||
|
||||
public:
|
||||
nsXBLBinding(nsIXBLPrototypeBinding* aProtoBinding);
|
||||
virtual ~nsXBLBinding();
|
||||
|
@ -47,8 +47,11 @@
|
||||
#include "nsSupportsArray.h"
|
||||
#include "nsINameSpace.h"
|
||||
#include "nsXBLService.h"
|
||||
#include "nsXBLBinding.h"
|
||||
#include "nsXBLPrototypeBinding.h"
|
||||
#include "nsFixedSizeAllocator.h"
|
||||
#include "xptinfo.h"
|
||||
#include "nsIInterfaceInfoManager.h"
|
||||
|
||||
// Helper Classes =====================================================================
|
||||
|
||||
@ -117,7 +120,9 @@ nsIAtom* nsXBLPrototypeBinding::kContentAtom = nsnull;
|
||||
nsIAtom* nsXBLPrototypeBinding::kInheritsAtom = nsnull;
|
||||
nsIAtom* nsXBLPrototypeBinding::kHTMLAtom = nsnull;
|
||||
nsIAtom* nsXBLPrototypeBinding::kValueAtom = nsnull;
|
||||
|
||||
nsIAtom* nsXBLPrototypeBinding::kXBLTextAtom = nsnull;
|
||||
nsIAtom* nsXBLPrototypeBinding::kImplementationAtom = nsnull;
|
||||
nsIAtom* nsXBLPrototypeBinding::kImplementsAtom = nsnull;
|
||||
nsFixedSizeAllocator nsXBLPrototypeBinding::kPool;
|
||||
|
||||
static const size_t kBucketSizes[] = {
|
||||
@ -140,7 +145,8 @@ nsXBLPrototypeBinding::nsXBLPrototypeBinding(const nsAReadableCString& aID, nsIC
|
||||
mInheritStyle(PR_TRUE),
|
||||
mHasBaseProto(PR_TRUE),
|
||||
mAttributeTable(nsnull),
|
||||
mInsertionPointTable(nsnull)
|
||||
mInsertionPointTable(nsnull),
|
||||
mInterfaceTable(nsnull)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
|
||||
@ -160,6 +166,9 @@ nsXBLPrototypeBinding::nsXBLPrototypeBinding(const nsAReadableCString& aID, nsIC
|
||||
kInheritsAtom = NS_NewAtom("inherits");
|
||||
kHTMLAtom = NS_NewAtom("html");
|
||||
kValueAtom = NS_NewAtom("value");
|
||||
kXBLTextAtom = NS_NewAtom("xbl:text");
|
||||
kImplementationAtom = NS_NewAtom("implementation");
|
||||
kImplementsAtom = NS_NewAtom("implements");
|
||||
}
|
||||
|
||||
// These all use atoms, so we have to do these ops last to ensure
|
||||
@ -178,6 +187,11 @@ nsXBLPrototypeBinding::nsXBLPrototypeBinding(const nsAReadableCString& aID, nsIC
|
||||
ConstructAttributeTable(content);
|
||||
ConstructInsertionTable(content);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> impl;
|
||||
GetImmediateChild(kImplementationAtom, getter_AddRefs(impl));
|
||||
if (impl)
|
||||
ConstructInterfaceTable(impl);
|
||||
}
|
||||
|
||||
|
||||
@ -185,6 +199,7 @@ nsXBLPrototypeBinding::~nsXBLPrototypeBinding(void)
|
||||
{
|
||||
delete mAttributeTable;
|
||||
delete mInsertionPointTable;
|
||||
delete mInterfaceTable;
|
||||
gRefCnt--;
|
||||
if (gRefCnt == 0) {
|
||||
NS_RELEASE(kInheritStyleAtom);
|
||||
@ -195,6 +210,9 @@ nsXBLPrototypeBinding::~nsXBLPrototypeBinding(void)
|
||||
NS_RELEASE(kInheritsAtom);
|
||||
NS_RELEASE(kHTMLAtom);
|
||||
NS_RELEASE(kValueAtom);
|
||||
NS_RELEASE(kXBLTextAtom);
|
||||
NS_RELEASE(kImplementationAtom);
|
||||
NS_RELEASE(kImplementsAtom);
|
||||
}
|
||||
}
|
||||
|
||||
@ -389,20 +407,35 @@ nsXBLPrototypeBinding::AttributeChanged(nsIAtom* aAttribute, PRInt32 aNameSpaceI
|
||||
if (aRemoveFlag)
|
||||
realElement->UnsetAttribute(aNameSpaceID, dstAttr, PR_TRUE);
|
||||
else {
|
||||
PRBool attrPresent = PR_TRUE;
|
||||
nsAutoString value;
|
||||
nsresult result = aChangedElement->GetAttribute(aNameSpaceID, aAttribute, value);
|
||||
PRBool attrPresent = (result == NS_CONTENT_ATTR_NO_VALUE ||
|
||||
result == NS_CONTENT_ATTR_HAS_VALUE);
|
||||
// Check to see if the src attribute is xbl:text. If so, then we need to obtain the
|
||||
// children of the real element and get the text nodes' values.
|
||||
if (aAttribute == kXBLTextAtom) {
|
||||
nsXBLBinding::GetTextData(aChangedElement, value);
|
||||
value.StripChar('\n');
|
||||
value.StripChar('\r');
|
||||
nsAutoString stripVal(value);
|
||||
stripVal.StripWhitespace();
|
||||
if (stripVal.IsEmpty())
|
||||
attrPresent = PR_FALSE;
|
||||
}
|
||||
else {
|
||||
nsresult result = aChangedElement->GetAttribute(aNameSpaceID, aAttribute, value);
|
||||
attrPresent = (result == NS_CONTENT_ATTR_NO_VALUE ||
|
||||
result == NS_CONTENT_ATTR_HAS_VALUE);
|
||||
}
|
||||
|
||||
if (attrPresent)
|
||||
realElement->SetAttribute(aNameSpaceID, dstAttr, value, PR_TRUE);
|
||||
}
|
||||
|
||||
// See if we're the <html> tag in XUL, and see if value is being
|
||||
// set or unset on us.
|
||||
// set or unset on us. We may also be a tag that is having
|
||||
// xbl:text set on us.
|
||||
nsCOMPtr<nsIAtom> tag;
|
||||
realElement->GetTag(*getter_AddRefs(tag));
|
||||
if ((tag.get() == kHTMLAtom) && (dstAttr.get() == kValueAtom)) {
|
||||
if (dstAttr.get() == kXBLTextAtom || (tag.get() == kHTMLAtom) && (dstAttr.get() == kValueAtom)) {
|
||||
// Flush out all our kids.
|
||||
PRInt32 childCount;
|
||||
realElement->ChildCount(childCount);
|
||||
@ -425,6 +458,7 @@ nsXBLPrototypeBinding::AttributeChanged(nsIAtom* aAttribute, PRInt32 aNameSpaceI
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIXBLAttributeEntry> tmpAttr = xblAttr;
|
||||
tmpAttr->GetNext(getter_AddRefs(xblAttr));
|
||||
}
|
||||
@ -521,6 +555,23 @@ nsXBLPrototypeBinding::GetBaseTag(PRInt32* aNamespaceID, nsIAtom** aResult)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLPrototypeBinding::ImplementsInterface(REFNSIID aIID, PRBool* aResult)
|
||||
{
|
||||
// Init the answer to FALSE.
|
||||
*aResult = PR_FALSE;
|
||||
|
||||
// Now check our IID table.
|
||||
if (mInterfaceTable) {
|
||||
nsIIDKey key(aIID);
|
||||
nsCOMPtr<nsISupports> supports = getter_AddRefs(NS_STATIC_CAST(nsISupports*,
|
||||
mInterfaceTable->Get(&key)));
|
||||
*aResult = supports != nsnull;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Internal helpers ///////////////////////////////////////////////////////////////////////
|
||||
|
||||
void
|
||||
@ -601,9 +652,23 @@ PRBool PR_CALLBACK SetAttrs(nsHashKey* aKey, void* aData, void* aClosure)
|
||||
entry->GetSrcAttribute(getter_AddRefs(src));
|
||||
|
||||
nsAutoString value;
|
||||
nsresult result = changeData->mBoundElement->GetAttribute(kNameSpaceID_None, src, value);
|
||||
PRBool attrPresent = (result == NS_CONTENT_ATTR_NO_VALUE ||
|
||||
result == NS_CONTENT_ATTR_HAS_VALUE);
|
||||
PRBool attrPresent = PR_TRUE;
|
||||
if (src.get() == nsXBLPrototypeBinding::kXBLTextAtom) {
|
||||
nsXBLBinding::GetTextData(changeData->mBoundElement, value);
|
||||
value.StripChar('\n');
|
||||
value.StripChar('\r');
|
||||
nsAutoString stripVal(value);
|
||||
stripVal.StripWhitespace();
|
||||
|
||||
if (stripVal.IsEmpty())
|
||||
attrPresent = PR_FALSE;
|
||||
}
|
||||
else {
|
||||
nsresult result = changeData->mBoundElement->GetAttribute(kNameSpaceID_None, src, value);
|
||||
attrPresent = (result == NS_CONTENT_ATTR_NO_VALUE ||
|
||||
result == NS_CONTENT_ATTR_HAS_VALUE);
|
||||
}
|
||||
|
||||
if (attrPresent) {
|
||||
nsCOMPtr<nsIContent> content;
|
||||
changeData->mProto->GetImmediateChild(nsXBLPrototypeBinding::kContentAtom, getter_AddRefs(content));
|
||||
@ -621,7 +686,8 @@ PRBool PR_CALLBACK SetAttrs(nsHashKey* aKey, void* aData, void* aClosure)
|
||||
realElement->SetAttribute(kNameSpaceID_None, dst, value, PR_FALSE);
|
||||
nsCOMPtr<nsIAtom> tag;
|
||||
realElement->GetTag(*getter_AddRefs(tag));
|
||||
if ((tag.get() == nsXBLPrototypeBinding::kHTMLAtom) && (dst.get() == nsXBLPrototypeBinding::kValueAtom) && !value.IsEmpty()) {
|
||||
if (dst.get() == nsXBLPrototypeBinding::kXBLTextAtom ||
|
||||
(tag.get() == nsXBLPrototypeBinding::kHTMLAtom) && (dst.get() == nsXBLPrototypeBinding::kValueAtom) && !value.IsEmpty()) {
|
||||
nsCOMPtr<nsIDOMText> textNode;
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
changeData->mBoundElement->GetDocument(*getter_AddRefs(doc));
|
||||
@ -652,6 +718,21 @@ nsXBLPrototypeBinding::SetInitialAttributes(nsIContent* aBoundElement, nsIConten
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLPrototypeBinding::ShouldBuildChildFrames(PRBool* aResult)
|
||||
{
|
||||
*aResult = PR_TRUE;
|
||||
if (mAttributeTable) {
|
||||
nsISupportsKey key(kXBLTextAtom);
|
||||
nsCOMPtr<nsISupports> supports = getter_AddRefs(NS_STATIC_CAST(nsISupports*,
|
||||
mAttributeTable->Get(&key)));
|
||||
|
||||
*aResult = !supports.get();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsXBLPrototypeBinding::ConstructAttributeTable(nsIContent* aElement)
|
||||
{
|
||||
@ -804,6 +885,55 @@ nsXBLPrototypeBinding::ConstructInsertionTable(nsIContent* aContent)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsXBLPrototypeBinding::ConstructInterfaceTable(nsIContent* aElement)
|
||||
{
|
||||
nsAutoString impls;
|
||||
aElement->GetAttribute(kNameSpaceID_None, kImplementsAtom, impls);
|
||||
if (!impls.IsEmpty()) {
|
||||
// Obtain the interface info manager that can tell us the IID
|
||||
// for a given interface name.
|
||||
nsCOMPtr<nsIInterfaceInfoManager> infoManager = getter_AddRefs(XPTI_GetInterfaceInfoManager());
|
||||
if (!infoManager)
|
||||
return;
|
||||
|
||||
// Create the table.
|
||||
if (!mInterfaceTable)
|
||||
mInterfaceTable = new nsSupportsHashtable(4);
|
||||
|
||||
// The user specified at least one attribute.
|
||||
char* str = impls.ToNewCString();
|
||||
char* newStr;
|
||||
// XXX We should use a strtok function that tokenizes PRUnichars
|
||||
// so that we don't have to convert from Unicode to ASCII and then back
|
||||
|
||||
char* token = nsCRT::strtok( str, ", ", &newStr );
|
||||
while( token != NULL ) {
|
||||
// Take the name and try obtain an IID.
|
||||
nsIID* iid = nsnull;
|
||||
infoManager->GetIIDForName(token, &iid);
|
||||
if (iid) {
|
||||
// We found a valid iid. Add it to our table.
|
||||
nsIIDKey key(*iid);
|
||||
mInterfaceTable->Put(&key, mBinding);
|
||||
nsMemory::Free(iid);
|
||||
}
|
||||
|
||||
token = nsCRT::strtok( newStr, ", ", &newStr );
|
||||
}
|
||||
|
||||
nsMemory::Free(str);
|
||||
}
|
||||
|
||||
// Recur into our children.
|
||||
PRInt32 childCount;
|
||||
aElement->ChildCount(childCount);
|
||||
for (PRInt32 i = 0; i < childCount; i++) {
|
||||
nsCOMPtr<nsIContent> child;
|
||||
aElement->ChildAt(i, *getter_AddRefs(child));
|
||||
ConstructAttributeTable(child);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsXBLPrototypeBinding::GetNestedChildren(nsIAtom* aTag, nsIContent* aContent, nsISupportsArray** aList)
|
||||
|
@ -84,6 +84,10 @@ class nsXBLPrototypeBinding: public nsIXBLPrototypeBinding
|
||||
NS_IMETHOD GetBaseTag(PRInt32* aNamespaceID, nsIAtom** aTag);
|
||||
NS_IMETHOD SetBaseTag(PRInt32 aNamespaceID, nsIAtom* aTag);
|
||||
|
||||
NS_IMETHOD ImplementsInterface(REFNSIID aIID, PRBool* aResult);
|
||||
|
||||
NS_IMETHOD ShouldBuildChildFrames(PRBool* aResult);
|
||||
|
||||
public:
|
||||
nsXBLPrototypeBinding(const nsAReadableCString& aRef, nsIContent* aElement,
|
||||
nsIXBLDocumentInfo* aInfo);
|
||||
@ -99,7 +103,10 @@ public:
|
||||
static nsIAtom* kInheritsAtom;
|
||||
static nsIAtom* kHTMLAtom;
|
||||
static nsIAtom* kValueAtom;
|
||||
|
||||
static nsIAtom* kXBLTextAtom;
|
||||
static nsIAtom* kImplementationAtom;
|
||||
static nsIAtom* kImplementsAtom;
|
||||
|
||||
static nsFixedSizeAllocator kPool;
|
||||
|
||||
// Internal member functions
|
||||
@ -112,8 +119,33 @@ protected:
|
||||
void ConstructHandlers();
|
||||
void ConstructAttributeTable(nsIContent* aElement);
|
||||
void ConstructInsertionTable(nsIContent* aElement);
|
||||
void ConstructInterfaceTable(nsIContent* aElement);
|
||||
void GetNestedChildren(nsIAtom* aTag, nsIContent* aContent, nsISupportsArray** aList);
|
||||
|
||||
protected:
|
||||
// Internal helper class for managing our IID table.
|
||||
class nsIIDKey : public nsHashKey {
|
||||
protected:
|
||||
nsIID mKey;
|
||||
|
||||
public:
|
||||
nsIIDKey(REFNSIID key) : mKey(key) {}
|
||||
~nsIIDKey(void) {}
|
||||
|
||||
PRUint32 HashCode(void) const {
|
||||
// Just use the 32-bit m0 field.
|
||||
return mKey.m0;
|
||||
}
|
||||
|
||||
PRBool Equals(const nsHashKey *aKey) const {
|
||||
return mKey.Equals( ((nsIIDKey*) aKey)->mKey);
|
||||
}
|
||||
|
||||
nsHashKey *Clone(void) const {
|
||||
return new nsIIDKey(mKey);
|
||||
}
|
||||
};
|
||||
|
||||
// MEMBER VARIABLES
|
||||
protected:
|
||||
nsCString mID;
|
||||
@ -134,6 +166,8 @@ protected:
|
||||
nsSupportsHashtable* mInsertionPointTable; // A table of insertion points for placing explicit content
|
||||
// underneath anonymous content.
|
||||
|
||||
nsSupportsHashtable* mInterfaceTable; // A table of cached interfaces that we support.
|
||||
|
||||
PRInt32 mBaseNameSpaceID; // If we extend a tagname/namespace, then that information will
|
||||
nsCOMPtr<nsIAtom> mBaseTag; // be stored in here.
|
||||
};
|
||||
|
@ -502,6 +502,7 @@ JSCList nsXBLService::gClassLRUList = JS_INIT_STATIC_CLIST(&nsXBLService::gClas
|
||||
PRUint32 nsXBLService::gClassLRUListLength = 0;
|
||||
PRUint32 nsXBLService::gClassLRUListQuota = 64;
|
||||
|
||||
nsIAtom* nsXBLService::kDisplayAtom = nsnull;
|
||||
nsIAtom* nsXBLService::kExtendsAtom = nsnull;
|
||||
nsIAtom* nsXBLService::kEventAtom = nsnull;
|
||||
nsIAtom* nsXBLService::kScrollbarAtom = nsnull;
|
||||
@ -542,6 +543,7 @@ nsXBLService::nsXBLService(void)
|
||||
if (NS_FAILED(rv)) return;
|
||||
|
||||
// Create our atoms
|
||||
kDisplayAtom = NS_NewAtom("display");
|
||||
kExtendsAtom = NS_NewAtom("extends");
|
||||
kEventAtom = NS_NewAtom("event");
|
||||
kScrollbarAtom = NS_NewAtom("scrollbar");
|
||||
@ -573,6 +575,7 @@ nsXBLService::~nsXBLService(void)
|
||||
NS_IF_RELEASE(gNameSpaceManager);
|
||||
|
||||
// Release our atoms
|
||||
NS_RELEASE(kDisplayAtom);
|
||||
NS_RELEASE(kExtendsAtom);
|
||||
NS_RELEASE(kEventAtom);
|
||||
NS_RELEASE(kScrollbarAtom);
|
||||
@ -1027,51 +1030,72 @@ NS_IMETHODIMP nsXBLService::GetBindingInternal(nsIContent* aBoundElement,
|
||||
}
|
||||
}
|
||||
else if (hasBase) {
|
||||
// Check for the presence of an extends attribute
|
||||
nsAutoString extends;
|
||||
// Check for the presence of a 'extends' and 'display' attributes
|
||||
nsAutoString display, extends;
|
||||
child->GetAttribute(kNameSpaceID_None, kDisplayAtom, display);
|
||||
child->GetAttribute(kNameSpaceID_None, kExtendsAtom, extends);
|
||||
PRBool hasDisplay = !display.IsEmpty();
|
||||
PRBool hasExtends = !extends.IsEmpty();
|
||||
|
||||
nsAutoString value(extends);
|
||||
if (extends.IsEmpty())
|
||||
|
||||
PRBool prefixIsDisplay = PR_FALSE;
|
||||
|
||||
if (!hasDisplay && !hasExtends)
|
||||
protoBinding->SetHasBasePrototype(PR_FALSE);
|
||||
else {
|
||||
nsAutoString prefix;
|
||||
PRInt32 offset = extends.FindChar(':');
|
||||
if (-1 != offset) {
|
||||
extends.Left(prefix, offset);
|
||||
extends.Cut(0, offset+1);
|
||||
PRInt32 offset;
|
||||
if (hasDisplay) {
|
||||
prefixIsDisplay = PR_TRUE;
|
||||
offset = display.FindChar(':');
|
||||
if (-1 != offset) {
|
||||
display.Left(prefix, offset);
|
||||
display.Cut(0, offset+1);
|
||||
}
|
||||
}
|
||||
else if (hasExtends) {
|
||||
offset = extends.FindChar(':');
|
||||
if (-1 != offset) {
|
||||
extends.Left(prefix, offset);
|
||||
extends.Cut(0, offset+1);
|
||||
display = extends;
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsINameSpace> tagSpace;
|
||||
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 extend some widget/frame. We don't really have a base binding.
|
||||
protoBinding->SetHasBasePrototype(PR_FALSE);
|
||||
PRInt32 nameSpaceID;
|
||||
tagSpace->GetNameSpaceID(nameSpaceID);
|
||||
nsCOMPtr<nsIAtom> tagName = getter_AddRefs(NS_NewAtom(extends));
|
||||
nsCOMPtr<nsIAtom> tagName = getter_AddRefs(NS_NewAtom(display));
|
||||
protoBinding->SetBaseTag(nameSpaceID, tagName);
|
||||
}
|
||||
else {
|
||||
// We have a base class binding. Load it right now.
|
||||
nsCAutoString urlCString; urlCString.AssignWithConversion(value);
|
||||
if (NS_FAILED(GetBindingInternal(aBoundElement, urlCString, aPeekOnly, aIsReady, getter_AddRefs(baseBinding))))
|
||||
return NS_ERROR_FAILURE; // Binding not yet ready or an error occurred.
|
||||
if (!aPeekOnly) {
|
||||
// Make sure to set the base prototype.
|
||||
baseBinding->GetPrototypeBinding(getter_AddRefs(baseProto));
|
||||
protoBinding->SetBasePrototype(baseProto);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hasExtends && (hasDisplay || (!hasDisplay && !tagSpace))) {
|
||||
// Look up the prefix.
|
||||
// We have a base class binding. Load it right now.
|
||||
nsCAutoString urlCString; urlCString.AssignWithConversion(value);
|
||||
if (NS_FAILED(GetBindingInternal(aBoundElement, urlCString, aPeekOnly, aIsReady, getter_AddRefs(baseBinding))))
|
||||
return NS_ERROR_FAILURE; // Binding not yet ready or an error occurred.
|
||||
if (!aPeekOnly) {
|
||||
// Make sure to set the base prototype.
|
||||
baseBinding->GetPrototypeBinding(getter_AddRefs(baseProto));
|
||||
protoBinding->SetBasePrototype(baseProto);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -128,6 +128,7 @@ public:
|
||||
static PRUint32 gClassLRUListQuota; // Quota on class LRU list.
|
||||
|
||||
// XBL Atoms
|
||||
static nsIAtom* kDisplayAtom;
|
||||
static nsIAtom* kExtendsAtom;
|
||||
static nsIAtom* kEventAtom;
|
||||
static nsIAtom* kScrollbarAtom;
|
||||
|
@ -41,6 +41,7 @@ class nsIXBLBindingAttachedHandler;
|
||||
class nsIXBLDocumentInfo;
|
||||
class nsIAtom;
|
||||
class nsIStreamListener;
|
||||
class nsIXPConnectWrappedJS;
|
||||
|
||||
// {55D70FE0-C8E5-11d3-97FB-00400553EEF0}
|
||||
#define NS_IBINDING_MANAGER_IID \
|
||||
@ -54,6 +55,9 @@ public:
|
||||
NS_IMETHOD GetBinding(nsIContent* aContent, nsIXBLBinding** aResult) = 0;
|
||||
NS_IMETHOD SetBinding(nsIContent* aContent, nsIXBLBinding* aBinding) = 0;
|
||||
|
||||
NS_IMETHOD GetWrappedJS(nsIContent* aContent, nsIXPConnectWrappedJS** aResult) = 0;
|
||||
NS_IMETHOD SetWrappedJS(nsIContent* aContent, nsIXPConnectWrappedJS* aResult) = 0;
|
||||
|
||||
/**
|
||||
* Notify the binding manager that an element
|
||||
* has been moved from one document to another,
|
||||
@ -100,6 +104,10 @@ public:
|
||||
|
||||
NS_IMETHOD InheritsStyle(nsIContent* aContent, PRBool* aResult) = 0;
|
||||
NS_IMETHOD FlushChromeBindings() = 0;
|
||||
|
||||
NS_IMETHOD GetBindingImplementation(nsIContent* aContent, void* aScriptObject, REFNSIID aIID, void** aResult)=0;
|
||||
|
||||
NS_IMETHOD ShouldBuildChildFrames(nsIContent* aContent, PRBool* aResult) = 0;
|
||||
};
|
||||
|
||||
#endif // nsIBinding_Manager_h__
|
||||
|
@ -98,6 +98,10 @@ public:
|
||||
|
||||
NS_IMETHOD MarkForDeath()=0;
|
||||
NS_IMETHOD MarkedForDeath(PRBool* aResult)=0;
|
||||
|
||||
NS_IMETHOD ImplementsInterface(REFNSIID aIID, PRBool* aResult)=0;
|
||||
|
||||
NS_IMETHOD ShouldBuildChildFrames(PRBool* aResult)=0;
|
||||
};
|
||||
|
||||
extern nsresult
|
||||
|
@ -84,6 +84,10 @@ public:
|
||||
|
||||
NS_IMETHOD GetBaseTag(PRInt32* aNamespaceID, nsIAtom** aTag)=0;
|
||||
NS_IMETHOD SetBaseTag(PRInt32 aNamespaceID, nsIAtom* aTag)=0;
|
||||
|
||||
NS_IMETHOD ImplementsInterface(REFNSIID aIID, PRBool* aResult)=0;
|
||||
|
||||
NS_IMETHOD ShouldBuildChildFrames(PRBool* aResult)=0;
|
||||
};
|
||||
|
||||
extern nsresult
|
||||
|
@ -62,6 +62,8 @@
|
||||
#include "nsIXBLPrototypeBinding.h"
|
||||
#include "nsIWeakReference.h"
|
||||
|
||||
#include "nsIXPConnect.h"
|
||||
|
||||
// Static IIDs/CIDs. Try to minimize these.
|
||||
static NS_DEFINE_CID(kNameSpaceManagerCID, NS_NAMESPACEMANAGER_CID);
|
||||
static NS_DEFINE_CID(kXMLDocumentCID, NS_XMLDOCUMENT_CID);
|
||||
@ -203,6 +205,9 @@ public:
|
||||
NS_IMETHOD GetBinding(nsIContent* aContent, nsIXBLBinding** aResult);
|
||||
NS_IMETHOD SetBinding(nsIContent* aContent, nsIXBLBinding* aBinding);
|
||||
|
||||
NS_IMETHOD GetWrappedJS(nsIContent* aContent, nsIXPConnectWrappedJS** aResult);
|
||||
NS_IMETHOD SetWrappedJS(nsIContent* aContent, nsIXPConnectWrappedJS* aResult);
|
||||
|
||||
NS_IMETHOD ChangeDocumentFor(nsIContent* aContent, nsIDocument* aOldDocument,
|
||||
nsIDocument* aNewDocument);
|
||||
|
||||
@ -234,12 +239,16 @@ public:
|
||||
NS_IMETHOD InheritsStyle(nsIContent* aContent, PRBool* aResult);
|
||||
NS_IMETHOD FlushChromeBindings();
|
||||
|
||||
NS_IMETHOD GetBindingImplementation(nsIContent* aContent, void* aScriptObject, REFNSIID aIID, void** aResult);
|
||||
|
||||
// nsIStyleRuleSupplier
|
||||
NS_IMETHOD UseDocumentRules(nsIContent* aContent, PRBool* aResult);
|
||||
NS_IMETHOD WalkRules(nsIStyleSet* aStyleSet,
|
||||
nsISupportsArrayEnumFunc aFunc, void* aData,
|
||||
nsIContent* aContent);
|
||||
|
||||
NS_IMETHOD ShouldBuildChildFrames(nsIContent* aContent, PRBool* aResult);
|
||||
|
||||
protected:
|
||||
void GetEnclosingScope(nsIContent* aContent, nsIContent** aParent);
|
||||
void GetOutermostStyleScope(nsIContent* aContent, nsIContent** aParent);
|
||||
@ -250,6 +259,7 @@ protected:
|
||||
// MEMBER VARIABLES
|
||||
protected:
|
||||
nsSupportsHashtable* mBindingTable;
|
||||
nsSupportsHashtable* mWrapperTable;
|
||||
nsSupportsHashtable* mDocumentTable;
|
||||
nsSupportsHashtable* mLoadingDocTable;
|
||||
|
||||
@ -269,7 +279,7 @@ nsBindingManager::nsBindingManager(void)
|
||||
NS_INIT_REFCNT();
|
||||
|
||||
mBindingTable = nsnull;
|
||||
|
||||
mWrapperTable = nsnull;
|
||||
mDocumentTable = nsnull;
|
||||
mLoadingDocTable = nsnull;
|
||||
|
||||
@ -279,6 +289,7 @@ nsBindingManager::nsBindingManager(void)
|
||||
nsBindingManager::~nsBindingManager(void)
|
||||
{
|
||||
delete mBindingTable;
|
||||
delete mWrapperTable;
|
||||
delete mDocumentTable;
|
||||
delete mLoadingDocTable;
|
||||
}
|
||||
@ -312,9 +323,43 @@ nsBindingManager::SetBinding(nsIContent* aContent, nsIXBLBinding* aBinding )
|
||||
if (aBinding) {
|
||||
mBindingTable->Put(&key, aBinding);
|
||||
}
|
||||
else
|
||||
else {
|
||||
mBindingTable->Remove(&key);
|
||||
|
||||
// The death of the bindings means the death of the JS wrapper.
|
||||
SetWrappedJS(aContent, nsnull);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBindingManager::GetWrappedJS(nsIContent* aContent, nsIXPConnectWrappedJS** aResult)
|
||||
{
|
||||
if (mWrapperTable) {
|
||||
nsISupportsKey key(aContent);
|
||||
*aResult = NS_STATIC_CAST(nsIXPConnectWrappedJS*, mWrapperTable->Get(&key));
|
||||
}
|
||||
else {
|
||||
*aResult = nsnull;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBindingManager::SetWrappedJS(nsIContent* aContent, nsIXPConnectWrappedJS* aWrappedJS)
|
||||
{
|
||||
if (!mWrapperTable)
|
||||
mWrapperTable = new nsSupportsHashtable;
|
||||
|
||||
nsISupportsKey key(aContent);
|
||||
if (aWrappedJS) {
|
||||
mWrapperTable->Put(&key, aWrappedJS);
|
||||
}
|
||||
else
|
||||
mWrapperTable->Remove(&key);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -669,6 +714,69 @@ nsBindingManager::FlushChromeBindings()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBindingManager::GetBindingImplementation(nsIContent* aContent, void* aScriptObject, REFNSIID aIID, void** aResult)
|
||||
{
|
||||
*aResult = nsnull;
|
||||
nsCOMPtr<nsIXBLBinding> binding;
|
||||
GetBinding(aContent, getter_AddRefs(binding));
|
||||
if (binding) {
|
||||
PRBool supportsInterface;
|
||||
binding->ImplementsInterface(aIID, &supportsInterface);
|
||||
if (supportsInterface) {
|
||||
nsCOMPtr<nsIXPConnectWrappedJS> wrappedJS;
|
||||
GetWrappedJS(aContent, getter_AddRefs(wrappedJS));
|
||||
|
||||
if (wrappedJS)
|
||||
return wrappedJS->AggregatedQueryInterface(aIID, aResult);
|
||||
|
||||
// We have never made a wrapper for this implementation.
|
||||
// Create an XPC wrapper for the script object and hand it back.
|
||||
JSObject* jsobj = (JSObject*)aScriptObject;
|
||||
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
aContent->GetDocument(*getter_AddRefs(doc));
|
||||
if (!doc)
|
||||
return NS_NOINTERFACE;
|
||||
|
||||
nsCOMPtr<nsIScriptGlobalObject> global;
|
||||
doc->GetScriptGlobalObject(getter_AddRefs(global));
|
||||
if (!global)
|
||||
return NS_NOINTERFACE;
|
||||
|
||||
nsCOMPtr<nsIScriptContext> context;
|
||||
global->GetContext(getter_AddRefs(context));
|
||||
if (!context)
|
||||
return NS_NOINTERFACE;
|
||||
|
||||
JSContext* jscontext = (JSContext*)context->GetNativeContext();
|
||||
if (!jscontext)
|
||||
return NS_NOINTERFACE;
|
||||
|
||||
nsCOMPtr<nsIXPConnect> xpConnect = do_GetService("@mozilla.org/js/xpc/XPConnect;1");
|
||||
if (!xpConnect)
|
||||
return NS_NOINTERFACE;
|
||||
|
||||
nsISupports* nativeThis = (nsISupports*)JS_GetPrivate(jscontext, jsobj);
|
||||
nsresult rv = xpConnect->WrapJSAggregatedToNative(nativeThis, jscontext, jsobj, aIID, aResult);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// We successfully created a wrapper. We will own this wrapper for as long as the binding remains
|
||||
// alive. At the time the binding is cleared out of the bindingManager, we will remove the wrapper
|
||||
// from the bindingManager as well.
|
||||
nsISupports* supp = NS_STATIC_CAST(nsISupports*, *aResult);
|
||||
wrappedJS = do_QueryInterface(supp);
|
||||
SetWrappedJS(aContent, wrappedJS);
|
||||
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
*aResult = nsnull;
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBindingManager::InheritsStyle(nsIContent* aContent, PRBool* aResult)
|
||||
{
|
||||
@ -781,6 +889,19 @@ nsBindingManager::WalkRules(nsIStyleSet* aStyleSet,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBindingManager::ShouldBuildChildFrames(nsIContent* aContent, PRBool* aResult)
|
||||
{
|
||||
*aResult = PR_TRUE;
|
||||
|
||||
nsCOMPtr<nsIXBLBinding> binding;
|
||||
GetBinding(aContent, getter_AddRefs(binding));
|
||||
|
||||
if (binding)
|
||||
return binding->ShouldBuildChildFrames(aResult);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Creation Routine ///////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
@ -993,9 +993,10 @@ nsXBLBinding::InstallProperties(nsIContent* aBoundElement)
|
||||
NS_IMETHODIMP
|
||||
nsXBLBinding::GetBaseTag(PRInt32* aNameSpaceID, nsIAtom** aResult)
|
||||
{
|
||||
if (mNextBinding)
|
||||
mPrototypeBinding->GetBaseTag(aNameSpaceID, aResult);
|
||||
if (!*aResult && mNextBinding)
|
||||
return mNextBinding->GetBaseTag(aNameSpaceID, aResult);
|
||||
return mPrototypeBinding->GetBaseTag(aNameSpaceID, aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -1467,6 +1468,27 @@ nsXBLBinding::MarkedForDeath(PRBool* aResult)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLBinding::ImplementsInterface(REFNSIID aIID, PRBool* aResult)
|
||||
{
|
||||
mPrototypeBinding->ImplementsInterface(aIID, aResult);
|
||||
if (!*aResult && mNextBinding)
|
||||
return mNextBinding->ImplementsInterface(aIID, aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLBinding::ShouldBuildChildFrames(PRBool* aResult)
|
||||
{
|
||||
*aResult = PR_TRUE;
|
||||
if (mContent)
|
||||
return mPrototypeBinding->ShouldBuildChildFrames(aResult);
|
||||
else if (mNextBinding)
|
||||
return mNextBinding->ShouldBuildChildFrames(aResult);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Creation Routine ///////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsresult
|
||||
|
@ -34,6 +34,7 @@ class nsISupportsArray;
|
||||
class nsSupportsHashtable;
|
||||
class nsIXBLService;
|
||||
class nsFixedSizeAllocator;
|
||||
class nsXBLEventHandler;
|
||||
|
||||
// *********************************************************************/
|
||||
// The XBLBinding class
|
||||
@ -93,6 +94,10 @@ class nsXBLBinding: public nsIXBLBinding
|
||||
NS_IMETHOD MarkForDeath();
|
||||
NS_IMETHOD MarkedForDeath(PRBool* aResult);
|
||||
|
||||
NS_IMETHOD ImplementsInterface(REFNSIID aIID, PRBool* aResult);
|
||||
|
||||
NS_IMETHOD ShouldBuildChildFrames(PRBool* aResult);
|
||||
|
||||
public:
|
||||
nsXBLBinding(nsIXBLPrototypeBinding* aProtoBinding);
|
||||
virtual ~nsXBLBinding();
|
||||
|
@ -47,8 +47,11 @@
|
||||
#include "nsSupportsArray.h"
|
||||
#include "nsINameSpace.h"
|
||||
#include "nsXBLService.h"
|
||||
#include "nsXBLBinding.h"
|
||||
#include "nsXBLPrototypeBinding.h"
|
||||
#include "nsFixedSizeAllocator.h"
|
||||
#include "xptinfo.h"
|
||||
#include "nsIInterfaceInfoManager.h"
|
||||
|
||||
// Helper Classes =====================================================================
|
||||
|
||||
@ -117,7 +120,9 @@ nsIAtom* nsXBLPrototypeBinding::kContentAtom = nsnull;
|
||||
nsIAtom* nsXBLPrototypeBinding::kInheritsAtom = nsnull;
|
||||
nsIAtom* nsXBLPrototypeBinding::kHTMLAtom = nsnull;
|
||||
nsIAtom* nsXBLPrototypeBinding::kValueAtom = nsnull;
|
||||
|
||||
nsIAtom* nsXBLPrototypeBinding::kXBLTextAtom = nsnull;
|
||||
nsIAtom* nsXBLPrototypeBinding::kImplementationAtom = nsnull;
|
||||
nsIAtom* nsXBLPrototypeBinding::kImplementsAtom = nsnull;
|
||||
nsFixedSizeAllocator nsXBLPrototypeBinding::kPool;
|
||||
|
||||
static const size_t kBucketSizes[] = {
|
||||
@ -140,7 +145,8 @@ nsXBLPrototypeBinding::nsXBLPrototypeBinding(const nsAReadableCString& aID, nsIC
|
||||
mInheritStyle(PR_TRUE),
|
||||
mHasBaseProto(PR_TRUE),
|
||||
mAttributeTable(nsnull),
|
||||
mInsertionPointTable(nsnull)
|
||||
mInsertionPointTable(nsnull),
|
||||
mInterfaceTable(nsnull)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
|
||||
@ -160,6 +166,9 @@ nsXBLPrototypeBinding::nsXBLPrototypeBinding(const nsAReadableCString& aID, nsIC
|
||||
kInheritsAtom = NS_NewAtom("inherits");
|
||||
kHTMLAtom = NS_NewAtom("html");
|
||||
kValueAtom = NS_NewAtom("value");
|
||||
kXBLTextAtom = NS_NewAtom("xbl:text");
|
||||
kImplementationAtom = NS_NewAtom("implementation");
|
||||
kImplementsAtom = NS_NewAtom("implements");
|
||||
}
|
||||
|
||||
// These all use atoms, so we have to do these ops last to ensure
|
||||
@ -178,6 +187,11 @@ nsXBLPrototypeBinding::nsXBLPrototypeBinding(const nsAReadableCString& aID, nsIC
|
||||
ConstructAttributeTable(content);
|
||||
ConstructInsertionTable(content);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> impl;
|
||||
GetImmediateChild(kImplementationAtom, getter_AddRefs(impl));
|
||||
if (impl)
|
||||
ConstructInterfaceTable(impl);
|
||||
}
|
||||
|
||||
|
||||
@ -185,6 +199,7 @@ nsXBLPrototypeBinding::~nsXBLPrototypeBinding(void)
|
||||
{
|
||||
delete mAttributeTable;
|
||||
delete mInsertionPointTable;
|
||||
delete mInterfaceTable;
|
||||
gRefCnt--;
|
||||
if (gRefCnt == 0) {
|
||||
NS_RELEASE(kInheritStyleAtom);
|
||||
@ -195,6 +210,9 @@ nsXBLPrototypeBinding::~nsXBLPrototypeBinding(void)
|
||||
NS_RELEASE(kInheritsAtom);
|
||||
NS_RELEASE(kHTMLAtom);
|
||||
NS_RELEASE(kValueAtom);
|
||||
NS_RELEASE(kXBLTextAtom);
|
||||
NS_RELEASE(kImplementationAtom);
|
||||
NS_RELEASE(kImplementsAtom);
|
||||
}
|
||||
}
|
||||
|
||||
@ -389,20 +407,35 @@ nsXBLPrototypeBinding::AttributeChanged(nsIAtom* aAttribute, PRInt32 aNameSpaceI
|
||||
if (aRemoveFlag)
|
||||
realElement->UnsetAttribute(aNameSpaceID, dstAttr, PR_TRUE);
|
||||
else {
|
||||
PRBool attrPresent = PR_TRUE;
|
||||
nsAutoString value;
|
||||
nsresult result = aChangedElement->GetAttribute(aNameSpaceID, aAttribute, value);
|
||||
PRBool attrPresent = (result == NS_CONTENT_ATTR_NO_VALUE ||
|
||||
result == NS_CONTENT_ATTR_HAS_VALUE);
|
||||
// Check to see if the src attribute is xbl:text. If so, then we need to obtain the
|
||||
// children of the real element and get the text nodes' values.
|
||||
if (aAttribute == kXBLTextAtom) {
|
||||
nsXBLBinding::GetTextData(aChangedElement, value);
|
||||
value.StripChar('\n');
|
||||
value.StripChar('\r');
|
||||
nsAutoString stripVal(value);
|
||||
stripVal.StripWhitespace();
|
||||
if (stripVal.IsEmpty())
|
||||
attrPresent = PR_FALSE;
|
||||
}
|
||||
else {
|
||||
nsresult result = aChangedElement->GetAttribute(aNameSpaceID, aAttribute, value);
|
||||
attrPresent = (result == NS_CONTENT_ATTR_NO_VALUE ||
|
||||
result == NS_CONTENT_ATTR_HAS_VALUE);
|
||||
}
|
||||
|
||||
if (attrPresent)
|
||||
realElement->SetAttribute(aNameSpaceID, dstAttr, value, PR_TRUE);
|
||||
}
|
||||
|
||||
// See if we're the <html> tag in XUL, and see if value is being
|
||||
// set or unset on us.
|
||||
// set or unset on us. We may also be a tag that is having
|
||||
// xbl:text set on us.
|
||||
nsCOMPtr<nsIAtom> tag;
|
||||
realElement->GetTag(*getter_AddRefs(tag));
|
||||
if ((tag.get() == kHTMLAtom) && (dstAttr.get() == kValueAtom)) {
|
||||
if (dstAttr.get() == kXBLTextAtom || (tag.get() == kHTMLAtom) && (dstAttr.get() == kValueAtom)) {
|
||||
// Flush out all our kids.
|
||||
PRInt32 childCount;
|
||||
realElement->ChildCount(childCount);
|
||||
@ -425,6 +458,7 @@ nsXBLPrototypeBinding::AttributeChanged(nsIAtom* aAttribute, PRInt32 aNameSpaceI
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIXBLAttributeEntry> tmpAttr = xblAttr;
|
||||
tmpAttr->GetNext(getter_AddRefs(xblAttr));
|
||||
}
|
||||
@ -521,6 +555,23 @@ nsXBLPrototypeBinding::GetBaseTag(PRInt32* aNamespaceID, nsIAtom** aResult)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLPrototypeBinding::ImplementsInterface(REFNSIID aIID, PRBool* aResult)
|
||||
{
|
||||
// Init the answer to FALSE.
|
||||
*aResult = PR_FALSE;
|
||||
|
||||
// Now check our IID table.
|
||||
if (mInterfaceTable) {
|
||||
nsIIDKey key(aIID);
|
||||
nsCOMPtr<nsISupports> supports = getter_AddRefs(NS_STATIC_CAST(nsISupports*,
|
||||
mInterfaceTable->Get(&key)));
|
||||
*aResult = supports != nsnull;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Internal helpers ///////////////////////////////////////////////////////////////////////
|
||||
|
||||
void
|
||||
@ -601,9 +652,23 @@ PRBool PR_CALLBACK SetAttrs(nsHashKey* aKey, void* aData, void* aClosure)
|
||||
entry->GetSrcAttribute(getter_AddRefs(src));
|
||||
|
||||
nsAutoString value;
|
||||
nsresult result = changeData->mBoundElement->GetAttribute(kNameSpaceID_None, src, value);
|
||||
PRBool attrPresent = (result == NS_CONTENT_ATTR_NO_VALUE ||
|
||||
result == NS_CONTENT_ATTR_HAS_VALUE);
|
||||
PRBool attrPresent = PR_TRUE;
|
||||
if (src.get() == nsXBLPrototypeBinding::kXBLTextAtom) {
|
||||
nsXBLBinding::GetTextData(changeData->mBoundElement, value);
|
||||
value.StripChar('\n');
|
||||
value.StripChar('\r');
|
||||
nsAutoString stripVal(value);
|
||||
stripVal.StripWhitespace();
|
||||
|
||||
if (stripVal.IsEmpty())
|
||||
attrPresent = PR_FALSE;
|
||||
}
|
||||
else {
|
||||
nsresult result = changeData->mBoundElement->GetAttribute(kNameSpaceID_None, src, value);
|
||||
attrPresent = (result == NS_CONTENT_ATTR_NO_VALUE ||
|
||||
result == NS_CONTENT_ATTR_HAS_VALUE);
|
||||
}
|
||||
|
||||
if (attrPresent) {
|
||||
nsCOMPtr<nsIContent> content;
|
||||
changeData->mProto->GetImmediateChild(nsXBLPrototypeBinding::kContentAtom, getter_AddRefs(content));
|
||||
@ -621,7 +686,8 @@ PRBool PR_CALLBACK SetAttrs(nsHashKey* aKey, void* aData, void* aClosure)
|
||||
realElement->SetAttribute(kNameSpaceID_None, dst, value, PR_FALSE);
|
||||
nsCOMPtr<nsIAtom> tag;
|
||||
realElement->GetTag(*getter_AddRefs(tag));
|
||||
if ((tag.get() == nsXBLPrototypeBinding::kHTMLAtom) && (dst.get() == nsXBLPrototypeBinding::kValueAtom) && !value.IsEmpty()) {
|
||||
if (dst.get() == nsXBLPrototypeBinding::kXBLTextAtom ||
|
||||
(tag.get() == nsXBLPrototypeBinding::kHTMLAtom) && (dst.get() == nsXBLPrototypeBinding::kValueAtom) && !value.IsEmpty()) {
|
||||
nsCOMPtr<nsIDOMText> textNode;
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
changeData->mBoundElement->GetDocument(*getter_AddRefs(doc));
|
||||
@ -652,6 +718,21 @@ nsXBLPrototypeBinding::SetInitialAttributes(nsIContent* aBoundElement, nsIConten
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLPrototypeBinding::ShouldBuildChildFrames(PRBool* aResult)
|
||||
{
|
||||
*aResult = PR_TRUE;
|
||||
if (mAttributeTable) {
|
||||
nsISupportsKey key(kXBLTextAtom);
|
||||
nsCOMPtr<nsISupports> supports = getter_AddRefs(NS_STATIC_CAST(nsISupports*,
|
||||
mAttributeTable->Get(&key)));
|
||||
|
||||
*aResult = !supports.get();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsXBLPrototypeBinding::ConstructAttributeTable(nsIContent* aElement)
|
||||
{
|
||||
@ -804,6 +885,55 @@ nsXBLPrototypeBinding::ConstructInsertionTable(nsIContent* aContent)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsXBLPrototypeBinding::ConstructInterfaceTable(nsIContent* aElement)
|
||||
{
|
||||
nsAutoString impls;
|
||||
aElement->GetAttribute(kNameSpaceID_None, kImplementsAtom, impls);
|
||||
if (!impls.IsEmpty()) {
|
||||
// Obtain the interface info manager that can tell us the IID
|
||||
// for a given interface name.
|
||||
nsCOMPtr<nsIInterfaceInfoManager> infoManager = getter_AddRefs(XPTI_GetInterfaceInfoManager());
|
||||
if (!infoManager)
|
||||
return;
|
||||
|
||||
// Create the table.
|
||||
if (!mInterfaceTable)
|
||||
mInterfaceTable = new nsSupportsHashtable(4);
|
||||
|
||||
// The user specified at least one attribute.
|
||||
char* str = impls.ToNewCString();
|
||||
char* newStr;
|
||||
// XXX We should use a strtok function that tokenizes PRUnichars
|
||||
// so that we don't have to convert from Unicode to ASCII and then back
|
||||
|
||||
char* token = nsCRT::strtok( str, ", ", &newStr );
|
||||
while( token != NULL ) {
|
||||
// Take the name and try obtain an IID.
|
||||
nsIID* iid = nsnull;
|
||||
infoManager->GetIIDForName(token, &iid);
|
||||
if (iid) {
|
||||
// We found a valid iid. Add it to our table.
|
||||
nsIIDKey key(*iid);
|
||||
mInterfaceTable->Put(&key, mBinding);
|
||||
nsMemory::Free(iid);
|
||||
}
|
||||
|
||||
token = nsCRT::strtok( newStr, ", ", &newStr );
|
||||
}
|
||||
|
||||
nsMemory::Free(str);
|
||||
}
|
||||
|
||||
// Recur into our children.
|
||||
PRInt32 childCount;
|
||||
aElement->ChildCount(childCount);
|
||||
for (PRInt32 i = 0; i < childCount; i++) {
|
||||
nsCOMPtr<nsIContent> child;
|
||||
aElement->ChildAt(i, *getter_AddRefs(child));
|
||||
ConstructAttributeTable(child);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsXBLPrototypeBinding::GetNestedChildren(nsIAtom* aTag, nsIContent* aContent, nsISupportsArray** aList)
|
||||
|
@ -84,6 +84,10 @@ class nsXBLPrototypeBinding: public nsIXBLPrototypeBinding
|
||||
NS_IMETHOD GetBaseTag(PRInt32* aNamespaceID, nsIAtom** aTag);
|
||||
NS_IMETHOD SetBaseTag(PRInt32 aNamespaceID, nsIAtom* aTag);
|
||||
|
||||
NS_IMETHOD ImplementsInterface(REFNSIID aIID, PRBool* aResult);
|
||||
|
||||
NS_IMETHOD ShouldBuildChildFrames(PRBool* aResult);
|
||||
|
||||
public:
|
||||
nsXBLPrototypeBinding(const nsAReadableCString& aRef, nsIContent* aElement,
|
||||
nsIXBLDocumentInfo* aInfo);
|
||||
@ -99,7 +103,10 @@ public:
|
||||
static nsIAtom* kInheritsAtom;
|
||||
static nsIAtom* kHTMLAtom;
|
||||
static nsIAtom* kValueAtom;
|
||||
|
||||
static nsIAtom* kXBLTextAtom;
|
||||
static nsIAtom* kImplementationAtom;
|
||||
static nsIAtom* kImplementsAtom;
|
||||
|
||||
static nsFixedSizeAllocator kPool;
|
||||
|
||||
// Internal member functions
|
||||
@ -112,8 +119,33 @@ protected:
|
||||
void ConstructHandlers();
|
||||
void ConstructAttributeTable(nsIContent* aElement);
|
||||
void ConstructInsertionTable(nsIContent* aElement);
|
||||
void ConstructInterfaceTable(nsIContent* aElement);
|
||||
void GetNestedChildren(nsIAtom* aTag, nsIContent* aContent, nsISupportsArray** aList);
|
||||
|
||||
protected:
|
||||
// Internal helper class for managing our IID table.
|
||||
class nsIIDKey : public nsHashKey {
|
||||
protected:
|
||||
nsIID mKey;
|
||||
|
||||
public:
|
||||
nsIIDKey(REFNSIID key) : mKey(key) {}
|
||||
~nsIIDKey(void) {}
|
||||
|
||||
PRUint32 HashCode(void) const {
|
||||
// Just use the 32-bit m0 field.
|
||||
return mKey.m0;
|
||||
}
|
||||
|
||||
PRBool Equals(const nsHashKey *aKey) const {
|
||||
return mKey.Equals( ((nsIIDKey*) aKey)->mKey);
|
||||
}
|
||||
|
||||
nsHashKey *Clone(void) const {
|
||||
return new nsIIDKey(mKey);
|
||||
}
|
||||
};
|
||||
|
||||
// MEMBER VARIABLES
|
||||
protected:
|
||||
nsCString mID;
|
||||
@ -134,6 +166,8 @@ protected:
|
||||
nsSupportsHashtable* mInsertionPointTable; // A table of insertion points for placing explicit content
|
||||
// underneath anonymous content.
|
||||
|
||||
nsSupportsHashtable* mInterfaceTable; // A table of cached interfaces that we support.
|
||||
|
||||
PRInt32 mBaseNameSpaceID; // If we extend a tagname/namespace, then that information will
|
||||
nsCOMPtr<nsIAtom> mBaseTag; // be stored in here.
|
||||
};
|
||||
|
@ -502,6 +502,7 @@ JSCList nsXBLService::gClassLRUList = JS_INIT_STATIC_CLIST(&nsXBLService::gClas
|
||||
PRUint32 nsXBLService::gClassLRUListLength = 0;
|
||||
PRUint32 nsXBLService::gClassLRUListQuota = 64;
|
||||
|
||||
nsIAtom* nsXBLService::kDisplayAtom = nsnull;
|
||||
nsIAtom* nsXBLService::kExtendsAtom = nsnull;
|
||||
nsIAtom* nsXBLService::kEventAtom = nsnull;
|
||||
nsIAtom* nsXBLService::kScrollbarAtom = nsnull;
|
||||
@ -542,6 +543,7 @@ nsXBLService::nsXBLService(void)
|
||||
if (NS_FAILED(rv)) return;
|
||||
|
||||
// Create our atoms
|
||||
kDisplayAtom = NS_NewAtom("display");
|
||||
kExtendsAtom = NS_NewAtom("extends");
|
||||
kEventAtom = NS_NewAtom("event");
|
||||
kScrollbarAtom = NS_NewAtom("scrollbar");
|
||||
@ -573,6 +575,7 @@ nsXBLService::~nsXBLService(void)
|
||||
NS_IF_RELEASE(gNameSpaceManager);
|
||||
|
||||
// Release our atoms
|
||||
NS_RELEASE(kDisplayAtom);
|
||||
NS_RELEASE(kExtendsAtom);
|
||||
NS_RELEASE(kEventAtom);
|
||||
NS_RELEASE(kScrollbarAtom);
|
||||
@ -1027,51 +1030,72 @@ NS_IMETHODIMP nsXBLService::GetBindingInternal(nsIContent* aBoundElement,
|
||||
}
|
||||
}
|
||||
else if (hasBase) {
|
||||
// Check for the presence of an extends attribute
|
||||
nsAutoString extends;
|
||||
// Check for the presence of a 'extends' and 'display' attributes
|
||||
nsAutoString display, extends;
|
||||
child->GetAttribute(kNameSpaceID_None, kDisplayAtom, display);
|
||||
child->GetAttribute(kNameSpaceID_None, kExtendsAtom, extends);
|
||||
PRBool hasDisplay = !display.IsEmpty();
|
||||
PRBool hasExtends = !extends.IsEmpty();
|
||||
|
||||
nsAutoString value(extends);
|
||||
if (extends.IsEmpty())
|
||||
|
||||
PRBool prefixIsDisplay = PR_FALSE;
|
||||
|
||||
if (!hasDisplay && !hasExtends)
|
||||
protoBinding->SetHasBasePrototype(PR_FALSE);
|
||||
else {
|
||||
nsAutoString prefix;
|
||||
PRInt32 offset = extends.FindChar(':');
|
||||
if (-1 != offset) {
|
||||
extends.Left(prefix, offset);
|
||||
extends.Cut(0, offset+1);
|
||||
PRInt32 offset;
|
||||
if (hasDisplay) {
|
||||
prefixIsDisplay = PR_TRUE;
|
||||
offset = display.FindChar(':');
|
||||
if (-1 != offset) {
|
||||
display.Left(prefix, offset);
|
||||
display.Cut(0, offset+1);
|
||||
}
|
||||
}
|
||||
else if (hasExtends) {
|
||||
offset = extends.FindChar(':');
|
||||
if (-1 != offset) {
|
||||
extends.Left(prefix, offset);
|
||||
extends.Cut(0, offset+1);
|
||||
display = extends;
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsINameSpace> tagSpace;
|
||||
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 extend some widget/frame. We don't really have a base binding.
|
||||
protoBinding->SetHasBasePrototype(PR_FALSE);
|
||||
PRInt32 nameSpaceID;
|
||||
tagSpace->GetNameSpaceID(nameSpaceID);
|
||||
nsCOMPtr<nsIAtom> tagName = getter_AddRefs(NS_NewAtom(extends));
|
||||
nsCOMPtr<nsIAtom> tagName = getter_AddRefs(NS_NewAtom(display));
|
||||
protoBinding->SetBaseTag(nameSpaceID, tagName);
|
||||
}
|
||||
else {
|
||||
// We have a base class binding. Load it right now.
|
||||
nsCAutoString urlCString; urlCString.AssignWithConversion(value);
|
||||
if (NS_FAILED(GetBindingInternal(aBoundElement, urlCString, aPeekOnly, aIsReady, getter_AddRefs(baseBinding))))
|
||||
return NS_ERROR_FAILURE; // Binding not yet ready or an error occurred.
|
||||
if (!aPeekOnly) {
|
||||
// Make sure to set the base prototype.
|
||||
baseBinding->GetPrototypeBinding(getter_AddRefs(baseProto));
|
||||
protoBinding->SetBasePrototype(baseProto);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hasExtends && (hasDisplay || (!hasDisplay && !tagSpace))) {
|
||||
// Look up the prefix.
|
||||
// We have a base class binding. Load it right now.
|
||||
nsCAutoString urlCString; urlCString.AssignWithConversion(value);
|
||||
if (NS_FAILED(GetBindingInternal(aBoundElement, urlCString, aPeekOnly, aIsReady, getter_AddRefs(baseBinding))))
|
||||
return NS_ERROR_FAILURE; // Binding not yet ready or an error occurred.
|
||||
if (!aPeekOnly) {
|
||||
// Make sure to set the base prototype.
|
||||
baseBinding->GetPrototypeBinding(getter_AddRefs(baseProto));
|
||||
protoBinding->SetBasePrototype(baseProto);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -128,6 +128,7 @@ public:
|
||||
static PRUint32 gClassLRUListQuota; // Quota on class LRU list.
|
||||
|
||||
// XBL Atoms
|
||||
static nsIAtom* kDisplayAtom;
|
||||
static nsIAtom* kExtendsAtom;
|
||||
static nsIAtom* kEventAtom;
|
||||
static nsIAtom* kScrollbarAtom;
|
||||
|
Loading…
x
Reference in New Issue
Block a user