1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/content/xml/document/src/nsXMLContentSink.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1648 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim: set ts=2 sw=2 et tw=78: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#include "nsCOMPtr.h" 1.11 +#include "nsXMLContentSink.h" 1.12 +#include "nsIParser.h" 1.13 +#include "nsIDocument.h" 1.14 +#include "nsIDOMDocument.h" 1.15 +#include "nsIDOMDocumentType.h" 1.16 +#include "nsIContent.h" 1.17 +#include "nsIURI.h" 1.18 +#include "nsNetUtil.h" 1.19 +#include "nsIDocShell.h" 1.20 +#include "nsIStyleSheetLinkingElement.h" 1.21 +#include "nsIDOMComment.h" 1.22 +#include "nsIDOMCDATASection.h" 1.23 +#include "DocumentType.h" 1.24 +#include "nsHTMLParts.h" 1.25 +#include "nsCRT.h" 1.26 +#include "nsCSSStyleSheet.h" 1.27 +#include "mozilla/css/Loader.h" 1.28 +#include "nsGkAtoms.h" 1.29 +#include "nsContentUtils.h" 1.30 +#include "nsIScriptContext.h" 1.31 +#include "nsNameSpaceManager.h" 1.32 +#include "nsIServiceManager.h" 1.33 +#include "nsIScriptSecurityManager.h" 1.34 +#include "nsIContentViewer.h" 1.35 +#include "prtime.h" 1.36 +#include "prlog.h" 1.37 +#include "prmem.h" 1.38 +#include "nsRect.h" 1.39 +#include "nsIWebNavigation.h" 1.40 +#include "nsIScriptElement.h" 1.41 +#include "nsScriptLoader.h" 1.42 +#include "nsStyleLinkElement.h" 1.43 +#include "nsReadableUtils.h" 1.44 +#include "nsUnicharUtils.h" 1.45 +#include "nsICookieService.h" 1.46 +#include "nsIPrompt.h" 1.47 +#include "nsIChannel.h" 1.48 +#include "nsIPrincipal.h" 1.49 +#include "nsXMLPrettyPrinter.h" 1.50 +#include "nsNodeInfoManager.h" 1.51 +#include "nsContentCreatorFunctions.h" 1.52 +#include "nsIContentPolicy.h" 1.53 +#include "nsContentPolicyUtils.h" 1.54 +#include "nsError.h" 1.55 +#include "nsIDOMProcessingInstruction.h" 1.56 +#include "nsNodeUtils.h" 1.57 +#include "nsIScriptGlobalObject.h" 1.58 +#include "nsIHTMLDocument.h" 1.59 +#include "mozAutoDocUpdate.h" 1.60 +#include "nsMimeTypes.h" 1.61 +#include "nsHtml5SVGLoadDispatcher.h" 1.62 +#include "nsTextNode.h" 1.63 +#include "mozilla/dom/CDATASection.h" 1.64 +#include "mozilla/dom/Comment.h" 1.65 +#include "mozilla/dom/Element.h" 1.66 +#include "mozilla/dom/ProcessingInstruction.h" 1.67 + 1.68 +using namespace mozilla::dom; 1.69 + 1.70 +// XXX Open Issues: 1.71 +// 1) what's not allowed - We need to figure out which HTML tags 1.72 +// (prefixed with a HTML namespace qualifier) are explicitly not 1.73 +// allowed (if any). 1.74 +// 2) factoring code with nsHTMLContentSink - There's some amount of 1.75 +// common code between this and the HTML content sink. This will 1.76 +// increase as we support more and more HTML elements. How can code 1.77 +// from the code be factored? 1.78 + 1.79 +nsresult 1.80 +NS_NewXMLContentSink(nsIXMLContentSink** aResult, 1.81 + nsIDocument* aDoc, 1.82 + nsIURI* aURI, 1.83 + nsISupports* aContainer, 1.84 + nsIChannel* aChannel) 1.85 +{ 1.86 + NS_PRECONDITION(nullptr != aResult, "null ptr"); 1.87 + if (nullptr == aResult) { 1.88 + return NS_ERROR_NULL_POINTER; 1.89 + } 1.90 + nsXMLContentSink* it = new nsXMLContentSink(); 1.91 + 1.92 + nsCOMPtr<nsIXMLContentSink> kungFuDeathGrip = it; 1.93 + nsresult rv = it->Init(aDoc, aURI, aContainer, aChannel); 1.94 + NS_ENSURE_SUCCESS(rv, rv); 1.95 + 1.96 + return CallQueryInterface(it, aResult); 1.97 +} 1.98 + 1.99 +nsXMLContentSink::nsXMLContentSink() 1.100 + : mConstrainSize(true), 1.101 + mPrettyPrintXML(true) 1.102 +{ 1.103 +} 1.104 + 1.105 +nsXMLContentSink::~nsXMLContentSink() 1.106 +{ 1.107 + if (mText) { 1.108 + PR_Free(mText); // Doesn't null out, unlike PR_FREEIF 1.109 + } 1.110 +} 1.111 + 1.112 +nsresult 1.113 +nsXMLContentSink::Init(nsIDocument* aDoc, 1.114 + nsIURI* aURI, 1.115 + nsISupports* aContainer, 1.116 + nsIChannel* aChannel) 1.117 +{ 1.118 + nsresult rv = nsContentSink::Init(aDoc, aURI, aContainer, aChannel); 1.119 + NS_ENSURE_SUCCESS(rv, rv); 1.120 + 1.121 + aDoc->AddObserver(this); 1.122 + mIsDocumentObserver = true; 1.123 + 1.124 + if (!mDocShell) { 1.125 + mPrettyPrintXML = false; 1.126 + } 1.127 + 1.128 + mState = eXMLContentSinkState_InProlog; 1.129 + mDocElement = nullptr; 1.130 + 1.131 + return NS_OK; 1.132 +} 1.133 + 1.134 +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsXMLContentSink) 1.135 + NS_INTERFACE_MAP_ENTRY(nsIContentSink) 1.136 + NS_INTERFACE_MAP_ENTRY(nsIXMLContentSink) 1.137 + NS_INTERFACE_MAP_ENTRY(nsIExpatSink) 1.138 + NS_INTERFACE_MAP_ENTRY(nsITransformObserver) 1.139 +NS_INTERFACE_MAP_END_INHERITING(nsContentSink) 1.140 + 1.141 +NS_IMPL_ADDREF_INHERITED(nsXMLContentSink, nsContentSink) 1.142 +NS_IMPL_RELEASE_INHERITED(nsXMLContentSink, nsContentSink) 1.143 + 1.144 +NS_IMPL_CYCLE_COLLECTION_CLASS(nsXMLContentSink) 1.145 + 1.146 +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXMLContentSink, 1.147 + nsContentSink) 1.148 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCurrentHead) 1.149 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocElement) 1.150 + for (uint32_t i = 0, count = tmp->mContentStack.Length(); i < count; i++) { 1.151 + const StackNode& node = tmp->mContentStack.ElementAt(i); 1.152 + cb.NoteXPCOMChild(node.mContent); 1.153 + } 1.154 +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END 1.155 + 1.156 +// nsIContentSink 1.157 +NS_IMETHODIMP 1.158 +nsXMLContentSink::WillParse(void) 1.159 +{ 1.160 + return WillParseImpl(); 1.161 +} 1.162 + 1.163 +NS_IMETHODIMP 1.164 +nsXMLContentSink::WillBuildModel(nsDTDMode aDTDMode) 1.165 +{ 1.166 + WillBuildModelImpl(); 1.167 + 1.168 + // Notify document that the load is beginning 1.169 + mDocument->BeginLoad(); 1.170 + 1.171 + // Check for correct load-command for maybe prettyprinting 1.172 + if (mPrettyPrintXML) { 1.173 + nsAutoCString command; 1.174 + GetParser()->GetCommand(command); 1.175 + if (!command.EqualsLiteral("view")) { 1.176 + mPrettyPrintXML = false; 1.177 + } 1.178 + } 1.179 + 1.180 + return NS_OK; 1.181 +} 1.182 + 1.183 +bool 1.184 +nsXMLContentSink::CanStillPrettyPrint() 1.185 +{ 1.186 + return mPrettyPrintXML && 1.187 + (!mPrettyPrintHasFactoredElements || mPrettyPrintHasSpecialRoot); 1.188 +} 1.189 + 1.190 +nsresult 1.191 +nsXMLContentSink::MaybePrettyPrint() 1.192 +{ 1.193 + if (!CanStillPrettyPrint()) { 1.194 + mPrettyPrintXML = false; 1.195 + 1.196 + return NS_OK; 1.197 + } 1.198 + 1.199 + // stop observing in order to avoid crashing when replacing content 1.200 + mDocument->RemoveObserver(this); 1.201 + mIsDocumentObserver = false; 1.202 + 1.203 + // Reenable the CSSLoader so that the prettyprinting stylesheets can load 1.204 + if (mCSSLoader) { 1.205 + mCSSLoader->SetEnabled(true); 1.206 + } 1.207 + 1.208 + nsRefPtr<nsXMLPrettyPrinter> printer; 1.209 + nsresult rv = NS_NewXMLPrettyPrinter(getter_AddRefs(printer)); 1.210 + NS_ENSURE_SUCCESS(rv, rv); 1.211 + 1.212 + bool isPrettyPrinting; 1.213 + rv = printer->PrettyPrint(mDocument, &isPrettyPrinting); 1.214 + NS_ENSURE_SUCCESS(rv, rv); 1.215 + 1.216 + mPrettyPrinting = isPrettyPrinting; 1.217 + return NS_OK; 1.218 +} 1.219 + 1.220 +static void 1.221 +CheckXSLTParamPI(nsIDOMProcessingInstruction* aPi, 1.222 + nsIDocumentTransformer* aProcessor, 1.223 + nsIDocument* aDocument) 1.224 +{ 1.225 + nsAutoString target, data; 1.226 + aPi->GetTarget(target); 1.227 + 1.228 + // Check for namespace declarations 1.229 + if (target.EqualsLiteral("xslt-param-namespace")) { 1.230 + aPi->GetData(data); 1.231 + nsAutoString prefix, namespaceAttr; 1.232 + nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::prefix, 1.233 + prefix); 1.234 + if (!prefix.IsEmpty() && 1.235 + nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::_namespace, 1.236 + namespaceAttr)) { 1.237 + aProcessor->AddXSLTParamNamespace(prefix, namespaceAttr); 1.238 + } 1.239 + } 1.240 + 1.241 + // Check for actual parameters 1.242 + else if (target.EqualsLiteral("xslt-param")) { 1.243 + aPi->GetData(data); 1.244 + nsAutoString name, namespaceAttr, select, value; 1.245 + nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::name, 1.246 + name); 1.247 + nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::_namespace, 1.248 + namespaceAttr); 1.249 + if (!nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::select, select)) { 1.250 + select.SetIsVoid(true); 1.251 + } 1.252 + if (!nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::value, value)) { 1.253 + value.SetIsVoid(true); 1.254 + } 1.255 + if (!name.IsEmpty()) { 1.256 + nsCOMPtr<nsIDOMNode> doc = do_QueryInterface(aDocument); 1.257 + aProcessor->AddXSLTParam(name, namespaceAttr, select, value, doc); 1.258 + } 1.259 + } 1.260 +} 1.261 + 1.262 +NS_IMETHODIMP 1.263 +nsXMLContentSink::DidBuildModel(bool aTerminated) 1.264 +{ 1.265 + if (!mParser) { 1.266 + // If mParser is null, this parse has already been terminated and must 1.267 + // not been terminated again. However, nsDocument may still think that 1.268 + // the parse has not been terminated and call back into here in the case 1.269 + // where the XML parser has finished but the XSLT transform associated 1.270 + // with the document has not. 1.271 + return NS_OK; 1.272 + } 1.273 + 1.274 + DidBuildModelImpl(aTerminated); 1.275 + 1.276 + if (mXSLTProcessor) { 1.277 + // stop observing in order to avoid crashing when replacing content 1.278 + mDocument->RemoveObserver(this); 1.279 + mIsDocumentObserver = false; 1.280 + 1.281 + // Check for xslt-param and xslt-param-namespace PIs 1.282 + for (nsIContent* child = mDocument->GetFirstChild(); 1.283 + child; 1.284 + child = child->GetNextSibling()) { 1.285 + if (child->IsNodeOfType(nsINode::ePROCESSING_INSTRUCTION)) { 1.286 + nsCOMPtr<nsIDOMProcessingInstruction> pi = do_QueryInterface(child); 1.287 + CheckXSLTParamPI(pi, mXSLTProcessor, mDocument); 1.288 + } 1.289 + else if (child->IsElement()) { 1.290 + // Only honor PIs in the prolog 1.291 + break; 1.292 + } 1.293 + } 1.294 + 1.295 + nsCOMPtr<nsIDOMDocument> currentDOMDoc(do_QueryInterface(mDocument)); 1.296 + mXSLTProcessor->SetSourceContentModel(currentDOMDoc); 1.297 + // Since the processor now holds a reference to us we drop our reference 1.298 + // to it to avoid owning cycles 1.299 + mXSLTProcessor = nullptr; 1.300 + } 1.301 + else { 1.302 + // Kick off layout for non-XSLT transformed documents. 1.303 + 1.304 + // Check if we want to prettyprint 1.305 + MaybePrettyPrint(); 1.306 + 1.307 + bool startLayout = true; 1.308 + 1.309 + if (mPrettyPrinting) { 1.310 + NS_ASSERTION(!mPendingSheetCount, "Shouldn't have pending sheets here!"); 1.311 + 1.312 + // We're pretty-printing now. See whether we should wait up on 1.313 + // stylesheet loads 1.314 + if (mDocument->CSSLoader()->HasPendingLoads() && 1.315 + NS_SUCCEEDED(mDocument->CSSLoader()->AddObserver(this))) { 1.316 + // wait for those sheets to load 1.317 + startLayout = false; 1.318 + } 1.319 + } 1.320 + 1.321 + if (startLayout) { 1.322 + StartLayout(false); 1.323 + 1.324 + ScrollToRef(); 1.325 + } 1.326 + 1.327 + mDocument->RemoveObserver(this); 1.328 + mIsDocumentObserver = false; 1.329 + 1.330 + mDocument->EndLoad(); 1.331 + } 1.332 + 1.333 + DropParserAndPerfHint(); 1.334 + 1.335 + return NS_OK; 1.336 +} 1.337 + 1.338 +NS_IMETHODIMP 1.339 +nsXMLContentSink::OnDocumentCreated(nsIDocument* aResultDocument) 1.340 +{ 1.341 + NS_ENSURE_ARG(aResultDocument); 1.342 + 1.343 + nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(aResultDocument); 1.344 + if (htmlDoc) { 1.345 + htmlDoc->SetDocWriteDisabled(true); 1.346 + } 1.347 + 1.348 + nsCOMPtr<nsIContentViewer> contentViewer; 1.349 + mDocShell->GetContentViewer(getter_AddRefs(contentViewer)); 1.350 + if (contentViewer) { 1.351 + return contentViewer->SetDocumentInternal(aResultDocument, true); 1.352 + } 1.353 + return NS_OK; 1.354 +} 1.355 + 1.356 +NS_IMETHODIMP 1.357 +nsXMLContentSink::OnTransformDone(nsresult aResult, 1.358 + nsIDocument* aResultDocument) 1.359 +{ 1.360 + NS_ASSERTION(NS_FAILED(aResult) || aResultDocument, 1.361 + "Don't notify about transform success without a document."); 1.362 + 1.363 + nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(aResultDocument); 1.364 + 1.365 + nsCOMPtr<nsIContentViewer> contentViewer; 1.366 + mDocShell->GetContentViewer(getter_AddRefs(contentViewer)); 1.367 + 1.368 + if (NS_FAILED(aResult) && contentViewer) { 1.369 + // Transform failed. 1.370 + if (domDoc) { 1.371 + aResultDocument->SetMayStartLayout(false); 1.372 + // We have an error document. 1.373 + contentViewer->SetDOMDocument(domDoc); 1.374 + } 1.375 + else { 1.376 + // We don't have an error document, display the 1.377 + // untransformed source document. 1.378 + nsCOMPtr<nsIDOMDocument> document = do_QueryInterface(mDocument); 1.379 + contentViewer->SetDOMDocument(document); 1.380 + } 1.381 + } 1.382 + 1.383 + nsCOMPtr<nsIDocument> originalDocument = mDocument; 1.384 + if (NS_SUCCEEDED(aResult) || aResultDocument) { 1.385 + // Transform succeeded or it failed and we have an error 1.386 + // document to display. 1.387 + mDocument = aResultDocument; 1.388 + nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(mDocument); 1.389 + if (htmlDoc) { 1.390 + htmlDoc->SetDocWriteDisabled(false); 1.391 + } 1.392 + } 1.393 + 1.394 + // Notify document observers that all the content has been stuck 1.395 + // into the document. 1.396 + // XXX do we need to notify for things like PIs? Or just the 1.397 + // documentElement? 1.398 + nsIContent *rootElement = mDocument->GetRootElement(); 1.399 + if (rootElement) { 1.400 + NS_ASSERTION(mDocument->IndexOf(rootElement) != -1, 1.401 + "rootElement not in doc?"); 1.402 + mDocument->BeginUpdate(UPDATE_CONTENT_MODEL); 1.403 + nsNodeUtils::ContentInserted(mDocument, rootElement, 1.404 + mDocument->IndexOf(rootElement)); 1.405 + mDocument->EndUpdate(UPDATE_CONTENT_MODEL); 1.406 + } 1.407 + 1.408 + // Start the layout process 1.409 + StartLayout(false); 1.410 + 1.411 + ScrollToRef(); 1.412 + 1.413 + originalDocument->EndLoad(); 1.414 + 1.415 + return NS_OK; 1.416 +} 1.417 + 1.418 +NS_IMETHODIMP 1.419 +nsXMLContentSink::StyleSheetLoaded(nsCSSStyleSheet* aSheet, 1.420 + bool aWasAlternate, 1.421 + nsresult aStatus) 1.422 +{ 1.423 + if (!mPrettyPrinting) { 1.424 + return nsContentSink::StyleSheetLoaded(aSheet, aWasAlternate, aStatus); 1.425 + } 1.426 + 1.427 + if (!mDocument->CSSLoader()->HasPendingLoads()) { 1.428 + mDocument->CSSLoader()->RemoveObserver(this); 1.429 + StartLayout(false); 1.430 + ScrollToRef(); 1.431 + } 1.432 + 1.433 + return NS_OK; 1.434 +} 1.435 + 1.436 +NS_IMETHODIMP 1.437 +nsXMLContentSink::WillInterrupt(void) 1.438 +{ 1.439 + return WillInterruptImpl(); 1.440 +} 1.441 + 1.442 +NS_IMETHODIMP 1.443 +nsXMLContentSink::WillResume(void) 1.444 +{ 1.445 + return WillResumeImpl(); 1.446 +} 1.447 + 1.448 +NS_IMETHODIMP 1.449 +nsXMLContentSink::SetParser(nsParserBase* aParser) 1.450 +{ 1.451 + NS_PRECONDITION(aParser, "Should have a parser here!"); 1.452 + mParser = aParser; 1.453 + return NS_OK; 1.454 +} 1.455 + 1.456 +nsresult 1.457 +nsXMLContentSink::CreateElement(const char16_t** aAtts, uint32_t aAttsCount, 1.458 + nsINodeInfo* aNodeInfo, uint32_t aLineNumber, 1.459 + nsIContent** aResult, bool* aAppendContent, 1.460 + FromParser aFromParser) 1.461 +{ 1.462 + NS_ASSERTION(aNodeInfo, "can't create element without nodeinfo"); 1.463 + 1.464 + *aResult = nullptr; 1.465 + *aAppendContent = true; 1.466 + nsresult rv = NS_OK; 1.467 + 1.468 + nsCOMPtr<nsINodeInfo> ni = aNodeInfo; 1.469 + nsCOMPtr<Element> content; 1.470 + rv = NS_NewElement(getter_AddRefs(content), ni.forget(), aFromParser); 1.471 + NS_ENSURE_SUCCESS(rv, rv); 1.472 + 1.473 + if (aNodeInfo->Equals(nsGkAtoms::script, kNameSpaceID_XHTML) 1.474 + || aNodeInfo->Equals(nsGkAtoms::script, kNameSpaceID_SVG) 1.475 + ) { 1.476 + nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(content); 1.477 + sele->SetScriptLineNumber(aLineNumber); 1.478 + sele->SetCreatorParser(GetParser()); 1.479 + mConstrainSize = false; 1.480 + } 1.481 + 1.482 + // XHTML needs some special attention 1.483 + if (aNodeInfo->NamespaceEquals(kNameSpaceID_XHTML)) { 1.484 + mPrettyPrintHasFactoredElements = true; 1.485 + } 1.486 + else { 1.487 + // If we care, find out if we just used a special factory. 1.488 + if (!mPrettyPrintHasFactoredElements && !mPrettyPrintHasSpecialRoot && 1.489 + mPrettyPrintXML) { 1.490 + mPrettyPrintHasFactoredElements = 1.491 + nsContentUtils::NameSpaceManager()-> 1.492 + HasElementCreator(aNodeInfo->NamespaceID()); 1.493 + } 1.494 + 1.495 + if (!aNodeInfo->NamespaceEquals(kNameSpaceID_SVG)) { 1.496 + content.forget(aResult); 1.497 + 1.498 + return NS_OK; 1.499 + } 1.500 + } 1.501 + 1.502 + if (aNodeInfo->Equals(nsGkAtoms::link, kNameSpaceID_XHTML) || 1.503 + aNodeInfo->Equals(nsGkAtoms::style, kNameSpaceID_XHTML) || 1.504 + aNodeInfo->Equals(nsGkAtoms::style, kNameSpaceID_SVG)) { 1.505 + nsCOMPtr<nsIStyleSheetLinkingElement> ssle(do_QueryInterface(content)); 1.506 + if (ssle) { 1.507 + ssle->InitStyleLinkElement(false); 1.508 + if (aFromParser) { 1.509 + ssle->SetEnableUpdates(false); 1.510 + } 1.511 + if (!aNodeInfo->Equals(nsGkAtoms::link, kNameSpaceID_XHTML)) { 1.512 + ssle->SetLineNumber(aFromParser ? aLineNumber : 0); 1.513 + } 1.514 + } 1.515 + } 1.516 + 1.517 + content.forget(aResult); 1.518 + 1.519 + return NS_OK; 1.520 +} 1.521 + 1.522 + 1.523 +nsresult 1.524 +nsXMLContentSink::CloseElement(nsIContent* aContent) 1.525 +{ 1.526 + NS_ASSERTION(aContent, "missing element to close"); 1.527 + 1.528 + nsINodeInfo *nodeInfo = aContent->NodeInfo(); 1.529 + 1.530 + // Some HTML nodes need DoneAddingChildren() called to initialize 1.531 + // properly (eg form state restoration). 1.532 + if ((nodeInfo->NamespaceID() == kNameSpaceID_XHTML && 1.533 + (nodeInfo->NameAtom() == nsGkAtoms::select || 1.534 + nodeInfo->NameAtom() == nsGkAtoms::textarea || 1.535 + nodeInfo->NameAtom() == nsGkAtoms::video || 1.536 + nodeInfo->NameAtom() == nsGkAtoms::audio || 1.537 + nodeInfo->NameAtom() == nsGkAtoms::object || 1.538 + nodeInfo->NameAtom() == nsGkAtoms::applet)) 1.539 + || nodeInfo->NameAtom() == nsGkAtoms::title 1.540 + ) { 1.541 + aContent->DoneAddingChildren(HaveNotifiedForCurrentContent()); 1.542 + } 1.543 + 1.544 + if (IsMonolithicContainer(nodeInfo)) { 1.545 + mInMonolithicContainer--; 1.546 + } 1.547 + 1.548 + if (!nodeInfo->NamespaceEquals(kNameSpaceID_XHTML) && 1.549 + !nodeInfo->NamespaceEquals(kNameSpaceID_SVG)) { 1.550 + return NS_OK; 1.551 + } 1.552 + 1.553 + if (nodeInfo->Equals(nsGkAtoms::script, kNameSpaceID_XHTML) 1.554 + || nodeInfo->Equals(nsGkAtoms::script, kNameSpaceID_SVG) 1.555 + ) { 1.556 + mConstrainSize = true; 1.557 + nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(aContent); 1.558 + 1.559 + if (mPreventScriptExecution) { 1.560 + sele->PreventExecution(); 1.561 + return NS_OK; 1.562 + } 1.563 + 1.564 + // Always check the clock in nsContentSink right after a script 1.565 + StopDeflecting(); 1.566 + 1.567 + // Now tell the script that it's ready to go. This may execute the script 1.568 + // or return true, or neither if the script doesn't need executing. 1.569 + bool block = sele->AttemptToExecute(); 1.570 + 1.571 + // If the parser got blocked, make sure to return the appropriate rv. 1.572 + // I'm not sure if this is actually needed or not. 1.573 + if (mParser && !mParser->IsParserEnabled()) { 1.574 + // XXX The HTML sink doesn't call BlockParser here, why do we? 1.575 + GetParser()->BlockParser(); 1.576 + block = true; 1.577 + } 1.578 + 1.579 + return block ? NS_ERROR_HTMLPARSER_BLOCK : NS_OK; 1.580 + } 1.581 + 1.582 + nsresult rv = NS_OK; 1.583 + if (nodeInfo->Equals(nsGkAtoms::meta, kNameSpaceID_XHTML) && 1.584 + // Need to check here to make sure this meta tag does not set 1.585 + // mPrettyPrintXML to false when we have a special root! 1.586 + (!mPrettyPrintXML || !mPrettyPrintHasSpecialRoot)) { 1.587 + rv = ProcessMETATag(aContent); 1.588 + } 1.589 + else if (nodeInfo->Equals(nsGkAtoms::link, kNameSpaceID_XHTML) || 1.590 + nodeInfo->Equals(nsGkAtoms::style, kNameSpaceID_XHTML) || 1.591 + nodeInfo->Equals(nsGkAtoms::style, kNameSpaceID_SVG)) { 1.592 + nsCOMPtr<nsIStyleSheetLinkingElement> ssle(do_QueryInterface(aContent)); 1.593 + if (ssle) { 1.594 + ssle->SetEnableUpdates(true); 1.595 + bool willNotify; 1.596 + bool isAlternate; 1.597 + rv = ssle->UpdateStyleSheet(mRunsToCompletion ? nullptr : this, 1.598 + &willNotify, 1.599 + &isAlternate); 1.600 + if (NS_SUCCEEDED(rv) && willNotify && !isAlternate && !mRunsToCompletion) { 1.601 + ++mPendingSheetCount; 1.602 + mScriptLoader->AddExecuteBlocker(); 1.603 + } 1.604 + } 1.605 + // Look for <link rel="dns-prefetch" href="hostname"> 1.606 + // and look for <link rel="next" href="hostname"> like in HTML sink 1.607 + if (nodeInfo->Equals(nsGkAtoms::link, kNameSpaceID_XHTML)) { 1.608 + nsAutoString relVal; 1.609 + aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::rel, relVal); 1.610 + if (!relVal.IsEmpty()) { 1.611 + uint32_t linkTypes = nsStyleLinkElement::ParseLinkTypes(relVal); 1.612 + bool hasPrefetch = linkTypes & nsStyleLinkElement::ePREFETCH; 1.613 + if (hasPrefetch || (linkTypes & nsStyleLinkElement::eNEXT)) { 1.614 + nsAutoString hrefVal; 1.615 + aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::href, hrefVal); 1.616 + if (!hrefVal.IsEmpty()) { 1.617 + PrefetchHref(hrefVal, aContent, hasPrefetch); 1.618 + } 1.619 + } 1.620 + if (linkTypes & nsStyleLinkElement::eDNS_PREFETCH) { 1.621 + nsAutoString hrefVal; 1.622 + aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::href, hrefVal); 1.623 + if (!hrefVal.IsEmpty()) { 1.624 + PrefetchDNS(hrefVal); 1.625 + } 1.626 + } 1.627 + } 1.628 + } 1.629 + } 1.630 + 1.631 + return rv; 1.632 +} 1.633 + 1.634 +nsresult 1.635 +nsXMLContentSink::AddContentAsLeaf(nsIContent *aContent) 1.636 +{ 1.637 + nsresult result = NS_OK; 1.638 + 1.639 + if ((eXMLContentSinkState_InProlog == mState) || 1.640 + (eXMLContentSinkState_InEpilog == mState)) { 1.641 + NS_ASSERTION(mDocument, "Fragments have no prolog or epilog"); 1.642 + mDocument->AppendChildTo(aContent, false); 1.643 + } 1.644 + else { 1.645 + nsCOMPtr<nsIContent> parent = GetCurrentContent(); 1.646 + 1.647 + if (parent) { 1.648 + result = parent->AppendChildTo(aContent, false); 1.649 + } 1.650 + } 1.651 + return result; 1.652 +} 1.653 + 1.654 +// Create an XML parser and an XSL content sink and start parsing 1.655 +// the XSL stylesheet located at the given URI. 1.656 +nsresult 1.657 +nsXMLContentSink::LoadXSLStyleSheet(nsIURI* aUrl) 1.658 +{ 1.659 + nsCOMPtr<nsIDocumentTransformer> processor = 1.660 + do_CreateInstance("@mozilla.org/document-transformer;1?type=xslt"); 1.661 + if (!processor) { 1.662 + // No XSLT processor available, continue normal document loading 1.663 + return NS_OK; 1.664 + } 1.665 + 1.666 + processor->Init(mDocument->NodePrincipal()); 1.667 + processor->SetTransformObserver(this); 1.668 + 1.669 + nsCOMPtr<nsILoadGroup> loadGroup = mDocument->GetDocumentLoadGroup(); 1.670 + if (!loadGroup) { 1.671 + return NS_ERROR_FAILURE; 1.672 + } 1.673 + 1.674 + if (NS_SUCCEEDED(processor->LoadStyleSheet(aUrl, loadGroup))) { 1.675 + mXSLTProcessor.swap(processor); 1.676 + } 1.677 + 1.678 + // Intentionally ignore errors here, we should continue loading the 1.679 + // XML document whether we're able to load the XSLT stylesheet or 1.680 + // not. 1.681 + 1.682 + return NS_OK; 1.683 +} 1.684 + 1.685 +nsresult 1.686 +nsXMLContentSink::ProcessStyleLink(nsIContent* aElement, 1.687 + const nsSubstring& aHref, 1.688 + bool aAlternate, 1.689 + const nsSubstring& aTitle, 1.690 + const nsSubstring& aType, 1.691 + const nsSubstring& aMedia) 1.692 +{ 1.693 + nsresult rv = NS_OK; 1.694 + mPrettyPrintXML = false; 1.695 + 1.696 + nsAutoCString cmd; 1.697 + if (mParser) 1.698 + GetParser()->GetCommand(cmd); 1.699 + if (cmd.EqualsASCII(kLoadAsData)) 1.700 + return NS_OK; // Do not load stylesheets when loading as data 1.701 + 1.702 + NS_ConvertUTF16toUTF8 type(aType); 1.703 + if (type.EqualsIgnoreCase(TEXT_XSL) || 1.704 + type.EqualsIgnoreCase(APPLICATION_XSLT_XML) || 1.705 + type.EqualsIgnoreCase(TEXT_XML) || 1.706 + type.EqualsIgnoreCase(APPLICATION_XML)) { 1.707 + if (aAlternate) { 1.708 + // don't load alternate XSLT 1.709 + return NS_OK; 1.710 + } 1.711 + // LoadXSLStyleSheet needs a mDocShell. 1.712 + if (!mDocShell) 1.713 + return NS_OK; 1.714 + 1.715 + nsCOMPtr<nsIURI> url; 1.716 + rv = NS_NewURI(getter_AddRefs(url), aHref, nullptr, 1.717 + mDocument->GetDocBaseURI()); 1.718 + NS_ENSURE_SUCCESS(rv, rv); 1.719 + 1.720 + // Do security check 1.721 + nsIScriptSecurityManager *secMan = nsContentUtils::GetSecurityManager(); 1.722 + rv = secMan-> 1.723 + CheckLoadURIWithPrincipal(mDocument->NodePrincipal(), url, 1.724 + nsIScriptSecurityManager::ALLOW_CHROME); 1.725 + NS_ENSURE_SUCCESS(rv, NS_OK); 1.726 + 1.727 + // Do content policy check 1.728 + int16_t decision = nsIContentPolicy::ACCEPT; 1.729 + rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_XSLT, 1.730 + url, 1.731 + mDocument->NodePrincipal(), 1.732 + aElement, 1.733 + type, 1.734 + nullptr, 1.735 + &decision, 1.736 + nsContentUtils::GetContentPolicy(), 1.737 + nsContentUtils::GetSecurityManager()); 1.738 + 1.739 + NS_ENSURE_SUCCESS(rv, rv); 1.740 + 1.741 + if (NS_CP_REJECTED(decision)) { 1.742 + return NS_OK; 1.743 + } 1.744 + 1.745 + return LoadXSLStyleSheet(url); 1.746 + } 1.747 + 1.748 + // Let nsContentSink deal with css. 1.749 + rv = nsContentSink::ProcessStyleLink(aElement, aHref, aAlternate, 1.750 + aTitle, aType, aMedia); 1.751 + 1.752 + // nsContentSink::ProcessStyleLink handles the bookkeeping here wrt 1.753 + // pending sheets. 1.754 + 1.755 + return rv; 1.756 +} 1.757 + 1.758 +NS_IMETHODIMP 1.759 +nsXMLContentSink::SetDocumentCharset(nsACString& aCharset) 1.760 +{ 1.761 + if (mDocument) { 1.762 + mDocument->SetDocumentCharacterSet(aCharset); 1.763 + } 1.764 + 1.765 + return NS_OK; 1.766 +} 1.767 + 1.768 +nsISupports * 1.769 +nsXMLContentSink::GetTarget() 1.770 +{ 1.771 + return mDocument; 1.772 +} 1.773 + 1.774 +bool 1.775 +nsXMLContentSink::IsScriptExecuting() 1.776 +{ 1.777 + return IsScriptExecutingImpl(); 1.778 +} 1.779 + 1.780 +nsresult 1.781 +nsXMLContentSink::FlushText(bool aReleaseTextNode) 1.782 +{ 1.783 + nsresult rv = NS_OK; 1.784 + 1.785 + if (mTextLength != 0) { 1.786 + if (mLastTextNode) { 1.787 + if ((mLastTextNodeSize + mTextLength) > mTextSize && !mXSLTProcessor) { 1.788 + mLastTextNodeSize = 0; 1.789 + mLastTextNode = nullptr; 1.790 + FlushText(aReleaseTextNode); 1.791 + } else { 1.792 + bool notify = HaveNotifiedForCurrentContent(); 1.793 + // We could probably always increase mInNotification here since 1.794 + // if AppendText doesn't notify it shouldn't trigger evil code. 1.795 + // But just in case it does, we don't want to mask any notifications. 1.796 + if (notify) { 1.797 + ++mInNotification; 1.798 + } 1.799 + rv = mLastTextNode->AppendText(mText, mTextLength, notify); 1.800 + if (notify) { 1.801 + --mInNotification; 1.802 + } 1.803 + 1.804 + mLastTextNodeSize += mTextLength; 1.805 + mTextLength = 0; 1.806 + } 1.807 + } else { 1.808 + nsRefPtr<nsTextNode> textContent = new nsTextNode(mNodeInfoManager); 1.809 + 1.810 + mLastTextNode = textContent; 1.811 + 1.812 + // Set the text in the text node 1.813 + textContent->SetText(mText, mTextLength, false); 1.814 + mLastTextNodeSize += mTextLength; 1.815 + mTextLength = 0; 1.816 + 1.817 + // Add text to its parent 1.818 + rv = AddContentAsLeaf(textContent); 1.819 + } 1.820 + } 1.821 + 1.822 + if (aReleaseTextNode) { 1.823 + mLastTextNodeSize = 0; 1.824 + mLastTextNode = nullptr; 1.825 + } 1.826 + 1.827 + return rv; 1.828 +} 1.829 + 1.830 +nsIContent* 1.831 +nsXMLContentSink::GetCurrentContent() 1.832 +{ 1.833 + if (mContentStack.Length() == 0) { 1.834 + return nullptr; 1.835 + } 1.836 + return GetCurrentStackNode()->mContent; 1.837 +} 1.838 + 1.839 +StackNode* 1.840 +nsXMLContentSink::GetCurrentStackNode() 1.841 +{ 1.842 + int32_t count = mContentStack.Length(); 1.843 + return count != 0 ? &mContentStack[count-1] : nullptr; 1.844 +} 1.845 + 1.846 + 1.847 +nsresult 1.848 +nsXMLContentSink::PushContent(nsIContent *aContent) 1.849 +{ 1.850 + NS_PRECONDITION(aContent, "Null content being pushed!"); 1.851 + StackNode *sn = mContentStack.AppendElement(); 1.852 + NS_ENSURE_TRUE(sn, NS_ERROR_OUT_OF_MEMORY); 1.853 + 1.854 + sn->mContent = aContent; 1.855 + sn->mNumFlushed = 0; 1.856 + return NS_OK; 1.857 +} 1.858 + 1.859 +void 1.860 +nsXMLContentSink::PopContent() 1.861 +{ 1.862 + int32_t count = mContentStack.Length(); 1.863 + 1.864 + if (count == 0) { 1.865 + NS_WARNING("Popping empty stack"); 1.866 + return; 1.867 + } 1.868 + 1.869 + mContentStack.RemoveElementAt(count - 1); 1.870 +} 1.871 + 1.872 +bool 1.873 +nsXMLContentSink::HaveNotifiedForCurrentContent() const 1.874 +{ 1.875 + uint32_t stackLength = mContentStack.Length(); 1.876 + if (stackLength) { 1.877 + const StackNode& stackNode = mContentStack[stackLength - 1]; 1.878 + nsIContent* parent = stackNode.mContent; 1.879 + return stackNode.mNumFlushed == parent->GetChildCount(); 1.880 + } 1.881 + return true; 1.882 +} 1.883 + 1.884 +void 1.885 +nsXMLContentSink::MaybeStartLayout(bool aIgnorePendingSheets) 1.886 +{ 1.887 + // XXXbz if aIgnorePendingSheets is true, what should we do when 1.888 + // mXSLTProcessor or CanStillPrettyPrint()? 1.889 + if (mLayoutStarted || mXSLTProcessor || CanStillPrettyPrint()) { 1.890 + return; 1.891 + } 1.892 + StartLayout(aIgnorePendingSheets); 1.893 +} 1.894 + 1.895 +//////////////////////////////////////////////////////////////////////// 1.896 + 1.897 +bool 1.898 +nsXMLContentSink::SetDocElement(int32_t aNameSpaceID, 1.899 + nsIAtom* aTagName, 1.900 + nsIContent *aContent) 1.901 +{ 1.902 + if (mDocElement) 1.903 + return false; 1.904 + 1.905 + // check for root elements that needs special handling for 1.906 + // prettyprinting 1.907 + if ((aNameSpaceID == kNameSpaceID_XBL && 1.908 + aTagName == nsGkAtoms::bindings) || 1.909 + (aNameSpaceID == kNameSpaceID_XSLT && 1.910 + (aTagName == nsGkAtoms::stylesheet || 1.911 + aTagName == nsGkAtoms::transform))) { 1.912 + mPrettyPrintHasSpecialRoot = true; 1.913 + if (mPrettyPrintXML) { 1.914 + // In this case, disable script execution, stylesheet 1.915 + // loading, and auto XLinks since we plan to prettyprint. 1.916 + mDocument->ScriptLoader()->SetEnabled(false); 1.917 + if (mCSSLoader) { 1.918 + mCSSLoader->SetEnabled(false); 1.919 + } 1.920 + } 1.921 + } 1.922 + 1.923 + mDocElement = aContent; 1.924 + nsresult rv = mDocument->AppendChildTo(mDocElement, NotifyForDocElement()); 1.925 + if (NS_FAILED(rv)) { 1.926 + // If we return false here, the caller will bail out because it won't 1.927 + // find a parent content node to append to, which is fine. 1.928 + return false; 1.929 + } 1.930 + 1.931 + if (aTagName == nsGkAtoms::html && 1.932 + aNameSpaceID == kNameSpaceID_XHTML) { 1.933 + ProcessOfflineManifest(aContent); 1.934 + } 1.935 + 1.936 + return true; 1.937 +} 1.938 + 1.939 +NS_IMETHODIMP 1.940 +nsXMLContentSink::HandleStartElement(const char16_t *aName, 1.941 + const char16_t **aAtts, 1.942 + uint32_t aAttsCount, 1.943 + int32_t aIndex, 1.944 + uint32_t aLineNumber) 1.945 +{ 1.946 + return HandleStartElement(aName, aAtts, aAttsCount, aIndex, aLineNumber, 1.947 + true); 1.948 +} 1.949 + 1.950 +nsresult 1.951 +nsXMLContentSink::HandleStartElement(const char16_t *aName, 1.952 + const char16_t **aAtts, 1.953 + uint32_t aAttsCount, 1.954 + int32_t aIndex, 1.955 + uint32_t aLineNumber, 1.956 + bool aInterruptable) 1.957 +{ 1.958 + NS_PRECONDITION(aIndex >= -1, "Bogus aIndex"); 1.959 + NS_PRECONDITION(aAttsCount % 2 == 0, "incorrect aAttsCount"); 1.960 + // Adjust aAttsCount so it's the actual number of attributes 1.961 + aAttsCount /= 2; 1.962 + 1.963 + nsresult result = NS_OK; 1.964 + bool appendContent = true; 1.965 + nsCOMPtr<nsIContent> content; 1.966 + 1.967 + // XXX Hopefully the parser will flag this before we get 1.968 + // here. If we're in the epilog, there should be no 1.969 + // new elements 1.970 + PR_ASSERT(eXMLContentSinkState_InEpilog != mState); 1.971 + 1.972 + FlushText(); 1.973 + DidAddContent(); 1.974 + 1.975 + mState = eXMLContentSinkState_InDocumentElement; 1.976 + 1.977 + int32_t nameSpaceID; 1.978 + nsCOMPtr<nsIAtom> prefix, localName; 1.979 + nsContentUtils::SplitExpatName(aName, getter_AddRefs(prefix), 1.980 + getter_AddRefs(localName), &nameSpaceID); 1.981 + 1.982 + if (!OnOpenContainer(aAtts, aAttsCount, nameSpaceID, localName, aLineNumber)) { 1.983 + return NS_OK; 1.984 + } 1.985 + 1.986 + nsCOMPtr<nsINodeInfo> nodeInfo; 1.987 + nodeInfo = mNodeInfoManager->GetNodeInfo(localName, prefix, nameSpaceID, 1.988 + nsIDOMNode::ELEMENT_NODE); 1.989 + 1.990 + result = CreateElement(aAtts, aAttsCount, nodeInfo, aLineNumber, 1.991 + getter_AddRefs(content), &appendContent, 1.992 + FROM_PARSER_NETWORK); 1.993 + NS_ENSURE_SUCCESS(result, result); 1.994 + 1.995 + // Have to do this before we push the new content on the stack... and have to 1.996 + // do that before we set attributes, call BindToTree, etc. Ideally we'd push 1.997 + // on the stack inside CreateElement (which is effectively what the HTML sink 1.998 + // does), but that's hard with all the subclass overrides going on. 1.999 + nsCOMPtr<nsIContent> parent = GetCurrentContent(); 1.1000 + 1.1001 + result = PushContent(content); 1.1002 + NS_ENSURE_SUCCESS(result, result); 1.1003 + 1.1004 + // Set the ID attribute atom on the node info object for this node 1.1005 + // This must occur before the attributes are added so the name 1.1006 + // of the id attribute is known. 1.1007 + if (aIndex != -1 && NS_SUCCEEDED(result)) { 1.1008 + nsCOMPtr<nsIAtom> IDAttr = do_GetAtom(aAtts[aIndex]); 1.1009 + 1.1010 + if (IDAttr) { 1.1011 + nodeInfo->SetIDAttributeAtom(IDAttr); 1.1012 + } 1.1013 + } 1.1014 + 1.1015 + // Set the attributes on the new content element 1.1016 + result = AddAttributes(aAtts, content); 1.1017 + 1.1018 + if (NS_OK == result) { 1.1019 + // Store the element 1.1020 + if (!SetDocElement(nameSpaceID, localName, content) && appendContent) { 1.1021 + NS_ENSURE_TRUE(parent, NS_ERROR_UNEXPECTED); 1.1022 + 1.1023 + parent->AppendChildTo(content, false); 1.1024 + } 1.1025 + } 1.1026 + 1.1027 + // Some HTML nodes need DoneCreatingElement() called to initialize 1.1028 + // properly (eg form state restoration). 1.1029 + if (nodeInfo->NamespaceID() == kNameSpaceID_XHTML) { 1.1030 + if (nodeInfo->NameAtom() == nsGkAtoms::input || 1.1031 + nodeInfo->NameAtom() == nsGkAtoms::button || 1.1032 + nodeInfo->NameAtom() == nsGkAtoms::menuitem || 1.1033 + nodeInfo->NameAtom() == nsGkAtoms::audio || 1.1034 + nodeInfo->NameAtom() == nsGkAtoms::video) { 1.1035 + content->DoneCreatingElement(); 1.1036 + } else if (nodeInfo->NameAtom() == nsGkAtoms::head && !mCurrentHead) { 1.1037 + mCurrentHead = content; 1.1038 + } 1.1039 + } 1.1040 + 1.1041 + if (IsMonolithicContainer(nodeInfo)) { 1.1042 + mInMonolithicContainer++; 1.1043 + } 1.1044 + 1.1045 + if (content != mDocElement && !mCurrentHead) { 1.1046 + // This isn't the root and we're not inside an XHTML <head>. 1.1047 + // Might need to start layout 1.1048 + MaybeStartLayout(false); 1.1049 + } 1.1050 + 1.1051 + if (content == mDocElement) { 1.1052 + NotifyDocElementCreated(mDocument); 1.1053 + } 1.1054 + 1.1055 + return aInterruptable && NS_SUCCEEDED(result) ? DidProcessATokenImpl() : 1.1056 + result; 1.1057 +} 1.1058 + 1.1059 +NS_IMETHODIMP 1.1060 +nsXMLContentSink::HandleEndElement(const char16_t *aName) 1.1061 +{ 1.1062 + return HandleEndElement(aName, true); 1.1063 +} 1.1064 + 1.1065 +nsresult 1.1066 +nsXMLContentSink::HandleEndElement(const char16_t *aName, 1.1067 + bool aInterruptable) 1.1068 +{ 1.1069 + nsresult result = NS_OK; 1.1070 + 1.1071 + // XXX Hopefully the parser will flag this before we get 1.1072 + // here. If we're in the prolog or epilog, there should be 1.1073 + // no close tags for elements. 1.1074 + PR_ASSERT(eXMLContentSinkState_InDocumentElement == mState); 1.1075 + 1.1076 + FlushText(); 1.1077 + 1.1078 + StackNode* sn = GetCurrentStackNode(); 1.1079 + if (!sn) { 1.1080 + return NS_ERROR_UNEXPECTED; 1.1081 + } 1.1082 + 1.1083 + nsCOMPtr<nsIContent> content; 1.1084 + sn->mContent.swap(content); 1.1085 + uint32_t numFlushed = sn->mNumFlushed; 1.1086 + 1.1087 + PopContent(); 1.1088 + NS_ASSERTION(content, "failed to pop content"); 1.1089 +#ifdef DEBUG 1.1090 + // Check that we're closing the right thing 1.1091 + nsCOMPtr<nsIAtom> debugNameSpacePrefix, debugTagAtom; 1.1092 + int32_t debugNameSpaceID; 1.1093 + nsContentUtils::SplitExpatName(aName, getter_AddRefs(debugNameSpacePrefix), 1.1094 + getter_AddRefs(debugTagAtom), 1.1095 + &debugNameSpaceID); 1.1096 + NS_ASSERTION(content->NodeInfo()->Equals(debugTagAtom, debugNameSpaceID), 1.1097 + "Wrong element being closed"); 1.1098 +#endif 1.1099 + 1.1100 + result = CloseElement(content); 1.1101 + 1.1102 + if (mCurrentHead == content) { 1.1103 + mCurrentHead = nullptr; 1.1104 + } 1.1105 + 1.1106 + if (mDocElement == content) { 1.1107 + // XXXbz for roots that don't want to be appended on open, we 1.1108 + // probably need to deal here.... (and stop appending them on open). 1.1109 + mState = eXMLContentSinkState_InEpilog; 1.1110 + 1.1111 + // We might have had no occasion to start layout yet. Do so now. 1.1112 + MaybeStartLayout(false); 1.1113 + } 1.1114 + 1.1115 + int32_t stackLen = mContentStack.Length(); 1.1116 + if (mNotifyLevel >= stackLen) { 1.1117 + if (numFlushed < content->GetChildCount()) { 1.1118 + NotifyAppend(content, numFlushed); 1.1119 + } 1.1120 + mNotifyLevel = stackLen - 1; 1.1121 + } 1.1122 + DidAddContent(); 1.1123 + 1.1124 + if (content->IsSVG(nsGkAtoms::svg)) { 1.1125 + FlushTags(); 1.1126 + nsCOMPtr<nsIRunnable> event = new nsHtml5SVGLoadDispatcher(content); 1.1127 + if (NS_FAILED(NS_DispatchToMainThread(event))) { 1.1128 + NS_WARNING("failed to dispatch svg load dispatcher"); 1.1129 + } 1.1130 + } 1.1131 + 1.1132 + return aInterruptable && NS_SUCCEEDED(result) ? DidProcessATokenImpl() : 1.1133 + result; 1.1134 +} 1.1135 + 1.1136 +NS_IMETHODIMP 1.1137 +nsXMLContentSink::HandleComment(const char16_t *aName) 1.1138 +{ 1.1139 + FlushText(); 1.1140 + 1.1141 + nsRefPtr<Comment> comment = new Comment(mNodeInfoManager); 1.1142 + comment->SetText(nsDependentString(aName), false); 1.1143 + nsresult rv = AddContentAsLeaf(comment); 1.1144 + DidAddContent(); 1.1145 + 1.1146 + return NS_SUCCEEDED(rv) ? DidProcessATokenImpl() : rv; 1.1147 +} 1.1148 + 1.1149 +NS_IMETHODIMP 1.1150 +nsXMLContentSink::HandleCDataSection(const char16_t *aData, 1.1151 + uint32_t aLength) 1.1152 +{ 1.1153 + // XSLT doesn't differentiate between text and cdata and wants adjacent 1.1154 + // textnodes merged, so add as text. 1.1155 + if (mXSLTProcessor) { 1.1156 + return AddText(aData, aLength); 1.1157 + } 1.1158 + 1.1159 + FlushText(); 1.1160 + 1.1161 + nsRefPtr<CDATASection> cdata = new CDATASection(mNodeInfoManager); 1.1162 + cdata->SetText(aData, aLength, false); 1.1163 + nsresult rv = AddContentAsLeaf(cdata); 1.1164 + DidAddContent(); 1.1165 + 1.1166 + return NS_SUCCEEDED(rv) ? DidProcessATokenImpl() : rv; 1.1167 +} 1.1168 + 1.1169 +NS_IMETHODIMP 1.1170 +nsXMLContentSink::HandleDoctypeDecl(const nsAString & aSubset, 1.1171 + const nsAString & aName, 1.1172 + const nsAString & aSystemId, 1.1173 + const nsAString & aPublicId, 1.1174 + nsISupports* aCatalogData) 1.1175 +{ 1.1176 + FlushText(); 1.1177 + 1.1178 + nsresult rv = NS_OK; 1.1179 + 1.1180 + NS_ASSERTION(mDocument, "Shouldn't get here from a document fragment"); 1.1181 + 1.1182 + nsCOMPtr<nsIAtom> name = do_GetAtom(aName); 1.1183 + NS_ENSURE_TRUE(name, NS_ERROR_OUT_OF_MEMORY); 1.1184 + 1.1185 + // Create a new doctype node 1.1186 + nsCOMPtr<nsIDOMDocumentType> docType; 1.1187 + rv = NS_NewDOMDocumentType(getter_AddRefs(docType), mNodeInfoManager, 1.1188 + name, aPublicId, aSystemId, aSubset); 1.1189 + if (NS_FAILED(rv) || !docType) { 1.1190 + return rv; 1.1191 + } 1.1192 + 1.1193 + if (aCatalogData && mCSSLoader && mDocument) { 1.1194 + // bug 124570 - we only expect additional agent sheets for now -- ignore 1.1195 + // exit codes, error are not fatal here, just that the stylesheet won't apply 1.1196 + nsCOMPtr<nsIURI> uri(do_QueryInterface(aCatalogData)); 1.1197 + if (uri) { 1.1198 + nsRefPtr<nsCSSStyleSheet> sheet; 1.1199 + mCSSLoader->LoadSheetSync(uri, true, true, getter_AddRefs(sheet)); 1.1200 + 1.1201 +#ifdef DEBUG 1.1202 + nsAutoCString uriStr; 1.1203 + uri->GetSpec(uriStr); 1.1204 + printf("Loading catalog stylesheet: %s ... %s\n", uriStr.get(), sheet.get() ? "Done" : "Failed"); 1.1205 +#endif 1.1206 + if (sheet) { 1.1207 + mDocument->BeginUpdate(UPDATE_STYLE); 1.1208 + mDocument->AddCatalogStyleSheet(sheet); 1.1209 + mDocument->EndUpdate(UPDATE_STYLE); 1.1210 + } 1.1211 + } 1.1212 + } 1.1213 + 1.1214 + nsCOMPtr<nsIContent> content = do_QueryInterface(docType); 1.1215 + NS_ASSERTION(content, "doctype isn't content?"); 1.1216 + 1.1217 + rv = mDocument->AppendChildTo(content, false); 1.1218 + DidAddContent(); 1.1219 + return NS_SUCCEEDED(rv) ? DidProcessATokenImpl() : rv; 1.1220 +} 1.1221 + 1.1222 +NS_IMETHODIMP 1.1223 +nsXMLContentSink::HandleCharacterData(const char16_t *aData, 1.1224 + uint32_t aLength) 1.1225 +{ 1.1226 + return HandleCharacterData(aData, aLength, true); 1.1227 +} 1.1228 + 1.1229 +nsresult 1.1230 +nsXMLContentSink::HandleCharacterData(const char16_t *aData, uint32_t aLength, 1.1231 + bool aInterruptable) 1.1232 +{ 1.1233 + nsresult rv = NS_OK; 1.1234 + if (aData && mState != eXMLContentSinkState_InProlog && 1.1235 + mState != eXMLContentSinkState_InEpilog) { 1.1236 + rv = AddText(aData, aLength); 1.1237 + } 1.1238 + return aInterruptable && NS_SUCCEEDED(rv) ? DidProcessATokenImpl() : rv; 1.1239 +} 1.1240 + 1.1241 +NS_IMETHODIMP 1.1242 +nsXMLContentSink::HandleProcessingInstruction(const char16_t *aTarget, 1.1243 + const char16_t *aData) 1.1244 +{ 1.1245 + FlushText(); 1.1246 + 1.1247 + const nsDependentString target(aTarget); 1.1248 + const nsDependentString data(aData); 1.1249 + 1.1250 + nsCOMPtr<nsIContent> node = 1.1251 + NS_NewXMLProcessingInstruction(mNodeInfoManager, target, data); 1.1252 + 1.1253 + nsCOMPtr<nsIStyleSheetLinkingElement> ssle(do_QueryInterface(node)); 1.1254 + if (ssle) { 1.1255 + ssle->InitStyleLinkElement(false); 1.1256 + ssle->SetEnableUpdates(false); 1.1257 + mPrettyPrintXML = false; 1.1258 + } 1.1259 + 1.1260 + nsresult rv = AddContentAsLeaf(node); 1.1261 + NS_ENSURE_SUCCESS(rv, rv); 1.1262 + DidAddContent(); 1.1263 + 1.1264 + if (ssle) { 1.1265 + // This is an xml-stylesheet processing instruction... but it might not be 1.1266 + // a CSS one if the type is set to something else. 1.1267 + ssle->SetEnableUpdates(true); 1.1268 + bool willNotify; 1.1269 + bool isAlternate; 1.1270 + rv = ssle->UpdateStyleSheet(mRunsToCompletion ? nullptr : this, 1.1271 + &willNotify, 1.1272 + &isAlternate); 1.1273 + NS_ENSURE_SUCCESS(rv, rv); 1.1274 + 1.1275 + if (willNotify) { 1.1276 + // Successfully started a stylesheet load 1.1277 + if (!isAlternate && !mRunsToCompletion) { 1.1278 + ++mPendingSheetCount; 1.1279 + mScriptLoader->AddExecuteBlocker(); 1.1280 + } 1.1281 + 1.1282 + return NS_OK; 1.1283 + } 1.1284 + } 1.1285 + 1.1286 + // If it's not a CSS stylesheet PI... 1.1287 + nsAutoString type; 1.1288 + nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::type, type); 1.1289 + 1.1290 + if (mState != eXMLContentSinkState_InProlog || 1.1291 + !target.EqualsLiteral("xml-stylesheet") || 1.1292 + type.IsEmpty() || 1.1293 + type.LowerCaseEqualsLiteral("text/css")) { 1.1294 + return DidProcessATokenImpl(); 1.1295 + } 1.1296 + 1.1297 + nsAutoString href, title, media; 1.1298 + bool isAlternate = false; 1.1299 + 1.1300 + // If there was no href, we can't do anything with this PI 1.1301 + if (!ParsePIData(data, href, title, media, isAlternate)) { 1.1302 + return DidProcessATokenImpl(); 1.1303 + } 1.1304 + 1.1305 + rv = ProcessStyleLink(node, href, isAlternate, title, type, media); 1.1306 + return NS_SUCCEEDED(rv) ? DidProcessATokenImpl() : rv; 1.1307 +} 1.1308 + 1.1309 +/* static */ 1.1310 +bool 1.1311 +nsXMLContentSink::ParsePIData(const nsString &aData, nsString &aHref, 1.1312 + nsString &aTitle, nsString &aMedia, 1.1313 + bool &aIsAlternate) 1.1314 +{ 1.1315 + // If there was no href, we can't do anything with this PI 1.1316 + if (!nsContentUtils::GetPseudoAttributeValue(aData, nsGkAtoms::href, aHref)) { 1.1317 + return false; 1.1318 + } 1.1319 + 1.1320 + nsContentUtils::GetPseudoAttributeValue(aData, nsGkAtoms::title, aTitle); 1.1321 + 1.1322 + nsContentUtils::GetPseudoAttributeValue(aData, nsGkAtoms::media, aMedia); 1.1323 + 1.1324 + nsAutoString alternate; 1.1325 + nsContentUtils::GetPseudoAttributeValue(aData, 1.1326 + nsGkAtoms::alternate, 1.1327 + alternate); 1.1328 + 1.1329 + aIsAlternate = alternate.EqualsLiteral("yes"); 1.1330 + 1.1331 + return true; 1.1332 +} 1.1333 + 1.1334 +NS_IMETHODIMP 1.1335 +nsXMLContentSink::HandleXMLDeclaration(const char16_t *aVersion, 1.1336 + const char16_t *aEncoding, 1.1337 + int32_t aStandalone) 1.1338 +{ 1.1339 + mDocument->SetXMLDeclaration(aVersion, aEncoding, aStandalone); 1.1340 + 1.1341 + return DidProcessATokenImpl(); 1.1342 +} 1.1343 + 1.1344 +NS_IMETHODIMP 1.1345 +nsXMLContentSink::ReportError(const char16_t* aErrorText, 1.1346 + const char16_t* aSourceText, 1.1347 + nsIScriptError *aError, 1.1348 + bool *_retval) 1.1349 +{ 1.1350 + NS_PRECONDITION(aError && aSourceText && aErrorText, "Check arguments!!!"); 1.1351 + nsresult rv = NS_OK; 1.1352 + 1.1353 + // The expat driver should report the error. We're just cleaning up the mess. 1.1354 + *_retval = true; 1.1355 + 1.1356 + mPrettyPrintXML = false; 1.1357 + 1.1358 + mState = eXMLContentSinkState_InProlog; 1.1359 + 1.1360 + // XXX need to stop scripts here -- hsivonen 1.1361 + 1.1362 + // stop observing in order to avoid crashing when removing content 1.1363 + mDocument->RemoveObserver(this); 1.1364 + mIsDocumentObserver = false; 1.1365 + 1.1366 + // Clear the current content and 1.1367 + // prepare to set <parsererror> as the document root 1.1368 + nsCOMPtr<nsIDOMNode> node(do_QueryInterface(mDocument)); 1.1369 + if (node) { 1.1370 + for (;;) { 1.1371 + nsCOMPtr<nsIDOMNode> child, dummy; 1.1372 + node->GetLastChild(getter_AddRefs(child)); 1.1373 + if (!child) 1.1374 + break; 1.1375 + node->RemoveChild(child, getter_AddRefs(dummy)); 1.1376 + } 1.1377 + } 1.1378 + mDocElement = nullptr; 1.1379 + 1.1380 + // Clear any buffered-up text we have. It's enough to set the length to 0. 1.1381 + // The buffer itself is allocated when we're created and deleted in our 1.1382 + // destructor, so don't mess with it. 1.1383 + mTextLength = 0; 1.1384 + 1.1385 + if (mXSLTProcessor) { 1.1386 + // Get rid of the XSLT processor. 1.1387 + mXSLTProcessor->CancelLoads(); 1.1388 + mXSLTProcessor = nullptr; 1.1389 + } 1.1390 + 1.1391 + // release the nodes on stack 1.1392 + mContentStack.Clear(); 1.1393 + mNotifyLevel = 0; 1.1394 + 1.1395 + rv = HandleProcessingInstruction(MOZ_UTF16("xml-stylesheet"), 1.1396 + MOZ_UTF16("href=\"chrome://global/locale/intl.css\" type=\"text/css\"")); 1.1397 + NS_ENSURE_SUCCESS(rv, rv); 1.1398 + 1.1399 + const char16_t* noAtts[] = { 0, 0 }; 1.1400 + 1.1401 + NS_NAMED_LITERAL_STRING(errorNs, 1.1402 + "http://www.mozilla.org/newlayout/xml/parsererror.xml"); 1.1403 + 1.1404 + nsAutoString parsererror(errorNs); 1.1405 + parsererror.Append((char16_t)0xFFFF); 1.1406 + parsererror.AppendLiteral("parsererror"); 1.1407 + 1.1408 + rv = HandleStartElement(parsererror.get(), noAtts, 0, -1, (uint32_t)-1, 1.1409 + false); 1.1410 + NS_ENSURE_SUCCESS(rv, rv); 1.1411 + 1.1412 + rv = HandleCharacterData(aErrorText, NS_strlen(aErrorText), false); 1.1413 + NS_ENSURE_SUCCESS(rv, rv); 1.1414 + 1.1415 + nsAutoString sourcetext(errorNs); 1.1416 + sourcetext.Append((char16_t)0xFFFF); 1.1417 + sourcetext.AppendLiteral("sourcetext"); 1.1418 + 1.1419 + rv = HandleStartElement(sourcetext.get(), noAtts, 0, -1, (uint32_t)-1, 1.1420 + false); 1.1421 + NS_ENSURE_SUCCESS(rv, rv); 1.1422 + 1.1423 + rv = HandleCharacterData(aSourceText, NS_strlen(aSourceText), false); 1.1424 + NS_ENSURE_SUCCESS(rv, rv); 1.1425 + 1.1426 + rv = HandleEndElement(sourcetext.get(), false); 1.1427 + NS_ENSURE_SUCCESS(rv, rv); 1.1428 + 1.1429 + rv = HandleEndElement(parsererror.get(), false); 1.1430 + NS_ENSURE_SUCCESS(rv, rv); 1.1431 + 1.1432 + FlushTags(); 1.1433 + 1.1434 + return NS_OK; 1.1435 +} 1.1436 + 1.1437 +nsresult 1.1438 +nsXMLContentSink::AddAttributes(const char16_t** aAtts, 1.1439 + nsIContent* aContent) 1.1440 +{ 1.1441 + // Add tag attributes to the content attributes 1.1442 + nsCOMPtr<nsIAtom> prefix, localName; 1.1443 + while (*aAtts) { 1.1444 + int32_t nameSpaceID; 1.1445 + nsContentUtils::SplitExpatName(aAtts[0], getter_AddRefs(prefix), 1.1446 + getter_AddRefs(localName), &nameSpaceID); 1.1447 + 1.1448 + // Add attribute to content 1.1449 + aContent->SetAttr(nameSpaceID, localName, prefix, 1.1450 + nsDependentString(aAtts[1]), false); 1.1451 + aAtts += 2; 1.1452 + } 1.1453 + 1.1454 + return NS_OK; 1.1455 +} 1.1456 + 1.1457 +#define NS_ACCUMULATION_BUFFER_SIZE 4096 1.1458 + 1.1459 +nsresult 1.1460 +nsXMLContentSink::AddText(const char16_t* aText, 1.1461 + int32_t aLength) 1.1462 +{ 1.1463 + // Create buffer when we first need it 1.1464 + if (0 == mTextSize) { 1.1465 + mText = (char16_t *) PR_MALLOC(sizeof(char16_t) * NS_ACCUMULATION_BUFFER_SIZE); 1.1466 + if (nullptr == mText) { 1.1467 + return NS_ERROR_OUT_OF_MEMORY; 1.1468 + } 1.1469 + mTextSize = NS_ACCUMULATION_BUFFER_SIZE; 1.1470 + } 1.1471 + 1.1472 + // Copy data from string into our buffer; flush buffer when it fills up 1.1473 + int32_t offset = 0; 1.1474 + while (0 != aLength) { 1.1475 + int32_t amount = mTextSize - mTextLength; 1.1476 + if (0 == amount) { 1.1477 + // XSLT wants adjacent textnodes merged. 1.1478 + if (mConstrainSize && !mXSLTProcessor) { 1.1479 + nsresult rv = FlushText(); 1.1480 + if (NS_OK != rv) { 1.1481 + return rv; 1.1482 + } 1.1483 + 1.1484 + amount = mTextSize - mTextLength; 1.1485 + } 1.1486 + else { 1.1487 + mTextSize += aLength; 1.1488 + mText = (char16_t *) PR_REALLOC(mText, sizeof(char16_t) * mTextSize); 1.1489 + if (nullptr == mText) { 1.1490 + mTextSize = 0; 1.1491 + 1.1492 + return NS_ERROR_OUT_OF_MEMORY; 1.1493 + } 1.1494 + 1.1495 + amount = aLength; 1.1496 + } 1.1497 + } 1.1498 + if (amount > aLength) { 1.1499 + amount = aLength; 1.1500 + } 1.1501 + memcpy(&mText[mTextLength], &aText[offset], sizeof(char16_t) * amount); 1.1502 + mTextLength += amount; 1.1503 + offset += amount; 1.1504 + aLength -= amount; 1.1505 + } 1.1506 + 1.1507 + return NS_OK; 1.1508 +} 1.1509 + 1.1510 +void 1.1511 +nsXMLContentSink::FlushPendingNotifications(mozFlushType aType) 1.1512 +{ 1.1513 + // Only flush tags if we're not doing the notification ourselves 1.1514 + // (since we aren't reentrant) 1.1515 + if (!mInNotification) { 1.1516 + if (mIsDocumentObserver) { 1.1517 + // Only flush if we're still a document observer (so that our child 1.1518 + // counts should be correct). 1.1519 + if (aType >= Flush_ContentAndNotify) { 1.1520 + FlushTags(); 1.1521 + } 1.1522 + else { 1.1523 + FlushText(false); 1.1524 + } 1.1525 + } 1.1526 + if (aType >= Flush_InterruptibleLayout) { 1.1527 + // Make sure that layout has started so that the reflow flush 1.1528 + // will actually happen. 1.1529 + MaybeStartLayout(true); 1.1530 + } 1.1531 + } 1.1532 +} 1.1533 + 1.1534 +/** 1.1535 + * NOTE!! Forked from SinkContext. Please keep in sync. 1.1536 + * 1.1537 + * Flush all elements that have been seen so far such that 1.1538 + * they are visible in the tree. Specifically, make sure 1.1539 + * that they are all added to their respective parents. 1.1540 + * Also, do notification at the top for all content that 1.1541 + * has been newly added so that the frame tree is complete. 1.1542 + */ 1.1543 +nsresult 1.1544 +nsXMLContentSink::FlushTags() 1.1545 +{ 1.1546 + mDeferredFlushTags = false; 1.1547 + bool oldBeganUpdate = mBeganUpdate; 1.1548 + uint32_t oldUpdates = mUpdatesInNotification; 1.1549 + 1.1550 + mUpdatesInNotification = 0; 1.1551 + ++mInNotification; 1.1552 + { 1.1553 + // Scope so we call EndUpdate before we decrease mInNotification 1.1554 + mozAutoDocUpdate updateBatch(mDocument, UPDATE_CONTENT_MODEL, true); 1.1555 + mBeganUpdate = true; 1.1556 + 1.1557 + // Don't release last text node in case we need to add to it again 1.1558 + FlushText(false); 1.1559 + 1.1560 + // Start from the base of the stack (growing downward) and do 1.1561 + // a notification from the node that is closest to the root of 1.1562 + // tree for any content that has been added. 1.1563 + 1.1564 + int32_t stackPos; 1.1565 + int32_t stackLen = mContentStack.Length(); 1.1566 + bool flushed = false; 1.1567 + uint32_t childCount; 1.1568 + nsIContent* content; 1.1569 + 1.1570 + for (stackPos = 0; stackPos < stackLen; ++stackPos) { 1.1571 + content = mContentStack[stackPos].mContent; 1.1572 + childCount = content->GetChildCount(); 1.1573 + 1.1574 + if (!flushed && (mContentStack[stackPos].mNumFlushed < childCount)) { 1.1575 + NotifyAppend(content, mContentStack[stackPos].mNumFlushed); 1.1576 + flushed = true; 1.1577 + } 1.1578 + 1.1579 + mContentStack[stackPos].mNumFlushed = childCount; 1.1580 + } 1.1581 + mNotifyLevel = stackLen - 1; 1.1582 + } 1.1583 + --mInNotification; 1.1584 + 1.1585 + if (mUpdatesInNotification > 1) { 1.1586 + UpdateChildCounts(); 1.1587 + } 1.1588 + 1.1589 + mUpdatesInNotification = oldUpdates; 1.1590 + mBeganUpdate = oldBeganUpdate; 1.1591 + 1.1592 + return NS_OK; 1.1593 +} 1.1594 + 1.1595 +/** 1.1596 + * NOTE!! Forked from SinkContext. Please keep in sync. 1.1597 + */ 1.1598 +void 1.1599 +nsXMLContentSink::UpdateChildCounts() 1.1600 +{ 1.1601 + // Start from the top of the stack (growing upwards) and see if any 1.1602 + // new content has been appended. If so, we recognize that reflows 1.1603 + // have been generated for it and we should make sure that no 1.1604 + // further reflows occur. Note that we have to include stackPos == 0 1.1605 + // to properly notify on kids of <html>. 1.1606 + int32_t stackLen = mContentStack.Length(); 1.1607 + int32_t stackPos = stackLen - 1; 1.1608 + while (stackPos >= 0) { 1.1609 + StackNode & node = mContentStack[stackPos]; 1.1610 + node.mNumFlushed = node.mContent->GetChildCount(); 1.1611 + 1.1612 + stackPos--; 1.1613 + } 1.1614 + mNotifyLevel = stackLen - 1; 1.1615 +} 1.1616 + 1.1617 +bool 1.1618 +nsXMLContentSink::IsMonolithicContainer(nsINodeInfo* aNodeInfo) 1.1619 +{ 1.1620 + return ((aNodeInfo->NamespaceID() == kNameSpaceID_XHTML && 1.1621 + (aNodeInfo->NameAtom() == nsGkAtoms::tr || 1.1622 + aNodeInfo->NameAtom() == nsGkAtoms::select || 1.1623 + aNodeInfo->NameAtom() == nsGkAtoms::object || 1.1624 + aNodeInfo->NameAtom() == nsGkAtoms::applet)) || 1.1625 + (aNodeInfo->NamespaceID() == kNameSpaceID_MathML && 1.1626 + (aNodeInfo->NameAtom() == nsGkAtoms::math)) 1.1627 + ); 1.1628 +} 1.1629 + 1.1630 +void 1.1631 +nsXMLContentSink::ContinueInterruptedParsingIfEnabled() 1.1632 +{ 1.1633 + if (mParser && mParser->IsParserEnabled()) { 1.1634 + GetParser()->ContinueInterruptedParsing(); 1.1635 + } 1.1636 +} 1.1637 + 1.1638 +void 1.1639 +nsXMLContentSink::ContinueInterruptedParsingAsync() 1.1640 +{ 1.1641 + nsCOMPtr<nsIRunnable> ev = NS_NewRunnableMethod(this, 1.1642 + &nsXMLContentSink::ContinueInterruptedParsingIfEnabled); 1.1643 + 1.1644 + NS_DispatchToCurrentThread(ev); 1.1645 +} 1.1646 + 1.1647 +nsIParser* 1.1648 +nsXMLContentSink::GetParser() 1.1649 +{ 1.1650 + return static_cast<nsIParser*>(mParser.get()); 1.1651 +}