Reviewed by Darin.
authormjs <mjs@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 2 Dec 2003 23:13:50 +0000 (23:13 +0000)
committermjs <mjs@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 2 Dec 2003 23:13:50 +0000 (23:13 +0000)
Implemented a simple form of document serialization, enough to take care of:

<rdar://problem/3487190>: implement send of DOMDocument for XMLHttpRequest

        * khtml/dom/dom_doc.cpp:
        (DOM::Document::toString):
        * khtml/dom/dom_doc.h:
        * khtml/ecma/xmlhttprequest.cpp:
        (KJS::XMLHttpRequest::urlMatchesDocumentDomain):
        (KJS::XMLHttpRequestProtoFunc::tryCall):
        * khtml/html/html_elementimpl.cpp:
        (HTMLElementImpl::toString):
        * khtml/html/html_elementimpl.h:
        * khtml/xml/dom_docimpl.cpp:
        (DocumentImpl::toString):
        (DocumentFragmentImpl::toString):
        (DocumentTypeImpl::copyFrom):
        (DocumentTypeImpl::toString):
        * khtml/xml/dom_docimpl.h:
        * khtml/xml/dom_elementimpl.cpp:
        (AttrImpl::toString):
        (ElementImpl::openTagStartToString):
        (ElementImpl::toString):
        * khtml/xml/dom_elementimpl.h:
        * khtml/xml/dom_nodeimpl.h:
        * khtml/xml/dom_textimpl.cpp:
        (CommentImpl::toString):
        (TextImpl::toString):
        (CDATASectionImpl::toString):
        * khtml/xml/dom_textimpl.h:
        * khtml/xml/dom_xmlimpl.cpp:
        (EntityImpl::toString):
        (EntityReferenceImpl::toString):
        (ProcessingInstructionImpl::setStyleSheet):
        (ProcessingInstructionImpl::toString):
        * khtml/xml/dom_xmlimpl.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@5656 268f45cc-cd09-0410-ab3c-d52691b4dbfc

15 files changed:
WebCore/ChangeLog-2005-08-23
WebCore/khtml/dom/dom_doc.cpp
WebCore/khtml/dom/dom_doc.h
WebCore/khtml/ecma/xmlhttprequest.cpp
WebCore/khtml/html/html_elementimpl.cpp
WebCore/khtml/html/html_elementimpl.h
WebCore/khtml/xml/dom_docimpl.cpp
WebCore/khtml/xml/dom_docimpl.h
WebCore/khtml/xml/dom_elementimpl.cpp
WebCore/khtml/xml/dom_elementimpl.h
WebCore/khtml/xml/dom_nodeimpl.h
WebCore/khtml/xml/dom_textimpl.cpp
WebCore/khtml/xml/dom_textimpl.h
WebCore/khtml/xml/dom_xmlimpl.cpp
WebCore/khtml/xml/dom_xmlimpl.h

index 3572e7a..c0e2bf0 100644 (file)
@@ -1,3 +1,44 @@
+2003-12-02  Maciej Stachowiak  <mjs@apple.com>
+
+        Reviewed by Darin.
+
+       Implemented a simple form of document serialization, enough to take care of:
+
+       <rdar://problem/3487190>: implement send of DOMDocument for XMLHttpRequest
+
+        * khtml/dom/dom_doc.cpp:
+        (DOM::Document::toString):
+        * khtml/dom/dom_doc.h:
+        * khtml/ecma/xmlhttprequest.cpp:
+        (KJS::XMLHttpRequest::urlMatchesDocumentDomain):
+        (KJS::XMLHttpRequestProtoFunc::tryCall):
+        * khtml/html/html_elementimpl.cpp:
+        (HTMLElementImpl::toString):
+        * khtml/html/html_elementimpl.h:
+        * khtml/xml/dom_docimpl.cpp:
+        (DocumentImpl::toString):
+        (DocumentFragmentImpl::toString):
+        (DocumentTypeImpl::copyFrom):
+        (DocumentTypeImpl::toString):
+        * khtml/xml/dom_docimpl.h:
+        * khtml/xml/dom_elementimpl.cpp:
+        (AttrImpl::toString):
+        (ElementImpl::openTagStartToString):
+        (ElementImpl::toString):
+        * khtml/xml/dom_elementimpl.h:
+        * khtml/xml/dom_nodeimpl.h:
+        * khtml/xml/dom_textimpl.cpp:
+        (CommentImpl::toString):
+        (TextImpl::toString):
+        (CDATASectionImpl::toString):
+        * khtml/xml/dom_textimpl.h:
+        * khtml/xml/dom_xmlimpl.cpp:
+        (EntityImpl::toString):
+        (EntityReferenceImpl::toString):
+        (ProcessingInstructionImpl::setStyleSheet):
+        (ProcessingInstructionImpl::toString):
+        * khtml/xml/dom_xmlimpl.h:
+
 2003-12-02  David Hyatt  <hyatt@apple.com>
 
        Fix for 3493677, containingBlock() null because we tried to support position:relative on table rows.  Fix
