1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/content/xml/document/src/nsXMLFragmentContentSink.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,431 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 +#include "nsCOMPtr.h" 1.9 +#include "nsXMLContentSink.h" 1.10 +#include "nsIFragmentContentSink.h" 1.11 +#include "nsIXMLContentSink.h" 1.12 +#include "nsContentSink.h" 1.13 +#include "nsIExpatSink.h" 1.14 +#include "nsIDTD.h" 1.15 +#include "nsIDocument.h" 1.16 +#include "nsIDOMDocumentFragment.h" 1.17 +#include "nsIContent.h" 1.18 +#include "nsGkAtoms.h" 1.19 +#include "nsINodeInfo.h" 1.20 +#include "nsContentCreatorFunctions.h" 1.21 +#include "nsError.h" 1.22 +#include "nsIConsoleService.h" 1.23 +#include "nsIScriptError.h" 1.24 +#include "nsNetUtil.h" 1.25 +#include "nsTHashtable.h" 1.26 +#include "nsHashKeys.h" 1.27 +#include "nsTArray.h" 1.28 +#include "nsCycleCollectionParticipant.h" 1.29 +#include "nsIDocShell.h" 1.30 +#include "nsScriptLoader.h" 1.31 +#include "mozilla/css/Loader.h" 1.32 +#include "mozilla/dom/DocumentFragment.h" 1.33 +#include "mozilla/dom/ProcessingInstruction.h" 1.34 + 1.35 +using namespace mozilla::dom; 1.36 + 1.37 +class nsXMLFragmentContentSink : public nsXMLContentSink, 1.38 + public nsIFragmentContentSink 1.39 +{ 1.40 +public: 1.41 + nsXMLFragmentContentSink(); 1.42 + virtual ~nsXMLFragmentContentSink(); 1.43 + 1.44 + NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW 1.45 + 1.46 + // nsISupports 1.47 + NS_DECL_ISUPPORTS_INHERITED 1.48 + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsXMLFragmentContentSink, 1.49 + nsXMLContentSink) 1.50 + 1.51 + // nsIExpatSink 1.52 + NS_IMETHOD HandleDoctypeDecl(const nsAString & aSubset, 1.53 + const nsAString & aName, 1.54 + const nsAString & aSystemId, 1.55 + const nsAString & aPublicId, 1.56 + nsISupports* aCatalogData); 1.57 + NS_IMETHOD HandleProcessingInstruction(const char16_t *aTarget, 1.58 + const char16_t *aData); 1.59 + NS_IMETHOD HandleXMLDeclaration(const char16_t *aVersion, 1.60 + const char16_t *aEncoding, 1.61 + int32_t aStandalone); 1.62 + NS_IMETHOD ReportError(const char16_t* aErrorText, 1.63 + const char16_t* aSourceText, 1.64 + nsIScriptError *aError, 1.65 + bool *_retval); 1.66 + 1.67 + // nsIContentSink 1.68 + NS_IMETHOD WillBuildModel(nsDTDMode aDTDMode); 1.69 + NS_IMETHOD DidBuildModel(bool aTerminated); 1.70 + NS_IMETHOD SetDocumentCharset(nsACString& aCharset); 1.71 + virtual nsISupports *GetTarget(); 1.72 + NS_IMETHOD DidProcessATokenImpl(); 1.73 + 1.74 + // nsIXMLContentSink 1.75 + 1.76 + // nsIFragmentContentSink 1.77 + NS_IMETHOD FinishFragmentParsing(nsIDOMDocumentFragment** aFragment); 1.78 + NS_IMETHOD SetTargetDocument(nsIDocument* aDocument); 1.79 + NS_IMETHOD WillBuildContent(); 1.80 + NS_IMETHOD DidBuildContent(); 1.81 + NS_IMETHOD IgnoreFirstContainer(); 1.82 + NS_IMETHOD SetPreventScriptExecution(bool aPreventScriptExecution); 1.83 + 1.84 +protected: 1.85 + virtual bool SetDocElement(int32_t aNameSpaceID, 1.86 + nsIAtom *aTagName, 1.87 + nsIContent *aContent); 1.88 + virtual nsresult CreateElement(const char16_t** aAtts, uint32_t aAttsCount, 1.89 + nsINodeInfo* aNodeInfo, uint32_t aLineNumber, 1.90 + nsIContent** aResult, bool* aAppendContent, 1.91 + mozilla::dom::FromParser aFromParser); 1.92 + virtual nsresult CloseElement(nsIContent* aContent); 1.93 + 1.94 + virtual void MaybeStartLayout(bool aIgnorePendingSheets); 1.95 + 1.96 + // nsContentSink overrides 1.97 + virtual nsresult ProcessStyleLink(nsIContent* aElement, 1.98 + const nsSubstring& aHref, 1.99 + bool aAlternate, 1.100 + const nsSubstring& aTitle, 1.101 + const nsSubstring& aType, 1.102 + const nsSubstring& aMedia); 1.103 + nsresult LoadXSLStyleSheet(nsIURI* aUrl); 1.104 + void StartLayout(); 1.105 + 1.106 + nsCOMPtr<nsIDocument> mTargetDocument; 1.107 + // the fragment 1.108 + nsCOMPtr<nsIContent> mRoot; 1.109 + bool mParseError; 1.110 +}; 1.111 + 1.112 +static nsresult 1.113 +NewXMLFragmentContentSinkHelper(nsIFragmentContentSink** aResult) 1.114 +{ 1.115 + nsXMLFragmentContentSink* it = new nsXMLFragmentContentSink(); 1.116 + 1.117 + NS_ADDREF(*aResult = it); 1.118 + 1.119 + return NS_OK; 1.120 +} 1.121 + 1.122 +nsresult 1.123 +NS_NewXMLFragmentContentSink(nsIFragmentContentSink** aResult) 1.124 +{ 1.125 + return NewXMLFragmentContentSinkHelper(aResult); 1.126 +} 1.127 + 1.128 +nsXMLFragmentContentSink::nsXMLFragmentContentSink() 1.129 + : mParseError(false) 1.130 +{ 1.131 + mRunsToCompletion = true; 1.132 +} 1.133 + 1.134 +nsXMLFragmentContentSink::~nsXMLFragmentContentSink() 1.135 +{ 1.136 +} 1.137 + 1.138 +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsXMLFragmentContentSink) 1.139 + NS_INTERFACE_MAP_ENTRY(nsIFragmentContentSink) 1.140 +NS_INTERFACE_MAP_END_INHERITING(nsXMLContentSink) 1.141 + 1.142 +NS_IMPL_ADDREF_INHERITED(nsXMLFragmentContentSink, nsXMLContentSink) 1.143 +NS_IMPL_RELEASE_INHERITED(nsXMLFragmentContentSink, nsXMLContentSink) 1.144 + 1.145 +NS_IMPL_CYCLE_COLLECTION_CLASS(nsXMLFragmentContentSink) 1.146 + 1.147 +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXMLFragmentContentSink, 1.148 + nsXMLContentSink) 1.149 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTargetDocument) 1.150 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRoot) 1.151 +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END 1.152 + 1.153 +NS_IMETHODIMP 1.154 +nsXMLFragmentContentSink::WillBuildModel(nsDTDMode aDTDMode) 1.155 +{ 1.156 + if (mRoot) { 1.157 + return NS_OK; 1.158 + } 1.159 + 1.160 + mState = eXMLContentSinkState_InDocumentElement; 1.161 + 1.162 + NS_ASSERTION(mTargetDocument, "Need a document!"); 1.163 + 1.164 + mRoot = new DocumentFragment(mNodeInfoManager); 1.165 + 1.166 + return NS_OK; 1.167 +} 1.168 + 1.169 +NS_IMETHODIMP 1.170 +nsXMLFragmentContentSink::DidBuildModel(bool aTerminated) 1.171 +{ 1.172 + nsRefPtr<nsParserBase> kungFuDeathGrip(mParser); 1.173 + 1.174 + // Drop our reference to the parser to get rid of a circular 1.175 + // reference. 1.176 + mParser = nullptr; 1.177 + 1.178 + return NS_OK; 1.179 +} 1.180 + 1.181 +NS_IMETHODIMP 1.182 +nsXMLFragmentContentSink::SetDocumentCharset(nsACString& aCharset) 1.183 +{ 1.184 + NS_NOTREACHED("fragments shouldn't set charset"); 1.185 + return NS_OK; 1.186 +} 1.187 + 1.188 +nsISupports * 1.189 +nsXMLFragmentContentSink::GetTarget() 1.190 +{ 1.191 + return mTargetDocument; 1.192 +} 1.193 + 1.194 +//////////////////////////////////////////////////////////////////////// 1.195 + 1.196 +bool 1.197 +nsXMLFragmentContentSink::SetDocElement(int32_t aNameSpaceID, 1.198 + nsIAtom* aTagName, 1.199 + nsIContent *aContent) 1.200 +{ 1.201 + // this is a fragment, not a document 1.202 + return false; 1.203 +} 1.204 + 1.205 +nsresult 1.206 +nsXMLFragmentContentSink::CreateElement(const char16_t** aAtts, uint32_t aAttsCount, 1.207 + nsINodeInfo* aNodeInfo, uint32_t aLineNumber, 1.208 + nsIContent** aResult, bool* aAppendContent, 1.209 + FromParser /*aFromParser*/) 1.210 +{ 1.211 + // Claim to not be coming from parser, since we don't do any of the 1.212 + // fancy CloseElement stuff. 1.213 + nsresult rv = nsXMLContentSink::CreateElement(aAtts, aAttsCount, 1.214 + aNodeInfo, aLineNumber, 1.215 + aResult, aAppendContent, 1.216 + NOT_FROM_PARSER); 1.217 + 1.218 + // When we aren't grabbing all of the content we, never open a doc 1.219 + // element, we run into trouble on the first element, so we don't append, 1.220 + // and simply push this onto the content stack. 1.221 + if (mContentStack.Length() == 0) { 1.222 + *aAppendContent = false; 1.223 + } 1.224 + 1.225 + return rv; 1.226 +} 1.227 + 1.228 +nsresult 1.229 +nsXMLFragmentContentSink::CloseElement(nsIContent* aContent) 1.230 +{ 1.231 + // don't do fancy stuff in nsXMLContentSink 1.232 + if (mPreventScriptExecution && aContent->Tag() == nsGkAtoms::script && 1.233 + (aContent->IsHTML() || aContent->IsSVG())) { 1.234 + nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(aContent); 1.235 + NS_ASSERTION(sele, "script did QI correctly!"); 1.236 + sele->PreventExecution(); 1.237 + } 1.238 + return NS_OK; 1.239 +} 1.240 + 1.241 +void 1.242 +nsXMLFragmentContentSink::MaybeStartLayout(bool aIgnorePendingSheets) 1.243 +{ 1.244 + return; 1.245 +} 1.246 + 1.247 +//////////////////////////////////////////////////////////////////////// 1.248 + 1.249 +NS_IMETHODIMP 1.250 +nsXMLFragmentContentSink::HandleDoctypeDecl(const nsAString & aSubset, 1.251 + const nsAString & aName, 1.252 + const nsAString & aSystemId, 1.253 + const nsAString & aPublicId, 1.254 + nsISupports* aCatalogData) 1.255 +{ 1.256 + NS_NOTREACHED("fragments shouldn't have doctype declarations"); 1.257 + 1.258 + return NS_OK; 1.259 +} 1.260 + 1.261 +NS_IMETHODIMP 1.262 +nsXMLFragmentContentSink::HandleProcessingInstruction(const char16_t *aTarget, 1.263 + const char16_t *aData) 1.264 +{ 1.265 + FlushText(); 1.266 + 1.267 + const nsDependentString target(aTarget); 1.268 + const nsDependentString data(aData); 1.269 + 1.270 + nsRefPtr<ProcessingInstruction> node = 1.271 + NS_NewXMLProcessingInstruction(mNodeInfoManager, target, data); 1.272 + 1.273 + // no special processing here. that should happen when the fragment moves into the document 1.274 + return AddContentAsLeaf(node); 1.275 +} 1.276 + 1.277 +NS_IMETHODIMP 1.278 +nsXMLFragmentContentSink::HandleXMLDeclaration(const char16_t *aVersion, 1.279 + const char16_t *aEncoding, 1.280 + int32_t aStandalone) 1.281 +{ 1.282 + NS_NOTREACHED("fragments shouldn't have XML declarations"); 1.283 + return NS_OK; 1.284 +} 1.285 + 1.286 +NS_IMETHODIMP 1.287 +nsXMLFragmentContentSink::ReportError(const char16_t* aErrorText, 1.288 + const char16_t* aSourceText, 1.289 + nsIScriptError *aError, 1.290 + bool *_retval) 1.291 +{ 1.292 + NS_PRECONDITION(aError && aSourceText && aErrorText, "Check arguments!!!"); 1.293 + 1.294 + // The expat driver should report the error. 1.295 + *_retval = true; 1.296 + 1.297 + mParseError = true; 1.298 + 1.299 +#ifdef DEBUG 1.300 + // Report the error to stderr. 1.301 + fprintf(stderr, 1.302 + "\n%s\n%s\n\n", 1.303 + NS_LossyConvertUTF16toASCII(aErrorText).get(), 1.304 + NS_LossyConvertUTF16toASCII(aSourceText).get()); 1.305 +#endif 1.306 + 1.307 + // The following code is similar to the cleanup in nsXMLContentSink::ReportError() 1.308 + mState = eXMLContentSinkState_InProlog; 1.309 + 1.310 + // Clear the current content 1.311 + nsCOMPtr<nsIDOMNode> node(do_QueryInterface(mRoot)); 1.312 + if (node) { 1.313 + for (;;) { 1.314 + nsCOMPtr<nsIDOMNode> child, dummy; 1.315 + node->GetLastChild(getter_AddRefs(child)); 1.316 + if (!child) 1.317 + break; 1.318 + node->RemoveChild(child, getter_AddRefs(dummy)); 1.319 + } 1.320 + } 1.321 + 1.322 + // Clear any buffered-up text we have. It's enough to set the length to 0. 1.323 + // The buffer itself is allocated when we're created and deleted in our 1.324 + // destructor, so don't mess with it. 1.325 + mTextLength = 0; 1.326 + 1.327 + return NS_OK; 1.328 +} 1.329 + 1.330 +nsresult 1.331 +nsXMLFragmentContentSink::ProcessStyleLink(nsIContent* aElement, 1.332 + const nsSubstring& aHref, 1.333 + bool aAlternate, 1.334 + const nsSubstring& aTitle, 1.335 + const nsSubstring& aType, 1.336 + const nsSubstring& aMedia) 1.337 +{ 1.338 + // don't process until moved to document 1.339 + return NS_OK; 1.340 +} 1.341 + 1.342 +nsresult 1.343 +nsXMLFragmentContentSink::LoadXSLStyleSheet(nsIURI* aUrl) 1.344 +{ 1.345 + NS_NOTREACHED("fragments shouldn't have XSL style sheets"); 1.346 + return NS_ERROR_UNEXPECTED; 1.347 +} 1.348 + 1.349 +void 1.350 +nsXMLFragmentContentSink::StartLayout() 1.351 +{ 1.352 + NS_NOTREACHED("fragments shouldn't layout"); 1.353 +} 1.354 + 1.355 +//////////////////////////////////////////////////////////////////////// 1.356 + 1.357 +NS_IMETHODIMP 1.358 +nsXMLFragmentContentSink::FinishFragmentParsing(nsIDOMDocumentFragment** aFragment) 1.359 +{ 1.360 + *aFragment = nullptr; 1.361 + mTargetDocument = nullptr; 1.362 + mNodeInfoManager = nullptr; 1.363 + mScriptLoader = nullptr; 1.364 + mCSSLoader = nullptr; 1.365 + mContentStack.Clear(); 1.366 + mDocumentURI = nullptr; 1.367 + mDocShell = nullptr; 1.368 + mDocElement = nullptr; 1.369 + mCurrentHead = nullptr; 1.370 + if (mParseError) { 1.371 + //XXX PARSE_ERR from DOM3 Load and Save would be more appropriate 1.372 + mRoot = nullptr; 1.373 + mParseError = false; 1.374 + return NS_ERROR_DOM_SYNTAX_ERR; 1.375 + } else if (mRoot) { 1.376 + nsresult rv = CallQueryInterface(mRoot, aFragment); 1.377 + mRoot = nullptr; 1.378 + return rv; 1.379 + } else { 1.380 + return NS_OK; 1.381 + } 1.382 +} 1.383 + 1.384 +NS_IMETHODIMP 1.385 +nsXMLFragmentContentSink::SetTargetDocument(nsIDocument* aTargetDocument) 1.386 +{ 1.387 + NS_ENSURE_ARG_POINTER(aTargetDocument); 1.388 + 1.389 + mTargetDocument = aTargetDocument; 1.390 + mNodeInfoManager = aTargetDocument->NodeInfoManager(); 1.391 + 1.392 + return NS_OK; 1.393 +} 1.394 + 1.395 +NS_IMETHODIMP 1.396 +nsXMLFragmentContentSink::WillBuildContent() 1.397 +{ 1.398 + PushContent(mRoot); 1.399 + 1.400 + return NS_OK; 1.401 +} 1.402 + 1.403 +NS_IMETHODIMP 1.404 +nsXMLFragmentContentSink::DidBuildContent() 1.405 +{ 1.406 + // Note: we need to FlushText() here because if we don't, we might not get 1.407 + // an end element to do it for us, so make sure. 1.408 + if (!mParseError) { 1.409 + FlushText(); 1.410 + } 1.411 + PopContent(); 1.412 + 1.413 + return NS_OK; 1.414 +} 1.415 + 1.416 +NS_IMETHODIMP 1.417 +nsXMLFragmentContentSink::DidProcessATokenImpl() 1.418 +{ 1.419 + return NS_OK; 1.420 +} 1.421 + 1.422 +NS_IMETHODIMP 1.423 +nsXMLFragmentContentSink::IgnoreFirstContainer() 1.424 +{ 1.425 + NS_NOTREACHED("XML isn't as broken as HTML"); 1.426 + return NS_ERROR_FAILURE; 1.427 +} 1.428 + 1.429 +NS_IMETHODIMP 1.430 +nsXMLFragmentContentSink::SetPreventScriptExecution(bool aPrevent) 1.431 +{ 1.432 + mPreventScriptExecution = aPrevent; 1.433 + return NS_OK; 1.434 +}