Fix for 80147, use XUL prototype elements in anonymous content of XBL. r=dbaron, sr=jst

This commit is contained in:
hyatt%netscape.com 2001-11-03 10:12:20 +00:00
Родитель b1b833578d
Коммит 0d3a2fa6bf
9 изменённых файлов: 194 добавлений и 30 удалений

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

@ -34,6 +34,7 @@ REQUIRES = xpcom \
dom \
gfx \
layout \
layout_xul \
widget \
view \
caps \
@ -42,11 +43,13 @@ REQUIRES = xpcom \
xpconnect \
pref \
docshell \
webshell \
chrome \
lwbrk \
xul \
xuldoc \
gfx2 \
rdf \
imglib2 \
unicharutil \
$(NULL)
@ -94,5 +97,6 @@ LOCAL_INCLUDES = \
-I$(srcdir)/../../html/document/src \
-I$(srcdir)/../../xml/document/src \
-I$(srcdir)/../../xsl/document/src \
-I$(srcdir)/../../xul/content/src \
$(NULL)

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

@ -30,17 +30,20 @@ REQUIRES = xpcom \
widget \
view \
caps \
layout_xul \
htmlparser \
necko \
xpconnect \
pref \
docshell \
webshell \
chrome \
lwbrk \
gfx2 \
imglib2 \
layout \
gfx \
rdf \
content_xul \
unicharutil \
$(NULL)
@ -108,6 +111,7 @@ LINCS=-I..\..\html\style\src -I..\..\html\base\src \
-I..\..\html\document\src \
-I..\..\xml\document\src \
-I..\..\xsl\document\src \
-I..\..\xul\content\src \
-I..\..\base\src \
$(NULL)

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

