/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * (C) Copyright The MITRE Corporation 1999 All rights reserved. * * The contents of this file are subject to the Mozilla Public License * Version 1.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * The program provided "as is" without any warranty express or * implied, including the warranty of non-infringement and the implied * warranties of merchantibility and fitness for a particular purpose. * The Copyright owner will not be liable for any damages suffered by * you as a result of using the Program. In no event will the Copyright * owner be liable for any special, indirect or consequential damages or * lost profits even if the Copyright owner has been advised of the * possibility of their occurrence. * * Please see release.txt distributed with this file for more information. * * Contributor(s): Tom Kneeland * Peter Van der Beken * */ /* Implementation of the wrapper class to convert the Mozilla nsIDOMDocument interface into a TransforMIIX Document interface. */ #include "mozilladom.h" #include "nsLayoutCID.h" #include "nsIURL.h" static NS_DEFINE_CID(kIDOMDOMImplementationCID, NS_DOM_IMPLEMENTATION_CID); PR_STATIC_CALLBACK(PRBool) DeleteWrapper(nsHashKey *aKey, void *aData, void* closure) { delete (MozillaObjectWrapper*)aData; return PR_TRUE; } /** * Construct a new Mozilla document and wrap it. The caller is responsible for * deleting the wrapper object! */ Document::Document() : Node(0, 0) { nsresult res; nsCOMPtr document; nsCOMPtr implementation = do_CreateInstance(kIDOMDOMImplementationCID, &res); //if (NS_FAILED(res)) return NULL; // Create an empty document from it nsAutoString emptyStr; res = implementation->CreateDocument(emptyStr, emptyStr, nsnull, getter_AddRefs(document)); //if (NS_FAILED(res)) return NULL; ownerDocument = this; wrapperHashTable = new nsObjectHashtable(nsnull, nsnull, DeleteWrapper, nsnull); #ifdef DEBUG bInHashTableDeletion = PR_FALSE; #endif nsCOMPtr doc(do_QueryInterface(document)); NS_ASSERTION(doc,"document doesn't implement nsIDocument"); if (doc) { doc->GetNameSpaceManager(*getter_AddRefs(nsNSManager)); NS_ASSERTION(nsNSManager, "Unable to get nsINamespaceManager"); } addWrapper(this); } /** * Construct a wrapper with the specified Mozilla object. The caller is * responsible for deleting the wrapper object! * * @param aDocument the nsIDOMDocument you want to wrap */ Document::Document(nsIDOMDocument* aDocument) : Node(aDocument, 0) { ownerDocument = this; wrapperHashTable = new nsObjectHashtable(nsnull, nsnull, DeleteWrapper, nsnull); #ifdef DEBUG bInHashTableDeletion = PR_FALSE; #endif nsCOMPtr doc(do_QueryInterface(aDocument)); NS_ASSERTION(doc,"document doesn't implement nsIDocument"); if (doc) { doc->GetNameSpaceManager(*getter_AddRefs(nsNSManager)); NS_ASSERTION(nsNSManager, "Unable to get nsINamespaceManager"); } addWrapper(this); } /** * Destructor */ Document::~Document() { removeWrapper(this); #ifdef DEBUG bInHashTableDeletion = PR_TRUE; #endif delete wrapperHashTable; } /** * Call nsIDOMDocument::GetDocumentElement to get the document's * DocumentElement. * * @return the document element */ Element* Document::getDocumentElement() { NSI_FROM_TX_NULL_CHECK(Document) nsCOMPtr theElement; if (NS_SUCCEEDED(nsDocument->GetDocumentElement( getter_AddRefs(theElement)))) return (Element*)createWrapper(theElement); else return NULL; } /** * Call nsIDOMDocument::GetDoctype to get the document's DocumentType. * * @return the DocumentType */ DocumentType* Document::getDoctype() { NSI_FROM_TX_NULL_CHECK(Document) nsCOMPtr theDocType; if (NS_SUCCEEDED(nsDocument->GetDoctype(getter_AddRefs(theDocType)))) return (DocumentType*)createWrapper(theDocType); else return NULL; } /** * Call nsIDOMDocument::GetImplementation to get the document's * DOMImplementation. * * @return the DOMImplementation */ DOMImplementation* Document::getImplementation() { NSI_FROM_TX_NULL_CHECK(Document) nsCOMPtr theImpl; if (NS_SUCCEEDED(nsDocument->GetImplementation(getter_AddRefs(theImpl)))) return createDOMImplementation(theImpl); else return NULL; } /** * Call nsIDOMDocument::CreateDocumentFragment to create a DocumentFragment. * * @return the DocumentFragment */ DocumentFragment* Document::createDocumentFragment() { NSI_FROM_TX_NULL_CHECK(Document) nsCOMPtr fragment; if (NS_SUCCEEDED(nsDocument->CreateDocumentFragment( getter_AddRefs(fragment)))) return createDocumentFragment(fragment); else return NULL; } /** * Create a wrapper for a nsIDOMDocumentFragment, reuses an existing wrapper if * possible. * * @param aFragment the nsIDOMDocumentFragment you want to wrap * * @return the DocumentFragment */ IMPL_CREATE_WRAPPER(DocumentFragment) /** * Call nsIDOMDocument::CreateElement to create an Element. * * @param aTagName the name of the element you want to create * * @return the Element */ Element* Document::createElement(const String& aTagName) { NSI_FROM_TX_NULL_CHECK(Document) nsCOMPtr element; if (NS_SUCCEEDED(nsDocument->CreateElement(aTagName.getConstNSString(), getter_AddRefs(element)))) return createElement(element); else return NULL; } /** * Call nsIDOMDocument::GetElementById to get Element with ID. * * @param aID the name of ID referencing the element * * @return the Element */ Element* Document::getElementById(const String aID) { NSI_FROM_TX_NULL_CHECK(Document) nsCOMPtr element; if (NS_SUCCEEDED(nsDocument->GetElementById(aID.getConstNSString(), getter_AddRefs(element)))) return createElement(element); else return NULL; } /** * Create a wrapper for a nsIDOMElement, reuses an existing wrapper if possible. * * @param aElement the nsIDOMElement you want to wrap * * @return the Element */ IMPL_CREATE_WRAPPER(Element) /** * Call nsIDOMDocument::CreateElementNS to create an Element. * * @param aNamespaceURI the URI of the namespace for the element * @param aTagName the name of the element you want to create * * @return the Element */ Element* Document::createElementNS(const String& aNamespaceURI, const String& aTagName) { NSI_FROM_TX_NULL_CHECK(Document) nsCOMPtr element; if (NS_SUCCEEDED(nsDocument->CreateElementNS( aNamespaceURI.getConstNSString(), aTagName.getConstNSString(), getter_AddRefs(element)))) return createElement(element); else return NULL; } /** * Call nsIDOMDocument::CreateAttribute to create an Attribute. * * @param aName the name of the attribute you want to create * * @return the Attribute */ Attr* Document::createAttribute(const String& aName) { NSI_FROM_TX_NULL_CHECK(Document) nsCOMPtr attr; if (NS_SUCCEEDED(nsDocument->CreateAttribute(aName.getConstNSString(), getter_AddRefs(attr)))) return createAttribute(attr); else return NULL; } /** * Call nsIDOMDocument::CreateAttributeNS to create an Attribute. * * @param aNamespaceURI the URI of the namespace for the element * @param aName the name of the attribute you want to create * * @return the Attribute */ Attr* Document::createAttributeNS(const String& aNamespaceURI, const String& aName) { NSI_FROM_TX_NULL_CHECK(Document) nsCOMPtr attr; if (NS_SUCCEEDED(nsDocument->CreateAttributeNS( aNamespaceURI.getConstNSString(), aName.getConstNSString(), getter_AddRefs(attr)))) return createAttribute(attr); else return NULL; } /** * Create a wrapper for a nsIDOMAttr, reuses an existing wrapper if possible. * * @param aAttr the nsIDOMAttr you want to wrap * * @return the Attribute */ IMPL_CREATE_WRAPPER2(Attr, createAttribute) /** * Call nsIDOMDocument::CreateTextNode to create a Text node. * * @param aData the data of the text node you want to create * * @return the Text node */ Text* Document::createTextNode(const String& aData) { NSI_FROM_TX_NULL_CHECK(Document) nsCOMPtr text; if (NS_SUCCEEDED(nsDocument->CreateTextNode(aData.getConstNSString(), getter_AddRefs(text)))) return createTextNode(text); else return NULL; } /** * Create a wrapper for a nsIDOMText, reuses an existing wrapper if possible. * * @param aText the nsIDOMText you want to wrap * * @return the Text node */ IMPL_CREATE_WRAPPER2(Text, createTextNode) /** * Call nsIDOMDocument::CreateComment to create a Comment node. * * @param aData the data of the comment node you want to create * * @return the Comment node */ Comment* Document::createComment(const String& aData) { NSI_FROM_TX_NULL_CHECK(Document) nsCOMPtr comment; if (NS_SUCCEEDED(nsDocument->CreateComment(aData.getConstNSString(), getter_AddRefs(comment)))) return createComment(comment); else return NULL; } /** * Create a wrapper for a nsIDOMComment, reuses an existing wrapper if possible. * * @param aComment the nsIDOMComment you want to wrap * * @return the Comment node */ IMPL_CREATE_WRAPPER(Comment) /** * Call nsIDOMDocument::CreateCDATASection to create a CDataSection. * * @param aData the data of the CDataSection you want to create * * @return the CDataSection node */ CDATASection* Document::createCDATASection(const String& aData) { NSI_FROM_TX_NULL_CHECK(Document) nsCOMPtr cdata; if (NS_SUCCEEDED(nsDocument->CreateCDATASection(aData.getConstNSString(), getter_AddRefs(cdata)))) return createCDATASection(cdata); else return NULL; } /** * Create a wrapper for a nsIDOMCDATASection, reuses an existing wrapper if * possible. * * @param aCdata the nsIDOMCDATASection you want to wrap * * @return the CDATASection node */ IMPL_CREATE_WRAPPER(CDATASection) /** * Call nsIDOMDocument::CreateProcessingInstruction to create a * ProcessingInstruction. * * @param aTarget the target of the ProcessingInstruction you want to create * @param aData the data of the ProcessingInstruction you want to create * * @return the ProcessingInstruction node */ ProcessingInstruction* Document::createProcessingInstruction( const String& aTarget, const String& aData) { NSI_FROM_TX_NULL_CHECK(Document) nsCOMPtr pi; if (NS_SUCCEEDED(nsDocument->CreateProcessingInstruction( aTarget.getConstNSString(), aData.getConstNSString(), getter_AddRefs(pi)))) return createProcessingInstruction(pi); else return NULL; } /** * Create a wrapper for a nsIDOMProcessingInstruction, reuses an existing * wrapper if possible. * * @param aPi the nsIDOMProcessingInstruction you want to wrap * * @return the ProcessingInstruction node */ IMPL_CREATE_WRAPPER(ProcessingInstruction) /** * Call nsIDOMDocument::CreateEntityReference to create a EntityReference. * * @param aName the name of the EntityReference you want to create * * @return the EntityReference */ EntityReference* Document::createEntityReference(const String& aName) { NSI_FROM_TX_NULL_CHECK(Document) nsCOMPtr entityRef; if (NS_SUCCEEDED(nsDocument->CreateEntityReference(aName.getConstNSString(), getter_AddRefs(entityRef)))) return createEntityReference(entityRef); else return NULL; } /** * Create a wrapper for a nsIDOMEntityReference, reuses an existing * wrapper if possible. * * @param aEntityRef the nsIDOMEntityReference you want to wrap * * @return the EntityReference */ IMPL_CREATE_WRAPPER(EntityReference) /** * Create a wrapper for a nsIDOMEntity, reuses an existing wrapper if possible. * * @param aEntity the nsIDOMEntity you want to wrap * * @return the Entity */ IMPL_CREATE_WRAPPER(Entity) /** * Create a wrapper for a nsIDOMNode, reuses an existing wrapper if possible. * * @param aNode the nsIDOMNode you want to wrap * * @return the Node */ IMPL_CREATE_WRAPPER(Node) /** * Create a wrapper for a nsIDOMNotation, reuses an existing wrapper if * possible. * * @param aNotation the nsIDOMNotation you want to wrap * * @return the Notation */ IMPL_CREATE_WRAPPER(Notation) /** * Create a wrapper for a nsIDOMDOMImplementation, reuses an existing wrapper if * possible. * * @param aImpl the nsIDOMDOMImplementation you want to wrap * * @return the DOMImplementation */ IMPL_CREATE_WRAPPER(DOMImplementation) /** * Create a wrapper for a nsIDOMDocumentType, reuses an existing wrapper if * possible. * * @param aDoctype the nsIDOMDocumentType you want to wrap * * @return the DocumentType */ IMPL_CREATE_WRAPPER(DocumentType) /** * Create a wrapper for a nsIDOMNodeList, reuses an existing wrapper if * possible. * * @param aList the nsIDOMNodeList you want to wrap * * @return the NodeList */ IMPL_CREATE_WRAPPER(NodeList) /** * Create a wrapper for a nsIDOMNamedNodeMap, reuses an existing wrapper if * possible. * * @param aMap the nsIDOMNamedNodeMap you want to wrap * * @return the NamedNodeMap */ IMPL_CREATE_WRAPPER(NamedNodeMap) /** * Create a wrapper for a nsIDOMNode, reuses an existing wrapper if possible. * This function creates the right kind of wrapper depending on the type of * the node. * * @param aNode the nsIDOMNode you want to wrap * * @return the Node */ Node* Document::createWrapper(nsIDOMNode* aNode) { unsigned short nodeType = 0; if (!aNode) return NULL; aNode->GetNodeType(&nodeType); switch (nodeType) { case nsIDOMNode::ELEMENT_NODE: return createElement((nsIDOMElement*)aNode); break; case nsIDOMNode::ATTRIBUTE_NODE: return createAttribute((nsIDOMAttr*)aNode); break; case nsIDOMNode::TEXT_NODE: return createTextNode((nsIDOMText*)aNode); break; case nsIDOMNode::CDATA_SECTION_NODE: return createCDATASection((nsIDOMCDATASection*)aNode); break; case nsIDOMNode::ENTITY_REFERENCE_NODE: return createEntityReference((nsIDOMEntityReference*)aNode); break; case nsIDOMNode::ENTITY_NODE: return createEntity((nsIDOMEntity*)aNode); break; case nsIDOMNode::PROCESSING_INSTRUCTION_NODE: return createProcessingInstruction( (nsIDOMProcessingInstruction*)aNode); break; case nsIDOMNode::COMMENT_NODE: return createComment((nsIDOMComment*)aNode); break; case nsIDOMNode::DOCUMENT_NODE: if (aNode == getNSObj()) return this; else { // XXX (pvdb) We need a createDocument here! return createNode(aNode); } break; case nsIDOMNode::DOCUMENT_TYPE_NODE: return createDocumentType((nsIDOMDocumentType*)aNode); break; case nsIDOMNode::DOCUMENT_FRAGMENT_NODE: return createDocumentFragment((nsIDOMDocumentFragment*)aNode); break; case nsIDOMNode::NOTATION_NODE: return createNotation((nsIDOMNotation*)aNode); break; default: return createNode(aNode); } } /** * Add a wrapper to the document's hash table using the specified hash value. * * @param aObj the TxObject you want to add * @param aHashValue the key for the object in the hash table */ void Document::addWrapper(MozillaObjectWrapper* aObject) { nsISupportsKey key(aObject->getNSObj()); wrapperHashTable->Put(&key, aObject); } /** * Remove a wrapper from the document's hash table and return it to the caller. * * @param aHashValue the key for the object you want to remove * * @return the wrapper as a TxObject */ TxObject* Document::removeWrapper(nsISupports* aMozillaObject) { nsISupportsKey key(aMozillaObject); return (TxObject*)wrapperHashTable->Remove(&key); } /** * Remove a wrapper from the document's hash table and return it to the caller. * * @param aHashValue the key for the object you want to remove * * @return the wrapper as a TxObject */ TxObject* Document::removeWrapper(MozillaObjectWrapper* aObject) { nsISupportsKey key(aObject->getNSObj()); return (TxObject*)wrapperHashTable->Remove(&key); } PRInt32 Document::namespaceURIToID(const String& aNamespaceURI) { PRInt32 namesspaceID = kNameSpaceID_Unknown; if (nsNSManager) nsNSManager->RegisterNameSpace(aNamespaceURI.getConstNSString(), namesspaceID); return namesspaceID; } void Document::namespaceIDToURI(PRInt32 aNamespaceID, String& aNamespaceURI) { if (nsNSManager) nsNSManager->GetNameSpaceURI(aNamespaceID, aNamespaceURI.getNSString()); return; }