index 50342f9..431377b 100644 (file)
@@ -443,6 +443,15 @@ DOMString Document::completeURL(const DOMString& url)
     return static_cast<DocumentImpl*>( impl )->completeURL( url.string() );
 }
 
+DOMString Document::toString() const
+{
+    if (!impl)
+       throw DOMException(DOMException::NOT_FOUND_ERR);
+
+    return static_cast<DocumentImpl*>(impl)->toString();
+}
+
+
 CSSStyleDeclaration Document::getOverrideStyle(const Element &elt, const DOMString &pseudoElt)
 {
     if (!impl)
index bcc5d5e..f812a55 100644 (file)
@@ -787,6 +787,7 @@ public:
      */
     DOMString completeURL(const DOMString& url);
 
+    DOMString toString() const;
 protected:
     Document( DocumentImpl *i);
 
index 07ed74e..3552144 100644 (file)
@@ -23,6 +23,7 @@
 #include "kjs_window.h"
 #include "kjs_events.h"
 
+#include "dom/dom_exception.h"
 #include "dom/dom_string.h"
 #include "misc/loader.h"
 #include "html/html_documentimpl.h"
@@ -199,13 +200,13 @@ bool XMLHttpRequest::urlMatchesDocumentDomain(const KURL& _url) const
   KURL documentURL(doc->URL());
 
   // a local file can load anything
-  if (documentURL.protocol() != "file") {
+  if (documentURL.protocol().lower() == "file") {
     return true;
   }
 
   // but a remote document can only load from the same port on the server
-  if (documentURL.protocol() == _url.protocol() &&
-      documentURL.host() == _url.host() &&
+  if (documentURL.protocol().lower() == _url.protocol().lower() &&
+      documentURL.host().lower() == _url.host().lower() &&
       documentURL.port() == _url.port()) {
     return true;
   }
@@ -489,8 +490,19 @@ Value XMLHttpRequestProtoFunc::tryCall(ExecState *exec, Object &thisObj, const L
       QString body;
 
       if (args.size() >= 1) {
-       // serializing document not handled yet
-       if (!args[0].toObject(exec).inherits(&DOMDocument::info)) {
+       if (args[0].toObject(exec).inherits(&DOMDocument::info)) {
+         DOM::Node docNode = static_cast<KJS::DOMDocument *>(args[0].toObject(exec).imp())->toNode();
+         DOM::DocumentImpl *doc = static_cast<DOM::DocumentImpl *>(docNode.handle());
+         
+         try {
+           body = doc->toString().string();
+           // FIXME: also need to set content type, including encoding!
+
+         } catch(DOM::DOMException& e) {
+            Object err = Error::create(exec, GeneralError, "Exception serializing document");
+            exec->setException(err);
+         }
+       } else {
          body = args[0].toString(exec).qstring();
        }
       }
index d464897..5de0a9d 100644 (file)
@@ -623,6 +623,26 @@ void HTMLElementImpl::click()
     dispatchMouseEvent(&evt, EventImpl::KHTML_CLICK_EVENT);
 }
 
+DOMString HTMLElementImpl::toString() const
+{
+    if (!hasChildNodes()) {
+       DOMString result = openTagStartToString();
+       result += ">";
+
+       if (endTag[id()] == REQUIRED) {
+           result += "</";
+           result += tagName();
+           result += ">";
+       }
+
+       return result;
+    }
+
+    return ElementImpl::toString();
+}
+
+
+
 // -------------------------------------------------------------------------
 HTMLGenericElementImpl::HTMLGenericElementImpl(DocumentPtr *doc, ushort i)
     : HTMLElementImpl(doc)
index 66a2ddf..831b556 100644 (file)
@@ -71,6 +71,8 @@ public:
     virtual bool isGenericFormElement() const { return false; }
 #endif
 
+    virtual DOMString toString() const;
+
 protected:
     // for IMG, OBJECT and APPLET
     void addHTMLAlignment( DOMString alignment );
index d80e574..6b416ae 100644 (file)
@@ -2573,6 +2573,17 @@ bool DocumentImpl::shouldCreateRenderers()
     return m_createRenderers;
 }
 
+DOMString DocumentImpl::toString() const
+{
+    DOMString result;
+
+    for (NodeImpl *child = firstChild(); child != NULL; child = child->nextSibling()) {
+       child = child->nextSibling();
+    }
+
+    return result;
+}
+
 #endif // APPLE_CHANGES
 
 // ----------------------------------------------------------------------------
@@ -2613,6 +2624,18 @@ bool DocumentFragmentImpl::childTypeAllowed( unsigned short type )
     }
 }
 
+DOMString DocumentFragmentImpl::toString() const
+{
+    DOMString result;
+
+    for (NodeImpl *child = firstChild(); child != NULL; child = child->nextSibling()) {
+       child = child->nextSibling();
+    }
+
+    return result;
+}
+
+
 NodeImpl *DocumentFragmentImpl::cloneNode ( bool deep )
 {
     DocumentFragmentImpl *clone = new DocumentFragmentImpl( docPtr() );
@@ -2656,6 +2679,33 @@ void DocumentTypeImpl::copyFrom(const DocumentTypeImpl& other)
     m_subset = other.m_subset;
 }
 
+DOMString DocumentTypeImpl::toString() const
+{
+    DOMString result = "<!DOCTYPE";
+    result += m_qualifiedName;
+    if (!m_publicId.isEmpty()) {
+       result += " PUBLIC \"";
+       result += m_publicId;
+       result += "\" \"";
+       result += m_systemId;
+       result += "\"";
+    } else if (!m_systemId.isEmpty()) {
+       result += " SYSTEM \"";
+       result += m_systemId;
+       result += "\"";
+    }
+
+    if (!m_subset.isEmpty()) {
+       result += " [";
+       result += m_subset;
+       result += "]";
+    }
+
+    result += ">";
+
+    return result;
+}
+
 DOMString DocumentTypeImpl::nodeName() const
 {
     return name();
index 9adc87f..56ac02b 100644 (file)
@@ -467,6 +467,8 @@ public:
     void removeElementById(const DOMString &elementId, ElementImpl *element);
 
     HTMLElementImpl* body();
+
+    DOMString toString() const;
     
 signals:
     void finishedParsing();
@@ -616,6 +618,8 @@ public:
 
     // Other methods (not part of DOM)
     virtual bool childTypeAllowed( unsigned short type );
+
+    virtual DOMString toString() const;
 };
 
 
@@ -647,6 +651,8 @@ public:
     DOMImplementationImpl *implementation() const { return m_implementation; }
     void copyFrom(const DocumentTypeImpl&);
 
+    virtual DOMString toString() const;
+
 #if APPLE_CHANGES
     static DocumentType createInstance (DocumentTypeImpl *impl);
 #endif
index 213ab4b..67f6ef2 100644 (file)
@@ -154,6 +154,29 @@ bool AttrImpl::childTypeAllowed( unsigned short type )
     }
 }
 
+DOMString AttrImpl::toString() const
+{
+    DOMString result;
+
+    result += nodeName();
+
+    // FIXME: substitute entities for any instances of " or ' --
+    // maybe easier to just use text value and ignore existing
+    // entity refs?
+
+    if (firstChild() != NULL) {
+       result += "=\"";
+
+       for (NodeImpl *child = firstChild(); child != NULL; child = child->nextSibling()) {
+           child = child->nextSibling();
+       }
+       
+       result += "\"";
+    }
+
+    return result;
+}
+
 // -------------------------------------------------------------------------
 
 ElementImpl::ElementImpl(DocumentPtr *doc)
@@ -494,6 +517,57 @@ void ElementImpl::dispatchAttrAdditionEvent(AttributeImpl *attr)
 //                                         attr->value(),getDocument()->attrName(attr->id()),MutationEvent::ADDITION),exceptioncode);
 }
 
+DOMString ElementImpl::openTagStartToString() const
+{
+    DOMString result = DOMString("<") + tagName();
+
+    NamedAttrMapImpl *attrMap = attributes(true);
+
+    if (attrMap) {
+       unsigned long numAttrs = attrMap->length();
+       for (unsigned long i = 0; i < numAttrs; i++) {
+           result += " ";
+
+           AttributeImpl *attribute = attrMap->attributeItem(i);
+           AttrImpl *attr = attribute->attrImpl();
+
+           if (attr) {
+               result += attr->toString();
+           } else {
+               result += getDocument()->attrName(attribute->id());
+               if (!attribute->value().isNull()) {
+                   result += "=\"";
+                   // FIXME: substitute entities for any instances of " or '
+                   result += attribute->value();
+                   result += "\"";
+               }
+           }
+       }
+    }
+
+    return result;
+}
+
+DOMString ElementImpl::toString() const
+{
+    DOMString result = openTagStartToString();
+
+    if (hasChildNodes()) {
+       result += ">";
+
+       for (NodeImpl *child = firstChild(); child != NULL; child = child->nextSibling()) {
+           child = child->nextSibling();
+       }
+
+       result += "</";
+       result += tagName();
+       result += ">";
+    } else {
+       result += " />";
+    }
+
+    return result;
+}
 
 void ElementImpl::updateId(DOMStringImpl* oldId, DOMStringImpl* newId)
 {
index 9cc47f6..ac89f15 100644 (file)
@@ -138,6 +138,8 @@ public:
     virtual bool childAllowed( NodeImpl *newChild );
     virtual bool childTypeAllowed( unsigned short type );
 
+    virtual DOMString toString() const;
+
 #if APPLE_CHANGES
     static Attr createInstance(AttrImpl *impl);
 #endif
@@ -213,6 +215,8 @@ public:
 
     virtual void accessKeyAction() {};
 
+    virtual DOMString toString() const;
+
 #ifndef NDEBUG
     virtual void dump(QTextStream *stream, QString ind = "") const;
 #endif
@@ -223,6 +227,7 @@ public:
 protected:
     void createAttributeMap() const;
     void createDecl();
+    DOMString openTagStartToString() const;
 
 private:
     // map of default attributes. derived element classes are responsible
index 57dae26..8312547 100644 (file)
@@ -369,7 +369,9 @@ public:
      * node that is of the type CDATA_SECTION_NODE, TEXT_NODE or COMMENT_NODE has changed it's value.
      */
     virtual void childrenChanged();
-    
+
+    virtual DOMString toString() const = 0;
+
 private: // members
     DocumentPtr *document;
     NodeImpl *m_previous;
index 9fdd580..65134e4 100644 (file)
@@ -283,6 +283,12 @@ bool CommentImpl::childTypeAllowed( unsigned short /*type*/ )
     return false;
 }
 
+DOMString CommentImpl::toString() const
+{
+    // FIXME: substitute entity references as needed!
+    return DOMString("<!--") + nodeValue() + "-->";
+}
+
 // ---------------------------------------------------------------------------
 
 // ### allow having children in text nodes for entities, comments etc.
@@ -441,6 +447,12 @@ TextImpl *TextImpl::createNew(DOMStringImpl *_str)
     return new TextImpl(docPtr(),_str);
 }
 
+DOMString TextImpl::toString() const
+{
+    // FIXME: substitute entity references as needed!
+    return nodeValue();
+}
+
 // ---------------------------------------------------------------------------
 
 CDATASectionImpl::CDATASectionImpl(DocumentPtr *impl, const DOMString &_text) : TextImpl(impl,_text)
@@ -481,6 +493,11 @@ TextImpl *CDATASectionImpl::createNew(DOMStringImpl *_str)
     return new CDATASectionImpl(docPtr(),_str);
 }
 
+DOMString CDATASectionImpl::toString() const
+{
+    // FIXME: substitute entity references as needed!
+    return DOMString("<![CDATA[") + nodeValue() + "]]>";
+}
 
 
 
index 202135a..0b78098 100644 (file)
@@ -98,6 +98,8 @@ public:
 
     virtual Id id() const;
     virtual bool childTypeAllowed( unsigned short type );
+
+    virtual DOMString toString() const;
 };
 
 // ----------------------------------------------------------------------------
@@ -128,6 +130,8 @@ public:
     virtual void recalcStyle( StyleChange = NoChange );
     virtual bool childTypeAllowed( unsigned short type );
 
+    virtual DOMString toString() const;
+
 #if APPLE_CHANGES
     static Text createInstance(TextImpl *impl);
 #endif
@@ -155,11 +159,11 @@ public:
 
     virtual bool childTypeAllowed( unsigned short type );
 
+    virtual DOMString toString() const;
+
 protected:
     virtual TextImpl *createNew(DOMStringImpl *_str);
 };
 
-
-
 }; //namespace
 #endif
index 10c30f0..ab87cec 100644 (file)
@@ -123,6 +123,38 @@ bool EntityImpl::childTypeAllowed( unsigned short type )
     }
 }
 
+DOMString EntityImpl::toString() const
+{
+    DOMString result = "<!ENTITY' ";
+
+    if (m_name && m_name->l != 0) {
+       result += " ";
+       result += m_name;
+    }
+
+    if (m_publicId && m_publicId->l != 0) {
+       result += " PUBLIC \"";
+       result += m_publicId;
+       result += "\" \"";
+       result += m_systemId;
+       result += "\"";
+    } else if (m_systemId && m_systemId->l != 0) {
+       result += " SYSTEM \"";
+       result += m_systemId;
+       result += "\"";
+    }
+
+    if (m_notationName && m_notationName->l != 0) {
+       result += " NDATA ";
+       result += m_notationName;
+    }
+
+    result += ">";
+
+    return result;
+}
+
+
 // -------------------------------------------------------------------------
 
 EntityReferenceImpl::EntityReferenceImpl(DocumentPtr *doc) : NodeBaseImpl(doc)
@@ -180,6 +212,15 @@ bool EntityReferenceImpl::childTypeAllowed( unsigned short type )
     }
 }
 
+DOMString EntityReferenceImpl::toString() const
+{
+    DOMString result = "&";
+    result += m_entityName;
+    result += ";";
+
+    return result;
+}
+
 // -------------------------------------------------------------------------
 
 NotationImpl::NotationImpl(DocumentPtr *doc) : NodeBaseImpl(doc)
@@ -436,6 +477,16 @@ void ProcessingInstructionImpl::setStyleSheet(CSSStyleSheetImpl* sheet)
         m_sheet->ref();
 }
 
+DOMString ProcessingInstructionImpl::toString() const
+{
+    DOMString result = "<?";
+    result += m_target;
+    result += " ";
+    result += m_data;
+    result += ">";
+    return result;
+}
+
 // -------------------------------------------------------------------------
 
 XMLAttributeReader::XMLAttributeReader(QString _attrString)
index 31501d0..8d08bff 100644 (file)
@@ -66,6 +66,8 @@ public:
 
     virtual bool childTypeAllowed( unsigned short type );
 
+    virtual DOMString toString() const;
+
 protected:
     DOMStringImpl *m_publicId;
     DOMStringImpl *m_systemId;
@@ -91,6 +93,7 @@ public:
 
     virtual bool childTypeAllowed( unsigned short type );
 
+    virtual DOMString toString() const;
 protected:
     DOMStringImpl *m_entityName;
 };
@@ -116,6 +119,7 @@ public:
     // Other methods (not part of DOM)
 
     virtual bool childTypeAllowed( unsigned short type );
+
 protected:
     DOMStringImpl *m_name;
     DOMStringImpl *m_publicId;
@@ -154,6 +158,8 @@ public:
     virtual void setStyleSheet(CSSStyleSheetImpl* sheet);
     bool isLoading() const;
     void sheetLoaded();
+
+    virtual DOMString toString() const;
     
 #if APPLE_CHANGES
     static ProcessingInstruction createInstance(ProcessingInstructionImpl *impl);