Don't play games with the <meta> tag when not serializing an entire document.
Bug 390735, patch by Ryan Jones <sciguyryan@gmail.com>, r+sr=bzbarsky, a=jst
--- a/content/base/public/nsIContentSerializer.h
+++ b/content/base/public/nsIContentSerializer.h
@@ -47,26 +47,27 @@ class nsIDOMComment; /* forward declarat
class nsIDOMDocumentType; /* forward declaration */
class nsIDOMElement; /* forward declaration */
class nsIDOMDocument; /* forward declaration */
class nsAString;
/* starting interface: nsIContentSerializer */
#define NS_ICONTENTSERIALIZER_IID \
-{ 0x0921afbc, 0x4c6f, 0x4249, \
- { 0xa7, 0xf5, 0x32, 0xe4, 0x91, 0xbf, 0x6e, 0x32 } }
+{ 0x34769de0, 0x30d0, 0x4cef, \
+ { 0x89, 0x4a, 0xfc, 0xd8, 0xbb, 0x27, 0xc4, 0xb4 } }
class nsIContentSerializer : public nsISupports {
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ICONTENTSERIALIZER_IID)
NS_IMETHOD Init(PRUint32 flags, PRUint32 aWrapColumn,
- const char* aCharSet, PRBool aIsCopying) = 0;
+ const char* aCharSet, PRBool aIsCopying,
+ PRBool aIsWholeDocument) = 0;
NS_IMETHOD AppendText(nsIDOMText* aText, PRInt32 aStartOffset,
PRInt32 aEndOffset, nsAString& aStr) = 0;
NS_IMETHOD AppendCDATASection(nsIDOMCDATASection* aCDATASection,
PRInt32 aStartOffset, PRInt32 aEndOffset,
nsAString& aStr) = 0;
--- a/content/base/src/mozSanitizingSerializer.cpp
+++ b/content/base/src/mozSanitizingSerializer.cpp
@@ -121,29 +121,30 @@ NS_IMPL_ISUPPORTS4(mozSanitizingHTMLSeri
nsIContentSerializer,
nsIContentSink,
nsIHTMLContentSink,
mozISanitizingHTMLSerializer)
NS_IMETHODIMP
mozSanitizingHTMLSerializer::Init(PRUint32 aFlags, PRUint32 dummy,
- const char* aCharSet, PRBool aIsCopying)
+ const char* aCharSet, PRBool aIsCopying,
+ PRBool aIsWholeDocument)
{
NS_ENSURE_TRUE(nsContentUtils::GetParserService(), NS_ERROR_UNEXPECTED);
return NS_OK;
}
NS_IMETHODIMP
mozSanitizingHTMLSerializer::Initialize(nsAString* aOutString,
PRUint32 aFlags,
const nsAString& allowedTags)
{
- nsresult rv = Init(aFlags, 0, nsnull, PR_FALSE);
+ nsresult rv = Init(aFlags, 0, nsnull, PR_FALSE, PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
// XXX This is wrong. It violates XPCOM string ownership rules.
// We're only getting away with this because instances of this
// class are restricted to single function scope.
// (Comment copied from nsPlaintextSerializer)
mOutputString = aOutString;
--- a/content/base/src/mozSanitizingSerializer.h
+++ b/content/base/src/mozSanitizingSerializer.h
@@ -67,17 +67,17 @@ public:
virtual ~mozSanitizingHTMLSerializer();
static PRBool PR_CALLBACK ReleaseProperties(nsHashKey* key, void* data,
void* closure);
NS_DECL_ISUPPORTS
// nsIContentSerializer
NS_IMETHOD Init(PRUint32 flags, PRUint32 dummy, const char* aCharSet,
- PRBool aIsCopying);
+ PRBool aIsCopying, PRBool aIsWholeDocument);
NS_IMETHOD AppendText(nsIDOMText* aText, PRInt32 aStartOffset,
PRInt32 aEndOffset, nsAString& aStr);
NS_IMETHOD AppendCDATASection(nsIDOMCDATASection* aCDATASection,
PRInt32 aStartOffset, PRInt32 aEndOffset,
nsAString& aStr)
{ return NS_OK; }
NS_IMETHOD AppendProcessingInstruction(nsIDOMProcessingInstruction* aPI,
--- a/content/base/src/nsDocumentEncoder.cpp
+++ b/content/base/src/nsDocumentEncoder.cpp
@@ -888,17 +888,19 @@ nsDocumentEncoder::EncodeToString(nsAStr
nsCOMPtr<nsIAtom> charsetAtom;
if (!mCharset.IsEmpty()) {
if (!mCharsetConverterManager) {
mCharsetConverterManager = do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
}
}
- mSerializer->Init(mFlags, mWrapColumn, mCharset.get(), mIsCopying);
+
+ PRBool isWholeDocument = !(mSelection || mRange || mNode);
+ mSerializer->Init(mFlags, mWrapColumn, mCharset.get(), mIsCopying, isWholeDocument);
if (mSelection) {
nsCOMPtr<nsIDOMRange> range;
PRInt32 i, count = 0;
rv = mSelection->GetRangeCount(&count);
NS_ENSURE_SUCCESS(rv, rv);
--- a/content/base/src/nsHTMLContentSerializer.cpp
+++ b/content/base/src/nsHTMLContentSerializer.cpp
@@ -88,16 +88,17 @@ nsresult NS_NewHTMLContentSerializer(nsI
}
nsHTMLContentSerializer::nsHTMLContentSerializer()
: mIndent(0),
mColPos(0),
mInBody(PR_FALSE),
mAddSpace(PR_FALSE),
mMayIgnoreLineBreakSequence(PR_FALSE),
+ mIsWholeDocument(PR_FALSE),
mInCDATA(PR_FALSE),
mNeedLineBreaker(PR_TRUE)
{
}
nsHTMLContentSerializer::~nsHTMLContentSerializer()
{
NS_ASSERTION(mOLStateStack.Count() == 0, "Expected OL State stack to be empty");
@@ -107,26 +108,28 @@ nsHTMLContentSerializer::~nsHTMLContentS
delete state;
mOLStateStack.RemoveElementAt(i);
}
}
}
NS_IMETHODIMP
nsHTMLContentSerializer::Init(PRUint32 aFlags, PRUint32 aWrapColumn,
- const char* aCharSet, PRBool aIsCopying)
+ const char* aCharSet, PRBool aIsCopying,
+ PRBool aIsWholeDocument)
{
mFlags = aFlags;
if (!aWrapColumn) {
mMaxColumn = 72;
}
else {
mMaxColumn = aWrapColumn;
}
+ mIsWholeDocument = aIsWholeDocument;
mIsCopying = aIsCopying;
mIsFirstChildOfOL = PR_FALSE;
mDoFormat = (mFlags & nsIDocumentEncoder::OutputFormatted) ? PR_TRUE
: PR_FALSE;
mBodyOnly = (mFlags & nsIDocumentEncoder::OutputBodyOnly) ? PR_TRUE
: PR_FALSE;
// Set the line break character:
if ((mFlags & nsIDocumentEncoder::OutputCRLineBreak)
@@ -631,17 +634,17 @@ nsHTMLContentSerializer::AppendElementSt
// even if we're not in pretty printing mode
PRBool hasDirtyAttr = content->HasAttr(kNameSpaceID_None,
nsGkAtoms::mozdirty);
nsIAtom *name = content->Tag();
// We need too skip any meta tags that set the content type
// becase we set our own later.
- if (name == nsGkAtoms::meta) {
+ if (mIsWholeDocument && name == nsGkAtoms::meta) {
nsAutoString header;
content->GetAttr(kNameSpaceID_None, nsGkAtoms::httpEquiv, header);
if (header.LowerCaseEqualsLiteral("content-type")) {
return NS_OK;
}
}
if (name == nsGkAtoms::br && mPreLevel > 0
@@ -733,17 +736,17 @@ nsHTMLContentSerializer::AppendElementSt
if (name == nsGkAtoms::script ||
name == nsGkAtoms::style ||
name == nsGkAtoms::noscript ||
name == nsGkAtoms::noframes) {
mInCDATA = PR_TRUE;
}
- if (name == nsGkAtoms::head) {
+ if (mIsWholeDocument && name == nsGkAtoms::head) {
AppendToString(mLineBreak, aStr);
AppendToString(NS_LITERAL_STRING("<meta http-equiv=\"content-type\""),
aStr);
AppendToString(NS_LITERAL_STRING(" content=\"text/html; charset="), aStr);
AppendToString(NS_ConvertASCIItoUTF16(mCharset), aStr);
AppendToString(NS_LITERAL_STRING("\">"), aStr);
}
@@ -760,17 +763,17 @@ nsHTMLContentSerializer::AppendElementEn
if (!content) return NS_ERROR_FAILURE;
PRBool hasDirtyAttr = content->HasAttr(kNameSpaceID_None,
nsGkAtoms::mozdirty);
nsIAtom *name = content->Tag();
// So that we don't mess up the line breaks.
- if (name == nsGkAtoms::meta) {
+ if (mIsWholeDocument && name == nsGkAtoms::meta) {
nsAutoString header;
content->GetAttr(kNameSpaceID_None, nsGkAtoms::httpEquiv, header);
if (header.LowerCaseEqualsLiteral("content-type")) {
return NS_OK;
}
}
if (name == nsGkAtoms::script) {
--- a/content/base/src/nsHTMLContentSerializer.h
+++ b/content/base/src/nsHTMLContentSerializer.h
@@ -53,17 +53,18 @@ class nsIContent;
class nsIAtom;
class nsHTMLContentSerializer : public nsXMLContentSerializer {
public:
nsHTMLContentSerializer();
virtual ~nsHTMLContentSerializer();
NS_IMETHOD Init(PRUint32 flags, PRUint32 aWrapColumn,
- const char* aCharSet, PRBool aIsCopying);
+ const char* aCharSet, PRBool aIsCopying,
+ PRBool aIsWholeDocument);
NS_IMETHOD AppendText(nsIDOMText* aText,
PRInt32 aStartOffset,
PRInt32 aEndOffset,
nsAString& aStr);
NS_IMETHOD AppendElementStart(nsIDOMElement *aElement,
nsIDOMElement *aOriginalElement,
nsAString& aStr);
@@ -134,16 +135,20 @@ class nsHTMLContentSerializer : public n
PRPackedBool mIsCopying; // Set to PR_TRUE only while copying
// Indicates that a space will be added if and only if content is
// continued on the same line while serializing source. Otherwise,
// the newline character acts as the whitespace and no space is needed.
PRPackedBool mAddSpace;
PRPackedBool mMayIgnoreLineBreakSequence;
+ // This is to ensure that we only do meta tag fixups when dealing with
+ // whole documents.
+ PRPackedBool mIsWholeDocument;
+
// To keep track of First LI child of OL in selected range
PRPackedBool mIsFirstChildOfOL;
PRInt32 mPreLevel;
/*
* mInCDATA is set to PR_TRUE while the serializer is serializing
* the content of a element whose content is considerd CDATA by the
* serializer (such elements are 'script', 'style', 'noscript' and
--- a/content/base/src/nsPlainTextSerializer.cpp
+++ b/content/base/src/nsPlainTextSerializer.cpp
@@ -144,17 +144,18 @@ NS_IMPL_ISUPPORTS4(nsPlainTextSerializer
nsIContentSerializer,
nsIContentSink,
nsIHTMLContentSink,
nsIHTMLToTextSink)
NS_IMETHODIMP
nsPlainTextSerializer::Init(PRUint32 aFlags, PRUint32 aWrapColumn,
- const char* aCharSet, PRBool aIsCopying)
+ const char* aCharSet, PRBool aIsCopying,
+ PRBool aIsWholeDocument)
{
#ifdef DEBUG
// Check if the major control flags are set correctly.
if(aFlags & nsIDocumentEncoder::OutputFormatFlowed) {
NS_ASSERTION(aFlags & nsIDocumentEncoder::OutputFormatted,
"If you want format=flowed, you must combine it with "
"nsIDocumentEncoder::OutputFormatted");
}
@@ -269,17 +270,17 @@ nsPlainTextSerializer::PopBool(nsVoidArr
}
return returnValue;
}
NS_IMETHODIMP
nsPlainTextSerializer::Initialize(nsAString* aOutString,
PRUint32 aFlags, PRUint32 aWrapCol)
{
- nsresult rv = Init(aFlags, aWrapCol, nsnull, PR_FALSE);
+ nsresult rv = Init(aFlags, aWrapCol, nsnull, PR_FALSE, PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
// XXX This is wrong. It violates XPCOM string ownership rules.
// We're only getting away with this because instances of this
// class are restricted to single function scope.
mOutputString = aOutString;
return NS_OK;
--- a/content/base/src/nsPlainTextSerializer.h
+++ b/content/base/src/nsPlainTextSerializer.h
@@ -64,17 +64,18 @@ class nsPlainTextSerializer : public nsI
public:
nsPlainTextSerializer();
virtual ~nsPlainTextSerializer();
NS_DECL_ISUPPORTS
// nsIContentSerializer
NS_IMETHOD Init(PRUint32 flags, PRUint32 aWrapColumn,
- const char* aCharSet, PRBool aIsCopying);
+ const char* aCharSet, PRBool aIsCopying,
+ PRBool aIsWholeDocument);
NS_IMETHOD AppendText(nsIDOMText* aText, PRInt32 aStartOffset,
PRInt32 aEndOffset, nsAString& aStr);
NS_IMETHOD AppendCDATASection(nsIDOMCDATASection* aCDATASection,
PRInt32 aStartOffset, PRInt32 aEndOffset,
nsAString& aStr);
NS_IMETHOD AppendProcessingInstruction(nsIDOMProcessingInstruction* aPI,
PRInt32 aStartOffset,
--- a/content/base/src/nsXMLContentSerializer.cpp
+++ b/content/base/src/nsXMLContentSerializer.cpp
@@ -88,17 +88,18 @@ nsXMLContentSerializer::nsXMLContentSeri
nsXMLContentSerializer::~nsXMLContentSerializer()
{
}
NS_IMPL_ISUPPORTS1(nsXMLContentSerializer, nsIContentSerializer)
NS_IMETHODIMP
nsXMLContentSerializer::Init(PRUint32 flags, PRUint32 aWrapColumn,
- const char* aCharSet, PRBool aIsCopying)
+ const char* aCharSet, PRBool aIsCopying,
+ PRBool aIsWholeDocument)
{
mCharset = aCharSet;
return NS_OK;
}
nsresult
nsXMLContentSerializer::AppendTextData(nsIDOMNode* aNode,
PRInt32 aStartOffset,
--- a/content/base/src/nsXMLContentSerializer.h
+++ b/content/base/src/nsXMLContentSerializer.h
@@ -55,17 +55,18 @@ class nsIAtom;
class nsXMLContentSerializer : public nsIContentSerializer {
public:
nsXMLContentSerializer();
virtual ~nsXMLContentSerializer();
NS_DECL_ISUPPORTS
NS_IMETHOD Init(PRUint32 flags, PRUint32 aWrapColumn,
- const char* aCharSet, PRBool aIsCopying);
+ const char* aCharSet, PRBool aIsCopying,
+ PRBool aIsWholeDocument);
NS_IMETHOD AppendText(nsIDOMText* aText, PRInt32 aStartOffset,
PRInt32 aEndOffset, nsAString& aStr);
NS_IMETHOD AppendCDATASection(nsIDOMCDATASection* aCDATASection,
PRInt32 aStartOffset, PRInt32 aEndOffset,
nsAString& aStr);
--- a/content/base/test/Makefile.in
+++ b/content/base/test/Makefile.in
@@ -81,16 +81,17 @@ include $(topsrcdir)/config/rules.mk
test_bug371576-2.html \
test_bug371576-3.html \
test_bug371576-4.html \
test_bug371576-5.html \
test_bug372086.html \
test_bug373181.xhtml \
test_bug375314.html \
test_bug382113.html \
+ test_bug390735.html \
bug382113_object.html \
test_CrossSiteXHR.html \
file_CrossSiteXHR_fail1.xml \
file_CrossSiteXHR_fail2.xml \
file_CrossSiteXHR_fail2.xml^headers^ \
file_CrossSiteXHR_fail3.xml \
file_CrossSiteXHR_fail4.xml \
file_CrossSiteXHR_pass1.xml \
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_bug390735.html
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=390735
+-->
+<head>
+ <meta http-equiv="content-type" content="text/html; charset=utf-8">
+ <title>Test for Bug 390735</title>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+/** Test for Bug 390735 **/
+
+var contents = document.getElementsByTagName("head")[0].innerHTML;
+var expectedFind = "<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">";
+
+ok(contents.indexOf(expectedFind) > -1, "The meta tag element was not found");
+</script>
+</pre>
+</body>
+</html>