Bug 596182 - Make fragment parsers global. Remove resulting dead code. r=Olli.Pettay, r=bzbarsky.

This commit is contained in:
Henri Sivonen 2011-08-01 10:48:24 +03:00
parent a471ea6945
commit 0176915bb7
34 changed files with 359 additions and 1233 deletions

View File

@ -80,6 +80,8 @@ static fp_except_t oldmask = fpsetmask(~allmask);
#include "nsINode.h"
#include "nsHashtable.h"
#include "nsIDOMNode.h"
#include "nsAHtml5FragmentParser.h"
#include "nsIFragmentContentSink.h"
struct nsNativeKeyEvent; // Don't include nsINativeKeyBindings.h here: it will force strange compilation error!
@ -1037,15 +1039,44 @@ public:
*
* @param aContextNode the node which is used to resolve namespaces
* @param aFragment the string which is parsed to a DocumentFragment
* @param aWillOwnFragment is PR_TRUE if ownership of the fragment should be
* transferred to the caller.
* @param aReturn [out] the created DocumentFragment
* @param aReturn the resulting fragment
*/
static nsresult CreateContextualFragment(nsINode* aContextNode,
const nsAString& aFragment,
PRBool aWillOwnFragment,
nsIDOMDocumentFragment** aReturn);
/**
* Invoke the fragment parsing algorithm (innerHTML) using the HTML parser.
*
* @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.
*/
static void ParseFragmentHTML(const nsAString& aSourceBuffer,
nsIContent* aTargetNode,
nsIAtom* aContextLocalName,
PRInt32 aContextNamespace,
PRBool aQuirks,
PRBool 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 aReturn the result fragment
*/
static nsresult ParseFragmentXML(const nsAString& aSourceBuffer,
nsIDocument* aDocument,
nsTArray<nsString>& aTagStack,
nsIDOMDocumentFragment** aReturn);
/**
* Creates a new XML document, which is marked to be loaded as data.
*
@ -1694,6 +1725,11 @@ public:
*/
static bool AllowXULXBLForPrincipal(nsIPrincipal* aPrincipal);
/**
* Perform cleanup that's appropriate for XPCOM shutdown.
*/
static void XPCOMShutdown();
enum ContentViewerType
{
TYPE_UNSUPPORTED,
@ -1758,6 +1794,8 @@ private:
static void InitializeModifierStrings();
static void DropFragmentParsers();
static nsIDOMScriptObjectFactory *sDOMScriptObjectFactory;
static nsIXPConnect *sXPConnect;
@ -1821,6 +1859,10 @@ private:
static PRBool sIsHandlingKeyBoardEvent;
static PRBool sAllowXULXBL_for_file;
static nsAHtml5FragmentParser* sHTMLFragmentParser;
static nsIParser* sXMLFragmentParser;
static nsIFragmentContentSink* sXMLFragmentSink;
static nsString* sShiftText;
static nsString* sControlText;
static nsString* sMetaText;

View File

@ -126,8 +126,8 @@ class Element;
#define NS_IDOCUMENT_IID \
{ 0xe4bc7342, 0x6528, 0x4979, \
{ 0x9e, 0xb5, 0x12, 0xef, 0x4a, 0x97, 0xe1, 0xea } }
{ 0xfac563fb, 0x2b6a, 0x4ac8, \
{ 0x85, 0xf7, 0xd5, 0x14, 0x4b, 0x3e, 0xce, 0x78 } }
// Flag for AddStyleSheet().
#define NS_STYLESHEET_FROM_CATALOG (1 << 0)
@ -1147,16 +1147,6 @@ public:
mMayStartLayout = aMayStartLayout;
}
// This method should return an addrefed nsIParser* or nsnull. Implementations
// should transfer ownership of the parser to the caller.
virtual already_AddRefed<nsIParser> GetFragmentParser() {
return nsnull;
}
virtual void SetFragmentParser(nsIParser* aParser) {
// Do nothing.
}
already_AddRefed<nsIDocumentEncoder> GetCachedEncoder()
{
return mCachedEncoder.forget();

View File

@ -103,6 +103,7 @@
#include "nsHTMLDNSPrefetch.h"
#include "nsISupportsPrimitives.h"
#include "mozilla/Preferences.h"
#include "nsParserConstants.h"
using namespace mozilla;
@ -335,6 +336,7 @@ nsContentSink::StyleSheetLoaded(nsCSSStyleSheet* aSheet,
PRBool aWasAlternate,
nsresult aStatus)
{
NS_ASSERTION(!mFragmentMode, "How come a fragment parser observed sheets?");
if (!aWasAlternate) {
NS_ASSERTION(mPendingSheetCount > 0, "How'd that happen?");
--mPendingSheetCount;
@ -873,12 +875,13 @@ nsContentSink::ProcessStyleLink(nsIContent* aElement,
return NS_OK;
}
// If this is a fragment parser, we don't want to observe.
PRBool isAlternate;
rv = mCSSLoader->LoadStyleLink(aElement, url, aTitle, aMedia, aAlternate,
this, &isAlternate);
mFragmentMode ? nsnull : this, &isAlternate);
NS_ENSURE_SUCCESS(rv, rv);
if (!isAlternate) {
if (!isAlternate && !mFragmentMode) {
++mPendingSheetCount;
mScriptLoader->AddExecuteBlocker();
}

View File

@ -264,6 +264,10 @@ nsString* nsContentUtils::sModifierSeparator = nsnull;
PRBool nsContentUtils::sInitialized = PR_FALSE;
nsAHtml5FragmentParser* nsContentUtils::sHTMLFragmentParser = nsnull;
nsIParser* nsContentUtils::sXMLFragmentParser = nsnull;
nsIFragmentContentSink* nsContentUtils::sXMLFragmentSink = nsnull;
static PLDHashTable sEventListenerManagersHash;
class EventListenerManagerMapEntry : public PLDHashEntryHdr
@ -3606,14 +3610,11 @@ nsContentUtils::IsValidNodeName(nsIAtom *aLocalName, nsIAtom *aPrefix,
nsresult
nsContentUtils::CreateContextualFragment(nsINode* aContextNode,
const nsAString& aFragment,
PRBool aWillOwnFragment,
nsIDOMDocumentFragment** aReturn)
{
*aReturn = nsnull;
NS_ENSURE_ARG(aContextNode);
nsresult rv;
// If we don't have a document here, we can't get the right security context
// for compiling event handlers... so just bail out.
nsCOMPtr<nsIDocument> document = aContextNode->GetOwnerDoc();
@ -3625,24 +3626,9 @@ nsContentUtils::CreateContextualFragment(nsINode* aContextNode,
NS_ASSERTION(!isHTML || htmlDoc, "Should have HTMLDocument here!");
#endif
if (isHTML && nsHtml5Module::sEnabled) {
// See if the document has a cached fragment parser. nsHTMLDocument is the
// only one that should really have one at the moment.
nsCOMPtr<nsIParser> parser = document->GetFragmentParser();
if (parser) {
// Get the parser ready to use.
parser->Reset();
}
else {
// Create a new parser for this operation.
parser = nsHtml5Module::NewHtml5Parser();
if (!parser) {
return NS_ERROR_OUT_OF_MEMORY;
}
}
if (isHTML) {
nsCOMPtr<nsIDOMDocumentFragment> frag;
rv = NS_NewDocumentFragment(getter_AddRefs(frag), document->NodeInfoManager());
NS_ENSURE_SUCCESS(rv, rv);
NS_NewDocumentFragment(getter_AddRefs(frag), document->NodeInfoManager());
nsCOMPtr<nsIContent> contextAsContent = do_QueryInterface(aContextNode);
if (contextAsContent && !contextAsContent->IsElement()) {
@ -3653,31 +3639,26 @@ nsContentUtils::CreateContextualFragment(nsINode* aContextNode,
}
}
nsAHtml5FragmentParser* asFragmentParser =
static_cast<nsAHtml5FragmentParser*> (parser.get());
nsCOMPtr<nsIContent> fragment = do_QueryInterface(frag);
if (contextAsContent &&
!(nsGkAtoms::html == contextAsContent->Tag() &&
contextAsContent->IsHTML())) {
asFragmentParser->ParseHtml5Fragment(aFragment,
fragment,
contextAsContent->Tag(),
contextAsContent->GetNameSpaceID(),
(document->GetCompatibilityMode() ==
eCompatibility_NavQuirks),
PR_FALSE);
if (contextAsContent && !contextAsContent->IsHTML(nsGkAtoms::html)) {
ParseFragmentHTML(aFragment,
fragment,
contextAsContent->Tag(),
contextAsContent->GetNameSpaceID(),
(document->GetCompatibilityMode() ==
eCompatibility_NavQuirks),
PR_FALSE);
} else {
asFragmentParser->ParseHtml5Fragment(aFragment,
fragment,
nsGkAtoms::body,
kNameSpaceID_XHTML,
(document->GetCompatibilityMode() ==
eCompatibility_NavQuirks),
PR_FALSE);
ParseFragmentHTML(aFragment,
fragment,
nsGkAtoms::body,
kNameSpaceID_XHTML,
(document->GetCompatibilityMode() ==
eCompatibility_NavQuirks),
PR_FALSE);
}
frag.swap(*aReturn);
document->SetFragmentParser(parser);
frag.forget(aReturn);
return NS_OK;
}
@ -3736,84 +3717,88 @@ nsContentUtils::CreateContextualFragment(nsINode* aContextNode,
content = content->GetParent();
}
nsCAutoString contentType;
nsAutoString buf;
document->GetContentType(buf);
LossyCopyUTF16toASCII(buf, contentType);
return ParseFragmentXML(aFragment, document, tagStack, aReturn);
}
// See if the document has a cached fragment parser. nsHTMLDocument is the
// only one that should really have one at the moment.
nsCOMPtr<nsIParser> parser = document->GetFragmentParser();
if (parser) {
// Get the parser ready to use.
parser->Reset();
/* static */
void
nsContentUtils::DropFragmentParsers()
{
NS_IF_RELEASE(sHTMLFragmentParser);
NS_IF_RELEASE(sXMLFragmentParser);
NS_IF_RELEASE(sXMLFragmentSink);
}
/* static */
void
nsContentUtils::XPCOMShutdown()
{
nsContentUtils::DropFragmentParsers();
}
/* static */
void
nsContentUtils::ParseFragmentHTML(const nsAString& aSourceBuffer,
nsIContent* aTargetNode,
nsIAtom* aContextLocalName,
PRInt32 aContextNamespace,
PRBool aQuirks,
PRBool aPreventScriptExecution)
{
if (!sHTMLFragmentParser) {
sHTMLFragmentParser =
static_cast<nsAHtml5FragmentParser*>(nsHtml5Module::NewHtml5Parser().get());
// Now sHTMLFragmentParser owns the object
}
else {
// Create a new parser for this operation.
parser = do_CreateInstance(kCParserCID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
sHTMLFragmentParser->ParseHtml5Fragment(aSourceBuffer,
aTargetNode,
aContextLocalName,
aContextNamespace,
aQuirks,
aPreventScriptExecution);
sHTMLFragmentParser->Reset();
}
/* static */
nsresult
nsContentUtils::ParseFragmentXML(const nsAString& aSourceBuffer,
nsIDocument* aDocument,
nsTArray<nsString>& aTagStack,
nsIDOMDocumentFragment** aReturn)
{
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
}
nsCOMPtr<nsIContentSink> contentsink = do_QueryInterface(sXMLFragmentSink);
NS_ABORT_IF_FALSE(contentsink, "Sink doesn't QI to nsIContentSink!");
sXMLFragmentParser->SetContentSink(contentsink);
sXMLFragmentSink->SetTargetDocument(aDocument);
nsresult rv =
sXMLFragmentParser->ParseFragment(aSourceBuffer,
aTagStack);
if (NS_FAILED(rv)) {
// Drop the fragment parser and sink that might be in an inconsistent state
NS_IF_RELEASE(sXMLFragmentParser);
NS_IF_RELEASE(sXMLFragmentSink);
return rv;
}
// See if the parser already has a content sink that we can reuse.
nsCOMPtr<nsIFragmentContentSink> sink;
nsCOMPtr<nsIContentSink> contentsink = parser->GetContentSink();
if (contentsink) {
// Make sure it's the correct type.
if (isHTML) {
nsCOMPtr<nsIHTMLContentSink> htmlsink = do_QueryInterface(contentsink);
sink = do_QueryInterface(htmlsink);
}
else {
nsCOMPtr<nsIXMLContentSink> xmlsink = do_QueryInterface(contentsink);
sink = do_QueryInterface(xmlsink);
}
}
rv = sXMLFragmentSink->FinishFragmentParsing(aReturn);
if (!sink) {
// Either there was no cached content sink or it was the wrong type. Make a
// new one.
if (isHTML) {
rv = NS_NewHTMLFragmentContentSink(getter_AddRefs(sink));
} else {
rv = NS_NewXMLFragmentContentSink(getter_AddRefs(sink));
}
NS_ENSURE_SUCCESS(rv, rv);
contentsink = do_QueryInterface(sink);
NS_ASSERTION(contentsink, "Sink doesn't QI to nsIContentSink!");
parser->SetContentSink(contentsink);
}
sink->SetTargetDocument(document);
nsDTDMode mode = eDTDMode_autodetect;
switch (document->GetCompatibilityMode()) {
case eCompatibility_NavQuirks:
mode = eDTDMode_quirks;
break;
case eCompatibility_AlmostStandards:
mode = eDTDMode_almost_standards;
break;
case eCompatibility_FullStandards:
mode = eDTDMode_full_standards;
break;
default:
NS_NOTREACHED("unknown mode");
break;
}
rv = parser->ParseFragment(aFragment, nsnull, tagStack,
!isHTML, contentType, mode);
if (NS_SUCCEEDED(rv)) {
rv = sink->GetFragment(aWillOwnFragment, aReturn);
}
document->SetFragmentParser(parser);
sXMLFragmentParser->Reset();
return rv;
}
/* static */
nsresult
nsContentUtils::CreateDocument(const nsAString& aNamespaceURI,

View File

@ -73,6 +73,7 @@
#include "nsIEditor.h"
#include "nsIHTMLEditor.h"
#include "mozilla/dom/Element.h"
#include "nsParserConstants.h"
using namespace mozilla::dom;

View File

@ -40,12 +40,12 @@
*/
#include "nsParserUtils.h"
#include "nsIParser.h" // for kQuote et. al.
#include "jsapi.h"
#include "nsReadableUtils.h"
#include "nsCRT.h"
#include "nsContentUtils.h"
#include "nsIParserService.h"
#include "nsParserConstants.h"
#define SKIP_WHITESPACE(iter, end_iter, end_res) \
while ((iter) != (end_iter) && nsCRT::IsAsciiSpace(*(iter))) { \

View File

@ -2054,7 +2054,7 @@ nsRange::CreateContextualFragment(const nsAString& aFragment,
{
if (mIsPositioned) {
return nsContentUtils::CreateContextualFragment(mStartParent, aFragment,
PR_TRUE, aReturn);
aReturn);
}
return NS_ERROR_FAILURE;
}

View File

@ -68,6 +68,7 @@
#include "nsLWBrkCIID.h"
#include "nsIScriptElement.h"
#include "nsAttrName.h"
#include "nsParserConstants.h"
static const char kMozStr[] = "moz";

View File

@ -65,6 +65,7 @@
#include "nsAttrName.h"
#include "nsILineBreaker.h"
#include "mozilla/dom/Element.h"
#include "nsParserConstants.h"
using namespace mozilla::dom;

View File

@ -751,27 +751,15 @@ nsGenericHTMLElement::SetInnerHTML(const nsAString& aInnerHTML)
PRBool scripts_enabled = loader->GetEnabled();
loader->SetEnabled(PR_FALSE);
if (doc->IsHTML() && nsHtml5Module::sEnabled) {
nsCOMPtr<nsIParser> parser = doc->GetFragmentParser();
if (parser) {
parser->Reset();
} else {
parser = nsHtml5Module::NewHtml5Parser();
NS_ENSURE_TRUE(parser, NS_ERROR_OUT_OF_MEMORY);
}
if (doc->IsHTML()) {
PRInt32 oldChildCount = GetChildCount();
nsAHtml5FragmentParser* asFragmentParser =
static_cast<nsAHtml5FragmentParser*> (parser.get());
asFragmentParser->ParseHtml5Fragment(aInnerHTML,
this,
Tag(),
GetNameSpaceID(),
doc->GetCompatibilityMode() ==
eCompatibility_NavQuirks,
PR_TRUE);
doc->SetFragmentParser(parser);
nsContentUtils::ParseFragmentHTML(aInnerHTML,
this,
Tag(),
GetNameSpaceID(),
doc->GetCompatibilityMode() ==
eCompatibility_NavQuirks,
PR_TRUE);
// HTML5 parser has notified, but not fired mutation events.
// Fire mutation events. Optimize for the case when there are no listeners
PRInt32 newChildCount = GetChildCount();
@ -787,7 +775,7 @@ nsGenericHTMLElement::SetInnerHTML(const nsAString& aInnerHTML)
nsGenericElement::FireNodeInserted(doc, this, childNodes);
}
} else {
rv = nsContentUtils::CreateContextualFragment(this, aInnerHTML, PR_FALSE,
rv = nsContentUtils::CreateContextualFragment(this, aInnerHTML,
getter_AddRefs(df));
nsCOMPtr<nsINode> fragment = do_QueryInterface(df);
if (NS_SUCCEEDED(rv)) {

View File

@ -49,7 +49,6 @@ LIBXUL_LIBRARY = 1
CPPSRCS = \
nsHTMLContentSink.cpp \
nsHTMLFragmentContentSink.cpp \
nsHTMLDocument.cpp \
ImageDocument.cpp \
MediaDocument.cpp \

View File

@ -2632,8 +2632,10 @@ HTMLContentSink::ProcessLINKTag(const nsIParserNode& aNode)
ssle->SetEnableUpdates(PR_TRUE);
PRBool willNotify;
PRBool isAlternate;
result = ssle->UpdateStyleSheet(this, &willNotify, &isAlternate);
if (NS_SUCCEEDED(result) && willNotify && !isAlternate) {
result = ssle->UpdateStyleSheet(mFragmentMode ? nsnull : this,
&willNotify,
&isAlternate);
if (NS_SUCCEEDED(result) && willNotify && !isAlternate && !mFragmentMode) {
++mPendingSheetCount;
mScriptLoader->AddExecuteBlocker();
}
@ -2845,8 +2847,10 @@ HTMLContentSink::ProcessSTYLEEndTag(nsGenericHTMLElement* content)
ssle->SetEnableUpdates(PR_TRUE);
PRBool willNotify;
PRBool isAlternate;
rv = ssle->UpdateStyleSheet(this, &willNotify, &isAlternate);
if (NS_SUCCEEDED(rv) && willNotify && !isAlternate) {
rv = ssle->UpdateStyleSheet(mFragmentMode ? nsnull : this,
&willNotify,
&isAlternate);
if (NS_SUCCEEDED(rv) && willNotify && !isAlternate && !mFragmentMode) {
++mPendingSheetCount;
mScriptLoader->AddExecuteBlocker();
}

View File

@ -285,7 +285,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsHTMLDocument, nsDocument)
nsIDOMNodeList)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mWyciwygChannel)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mMidasCommandManager)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFragmentParser)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsHTMLDocument, nsDocument)
@ -298,7 +297,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsHTMLDocument, nsDocument)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFormControls)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mWyciwygChannel)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mMidasCommandManager)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFragmentParser)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_ADDREF_INHERITED(nsHTMLDocument, nsDocument)

View File

@ -194,13 +194,6 @@ public:
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsHTMLDocument, nsDocument)
virtual already_AddRefed<nsIParser> GetFragmentParser() {
return mFragmentParser.forget();
}
virtual void SetFragmentParser(nsIParser* aParser) {
mFragmentParser = aParser;
}
virtual nsresult SetEditingState(EditingState aState);
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
@ -342,9 +335,6 @@ protected:
// When false, the .cookies property is completely disabled
PRBool mDisableCookieAccess;
// Parser used for constructing document fragments.
nsCOMPtr<nsIParser> mFragmentParser;
};
#define NS_HTML_DOCUMENT_INTERFACE_TABLE_BEGIN(_class) \

View File

@ -1,780 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=2 et tw=80: */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (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/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Robert Sayre <sayrer@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsCOMPtr.h"
#include "nsIServiceManager.h"
#include "nsIFragmentContentSink.h"
#include "nsIDTD.h"
#include "nsIHTMLContentSink.h"
#include "nsIParser.h"
#include "nsIParserService.h"
#include "nsGkAtoms.h"
#include "nsHTMLTokens.h"
#include "nsGenericHTMLElement.h"
#include "nsIDOMText.h"
#include "nsIDOMComment.h"
#include "nsIDOMHTMLFormElement.h"
#include "nsIDOMDocumentFragment.h"
#include "nsTArray.h"
#include "nsINameSpaceManager.h"
#include "nsIDocument.h"
#include "nsINodeInfo.h"
#include "prmem.h"
#include "nsReadableUtils.h"
#include "nsUnicharUtils.h"
#include "nsContentUtils.h"
#include "nsEscape.h"
#include "nsNodeInfoManager.h"
#include "nsNullPrincipal.h"
#include "nsContentCreatorFunctions.h"
#include "nsNetUtil.h"
#include "nsIScriptSecurityManager.h"
#include "nsContentSink.h"
#include "nsTHashtable.h"
#include "nsCycleCollectionParticipant.h"
#include "nsCSSParser.h"
#include "nsCSSProperty.h"
#include "mozilla/css/Declaration.h"
#include "mozilla/css/StyleRule.h"
#include "nsCSSStyleSheet.h"
#include "nsICSSRuleList.h"
#include "nsIDOMCSSRule.h"
using namespace mozilla::dom;
namespace css = mozilla::css;
//
// XXX THIS IS TEMPORARY CODE
// There's a considerable amount of copied code from the
// regular nsHTMLContentSink. All of it will be factored
// at some pointe really soon!
//
class nsHTMLFragmentContentSink : public nsIFragmentContentSink,
public nsIHTMLContentSink {
public:
/**
* @param aAllContent Whether there is context information available for the fragment.
*/
nsHTMLFragmentContentSink(PRBool aAllContent = PR_FALSE);
virtual ~nsHTMLFragmentContentSink();
// nsISupports
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsHTMLFragmentContentSink,
nsIContentSink)
NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
// nsIContentSink
NS_IMETHOD WillParse(void) { return NS_OK; }
NS_IMETHOD WillBuildModel(nsDTDMode aDTDMode);
NS_IMETHOD DidBuildModel(PRBool aTerminated);
NS_IMETHOD WillInterrupt(void);
NS_IMETHOD WillResume(void);
NS_IMETHOD SetParser(nsIParser* aParser);
virtual void FlushPendingNotifications(mozFlushType aType) { }
NS_IMETHOD SetDocumentCharset(nsACString& aCharset) { return NS_OK; }
virtual nsISupports *GetTarget() { return mTargetDocument; }
// nsIHTMLContentSink
NS_IMETHOD BeginContext(PRInt32 aID);
NS_IMETHOD EndContext(PRInt32 aID);
NS_IMETHOD OpenHead();
NS_IMETHOD IsEnabled(PRInt32 aTag, PRBool* aReturn) {
*aReturn = PR_TRUE;
return NS_OK;
}
NS_IMETHOD_(PRBool) IsFormOnStack() { return PR_FALSE; }
NS_IMETHOD DidProcessTokens(void) { return NS_OK; }
NS_IMETHOD WillProcessAToken(void) { return NS_OK; }
NS_IMETHOD DidProcessAToken(void) { return NS_OK; }
NS_IMETHOD NotifyTagObservers(nsIParserNode* aNode) { return NS_OK; }
NS_IMETHOD OpenContainer(const nsIParserNode& aNode);
NS_IMETHOD CloseContainer(const nsHTMLTag aTag);
NS_IMETHOD AddLeaf(const nsIParserNode& aNode);
NS_IMETHOD AddComment(const nsIParserNode& aNode);
NS_IMETHOD AddProcessingInstruction(const nsIParserNode& aNode);
NS_IMETHOD AddDocTypeDecl(const nsIParserNode& aNode);
// nsIFragmentContentSink
NS_IMETHOD GetFragment(PRBool aWillOwnFragment,
nsIDOMDocumentFragment** aFragment);
NS_IMETHOD SetTargetDocument(nsIDocument* aDocument);
NS_IMETHOD WillBuildContent();
NS_IMETHOD DidBuildContent();
NS_IMETHOD IgnoreFirstContainer();
nsIContent* GetCurrentContent();
PRInt32 PushContent(nsIContent *aContent);
nsIContent* PopContent();
virtual nsresult AddAttributes(const nsIParserNode& aNode,
nsIContent* aContent);
nsresult AddText(const nsAString& aString);
nsresult FlushText();
PRPackedBool mAllContent;
PRPackedBool mProcessing;
PRPackedBool mSeenBody;
PRPackedBool mIgnoreContainer;
PRPackedBool mIgnoreNextCloseHead;
nsCOMPtr<nsIContent> mRoot;
nsCOMPtr<nsIParser> mParser;
nsTArray<nsIContent*>* mContentStack;
PRUnichar* mText;
PRInt32 mTextLength;
PRInt32 mTextSize;
nsCOMPtr<nsIDocument> mTargetDocument;
nsRefPtr<nsNodeInfoManager> mNodeInfoManager;
nsINodeInfo* mNodeInfoCache[NS_HTML_TAG_MAX + 1];
};
static nsresult
NewHTMLFragmentContentSinkHelper(PRBool aAllContent, nsIFragmentContentSink** aResult)
{
NS_PRECONDITION(aResult, "Null out ptr");
if (nsnull == aResult) {
return NS_ERROR_NULL_POINTER;
}
nsHTMLFragmentContentSink* it = new nsHTMLFragmentContentSink(aAllContent);
if (nsnull == it) {
return NS_ERROR_OUT_OF_MEMORY;
}
NS_ADDREF(*aResult = it);
return NS_OK;
}
nsresult
NS_NewHTMLFragmentContentSink2(nsIFragmentContentSink** aResult)
{
return NewHTMLFragmentContentSinkHelper(PR_TRUE,aResult);
}
nsresult
NS_NewHTMLFragmentContentSink(nsIFragmentContentSink** aResult)
{
return NewHTMLFragmentContentSinkHelper(PR_FALSE,aResult);
}
nsHTMLFragmentContentSink::nsHTMLFragmentContentSink(PRBool aAllContent)
: mAllContent(aAllContent),
mProcessing(aAllContent),
mSeenBody(!aAllContent)
{
// Note: operator new zeros our memory
}
nsHTMLFragmentContentSink::~nsHTMLFragmentContentSink()
{
// Should probably flush the text buffer here, just to make sure:
//FlushText();
if (nsnull != mContentStack) {
// there shouldn't be anything here except in an error condition
PRInt32 indx = mContentStack->Length();
while (0 < indx--) {
nsIContent* content = mContentStack->ElementAt(indx);
NS_RELEASE(content);
}
delete mContentStack;
}
PR_FREEIF(mText);
PRUint32 i;
for (i = 0; i < NS_ARRAY_LENGTH(mNodeInfoCache); ++i) {
NS_IF_RELEASE(mNodeInfoCache[i]);
}
}
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsHTMLFragmentContentSink)
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsHTMLFragmentContentSink)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsHTMLFragmentContentSink)
NS_INTERFACE_MAP_ENTRY(nsIFragmentContentSink)
NS_INTERFACE_MAP_ENTRY(nsIHTMLContentSink)
NS_INTERFACE_MAP_ENTRY(nsIContentSink)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContentSink)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTION_CLASS(nsHTMLFragmentContentSink)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsHTMLFragmentContentSink)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mParser)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTargetDocument)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mRoot)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mNodeInfoManager)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsHTMLFragmentContentSink)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mParser)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTargetDocument)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mRoot)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_MEMBER(mNodeInfoManager,
nsNodeInfoManager)
{
PRUint32 i;
for (i = 0; i < NS_ARRAY_LENGTH(tmp->mNodeInfoCache); ++i) {
cb.NoteXPCOMChild(tmp->mNodeInfoCache[i]);
}
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMETHODIMP
nsHTMLFragmentContentSink::WillBuildModel(nsDTDMode)
{
if (mRoot) {
return NS_OK;
}
NS_ASSERTION(mNodeInfoManager, "Need a nodeinfo manager!");
nsCOMPtr<nsIDOMDocumentFragment> frag;
nsresult rv = NS_NewDocumentFragment(getter_AddRefs(frag), mNodeInfoManager);
NS_ENSURE_SUCCESS(rv, rv);
mRoot = do_QueryInterface(frag, &rv);
return rv;
}
NS_IMETHODIMP
nsHTMLFragmentContentSink::DidBuildModel(PRBool aTerminated)
{
FlushText();
// Drop our reference to the parser to get rid of a circular
// reference.
mParser = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsHTMLFragmentContentSink::WillInterrupt(void)
{
return NS_OK;
}
NS_IMETHODIMP
nsHTMLFragmentContentSink::WillResume(void)
{
return NS_OK;
}
NS_IMETHODIMP
nsHTMLFragmentContentSink::SetParser(nsIParser* aParser)
{
mParser = aParser;
return NS_OK;
}
NS_IMETHODIMP
nsHTMLFragmentContentSink::BeginContext(PRInt32 aID)
{
return NS_OK;
}
NS_IMETHODIMP
nsHTMLFragmentContentSink::EndContext(PRInt32 aID)
{
return NS_OK;
}
NS_IMETHODIMP
nsHTMLFragmentContentSink::OpenHead()
{
mIgnoreNextCloseHead = PR_TRUE;
return NS_OK;
}
NS_IMETHODIMP
nsHTMLFragmentContentSink::OpenContainer(const nsIParserNode& aNode)
{
NS_ENSURE_TRUE(mNodeInfoManager, NS_ERROR_NOT_INITIALIZED);
nsresult result = NS_OK;
nsHTMLTag nodeType = nsHTMLTag(aNode.GetNodeType());
if (nodeType == eHTMLTag_html) {
return NS_OK;
}
// Ignore repeated BODY elements. The DTD is just sending them
// to us for compatibility reasons that don't apply here.
if (nodeType == eHTMLTag_body) {
if (mSeenBody) {
return NS_OK;
}
mSeenBody = PR_TRUE;
}
if (mProcessing && !mIgnoreContainer) {
FlushText();
nsIContent *content = nsnull;
nsCOMPtr<nsINodeInfo> nodeInfo;
if (nodeType == eHTMLTag_userdefined) {
nsAutoString lower;
nsContentUtils::ASCIIToLower(aNode.GetText(), lower);
nsCOMPtr<nsIAtom> name = do_GetAtom(lower);
nodeInfo = mNodeInfoManager->GetNodeInfo(name,
nsnull,
kNameSpaceID_XHTML,
nsIDOMNode::ELEMENT_NODE);
NS_ENSURE_TRUE(nodeInfo, NS_ERROR_OUT_OF_MEMORY);
}
else if (mNodeInfoCache[nodeType]) {
nodeInfo = mNodeInfoCache[nodeType];
}
else {
nsIParserService* parserService = nsContentUtils::GetParserService();
if (!parserService)
return NS_ERROR_OUT_OF_MEMORY;
nsIAtom *name = parserService->HTMLIdToAtomTag(nodeType);
NS_ASSERTION(name, "This should not happen!");
nodeInfo = mNodeInfoManager->GetNodeInfo(name,
nsnull,
kNameSpaceID_XHTML,
nsIDOMNode::ELEMENT_NODE);
NS_ENSURE_TRUE(nodeInfo, NS_ERROR_OUT_OF_MEMORY);
NS_ADDREF(mNodeInfoCache[nodeType] = nodeInfo);
}
content =
CreateHTMLElement(nodeType, nodeInfo.forget(), NOT_FROM_PARSER).get();
NS_ENSURE_TRUE(content, NS_ERROR_OUT_OF_MEMORY);
result = AddAttributes(aNode, content);
if (NS_FAILED(result)) {
NS_RELEASE(content);
return result;
}
nsIContent *parent = GetCurrentContent();
if (!parent) {
parent = mRoot;
}
parent->AppendChildTo(content, PR_FALSE);
PushContent(content);
}
else if (mProcessing && mIgnoreContainer) {
mIgnoreContainer = PR_FALSE;
}
return result;
}
NS_IMETHODIMP
nsHTMLFragmentContentSink::CloseContainer(const nsHTMLTag aTag)
{
if (aTag == eHTMLTag_html) {
return NS_OK;
}
if (mIgnoreNextCloseHead && aTag == eHTMLTag_head) {
mIgnoreNextCloseHead = PR_FALSE;
return NS_OK;
}
if (mProcessing && (nsnull != GetCurrentContent())) {
nsIContent* content;
FlushText();
content = PopContent();
NS_RELEASE(content);
}
return NS_OK;
}
NS_IMETHODIMP
nsHTMLFragmentContentSink::AddLeaf(const nsIParserNode& aNode)
{
NS_ENSURE_TRUE(mNodeInfoManager, NS_ERROR_NOT_INITIALIZED);
nsresult result = NS_OK;
switch (aNode.GetTokenType()) {
case eToken_start:
{
FlushText();
// Create new leaf content object
nsRefPtr<nsGenericHTMLElement> content;
nsHTMLTag nodeType = nsHTMLTag(aNode.GetNodeType());
nsIParserService* parserService = nsContentUtils::GetParserService();
if (!parserService)
return NS_ERROR_OUT_OF_MEMORY;
nsCOMPtr<nsINodeInfo> nodeInfo;
if (nodeType == eHTMLTag_userdefined) {
nsAutoString lower;
nsContentUtils::ASCIIToLower(aNode.GetText(), lower);
nsCOMPtr<nsIAtom> name = do_GetAtom(lower);
nodeInfo = mNodeInfoManager->GetNodeInfo(name, nsnull,
kNameSpaceID_XHTML,
nsIDOMNode::ELEMENT_NODE);
NS_ENSURE_TRUE(nodeInfo, NS_ERROR_OUT_OF_MEMORY);
}
else if (mNodeInfoCache[nodeType]) {
nodeInfo = mNodeInfoCache[nodeType];
}
else {
nsIAtom *name = parserService->HTMLIdToAtomTag(nodeType);
NS_ASSERTION(name, "This should not happen!");
nodeInfo = mNodeInfoManager->GetNodeInfo(name, nsnull,
kNameSpaceID_XHTML,
nsIDOMNode::ELEMENT_NODE);
NS_ENSURE_TRUE(nodeInfo, NS_ERROR_OUT_OF_MEMORY);
NS_ADDREF(mNodeInfoCache[nodeType] = nodeInfo);
}
content =
CreateHTMLElement(nodeType, nodeInfo.forget(), NOT_FROM_PARSER);
NS_ENSURE_TRUE(content, NS_ERROR_OUT_OF_MEMORY);
result = AddAttributes(aNode, content);
NS_ENSURE_SUCCESS(result, result);
nsIContent *parent = GetCurrentContent();
if (!parent) {
parent = mRoot;
}
parent->AppendChildTo(content, PR_FALSE);
}
break;
case eToken_text:
case eToken_whitespace:
case eToken_newline:
result = AddText(aNode.GetText());
break;
case eToken_entity:
{
nsAutoString tmp;
PRInt32 unicode = aNode.TranslateToUnicodeStr(tmp);
if (unicode < 0) {
result = AddText(aNode.GetText());
}
else {
result = AddText(tmp);
}
}
break;
}
return result;
}
NS_IMETHODIMP
nsHTMLFragmentContentSink::AddComment(const nsIParserNode& aNode)
{
nsCOMPtr<nsIContent> comment;
nsresult result = NS_OK;
FlushText();
result = NS_NewCommentNode(getter_AddRefs(comment), mNodeInfoManager);
if (NS_SUCCEEDED(result)) {
comment->SetText(aNode.GetText(), PR_FALSE);
nsIContent *parent = GetCurrentContent();
if (nsnull == parent) {
parent = mRoot;
}
parent->AppendChildTo(comment, PR_FALSE);
}
return NS_OK;
}
NS_IMETHODIMP
nsHTMLFragmentContentSink::AddProcessingInstruction(const nsIParserNode& aNode)
{
return NS_OK;
}
/**
* This gets called by the parser when it encounters
* a DOCTYPE declaration in the HTML document.
*/
NS_IMETHODIMP
nsHTMLFragmentContentSink::AddDocTypeDecl(const nsIParserNode& aNode)
{
return NS_OK;
}
NS_IMETHODIMP
nsHTMLFragmentContentSink::GetFragment(PRBool aWillOwnFragment,
nsIDOMDocumentFragment** aFragment)
{
if (mRoot) {
nsresult rv = CallQueryInterface(mRoot, aFragment);
if (NS_SUCCEEDED(rv) && aWillOwnFragment) {
mRoot = nsnull;
}
return rv;
}
*aFragment = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsHTMLFragmentContentSink::SetTargetDocument(nsIDocument* aTargetDocument)
{
NS_ENSURE_ARG_POINTER(aTargetDocument);
mTargetDocument = aTargetDocument;
mNodeInfoManager = aTargetDocument->NodeInfoManager();
return NS_OK;
}
NS_IMETHODIMP
nsHTMLFragmentContentSink::WillBuildContent()
{
mProcessing = PR_TRUE;
return NS_OK;
}
NS_IMETHODIMP
nsHTMLFragmentContentSink::DidBuildContent()
{
if (!mAllContent) {
FlushText();
DidBuildModel(PR_FALSE); // Release our ref to the parser now.
mProcessing = PR_FALSE;
}
return NS_OK;
}
NS_IMETHODIMP
nsHTMLFragmentContentSink::IgnoreFirstContainer()
{
mIgnoreContainer = PR_TRUE;
return NS_OK;
}
nsIContent*
nsHTMLFragmentContentSink::GetCurrentContent()
{
if (nsnull != mContentStack) {
PRInt32 indx = mContentStack->Length() - 1;
if (indx >= 0)
return mContentStack->ElementAt(indx);
}
return nsnull;
}
PRInt32
nsHTMLFragmentContentSink::PushContent(nsIContent *aContent)
{
if (nsnull == mContentStack) {
mContentStack = new nsTArray<nsIContent*>();
}
mContentStack->AppendElement(aContent);
return mContentStack->Length();
}
nsIContent*
nsHTMLFragmentContentSink::PopContent()
{
nsIContent* content = nsnull;
if (nsnull != mContentStack) {
PRInt32 indx = mContentStack->Length() - 1;
if (indx >= 0) {
content = mContentStack->ElementAt(indx);
mContentStack->RemoveElementAt(indx);
}
}
return content;
}
#define NS_ACCUMULATION_BUFFER_SIZE 4096
nsresult
nsHTMLFragmentContentSink::AddText(const nsAString& aString)
{
PRInt32 addLen = aString.Length();
if (0 == addLen) {
return NS_OK;
}
// Create buffer when we first need it
if (0 == mTextSize) {
mText = (PRUnichar *) PR_MALLOC(sizeof(PRUnichar) * NS_ACCUMULATION_BUFFER_SIZE);
if (nsnull == mText) {
return NS_ERROR_OUT_OF_MEMORY;
}
mTextSize = NS_ACCUMULATION_BUFFER_SIZE;
}
// Copy data from string into our buffer; flush buffer when it fills up
PRInt32 offset = 0;
PRBool isLastCharCR = PR_FALSE;
while (0 != addLen) {
PRInt32 amount = mTextSize - mTextLength;
if (amount > addLen) {
amount = addLen;
}
if (0 == amount) {
nsresult rv = FlushText();
if (NS_OK != rv) {
return rv;
}
}
mTextLength +=
nsContentUtils::CopyNewlineNormalizedUnicodeTo(aString,
offset,
&mText[mTextLength],
amount,
isLastCharCR);
offset += amount;
addLen -= amount;
}
return NS_OK;
}
nsresult
nsHTMLFragmentContentSink::FlushText()
{
if (0 == mTextLength) {
return NS_OK;
}
nsCOMPtr<nsIContent> content;
nsresult rv = NS_NewTextNode(getter_AddRefs(content), mNodeInfoManager);
NS_ENSURE_SUCCESS(rv, rv);
// Set the text in the text node
content->SetText(mText, mTextLength, PR_FALSE);
// Add text to its parent
nsIContent *parent = GetCurrentContent();
if (!parent) {
parent = mRoot;
}
rv = parent->AppendChildTo(content, PR_FALSE);
mTextLength = 0;
return rv;
}
// XXX Code copied from nsHTMLContentSink. It should be shared.
nsresult
nsHTMLFragmentContentSink::AddAttributes(const nsIParserNode& aNode,
nsIContent* aContent)
{
// Add tag attributes to the content attributes
PRInt32 ac = aNode.GetAttributeCount();
if (ac == 0) {
// No attributes, nothing to do. Do an early return to avoid
// constructing the nsAutoString object for nothing.
return NS_OK;
}
nsAutoString k;
nsHTMLTag nodeType = nsHTMLTag(aNode.GetNodeType());
// The attributes are on the parser node in the order they came in in the
// source. What we want to happen if a single attribute is set multiple
// times on an element is that the first time should "win". That is, <input
// value="foo" value="bar"> should show "foo". So we loop over the
// attributes backwards; this ensures that the first attribute in the set
// wins. This does mean that we do some extra work in the case when the same
// attribute is set multiple times, but we save a HasAttr call in the much
// more common case of reasonable HTML.
for (PRInt32 i = ac - 1; i >= 0; i--) {
// Get lower-cased key
nsContentUtils::ASCIIToLower(aNode.GetKeyAt(i), k);
nsCOMPtr<nsIAtom> keyAtom = do_GetAtom(k);
// Get value and remove mandatory quotes
static const char* kWhitespace = "\n\r\t\b";
const nsAString& v =
nsContentUtils::TrimCharsInSet(kWhitespace, aNode.GetValueAt(i));
if (nodeType == eHTMLTag_a && keyAtom == nsGkAtoms::name) {
NS_ConvertUTF16toUTF8 cname(v);
NS_ConvertUTF8toUTF16 uv(nsUnescape(cname.BeginWriting()));
// Add attribute to content
aContent->SetAttr(kNameSpaceID_None, keyAtom, uv, PR_FALSE);
} else {
// Add attribute to content
aContent->SetAttr(kNameSpaceID_None, keyAtom, v, PR_FALSE);
}
}
return NS_OK;
}

View File

@ -631,8 +631,10 @@ nsXMLContentSink::CloseElement(nsIContent* aContent)
ssle->SetEnableUpdates(PR_TRUE);
PRBool willNotify;
PRBool isAlternate;
rv = ssle->UpdateStyleSheet(this, &willNotify, &isAlternate);
if (NS_SUCCEEDED(rv) && willNotify && !isAlternate) {
rv = ssle->UpdateStyleSheet(mFragmentMode ? nsnull : this,
&willNotify,
&isAlternate);
if (NS_SUCCEEDED(rv) && willNotify && !isAlternate && !mFragmentMode) {
++mPendingSheetCount;
mScriptLoader->AddExecuteBlocker();
}
@ -1307,12 +1309,14 @@ nsXMLContentSink::HandleProcessingInstruction(const PRUnichar *aTarget,
ssle->SetEnableUpdates(PR_TRUE);
PRBool willNotify;
PRBool isAlternate;
rv = ssle->UpdateStyleSheet(this, &willNotify, &isAlternate);
rv = ssle->UpdateStyleSheet(mFragmentMode ? nsnull : this,
&willNotify,
&isAlternate);
NS_ENSURE_SUCCESS(rv, rv);
if (willNotify) {
// Successfully started a stylesheet load
if (!isAlternate) {
if (!isAlternate && !mFragmentMode) {
++mPendingSheetCount;
mScriptLoader->AddExecuteBlocker();
}

View File

@ -63,6 +63,9 @@
#include "nsHashKeys.h"
#include "nsTArray.h"
#include "nsCycleCollectionParticipant.h"
#include "nsIDocShell.h"
#include "nsScriptLoader.h"
#include "mozilla/css/Loader.h"
using namespace mozilla::dom;
@ -70,7 +73,7 @@ class nsXMLFragmentContentSink : public nsXMLContentSink,
public nsIFragmentContentSink
{
public:
nsXMLFragmentContentSink(PRBool aAllContent = PR_FALSE);
nsXMLFragmentContentSink();
virtual ~nsXMLFragmentContentSink();
NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
@ -106,8 +109,7 @@ public:
// nsIXMLContentSink
// nsIFragmentContentSink
NS_IMETHOD GetFragment(PRBool aWillOwnFragment,
nsIDOMDocumentFragment** aFragment);
NS_IMETHOD FinishFragmentParsing(nsIDOMDocumentFragment** aFragment);
NS_IMETHOD SetTargetDocument(nsIDocument* aDocument);
NS_IMETHOD WillBuildContent();
NS_IMETHOD DidBuildContent();
@ -139,15 +141,12 @@ protected:
// the fragment
nsCOMPtr<nsIContent> mRoot;
PRPackedBool mParseError;
// if FALSE, take content inside endnote tag
PRPackedBool mAllContent;
};
static nsresult
NewXMLFragmentContentSinkHelper(PRBool aAllContent, nsIFragmentContentSink** aResult)
NewXMLFragmentContentSinkHelper(nsIFragmentContentSink** aResult)
{
nsXMLFragmentContentSink* it = new nsXMLFragmentContentSink(aAllContent);
nsXMLFragmentContentSink* it = new nsXMLFragmentContentSink();
if (!it) {
return NS_ERROR_OUT_OF_MEMORY;
}
@ -157,21 +156,16 @@ NewXMLFragmentContentSinkHelper(PRBool aAllContent, nsIFragmentContentSink** aRe
return NS_OK;
}
nsresult
NS_NewXMLFragmentContentSink2(nsIFragmentContentSink** aResult)
{
return NewXMLFragmentContentSinkHelper(PR_TRUE, aResult);
}
nsresult
NS_NewXMLFragmentContentSink(nsIFragmentContentSink** aResult)
{
return NewXMLFragmentContentSinkHelper(PR_FALSE, aResult);
return NewXMLFragmentContentSinkHelper(aResult);
}
nsXMLFragmentContentSink::nsXMLFragmentContentSink(PRBool aAllContent)
: mParseError(PR_FALSE), mAllContent(aAllContent)
nsXMLFragmentContentSink::nsXMLFragmentContentSink()
: mParseError(PR_FALSE)
{
mFragmentMode = PR_TRUE;
}
nsXMLFragmentContentSink::~nsXMLFragmentContentSink()
@ -210,21 +204,12 @@ nsXMLFragmentContentSink::WillBuildModel(nsDTDMode aDTDMode)
mRoot = do_QueryInterface(frag);
if (mAllContent) {
// Preload content stack because we know all content goes in the fragment
PushContent(mRoot);
}
return rv;
}
NS_IMETHODIMP
nsXMLFragmentContentSink::DidBuildModel(PRBool aTerminated)
{
if (mAllContent) {
PopContent(); // remove mRoot pushed above
}
nsCOMPtr<nsIParser> kungFuDeathGrip(mParser);
// Drop our reference to the parser to get rid of a circular
@ -274,7 +259,7 @@ nsXMLFragmentContentSink::CreateElement(const PRUnichar** aAtts, PRUint32 aAttsC
// When we aren't grabbing all of the content we, never open a doc
// element, we run into trouble on the first element, so we don't append,
// and simply push this onto the content stack.
if (!mAllContent && mContentStack.Length() == 0) {
if (mContentStack.Length() == 0) {
*aAppendContent = PR_FALSE;
}
@ -410,18 +395,24 @@ nsXMLFragmentContentSink::StartLayout()
////////////////////////////////////////////////////////////////////////
NS_IMETHODIMP
nsXMLFragmentContentSink::GetFragment(PRBool aWillOwnFragment,
nsIDOMDocumentFragment** aFragment)
nsXMLFragmentContentSink::FinishFragmentParsing(nsIDOMDocumentFragment** aFragment)
{
*aFragment = nsnull;
mTargetDocument = nsnull;
mNodeInfoManager = nsnull;
mScriptLoader = nsnull;
mCSSLoader = nsnull;
mContentStack.Clear();
mDocumentURI = nsnull;
mDocShell = nsnull;
if (mParseError) {
//XXX PARSE_ERR from DOM3 Load and Save would be more appropriate
mRoot = nsnull;
mParseError = PR_FALSE;
return NS_ERROR_DOM_SYNTAX_ERR;
} else if (mRoot) {
nsresult rv = CallQueryInterface(mRoot, aFragment);
if (NS_SUCCEEDED(rv) && aWillOwnFragment) {
mRoot = nsnull;
}
mRoot = nsnull;
return rv;
} else {
return NS_OK;
@ -442,11 +433,7 @@ nsXMLFragmentContentSink::SetTargetDocument(nsIDocument* aTargetDocument)
NS_IMETHODIMP
nsXMLFragmentContentSink::WillBuildContent()
{
// If we're taking all of the content, then we've already pushed mRoot
// onto the content stack, otherwise, start here.
if (!mAllContent) {
PushContent(mRoot);
}
PushContent(mRoot);
return NS_OK;
}
@ -454,15 +441,12 @@ nsXMLFragmentContentSink::WillBuildContent()
NS_IMETHODIMP
nsXMLFragmentContentSink::DidBuildContent()
{
// If we're taking all of the content, then this is handled in DidBuildModel
if (!mAllContent) {
// Note: we need to FlushText() here because if we don't, we might not get
// an end element to do it for us, so make sure.
if (!mParseError) {
FlushText();
}
PopContent();
// Note: we need to FlushText() here because if we don't, we might not get
// an end element to do it for us, so make sure.
if (!mParseError) {
FlushText();
}
PopContent();
return NS_OK;
}

View File

@ -2689,24 +2689,17 @@ nsresult nsHTMLEditor::ParseFragment(const nsAString & aFragStr,
nsCOMPtr<nsIDOMNode> *outNode,
PRBool aTrustedInput)
{
// The old code created a new parser every time. This is inefficient.
// However, the target document is not required to be an HTML document,
// So avoid using the cached parser of aDocument. Once bug 596182 is fixed,
// use the global parser here.
nsCOMPtr<nsIParser> parser = nsHtml5Module::NewHtml5Parser();
nsAHtml5FragmentParser* asFragmentParser =
static_cast<nsAHtml5FragmentParser*> (parser.get());
nsCOMPtr<nsIDOMDocumentFragment> frag;
NS_NewDocumentFragment(getter_AddRefs(frag),
aTargetDocument->NodeInfoManager());
nsCOMPtr<nsIContent> fragment = do_QueryInterface(frag);
asFragmentParser->ParseHtml5Fragment(aFragStr,
fragment,
aContextLocalName ?
aContextLocalName : nsGkAtoms::body,
kNameSpaceID_XHTML,
PR_FALSE,
PR_TRUE);
nsContentUtils::ParseFragmentHTML(aFragStr,
fragment,
aContextLocalName ?
aContextLocalName : nsGkAtoms::body,
kNameSpaceID_XHTML,
PR_FALSE,
PR_TRUE);
if (!aTrustedInput) {
nsTreeSanitizer sanitizer(!!aContextLocalName, !aContextLocalName);
sanitizer.Sanitize(fragment);

View File

@ -62,7 +62,6 @@
#include "nsIDocumentViewer.h"
#include "nsIFactory.h"
#include "nsIFrameUtil.h"
#include "nsIFragmentContentSink.h"
#include "nsHTMLStyleSheet.h"
#include "nsIHTMLToTextSink.h"
#include "nsILayoutDebugger.h"
@ -348,8 +347,10 @@ LayoutShutdownObserver::Observe(nsISupports *aSubject,
const char *aTopic,
const PRUnichar *someData)
{
if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID))
if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
Shutdown();
nsContentUtils::XPCOMShutdown();
}
return NS_OK;
}
@ -529,10 +530,6 @@ MAKE_CTOR(CreateXMLContentSerializer, nsIContentSerializer, NS_NewXML
MAKE_CTOR(CreateHTMLContentSerializer, nsIContentSerializer, NS_NewHTMLContentSerializer)
MAKE_CTOR(CreateXHTMLContentSerializer, nsIContentSerializer, NS_NewXHTMLContentSerializer)
MAKE_CTOR(CreatePlainTextSerializer, nsIContentSerializer, NS_NewPlainTextSerializer)
MAKE_CTOR(CreateHTMLFragmentSink, nsIFragmentContentSink, NS_NewHTMLFragmentContentSink)
MAKE_CTOR(CreateHTMLFragmentSink2, nsIFragmentContentSink, NS_NewHTMLFragmentContentSink2)
MAKE_CTOR(CreateXMLFragmentSink, nsIFragmentContentSink, NS_NewXMLFragmentContentSink)
MAKE_CTOR(CreateXMLFragmentSink2, nsIFragmentContentSink, NS_NewXMLFragmentContentSink2)
MAKE_CTOR(CreateSanitizingHTMLSerializer, nsIContentSerializer, NS_NewSanitizingHTMLSerializer)
MAKE_CTOR(CreateXBLService, nsIXBLService, NS_NewXBLService)
MAKE_CTOR(CreateContentPolicy, nsIContentPolicy, NS_NewContentPolicy)
@ -776,11 +773,7 @@ NS_DEFINE_NAMED_CID(NS_XMLCONTENTSERIALIZER_CID);
NS_DEFINE_NAMED_CID(NS_XHTMLCONTENTSERIALIZER_CID);
NS_DEFINE_NAMED_CID(NS_HTMLCONTENTSERIALIZER_CID);
NS_DEFINE_NAMED_CID(NS_PLAINTEXTSERIALIZER_CID);
NS_DEFINE_NAMED_CID(NS_HTMLFRAGMENTSINK_CID);
NS_DEFINE_NAMED_CID(NS_HTMLFRAGMENTSINK2_CID);
NS_DEFINE_NAMED_CID(MOZ_SANITIZINGHTMLSERIALIZER_CID);
NS_DEFINE_NAMED_CID(NS_XMLFRAGMENTSINK_CID);
NS_DEFINE_NAMED_CID(NS_XMLFRAGMENTSINK2_CID);
NS_DEFINE_NAMED_CID(NS_XBLSERVICE_CID);
NS_DEFINE_NAMED_CID(NS_CONTENTPOLICY_CID);
NS_DEFINE_NAMED_CID(NS_DATADOCUMENTCONTENTPOLICY_CID);
@ -915,11 +908,7 @@ static const mozilla::Module::CIDEntry kLayoutCIDs[] = {
{ &kNS_HTMLCONTENTSERIALIZER_CID, false, NULL, CreateHTMLContentSerializer },
{ &kNS_XHTMLCONTENTSERIALIZER_CID, false, NULL, CreateXHTMLContentSerializer },
{ &kNS_PLAINTEXTSERIALIZER_CID, false, NULL, CreatePlainTextSerializer },
{ &kNS_HTMLFRAGMENTSINK_CID, false, NULL, CreateHTMLFragmentSink },
{ &kNS_HTMLFRAGMENTSINK2_CID, false, NULL, CreateHTMLFragmentSink2 },
{ &kMOZ_SANITIZINGHTMLSERIALIZER_CID, false, NULL, CreateSanitizingHTMLSerializer },
{ &kNS_XMLFRAGMENTSINK_CID, false, NULL, CreateXMLFragmentSink },
{ &kNS_XMLFRAGMENTSINK2_CID, false, NULL, CreateXMLFragmentSink2 },
{ &kNS_XBLSERVICE_CID, false, NULL, CreateXBLService },
{ &kNS_CONTENTPOLICY_CID, false, NULL, CreateContentPolicy },
{ &kNS_DATADOCUMENTCONTENTPOLICY_CID, false, NULL, nsDataDocumentContentPolicyConstructor },
@ -1055,11 +1044,7 @@ static const mozilla::Module::ContractIDEntry kLayoutContracts[] = {
{ NS_CONTENTSERIALIZER_CONTRACTID_PREFIX "application/vnd.mozilla.xul+xml", &kNS_XMLCONTENTSERIALIZER_CID },
{ NS_CONTENTSERIALIZER_CONTRACTID_PREFIX "text/plain", &kNS_PLAINTEXTSERIALIZER_CID },
{ NS_PLAINTEXTSINK_CONTRACTID, &kNS_PLAINTEXTSERIALIZER_CID },
{ NS_HTMLFRAGMENTSINK_CONTRACTID, &kNS_HTMLFRAGMENTSINK_CID },
{ NS_HTMLFRAGMENTSINK2_CONTRACTID, &kNS_HTMLFRAGMENTSINK2_CID },
{ MOZ_SANITIZINGHTMLSERIALIZER_CONTRACTID, &kMOZ_SANITIZINGHTMLSERIALIZER_CID },
{ NS_XMLFRAGMENTSINK_CONTRACTID, &kNS_XMLFRAGMENTSINK_CID },
{ NS_XMLFRAGMENTSINK2_CONTRACTID, &kNS_XMLFRAGMENTSINK2_CID },
{ "@mozilla.org/xbl;1", &kNS_XBLSERVICE_CID },
{ NS_CONTENTPOLICY_CONTRACTID, &kNS_CONTENTPOLICY_CID },
{ NS_DATADOCUMENTCONTENTPOLICY_CONTRACTID, &kNS_DATADOCUMENTCONTENTPOLICY_CID },

View File

@ -464,21 +464,7 @@ nsHtml5Parser::Terminate()
NS_IMETHODIMP
nsHtml5Parser::ParseFragment(const nsAString& aSourceBuffer,
void* aKey,
nsTArray<nsString>& aTagStack,
PRBool aXMLMode,
const nsACString& aContentType,
nsDTDMode aMode)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsHtml5Parser::ParseFragment(const nsAString& aSourceBuffer,
nsIContent* aTargetNode,
nsIAtom* aContextLocalName,
PRInt32 aContextNamespace,
PRBool aQuirks)
nsTArray<nsString>& aTagStack)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
@ -512,6 +498,9 @@ nsHtml5Parser::ParseHtml5Fragment(const nsAString& aSourceBuffer,
#ifdef DEBUG
if (!aPreventScriptExecution) {
NS_ASSERTION(!aTargetNode->IsInDoc(),
"If script execution isn't prevented, "
"the target node must not be in doc.");
nsCOMPtr<nsIDOMDocumentFragment> domFrag = do_QueryInterface(aTargetNode);
NS_ASSERTION(domFrag,
"If script execution isn't prevented, must parse to DOM fragment.");

View File

@ -207,20 +207,7 @@ class nsHtml5Parser : public nsAHtml5FragmentParser, // inherits nsIParser
* Don't call. For interface backwards compat only.
*/
NS_IMETHOD ParseFragment(const nsAString& aSourceBuffer,
void* aKey,
nsTArray<nsString>& aTagStack,
PRBool aXMLMode,
const nsACString& aContentType,
nsDTDMode aMode = eDTDMode_autodetect);
/**
* Don't call. For interface backwards compat only.
*/
NS_IMETHOD ParseFragment(const nsAString& aSourceBuffer,
nsIContent* aTargetNode,
nsIAtom* aContextLocalName,
PRInt32 aContextNamespace,
PRBool aQuirks);
nsTArray<nsString>& aTagStack);
/**
* Don't call. For interface compat only.

View File

@ -57,6 +57,7 @@
#include "nsHtml5Tokenizer.h"
#include "nsHtml5TreeBuilder.h"
#include "nsHtml5StreamParser.h"
#include "mozilla/css/Loader.h"
NS_IMPL_CYCLE_COLLECTION_CLASS(nsHtml5TreeOpExecutor)
@ -307,8 +308,10 @@ nsHtml5TreeOpExecutor::UpdateStyleSheet(nsIContent* aElement)
PRBool willNotify;
PRBool isAlternate;
nsresult rv = ssle->UpdateStyleSheet(this, &willNotify, &isAlternate);
if (NS_SUCCEEDED(rv) && willNotify && !isAlternate) {
nsresult rv = ssle->UpdateStyleSheet(mFragmentMode ? nsnull : this,
&willNotify,
&isAlternate);
if (NS_SUCCEEDED(rv) && willNotify && !isAlternate && !mFragmentMode) {
++mPendingSheetCount;
mScriptLoader->AddExecuteBlocker();
}
@ -805,14 +808,26 @@ nsHtml5TreeOpExecutor::GetTokenizer()
}
void
nsHtml5TreeOpExecutor::Reset() {
nsHtml5TreeOpExecutor::Reset()
{
DropHeldElements();
mReadingFromStage = PR_FALSE;
mOpQueue.Clear();
mStarted = PR_FALSE;
mFlushState = eNotFlushing;
mRunFlushLoopOnStack = PR_FALSE;
mFragmentMode = PR_FALSE;
}
void
nsHtml5TreeOpExecutor::DropHeldElements()
{
mScriptLoader = nsnull;
mDocument = nsnull;
mNodeInfoManager = nsnull;
mCSSLoader = nsnull;
mDocumentURI = nsnull;
mDocShell = nsnull;
mOwnedElements.Clear();
}
void

View File

@ -369,9 +369,7 @@ class nsHtml5TreeOpExecutor : public nsContentSink,
mOwnedElements.AppendObject(aContent);
}
void DropHeldElements() {
mOwnedElements.Clear();
}
void DropHeldElements();
/**
* Flush the operations from the tree operations from the argument

View File

@ -67,6 +67,7 @@ EXPORTS = \
nsScannerString.h \
nsParserCIID.h \
nsToken.h \
nsParserConstants.h \
$(NULL)
ifdef MOZ_DEBUG

View File

@ -43,8 +43,8 @@ class nsIDOMDocumentFragment;
class nsIDocument;
#define NS_I_FRAGMENT_CONTENT_SINK_IID \
{ 0x1ecdb30d, 0x1f10, 0x45d2, \
{ 0xa4, 0xf4, 0xec, 0xbc, 0x03, 0x52, 0x9a, 0x7e } }
{ 0x7c78cbad, 0xdaf5, 0x487e, \
{ 0x96, 0x98, 0xab, 0xcc, 0x21, 0x5a, 0x8d, 0x39 } }
/**
* The fragment sink allows a client to parse a fragment of sink, possibly
@ -57,14 +57,11 @@ public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_I_FRAGMENT_CONTENT_SINK_IID)
/**
* This method is used to obtain the fragment created by
* a fragment content sink. The value returned will be null
* if the content sink hasn't yet received parser notifications.
* a fragment content sink and to release resources held by the parser.
*
* If aWillOwnFragment is PR_TRUE then the sink should drop its
* ownership of the fragment.
* The sink drops its reference to the fragment.
*/
NS_IMETHOD GetFragment(PRBool aWillOwnFragment,
nsIDOMDocumentFragment** aFragment) = 0;
NS_IMETHOD FinishFragmentParsing(nsIDOMDocumentFragment** aFragment) = 0;
/**
* This method is used to set the target document for this fragment
@ -120,22 +117,7 @@ public:
virtual void AllowComments() = 0;
};
/**
* Base version takes string nested in context, content surrounded by
* WillBuildContent()/DidBuildContent() calls. The 2nd version just loads
* the whole string.
*/
#define NS_HTMLFRAGMENTSINK_CONTRACTID "@mozilla.org/layout/htmlfragmentsink;1"
#define NS_HTMLFRAGMENTSINK2_CONTRACTID "@mozilla.org/layout/htmlfragmentsink;2"
#define NS_XMLFRAGMENTSINK_CONTRACTID "@mozilla.org/layout/xmlfragmentsink;1"
#define NS_XMLFRAGMENTSINK2_CONTRACTID "@mozilla.org/layout/xmlfragmentsink;2"
// the HTML versions are in nsHTMLParts.h
nsresult
NS_NewXMLFragmentContentSink(nsIFragmentContentSink** aInstancePtrResult);
nsresult
NS_NewXMLFragmentContentSink2(nsIFragmentContentSink** aInstancePtrResult);
#endif

View File

@ -249,25 +249,11 @@ class nsIParser : public nsISupports {
* been given a fragment content sink.
*
* @param aSourceBuffer The XML or HTML that hasn't been parsed yet.
* @param aKey The key used by the parser.
* @param aTagStack The context of the source buffer.
* @param aXMLMode Whether this is XML or HTML
* @param aContentType The content-type of this document.
* @param aMode The DTDMode that the parser should parse this fragment in.
* @return Success or failure.
*/
NS_IMETHOD ParseFragment(const nsAString& aSourceBuffer,
void* aKey,
nsTArray<nsString>& aTagStack,
PRBool aXMLMode,
const nsACString& aContentType,
nsDTDMode aMode = eDTDMode_autodetect) = 0;
NS_IMETHOD ParseFragment(const nsAString& aSourceBuffer,
nsIContent* aTargetNode,
nsIAtom* aContextLocalName,
PRInt32 aContextNamespace,
PRBool aQuirks) = 0;
nsTArray<nsString>& aTagStack) = 0;
/**
* This method gets called when the tokens have been consumed, and it's time
@ -369,36 +355,6 @@ const PRUint32 kHierarchyTooDeep = NS_ERROR_HTMLPARSER_HIERARCHYTOODEEP;
const PRUint32 kFakeEndTag = NS_ERROR_HTMLPARSER_FAKE_ENDTAG;
const PRUint32 kNotAComment = NS_ERROR_HTMLPARSER_INVALID_COMMENT;
const PRUnichar kNewLine = '\n';
const PRUnichar kCR = '\r';
const PRUnichar kLF = '\n';
const PRUnichar kTab = '\t';
const PRUnichar kSpace = ' ';
const PRUnichar kQuote = '"';
const PRUnichar kApostrophe = '\'';
const PRUnichar kLessThan = '<';
const PRUnichar kGreaterThan = '>';
const PRUnichar kAmpersand = '&';
const PRUnichar kForwardSlash = '/';
const PRUnichar kBackSlash = '\\';
const PRUnichar kEqual = '=';
const PRUnichar kMinus = '-';
const PRUnichar kPlus = '+';
const PRUnichar kExclamation = '!';
const PRUnichar kSemicolon = ';';
const PRUnichar kHashsign = '#';
const PRUnichar kAsterisk = '*';
const PRUnichar kUnderbar = '_';
const PRUnichar kComma = ',';
const PRUnichar kLeftParen = '(';
const PRUnichar kRightParen = ')';
const PRUnichar kLeftBrace = '{';
const PRUnichar kRightBrace = '}';
const PRUnichar kQuestionMark = '?';
const PRUnichar kLeftSquareBracket = '[';
const PRUnichar kRightSquareBracket = ']';
const PRUnichar kNullCh = '\0';
#define NS_IPARSER_FLAG_UNKNOWN_MODE 0x00000000
#define NS_IPARSER_FLAG_QUIRKS_MODE 0x00000002
#define NS_IPARSER_FLAG_STRICT_MODE 0x00000004

View File

@ -0,0 +1,71 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set ts=2 sw=2 et tw=78: */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (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/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsParserConstants_h_
#define nsParserConstants_h_
const PRUnichar kNewLine = '\n';
const PRUnichar kCR = '\r';
const PRUnichar kLF = '\n';
const PRUnichar kTab = '\t';
const PRUnichar kSpace = ' ';
const PRUnichar kQuote = '"';
const PRUnichar kApostrophe = '\'';
const PRUnichar kLessThan = '<';
const PRUnichar kGreaterThan = '>';
const PRUnichar kAmpersand = '&';
const PRUnichar kForwardSlash = '/';
const PRUnichar kBackSlash = '\\';
const PRUnichar kEqual = '=';
const PRUnichar kMinus = '-';
const PRUnichar kPlus = '+';
const PRUnichar kExclamation = '!';
const PRUnichar kSemicolon = ';';
const PRUnichar kHashsign = '#';
const PRUnichar kAsterisk = '*';
const PRUnichar kUnderbar = '_';
const PRUnichar kComma = ',';
const PRUnichar kLeftParen = '(';
const PRUnichar kRightParen = ')';
const PRUnichar kLeftBrace = '{';
const PRUnichar kRightBrace = '}';
const PRUnichar kQuestionMark = '?';
const PRUnichar kLeftSquareBracket = '[';
const PRUnichar kRightSquareBracket = ']';
const PRUnichar kNullCh = '\0';
#endif // nsParserConstants_h_

View File

@ -59,6 +59,7 @@
#include "nsUnicharUtils.h"
#include "prmem.h"
#include "nsIServiceManager.h"
#include "nsParserConstants.h"
#ifdef NS_DEBUG
#include "nsLoggingSink.h"

View File

@ -53,6 +53,7 @@
#include "nsElementTable.h"
#include "nsReadableUtils.h"
#include "nsUnicharUtils.h"
#include "nsParserConstants.h"
/************************************************************************
And now for the main class -- nsHTMLTokenizer...

View File

@ -51,7 +51,7 @@
#include "nsReadableUtils.h"
#include "nsUnicharUtils.h"
#include "nsScanner.h"
#include "nsParserConstants.h"
static const PRUnichar sUserdefined[] = {'u', 's', 'e', 'r', 'd', 'e', 'f',
'i', 'n', 'e', 'd', 0};

View File

@ -74,6 +74,7 @@
#include "nsViewSourceHTML.h"
#include "mozilla/CondVar.h"
#include "mozilla/Mutex.h"
#include "nsParserConstants.h"
using namespace mozilla;
@ -2024,21 +2025,7 @@ nsParser::Parse(const nsAString& aSourceBuffer,
NS_IMETHODIMP
nsParser::ParseFragment(const nsAString& aSourceBuffer,
nsIContent* aTargetNode,
nsIAtom* aContextLocalName,
PRInt32 aContextNamespace,
PRBool aQuirks)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsParser::ParseFragment(const nsAString& aSourceBuffer,
void* aKey,
nsTArray<nsString>& aTagStack,
PRBool aXMLMode,
const nsACString& aMimeType,
nsDTDMode aMode)
nsTArray<nsString>& aTagStack)
{
nsresult result = NS_OK;
nsAutoString theContext;
@ -2064,7 +2051,11 @@ nsParser::ParseFragment(const nsAString& aSourceBuffer,
// First, parse the context to build up the DTD's tag stack. Note that we
// pass PR_FALSE for the aLastCall parameter.
result = Parse(theContext, (void*)&theContext, aMimeType, PR_FALSE, aMode);
result = Parse(theContext,
(void*)&theContext,
NS_LITERAL_CSTRING("application/xml"),
PR_FALSE,
eDTDMode_full_standards);
if (NS_FAILED(result)) {
mFlags |= NS_PARSER_FLAG_OBSERVERS_ENABLED;
return result;
@ -2072,64 +2063,32 @@ nsParser::ParseFragment(const nsAString& aSourceBuffer,
if (!mSink) {
// Parse must have failed in the XML case and so the sink was killed.
NS_ASSERTION(aXMLMode, "Unexpected!");
return NS_ERROR_HTMLPARSER_STOPPARSING;
}
nsCOMPtr<nsIFragmentContentSink> fragSink = do_QueryInterface(mSink);
NS_ASSERTION(fragSink, "ParseFragment requires a fragment content sink");
if (!aXMLMode && theCount) {
// First, we have to flush any tags that don't belong in the head if there
// was no <body> in the context.
// XXX This is extremely ugly. Maybe CNavDTD should have FlushMisplaced()?
NS_ASSERTION(mParserContext, "Parsing didn't create a parser context?");
CNavDTD* dtd = static_cast<CNavDTD*>
(static_cast<nsIDTD*>(mDTD));
NS_ASSERTION(dtd, "How did we parse anything without a dtd?");
CStartToken bodyToken(NS_LITERAL_STRING("BODY"), eHTMLTag_body);
nsCParserNode bodyNode(&bodyToken, 0);
dtd->OpenContainer(&bodyNode, eHTMLTag_body);
// Now parse the flushed out tags.
result = BuildModel();
if (NS_FAILED(result)) {
mFlags |= NS_PARSER_FLAG_OBSERVERS_ENABLED;
return result;
}
// Now that we've flushed all of the tags out of the body, we have to make
// sure that there aren't any context tags left in the scanner.
NS_ASSERTION(mParserContext->mScanner, "Where'd the scanner go?");
PRUnichar next;
if (NS_SUCCEEDED(mParserContext->mScanner->Peek(next))) {
// Uh, oh. This must mean that the context stack has a special tag on
// it, such as <textarea> or <title> that requires its end tag before it
// will be consumed. Tell the content sink that it will be coming.
// Note: For now, we can assume that there is only one such tag.
NS_ASSERTION(next == '<', "The tokenizer failed to consume a token");
fragSink->IgnoreFirstContainer();
}
}
fragSink->WillBuildContent();
// Now, parse the actual content. Note that this is the last call
// for HTML content, but for XML, we will want to build and parse
// the end tags. However, if tagStack is empty, it's the last call
// for XML as well.
if (!aXMLMode || (theCount == 0)) {
result = Parse(aSourceBuffer, &theContext, aMimeType,
PR_TRUE, aMode);
if (theCount == 0) {
result = Parse(aSourceBuffer,
&theContext,
NS_LITERAL_CSTRING("application/xml"),
PR_TRUE,
eDTDMode_full_standards);
fragSink->DidBuildContent();
} else {
// Add an end tag chunk, so expat will read the whole source buffer,
// and not worry about ']]' etc.
result = Parse(aSourceBuffer + NS_LITERAL_STRING("</"),
&theContext, aMimeType, PR_FALSE, aMode);
&theContext,
NS_LITERAL_CSTRING("application/xml"),
PR_FALSE,
eDTDMode_full_standards);
fragSink->DidBuildContent();
if (NS_SUCCEEDED(result)) {
@ -2152,8 +2111,11 @@ nsParser::ParseFragment(const nsAString& aSourceBuffer,
endContext.AppendLiteral(">");
}
result = Parse(endContext, &theContext, aMimeType,
PR_TRUE, aMode);
result = Parse(endContext,
&theContext,
NS_LITERAL_CSTRING("application/xml"),
PR_TRUE,
eDTDMode_full_standards);
}
}

View File

@ -210,17 +210,7 @@ class nsParser : public nsIParser,
* This method needs documentation
*/
NS_IMETHOD ParseFragment(const nsAString& aSourceBuffer,
void* aKey,
nsTArray<nsString>& aTagStack,
PRBool aXMLMode,
const nsACString& aContentType,
nsDTDMode aMode = eDTDMode_autodetect);
NS_IMETHOD ParseFragment(const nsAString& aSourceBuffer,
nsIContent* aTargetNode,
nsIAtom* aContextLocalName,
PRInt32 aContextNamespace,
PRBool aQuirks);
nsTArray<nsString>& aTagStack);
/**
* This method gets called when the tokens have been consumed, and it's time

View File

@ -60,6 +60,7 @@
#include "nsPrintfCString.h"
#include "nsNetUtil.h"
#include "nsHTMLEntities.h"
#include "nsParserConstants.h"
#include "nsIServiceManager.h"

View File

@ -171,37 +171,21 @@ nsScriptableUnescapeHTML::ParseFragment(const nsAString &aFragment,
if (NS_SUCCEEDED(rv)) {
nsCOMPtr<nsIContent> fragment;
if (aIsXML) {
nsCAutoString contentType;
nsCOMPtr<nsIFragmentContentSink> sink;
contentType = NS_LITERAL_CSTRING("application/xhtml+xml");
sink = do_CreateInstance(NS_XMLFRAGMENTSINK_CONTRACTID);
if (sink) {
sink->SetTargetDocument(document);
nsCOMPtr<nsIContentSink> contentsink(do_QueryInterface(sink));
parser->SetContentSink(contentsink);
rv = parser->ParseFragment(aFragment, nsnull, tagStack,
aIsXML, contentType,
eDTDMode_full_standards);
if (NS_SUCCEEDED(rv)) {
rv = sink->GetFragment(PR_TRUE, aReturn);
fragment = do_QueryInterface(*aReturn);
}
} else {
rv = NS_ERROR_FAILURE;
}
rv = nsContentUtils::ParseFragmentXML(aFragment,
document,
tagStack,
aReturn);
fragment = do_QueryInterface(*aReturn);
} else {
nsCOMPtr<nsIParser> parser = nsHtml5Module::NewHtml5Parser();
nsAHtml5FragmentParser* asFragmentParser =
static_cast<nsAHtml5FragmentParser*> (parser.get());
NS_NewDocumentFragment(aReturn,
document->NodeInfoManager());
fragment = do_QueryInterface(*aReturn);
asFragmentParser->ParseHtml5Fragment(aFragment,
fragment,
nsGkAtoms::body,
kNameSpaceID_XHTML,
PR_FALSE,
PR_TRUE);
nsContentUtils::ParseFragmentHTML(aFragment,
fragment,
nsGkAtoms::body,
kNameSpaceID_XHTML,
PR_FALSE,
PR_TRUE);
// Now, set the base URI on all subtree roots.
aBaseURI->GetSpec(spec);
nsAutoString spec16;