author | Henri Sivonen <hsivonen@iki.fi> |
Fri, 14 Oct 2011 13:39:19 +0300 | |
changeset 78734 | 2244089600ffab5d1db0ea72ed68ca06c92a9a0c |
parent 78733 | d50bd6d5b097d2790c9125c3a060ae2773f98e53 |
child 78735 | fa65bb9a09092e9cffa8cf352ddd4eaf8d3bef00 |
push id | 21329 |
push user | eakhgari@mozilla.com |
push date | Fri, 14 Oct 2011 14:37:50 +0000 |
treeherder | mozilla-central@349f3d4b2d87 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | bzbarsky |
bugs | 677050 |
milestone | 10.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/content/base/public/nsContentUtils.h +++ b/content/base/public/nsContentUtils.h @@ -184,16 +184,17 @@ struct nsShortcutCandidate { } PRUint32 mCharCode; bool mIgnoreShift; }; class nsContentUtils { friend class nsAutoScriptBlockerSuppressNodeRemoved; + friend class mozilla::AutoRestore<bool>; typedef mozilla::dom::Element Element; typedef mozilla::TimeDuration TimeDuration; public: static nsresult Init(); /** * Get a JSContext from the document's scope object. @@ -1056,32 +1057,36 @@ public: * @param aSourceBuffer the string being set as innerHTML * @param aTargetNode the target container * @param aContextLocalName local name of context node * @param aContextNamespace namespace of context node * @param aQuirks true to make <table> not close <p> * @param aPreventScriptExecution true to prevent scripts from executing; * don't set to false when parsing into a target node that has been * bound to tree. + * @return NS_ERROR_DOM_INVALID_STATE_ERR if a re-entrant attempt to parse + * fragments is made and NS_OK otherwise. */ - static void ParseFragmentHTML(const nsAString& aSourceBuffer, - nsIContent* aTargetNode, - nsIAtom* aContextLocalName, - PRInt32 aContextNamespace, - bool aQuirks, - bool aPreventScriptExecution); + static nsresult ParseFragmentHTML(const nsAString& aSourceBuffer, + nsIContent* aTargetNode, + nsIAtom* aContextLocalName, + PRInt32 aContextNamespace, + bool aQuirks, + bool aPreventScriptExecution); /** * Invoke the fragment parsing algorithm (innerHTML) using the XML parser. * * @param aSourceBuffer the string being set as innerHTML * @param aTargetNode the target container * @param aTagStack the namespace mapping context * @param aPreventExecution whether to mark scripts as already started * @param aReturn the result fragment + * @return NS_ERROR_DOM_INVALID_STATE_ERR if a re-entrant attempt to parse + * fragments is made, a return code from the XML parser. */ static nsresult ParseFragmentXML(const nsAString& aSourceBuffer, nsIDocument* aDocument, nsTArray<nsString>& aTagStack, bool aPreventScriptExecution, nsIDOMDocumentFragment** aReturn); /** @@ -1906,16 +1911,21 @@ private: static bool sTrustedFullScreenOnly; static bool sFullScreenKeyInputRestricted; static PRUint32 sHandlingInputTimeout; static nsHtml5Parser* sHTMLFragmentParser; static nsIParser* sXMLFragmentParser; static nsIFragmentContentSink* sXMLFragmentSink; + /** + * True if there's a fragment parser activation on the stack. + */ + static bool sFragmentParsingActive; + static nsString* sShiftText; static nsString* sControlText; static nsString* sMetaText; static nsString* sAltText; static nsString* sModifierSeparator; }; #define NS_HOLD_JS_OBJECTS(obj, clazz) \
--- a/content/base/src/nsContentUtils.cpp +++ b/content/base/src/nsContentUtils.cpp @@ -267,16 +267,17 @@ bool nsContentUtils::sIsFullScreenApiEna bool nsContentUtils::sTrustedFullScreenOnly = true; bool nsContentUtils::sFullScreenKeyInputRestricted = true; PRUint32 nsContentUtils::sHandlingInputTimeout = 1000; nsHtml5Parser* nsContentUtils::sHTMLFragmentParser = nsnull; nsIParser* nsContentUtils::sXMLFragmentParser = nsnull; nsIFragmentContentSink* nsContentUtils::sXMLFragmentSink = nsnull; +bool nsContentUtils::sFragmentParsingActive = false; static PLDHashTable sEventListenerManagersHash; class EventListenerManagerMapEntry : public PLDHashEntryHdr { public: EventListenerManagerMapEntry(const void *aKey) : mKey(aKey) @@ -3504,37 +3505,38 @@ nsContentUtils::CreateContextualFragment if (contextAsContent && !contextAsContent->IsElement()) { contextAsContent = contextAsContent->GetParent(); if (contextAsContent && !contextAsContent->IsElement()) { // can this even happen? contextAsContent = nsnull; } } + nsresult rv; nsCOMPtr<nsIContent> fragment = do_QueryInterface(frag); if (contextAsContent && !contextAsContent->IsHTML(nsGkAtoms::html)) { - ParseFragmentHTML(aFragment, - fragment, - contextAsContent->Tag(), - contextAsContent->GetNameSpaceID(), - (document->GetCompatibilityMode() == - eCompatibility_NavQuirks), - aPreventScriptExecution); + rv = ParseFragmentHTML(aFragment, + fragment, + contextAsContent->Tag(), + contextAsContent->GetNameSpaceID(), + (document->GetCompatibilityMode() == + eCompatibility_NavQuirks), + aPreventScriptExecution); } else { - ParseFragmentHTML(aFragment, - fragment, - nsGkAtoms::body, - kNameSpaceID_XHTML, - (document->GetCompatibilityMode() == - eCompatibility_NavQuirks), - aPreventScriptExecution); + rv = ParseFragmentHTML(aFragment, + fragment, + nsGkAtoms::body, + kNameSpaceID_XHTML, + (document->GetCompatibilityMode() == + eCompatibility_NavQuirks), + aPreventScriptExecution); } frag.forget(aReturn); - return NS_OK; + return rv; } nsAutoTArray<nsString, 32> tagStack; nsAutoString uriStr, nameStr; nsCOMPtr<nsIContent> content = do_QueryInterface(aContextNode); // just in case we have a text node if (content && !content->IsElement()) content = content->GetParent(); @@ -3606,46 +3608,59 @@ nsContentUtils::DropFragmentParsers() /* static */ void nsContentUtils::XPCOMShutdown() { nsContentUtils::DropFragmentParsers(); } /* static */ -void +nsresult nsContentUtils::ParseFragmentHTML(const nsAString& aSourceBuffer, nsIContent* aTargetNode, nsIAtom* aContextLocalName, PRInt32 aContextNamespace, bool aQuirks, bool aPreventScriptExecution) { + if (nsContentUtils::sFragmentParsingActive) { + NS_NOTREACHED("Re-entrant fragment parsing attempted."); + return NS_ERROR_DOM_INVALID_STATE_ERR; + } + mozilla::AutoRestore<bool> guard(nsContentUtils::sFragmentParsingActive); + nsContentUtils::sFragmentParsingActive = true; if (!sHTMLFragmentParser) { sHTMLFragmentParser = static_cast<nsHtml5Parser*>(nsHtml5Module::NewHtml5Parser().get()); // Now sHTMLFragmentParser owns the object } sHTMLFragmentParser->ParseHtml5Fragment(aSourceBuffer, aTargetNode, aContextLocalName, aContextNamespace, aQuirks, aPreventScriptExecution); sHTMLFragmentParser->Reset(); + return NS_OK; } /* static */ nsresult nsContentUtils::ParseFragmentXML(const nsAString& aSourceBuffer, nsIDocument* aDocument, nsTArray<nsString>& aTagStack, bool aPreventScriptExecution, nsIDOMDocumentFragment** aReturn) { + if (nsContentUtils::sFragmentParsingActive) { + NS_NOTREACHED("Re-entrant fragment parsing attempted."); + return NS_ERROR_DOM_INVALID_STATE_ERR; + } + mozilla::AutoRestore<bool> guard(nsContentUtils::sFragmentParsingActive); + nsContentUtils::sFragmentParsingActive = true; if (!sXMLFragmentParser) { nsCOMPtr<nsIParser> parser = do_CreateInstance(kCParserCID); parser.forget(&sXMLFragmentParser); // sXMLFragmentParser now owns the parser } if (!sXMLFragmentSink) { NS_NewXMLFragmentContentSink(&sXMLFragmentSink); // sXMLFragmentSink now owns the sink
--- a/content/html/content/src/nsGenericHTMLElement.cpp +++ b/content/html/content/src/nsGenericHTMLElement.cpp @@ -765,23 +765,23 @@ nsGenericHTMLElement::SetInnerHTML(const } nsAutoScriptLoaderDisabler sld(doc); nsCOMPtr<nsIDOMDocumentFragment> df; if (doc->IsHTML()) { PRInt32 oldChildCount = GetChildCount(); - nsContentUtils::ParseFragmentHTML(aInnerHTML, - this, - Tag(), - GetNameSpaceID(), - doc->GetCompatibilityMode() == - eCompatibility_NavQuirks, - PR_TRUE); + rv = nsContentUtils::ParseFragmentHTML(aInnerHTML, + this, + Tag(), + GetNameSpaceID(), + doc->GetCompatibilityMode() == + eCompatibility_NavQuirks, + PR_TRUE); // HTML5 parser has notified, but not fired mutation events. FireMutationEventsForDirectParsing(doc, this, oldChildCount); } else { rv = nsContentUtils::CreateContextualFragment(this, aInnerHTML, PR_TRUE, getter_AddRefs(df)); nsCOMPtr<nsINode> fragment = do_QueryInterface(df); if (NS_SUCCEEDED(rv)) { @@ -836,48 +836,49 @@ nsGenericHTMLElement::InsertAdjacentHTML // Needed when insertAdjacentHTML is used in combination with contenteditable mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, PR_TRUE); nsAutoScriptLoaderDisabler sld(doc); // Batch possible DOMSubtreeModified events. mozAutoSubtreeModified subtree(doc, nsnull); + nsresult rv; // Parse directly into destination if possible if (doc->IsHTML() && (position == eBeforeEnd || (position == eAfterEnd && !GetNextSibling()) || (position == eAfterBegin && !GetFirstChild()))) { PRInt32 oldChildCount = destination->GetChildCount(); PRInt32 contextNs = destination->GetNameSpaceID(); nsIAtom* contextLocal = destination->Tag(); if (contextLocal == nsGkAtoms::html && contextNs == kNameSpaceID_XHTML) { // For compat with IE6 through IE9. Willful violation of HTML5 as of // 2011-04-06. CreateContextualFragment does the same already. // Spec bug: http://www.w3.org/Bugs/Public/show_bug.cgi?id=12434 contextLocal = nsGkAtoms::body; } - nsContentUtils::ParseFragmentHTML(aText, - destination, - contextLocal, - contextNs, - doc->GetCompatibilityMode() == - eCompatibility_NavQuirks, - PR_TRUE); + rv = nsContentUtils::ParseFragmentHTML(aText, + destination, + contextLocal, + contextNs, + doc->GetCompatibilityMode() == + eCompatibility_NavQuirks, + PR_TRUE); // HTML5 parser has notified, but not fired mutation events. FireMutationEventsForDirectParsing(doc, destination, oldChildCount); - return NS_OK; + return rv; } // couldn't parse directly nsCOMPtr<nsIDOMDocumentFragment> df; - nsresult rv = nsContentUtils::CreateContextualFragment(destination, - aText, - PR_TRUE, - getter_AddRefs(df)); + rv = nsContentUtils::CreateContextualFragment(destination, + aText, + PR_TRUE, + getter_AddRefs(df)); nsCOMPtr<nsINode> fragment = do_QueryInterface(df); NS_ENSURE_SUCCESS(rv, rv); // Suppress assertion about node removal mutation events that can't have // listeners anyway, because no one has had the chance to register mutation // listeners on the fragment that comes from the parser. nsAutoScriptBlockerSuppressNodeRemoved scriptBlocker;
--- a/editor/libeditor/html/nsHTMLDataTransfer.cpp +++ b/editor/libeditor/html/nsHTMLDataTransfer.cpp @@ -2702,33 +2702,34 @@ nsresult nsHTMLEditor::CreateDOMFragment nsresult nsHTMLEditor::ParseFragment(const nsAString & aFragStr, nsIAtom* aContextLocalName, nsIDocument* aTargetDocument, nsCOMPtr<nsIDOMNode> *outNode, bool aTrustedInput) { + nsresult rv; nsCOMPtr<nsIDOMDocumentFragment> frag; NS_NewDocumentFragment(getter_AddRefs(frag), aTargetDocument->NodeInfoManager()); nsCOMPtr<nsIContent> fragment = do_QueryInterface(frag); - nsContentUtils::ParseFragmentHTML(aFragStr, - fragment, - aContextLocalName ? - aContextLocalName : nsGkAtoms::body, - kNameSpaceID_XHTML, - PR_FALSE, - PR_TRUE); + rv = nsContentUtils::ParseFragmentHTML(aFragStr, + fragment, + aContextLocalName ? + aContextLocalName : nsGkAtoms::body, + kNameSpaceID_XHTML, + PR_FALSE, + PR_TRUE); if (!aTrustedInput) { nsTreeSanitizer sanitizer(!!aContextLocalName, !aContextLocalName); sanitizer.Sanitize(fragment); } *outNode = do_QueryInterface(frag); - return NS_OK; + return rv; } nsresult nsHTMLEditor::CreateListOfNodesToPaste(nsIDOMNode *aFragmentAsNode, nsCOMArray<nsIDOMNode>& outNodeList, nsIDOMNode *aStartNode, PRInt32 aStartOffset, nsIDOMNode *aEndNode, PRInt32 aEndOffset)
--- a/toolkit/components/feeds/nsScriptableUnescapeHTML.cpp +++ b/toolkit/components/feeds/nsScriptableUnescapeHTML.cpp @@ -175,22 +175,22 @@ nsScriptableUnescapeHTML::ParseFragment( tagStack, PR_TRUE, aReturn); fragment = do_QueryInterface(*aReturn); } else { NS_NewDocumentFragment(aReturn, document->NodeInfoManager()); fragment = do_QueryInterface(*aReturn); - nsContentUtils::ParseFragmentHTML(aFragment, - fragment, - nsGkAtoms::body, - kNameSpaceID_XHTML, - PR_FALSE, - PR_TRUE); + rv = nsContentUtils::ParseFragmentHTML(aFragment, + fragment, + nsGkAtoms::body, + kNameSpaceID_XHTML, + PR_FALSE, + PR_TRUE); // Now, set the base URI on all subtree roots. if (aBaseURI) { aBaseURI->GetSpec(spec); nsAutoString spec16; CopyUTF8toUTF16(spec, spec16); nsIContent* node = fragment->GetFirstChild(); while (node) { if (node->IsElement()) {