@ -20,6 +20,7 @@
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* David Hyatt <hyatt@netscape.com> (Original Author)
*
*
* Alternatively, the contents of this file may be used under the terms of
@ -48,6 +49,10 @@
#include "nsHTMLTokens.h"
#include "nsIURI.h"
#include "nsTextFragment.h"
#include "nsXULElement.h"
#include "nsXULAtoms.h"
static NS_DEFINE_CID(kCSSParserCID, NS_CSSPARSER_CID);
nsresult
NS_NewXBLContentSink(nsIXMLContentSink** aResult,
@ -250,6 +255,130 @@ nsXBLContentSink::AddLeaf(const nsIParserNode& aNode)
return nsXMLContentSink::AddLeaf(aNode);
}
nsresult
nsXBLContentSink::AddAttributesToXULPrototype(const nsIParserNode& aNode, nsXULPrototypeElement* aElement)
{
// Add tag attributes to the element
nsresult rv;
PRInt32 count = aNode.GetAttributeCount();
// Create storage for the attributes
nsXULPrototypeAttribute* attrs = nsnull;
if (count > 0) {
attrs = new nsXULPrototypeAttribute[count];
if (!attrs)
return NS_ERROR_OUT_OF_MEMORY;
}
aElement->mAttributes = attrs;
aElement->mNumAttributes = count;
// Copy the attributes into the prototype
nsCOMPtr<nsIAtom> nameSpacePrefix, nameAtom;
for (PRInt32 i = 0; i < count; i++) {
const nsAReadableString& key = aNode.GetKeyAt(i);
SplitXMLName(key, getter_AddRefs(nameSpacePrefix),
getter_AddRefs(nameAtom));
PRInt32 nameSpaceID;
if (nameSpacePrefix)
nameSpaceID = GetNameSpaceId(nameSpacePrefix);
else {
if (nameAtom == nsLayoutAtoms::xmlnsNameSpace)
nameSpaceID = kNameSpaceID_XMLNS;
else
nameSpaceID = kNameSpaceID_None;
}
if (kNameSpaceID_Unknown == nameSpaceID) {
nameSpaceID = kNameSpaceID_None;
nameAtom = dont_AddRef(NS_NewAtom(key));
nameSpacePrefix = nsnull;
}
mNodeInfoManager->GetNodeInfo(nameAtom, nameSpacePrefix, nameSpaceID,
*getter_AddRefs(attrs->mNodeInfo));
const nsAReadableString& valueStr = aNode.GetValueAt(i);
attrs->mValue.SetValue(valueStr);
++attrs;
}
// XUL elements may require some additional work to compute
// derived information.
if (aElement->mNodeInfo->NamespaceEquals(nsXULAtoms::nameSpaceID)) {
nsAutoString value;
// Compute the element's class list if the element has a 'class' attribute.
rv = aElement->GetAttr(kNameSpaceID_None, nsXULAtoms::clazz, value);
if (NS_FAILED(rv)) return rv;
if (rv == NS_CONTENT_ATTR_HAS_VALUE) {
rv = nsClassList::ParseClasses(&aElement->mClassList, value);
if (NS_FAILED(rv)) return rv;
}
// Parse the element's 'style' attribute
rv = aElement->GetAttr(kNameSpaceID_None, nsHTMLAtoms::style, value);
if (NS_FAILED(rv)) return rv;
if (rv == NS_CONTENT_ATTR_HAS_VALUE) {
if (!mCSSParser) {
rv = nsComponentManager::CreateInstance(kCSSParserCID,
nsnull,
NS_GET_IID(nsICSSParser),
getter_AddRefs(mCSSParser));
if (NS_FAILED(rv)) return rv;
}
rv = mCSSParser->ParseStyleAttribute(value, mDocumentURL,
getter_AddRefs(aElement->mInlineStyleRule));
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to parse style rule");
if (NS_FAILED(rv)) return rv;
}
}
return NS_OK;
}
nsresult
nsXBLContentSink::CreateElement(const nsIParserNode& aNode, PRInt32 aNameSpaceID,
nsINodeInfo* aNodeInfo, nsIContent** aResult)
{
if (aNameSpaceID == nsXULAtoms::nameSpaceID) {
nsXULPrototypeElement* prototype = new nsXULPrototypeElement(0);
if (!prototype)
return NS_ERROR_OUT_OF_MEMORY;
prototype->mType = nsXULPrototypeNode::eType_RefCounted_Element;
prototype->mNodeInfo = aNodeInfo;
AddAttributesToXULPrototype(aNode, prototype);
nsresult rv = nsXULElement::Create(prototype, mDocument, PR_TRUE, aResult);
if (NS_FAILED(rv)) return rv;
return NS_OK;
}
else
return nsXMLContentSink::CreateElement(aNode, aNameSpaceID, aNodeInfo, aResult);
}
nsresult
nsXBLContentSink::AddAttributes(const nsIParserNode& aNode,
nsIContent* aContent,
PRBool aIsHTML)
{
if (aContent->IsContentOfType(nsIContent::eXUL))
return NS_OK; // Nothing to do, since the proto already has the attrs.
else
return nsXMLContentSink::AddAttributes(aNode, aContent, aIsHTML);
}
void
nsXBLContentSink::ConstructBinding()
{
@ -288,7 +417,7 @@ nsXBLContentSink::ConstructHandler(const nsIParserNode& aNode)
SplitXMLName(key, getter_AddRefs(nameSpacePrefix),
getter_AddRefs(nameAtom));
if (nameSpacePrefix || nameAtom.get() == nsLayoutAtoms::xmlnsNameSpace)
if (nameSpacePrefix || nameAtom == nsLayoutAtoms::xmlnsNameSpace)
continue;
// Is this attribute one of the ones we care about?

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

@ -43,6 +43,8 @@
#include "nsXBLDocumentInfo.h"
#include "nsIXBLPrototypeBinding.h"
#include "nsIXBLPrototypeHandler.h"
#include "nsICSSParser.h"
#include "nsLayoutCID.h"
typedef enum {
eXBL_InDocument,
@ -63,6 +65,8 @@ typedef enum {
eXBL_InSetter
} XBLSecondaryState;
class nsXULPrototypeElement;
// The XBL content sink overrides the XML content sink to
// builds its own lightweight data structures for the <resources>,
// <handlers>, <implementation>, and
@ -86,10 +90,16 @@ protected:
PRBool OnOpenContainer(const nsIParserNode& aNode, PRInt32 aNameSpaceID, nsIAtom* aTagName);
nsresult FlushText(PRBool aCreateTextNode=PR_TRUE,
PRBool* aDidFlush=nsnull);
nsresult CreateElement(const nsIParserNode& aNode, PRInt32 aNameSpaceID,
nsINodeInfo* aNodeInfo, nsIContent** aResult);
nsresult AddAttributes(const nsIParserNode& aNode,
nsIContent* aContent,
PRBool aIsHTML);
// Our own helpers for constructing XBL prototype objects.
void ConstructBinding();
void ConstructHandler(const nsIParserNode& aNode);
nsresult AddAttributesToXULPrototype(const nsIParserNode& aNode, nsXULPrototypeElement* aElement);
protected:
XBLPrimaryState mState;
@ -97,6 +107,8 @@ protected:
nsIXBLDocumentInfo* mDocInfo;
PRBool mIsChromeOrResource; // For bug #45989
nsCOMPtr<nsICSSParser> mCSSParser; // [OWNER]
nsCOMPtr<nsIXBLPrototypeBinding> mBinding;
nsCOMPtr<nsIXBLPrototypeHandler> mHandler;
};

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

@ -743,24 +743,8 @@ nsXMLContentSink::OpenContainer(const nsIParserNode& aNode)
}
}
}
else {
// The first step here is to see if someone has provided their
// own content element implementation (e.g., XUL or MathML).
// This is done based off a contractid/namespace scheme.
nsCOMPtr<nsIElementFactory> elementFactory;
GetElementFactory(nameSpaceID, getter_AddRefs(elementFactory));
if (elementFactory) {
// Create the content element using the element factory.
elementFactory->CreateInstanceByTag(nodeInfo, getter_AddRefs(content));
}
else {
nsCOMPtr<nsIXMLContent> xmlContent;
result = NS_NewXMLElement(getter_AddRefs(xmlContent), nodeInfo);
content = do_QueryInterface(xmlContent);
}
}
else
CreateElement(aNode, nameSpaceID, nodeInfo, getter_AddRefs(content));
if (NS_OK == result) {
PRInt32 id;
@ -823,6 +807,27 @@ nsXMLContentSink::OpenContainer(const nsIParserNode& aNode)
return result;
}
nsresult
nsXMLContentSink::CreateElement(const nsIParserNode& aNode, PRInt32 aNameSpaceID,
nsINodeInfo* aNodeInfo, nsIContent** aResult)
{
// The first step here is to see if someone has provided their
// own content element implementation (e.g., XUL or MathML).
// This is done based off a contractid/namespace scheme.
nsCOMPtr<nsIElementFactory> elementFactory;
GetElementFactory(aNameSpaceID, getter_AddRefs(elementFactory));
if (elementFactory)
// Create the content element using the element factory.
elementFactory->CreateInstanceByTag(aNodeInfo, aResult);
else {
nsCOMPtr<nsIXMLContent> xmlContent;
NS_NewXMLElement(getter_AddRefs(xmlContent), aNodeInfo);
return CallQueryInterface(xmlContent, aResult);
}
return NS_OK;
}
NS_IMETHODIMP
nsXMLContentSink::CloseContainer(const nsIParserNode& aNode)
{

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

@ -135,10 +135,12 @@ protected:
virtual nsresult FlushText(PRBool aCreateTextNode=PR_TRUE,
PRBool* aDidFlush=nsnull);
nsresult AddAttributes(const nsIParserNode& aNode,
nsIContent* aContent,
PRBool aIsHTML);
virtual nsresult AddAttributes(const nsIParserNode& aNode,
nsIContent* aContent,
PRBool aIsHTML);
nsresult AddContentAsLeaf(nsIContent *aContent);
virtual nsresult CreateElement(const nsIParserNode& aNode, PRInt32 aNameSpaceID,
nsINodeInfo* aNodeInfo, nsIContent** aResult);
nsresult PushNameSpacesFrom(const nsIParserNode& aNode);
static void SplitXMLName(nsAReadableString& aString, nsIAtom **aPrefix,
nsIAtom **aTagName);

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

@ -515,6 +515,12 @@ nsXULElement::Init()
nsXULElement::~nsXULElement()
{
if (mPrototype && mPrototype->mType == nsXULPrototypeNode::eType_RefCounted_Element) {
mPrototype->mRefCnt--;
if (mPrototype->mRefCnt == 0)
delete mPrototype;
}
delete mSlots;
//NS_IF_RELEASE(mDocument); // not refcounted
@ -553,10 +559,6 @@ nsXULElement::Create(nsXULPrototypeElement* aPrototype,
if (! aPrototype)
return NS_ERROR_NULL_POINTER;
NS_PRECONDITION(aDocument != nsnull, "null ptr");
if (! aDocument)
return NS_ERROR_NULL_POINTER;
NS_PRECONDITION(aResult != nsnull, "null ptr");
if (! aResult)
return NS_ERROR_NULL_POINTER;
@ -576,6 +578,9 @@ nsXULElement::Create(nsXULPrototypeElement* aPrototype,
element->mPrototype = aPrototype;
element->mDocument = aDocument;
if (aPrototype->mType == nsXULPrototypeNode::eType_RefCounted_Element)
aPrototype->mRefCnt++;
if (aIsScriptable) {
// Check each attribute on the prototype to see if we need to do
// any additional processing and hookup that would otherwise be

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

@ -186,10 +186,14 @@ public:
class nsXULPrototypeNode
{
public:
enum Type { eType_Element, eType_Script, eType_Text };
enum Type { eType_Element, eType_RefCounted_Element, eType_Script, eType_Text };
Type mType;
PRInt32 mLineNo;
union {
PRInt32 mLineNo;
PRInt32 mRefCnt;
};
virtual ~nsXULPrototypeNode() {}
virtual nsresult Serialize(nsIObjectOutputStream* aStream,

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

@ -1253,8 +1253,7 @@ XULContentSinkImpl::AddAttributes(const nsIParserNode& aNode, nsXULPrototypeElem
continue;
}
nsAutoString valueStr;
valueStr = aNode.GetValueAt(i);
const nsAReadableString& valueStr = aNode.GetValueAt(i);
attrs->mValue.SetValue( valueStr );