зеркало из https://github.com/mozilla/gecko-dev.git
Fix for 80147, use XUL prototype elements in anonymous content of XBL. r=dbaron, sr=jst
This commit is contained in:
Родитель
b1b833578d
Коммит
0d3a2fa6bf
|
@ -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 );
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче