diff --git a/content/base/public/nsIDocumentEncoder.idl b/content/base/public/nsIDocumentEncoder.idl index 2f60bc403027..e6139f2a0a0b 100644 --- a/content/base/public/nsIDocumentEncoder.idl +++ b/content/base/public/nsIDocumentEncoder.idl @@ -44,7 +44,7 @@ interface nsISelection; interface nsIDOMNode; interface nsIOutputStream; -[scriptable, uuid(e770c650-b3d3-11da-a94d-0800200c9a66)] +[scriptable, uuid(3c556e41-0f73-4e1d-b724-1474884fe2e3)] interface nsIDocumentEncoderNodeFixup : nsISupports { /** @@ -53,9 +53,12 @@ interface nsIDocumentEncoderNodeFixup : nsISupports * may return a new node with fixed up attributes or null. If null is * returned the node should be used as-is. * @param aNode Node to fixup. + * @param [OUT] aSerializeCloneKids True if the document encoder should + * apply recursive serialization to the children of the fixed up node + * instead of the children of the original node. * @return The resulting fixed up node. */ - nsIDOMNode fixupNode(in nsIDOMNode aNode); + nsIDOMNode fixupNode(in nsIDOMNode aNode, out boolean aSerializeCloneKids); }; [scriptable, uuid(f85c5a20-258d-11db-a98b-0800200c9a66)] diff --git a/content/base/src/nsDocumentEncoder.cpp b/content/base/src/nsDocumentEncoder.cpp index e0126ec2664f..9961e156ddc9 100644 --- a/content/base/src/nsDocumentEncoder.cpp +++ b/content/base/src/nsDocumentEncoder.cpp @@ -97,7 +97,8 @@ public: protected: void Initialize(); nsresult SerializeNodeStart(nsIDOMNode* aNode, PRInt32 aStartOffset, - PRInt32 aEndOffset, nsAString& aStr); + PRInt32 aEndOffset, nsAString& aStr, + nsIDOMNode* aOriginalNode = nsnull); nsresult SerializeToStringRecursive(nsIDOMNode* aNode, nsAString& aStr, PRBool aDontSerializeRoot); @@ -259,28 +260,34 @@ nsDocumentEncoder::IncludeInContext(nsIDOMNode *aNode) } nsresult -nsDocumentEncoder::SerializeNodeStart(nsIDOMNode* aNode, PRInt32 aStartOffset, +nsDocumentEncoder::SerializeNodeStart(nsIDOMNode* aNode, + PRInt32 aStartOffset, PRInt32 aEndOffset, - nsAString& aStr) + nsAString& aStr, + nsIDOMNode* aOriginalNode) { PRUint16 type; nsCOMPtr node; - if (mNodeFixup) - { - mNodeFixup->FixupNode(aNode, getter_AddRefs(node)); + + // Caller didn't do fixup, so we'll do it ourselves + if (!aOriginalNode && mNodeFixup) { + aOriginalNode = aNode; + PRBool dummy; + mNodeFixup->FixupNode(aNode, &dummy, getter_AddRefs(node)); } + + // Either there was no fixed-up node, + // or the caller did fixup themselves and aNode is already fixed if (!node) - { - node = do_QueryInterface(aNode); - } + node = aNode; node->GetNodeType(&type); switch (type) { case nsIDOMNode::ELEMENT_NODE: { nsCOMPtr element = do_QueryInterface(node); - nsCOMPtr originalElement = do_QueryInterface(aNode); + nsCOMPtr originalElement = do_QueryInterface(aOriginalNode); mSerializer->AppendElementStart(element, originalElement, aStr); break; } @@ -345,18 +352,32 @@ nsDocumentEncoder::SerializeToStringRecursive(nsIDOMNode* aNode, PRBool aDontSerializeRoot) { nsresult rv = NS_OK; + PRBool serializeClonedChildren; + nsCOMPtr maybeFixedNode; + + if (mNodeFixup) + mNodeFixup->FixupNode(aNode, &serializeClonedChildren, getter_AddRefs(maybeFixedNode)); + + if (!maybeFixedNode) + maybeFixedNode = aNode; + if (!aDontSerializeRoot) { - rv = SerializeNodeStart(aNode, 0, -1, aStr); + rv = SerializeNodeStart(maybeFixedNode, 0, -1, aStr, aNode); NS_ENSURE_SUCCESS(rv, rv); } - PRBool hasChildren = PR_FALSE; + nsIDOMNode *node; + if (serializeClonedChildren) + node = maybeFixedNode; + else + node = aNode; - aNode->HasChildNodes(&hasChildren); + PRBool hasChildren = PR_FALSE; + node->HasChildNodes(&hasChildren); if (hasChildren) { nsCOMPtr childNodes; - rv = aNode->GetChildNodes(getter_AddRefs(childNodes)); + rv = node->GetChildNodes(getter_AddRefs(childNodes)); NS_ENSURE_TRUE(childNodes, NS_SUCCEEDED(rv) ? NS_ERROR_FAILURE : rv); PRInt32 index, count; @@ -374,7 +395,7 @@ nsDocumentEncoder::SerializeToStringRecursive(nsIDOMNode* aNode, } if (!aDontSerializeRoot) { - rv = SerializeNodeEnd(aNode, aStr); + rv = SerializeNodeEnd(node, aStr); NS_ENSURE_SUCCESS(rv, rv); } diff --git a/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.cpp b/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.cpp index 0b2033919faf..83283114c58d 100644 --- a/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.cpp +++ b/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.cpp @@ -86,6 +86,8 @@ #include "nsIPrompt.h" #include "nsISHEntry.h" #include "nsIWebPageDescriptor.h" +#include "nsIFormControl.h" +#include "nsIDOM3Node.h" #include "nsIDOMNodeFilter.h" #include "nsIDOMProcessingInstruction.h" @@ -105,7 +107,10 @@ #include "nsIDOMHTMLEmbedElement.h" #include "nsIDOMHTMLObjectElement.h" #include "nsIDOMHTMLAppletElement.h" +#include "nsIDOMHTMLOptionElement.h" +#include "nsIDOMHTMLTextAreaElement.h" #include "nsIDOMHTMLDocument.h" +#include "nsIDOMText.h" #ifdef MOZ_SVG #include "nsIDOMSVGImageElement.h" #include "nsIDOMSVGScriptElement.h" @@ -2971,11 +2976,12 @@ nsWebBrowserPersist::GetNodeToFixup(nsIDOMNode *aNodeIn, nsIDOMNode **aNodeOut) } nsresult -nsWebBrowserPersist::CloneNodeWithFixedUpURIAttributes( - nsIDOMNode *aNodeIn, nsIDOMNode **aNodeOut) +nsWebBrowserPersist::CloneNodeWithFixedUpAttributes( + nsIDOMNode *aNodeIn, PRBool *aSerializeCloneKids, nsIDOMNode **aNodeOut) { nsresult rv; *aNodeOut = nsnull; + *aSerializeCloneKids = PR_FALSE; // Fixup xml-stylesheet processing instructions nsCOMPtr nodeAsPI = do_QueryInterface(aNodeIn); @@ -3266,6 +3272,62 @@ nsWebBrowserPersist::CloneNodeWithFixedUpURIAttributes( imgCon->SetLoadingEnabled(PR_FALSE); FixupNodeAttribute(*aNodeOut, "src"); + + nsAutoString valueStr; + NS_NAMED_LITERAL_STRING(valueAttr, "value"); + // Update element node attributes with user-entered form state + nsCOMPtr outElt = do_QueryInterface(*aNodeOut); + nsCOMPtr formControl = do_QueryInterface(*aNodeOut); + switch (formControl->GetType()) { + case NS_FORM_INPUT_TEXT: + nodeAsInput->GetValue(valueStr); + // Avoid superfluous value="" serialization + if (valueStr.IsEmpty()) + outElt->RemoveAttribute(valueAttr); + else + outElt->SetAttribute(valueAttr, valueStr); + break; + case NS_FORM_INPUT_CHECKBOX: + case NS_FORM_INPUT_RADIO: + PRBool checked; + nodeAsInput->GetChecked(&checked); + outElt->SetDefaultChecked(checked); + break; + default: + break; + } + } + return rv; + } + + nsCOMPtr nodeAsTextArea = do_QueryInterface(aNodeIn); + if (nodeAsTextArea) + { + rv = GetNodeToFixup(aNodeIn, aNodeOut); + if (NS_SUCCEEDED(rv) && *aNodeOut) + { + // Tell the document encoder to serialize the text child we create below + *aSerializeCloneKids = PR_TRUE; + + nsAutoString valueStr; + nodeAsTextArea->GetValue(valueStr); + + nsCOMPtr out = do_QueryInterface(*aNodeOut); + out->SetTextContent(valueStr); + } + return rv; + } + + nsCOMPtr nodeAsOption = do_QueryInterface(aNodeIn); + if (nodeAsOption) + { + rv = GetNodeToFixup(aNodeIn, aNodeOut); + if (NS_SUCCEEDED(rv) && *aNodeOut) + { + nsCOMPtr outElt = do_QueryInterface(*aNodeOut); + PRBool selected; + nodeAsOption->GetSelected(&selected); + outElt->SetDefaultSelected(selected); } return rv; } @@ -4097,7 +4159,7 @@ NS_INTERFACE_MAP_END NS_IMETHODIMP nsEncoderNodeFixup::FixupNode( - nsIDOMNode *aNode, nsIDOMNode **aOutNode) + nsIDOMNode *aNode, PRBool *aSerializeCloneKids, nsIDOMNode **aOutNode) { NS_ENSURE_ARG_POINTER(aNode); NS_ENSURE_ARG_POINTER(aOutNode); @@ -4111,7 +4173,7 @@ NS_IMETHODIMP nsEncoderNodeFixup::FixupNode( if (type == nsIDOMNode::ELEMENT_NODE || type == nsIDOMNode::PROCESSING_INSTRUCTION_NODE) { - return mWebBrowserPersist->CloneNodeWithFixedUpURIAttributes(aNode, aOutNode); + return mWebBrowserPersist->CloneNodeWithFixedUpAttributes(aNode, aSerializeCloneKids, aOutNode); } return NS_OK; diff --git a/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.h b/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.h index 121a51eb696e..69407e61bf54 100644 --- a/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.h +++ b/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.h @@ -90,8 +90,8 @@ public: // Protected members protected: virtual ~nsWebBrowserPersist(); - nsresult CloneNodeWithFixedUpURIAttributes( - nsIDOMNode *aNodeIn, nsIDOMNode **aNodeOut); + nsresult CloneNodeWithFixedUpAttributes( + nsIDOMNode *aNodeIn, PRBool *aSerializeCloneKids, nsIDOMNode **aNodeOut); nsresult SaveURIInternal( nsIURI *aURI, nsISupports *aCacheKey, nsIURI *aReferrer, nsIInputStream *aPostData, const char *aExtraHeaders, nsIURI *aFile, @@ -250,7 +250,7 @@ public: nsEncoderNodeFixup(); NS_DECL_ISUPPORTS - NS_IMETHOD FixupNode(nsIDOMNode *aNode, nsIDOMNode **aOutNode); + NS_IMETHOD FixupNode(nsIDOMNode *aNode, PRBool *aSerializeCloneKids, nsIDOMNode **aOutNode); nsWebBrowserPersist *mWebBrowserPersist;