From 36d22d82aa202bb199967e9512281e9a53db42c9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 21:33:14 +0200 Subject: Adding upstream version 115.7.0esr. Signed-off-by: Daniel Baumann --- dom/xml/CDATASection.cpp | 50 + dom/xml/CDATASection.h | 56 + dom/xml/ProcessingInstruction.cpp | 107 ++ dom/xml/ProcessingInstruction.h | 74 + dom/xml/XMLDocument.cpp | 338 ++++ dom/xml/XMLDocument.h | 86 + dom/xml/XMLStylesheetProcessingInstruction.cpp | 157 ++ dom/xml/XMLStylesheetProcessingInstruction.h | 84 + dom/xml/crashtests/1038887.xhtml | 1 + dom/xml/crashtests/136896-1.xml | 62 + dom/xml/crashtests/1405878.xml | 11 + dom/xml/crashtests/1523655.xml | 3 + dom/xml/crashtests/185285-1.xml | 2 + dom/xml/crashtests/382636-1.xml | 9 + dom/xml/crashtests/382636-2.svg | 5 + dom/xml/crashtests/382636-3.xhtml | 9 + dom/xml/crashtests/382636-4.xhtml | 5 + dom/xml/crashtests/420429.xhtml | 18 + dom/xml/crashtests/431703-1.xhtml | 17 + dom/xml/crashtests/453278-frame.xml | 3 + dom/xml/crashtests/453278.html | 9 + dom/xml/crashtests/803586.xhtml | 8 + dom/xml/crashtests/994740-1.xhtml | 15 + dom/xml/crashtests/crashtests.list | 14 + dom/xml/crashtests/tree.gif | Bin 0 -> 1140 bytes dom/xml/htmlmathml-f.ent | 2164 ++++++++++++++++++++++++ dom/xml/moz.build | 51 + dom/xml/nsIXMLContentSink.h | 61 + dom/xml/nsXMLContentSink.cpp | 1536 +++++++++++++++++ dom/xml/nsXMLContentSink.h | 217 +++ dom/xml/nsXMLElement.cpp | 54 + dom/xml/nsXMLElement.h | 35 + dom/xml/nsXMLFragmentContentSink.cpp | 372 ++++ dom/xml/nsXMLPrettyPrinter.cpp | 189 +++ dom/xml/nsXMLPrettyPrinter.h | 59 + dom/xml/resources/XMLPrettyPrint.css | 58 + dom/xml/resources/XMLPrettyPrint.xsl | 133 ++ dom/xml/resources/jar.mn | 7 + dom/xml/resources/moz.build | 7 + dom/xml/test/file_bug293347.xml | 2 + dom/xml/test/file_bug293347xslt.xml | 19 + dom/xml/test/file_bug343870.xml | 6 + dom/xml/test/file_bug691215.xml | 2 + dom/xml/test/mochitest.ini | 14 + dom/xml/test/old/books/bethlehem.gif | Bin 0 -> 5565 bytes dom/xml/test/old/books/bill.gif | Bin 0 -> 5022 bytes dom/xml/test/old/books/books.js | 90 + dom/xml/test/old/books/books.xml | 103 ++ dom/xml/test/old/books/charing.gif | Bin 0 -> 5947 bytes dom/xml/test/old/books/classic.css | 78 + dom/xml/test/old/books/common.css | 43 + dom/xml/test/old/books/kerouac.gif | Bin 0 -> 50387 bytes dom/xml/test/old/books/list.css | 61 + dom/xml/test/old/books/road.gif | Bin 0 -> 8004 bytes dom/xml/test/old/books/welville.gif | Bin 0 -> 4535 bytes dom/xml/test/old/docbook.css | 621 +++++++ dom/xml/test/old/docbooktest.xml | 126 ++ dom/xml/test/old/flamer.gif | Bin 0 -> 11284 bytes dom/xml/test/old/script.xml | 67 + dom/xml/test/old/simple.xml | 10 + dom/xml/test/old/toc/book.css | 137 ++ dom/xml/test/old/toc/irslogo.gif | Bin 0 -> 2605 bytes dom/xml/test/old/toc/minus.gif | Bin 0 -> 85 bytes dom/xml/test/old/toc/plus.gif | Bin 0 -> 88 bytes dom/xml/test/old/toc/rights.xml | 292 ++++ dom/xml/test/old/toc/toc.css | 77 + dom/xml/test/old/toc/toc.js | 131 ++ dom/xml/test/old/xlink/auto.xml | 16 + dom/xml/test/old/xlink/link.css | 22 + dom/xml/test/old/xlink/manual.xml | 14 + dom/xml/test/old/xmlbase/xmlbase.css | 28 + dom/xml/test/old/xmlbase/xmlbase.xml | 82 + dom/xml/test/test_bug232004.xhtml | 38 + dom/xml/test/test_bug293347.html | 33 + dom/xml/test/test_bug343870.xhtml | 39 + dom/xml/test/test_bug355213.xhtml | 35 + dom/xml/test/test_bug691215.html | 53 + 77 files changed, 8325 insertions(+) create mode 100644 dom/xml/CDATASection.cpp create mode 100644 dom/xml/CDATASection.h create mode 100644 dom/xml/ProcessingInstruction.cpp create mode 100644 dom/xml/ProcessingInstruction.h create mode 100644 dom/xml/XMLDocument.cpp create mode 100644 dom/xml/XMLDocument.h create mode 100644 dom/xml/XMLStylesheetProcessingInstruction.cpp create mode 100644 dom/xml/XMLStylesheetProcessingInstruction.h create mode 100644 dom/xml/crashtests/1038887.xhtml create mode 100644 dom/xml/crashtests/136896-1.xml create mode 100644 dom/xml/crashtests/1405878.xml create mode 100644 dom/xml/crashtests/1523655.xml create mode 100644 dom/xml/crashtests/185285-1.xml create mode 100644 dom/xml/crashtests/382636-1.xml create mode 100644 dom/xml/crashtests/382636-2.svg create mode 100644 dom/xml/crashtests/382636-3.xhtml create mode 100644 dom/xml/crashtests/382636-4.xhtml create mode 100644 dom/xml/crashtests/420429.xhtml create mode 100644 dom/xml/crashtests/431703-1.xhtml create mode 100644 dom/xml/crashtests/453278-frame.xml create mode 100644 dom/xml/crashtests/453278.html create mode 100644 dom/xml/crashtests/803586.xhtml create mode 100644 dom/xml/crashtests/994740-1.xhtml create mode 100644 dom/xml/crashtests/crashtests.list create mode 100644 dom/xml/crashtests/tree.gif create mode 100644 dom/xml/htmlmathml-f.ent create mode 100644 dom/xml/moz.build create mode 100644 dom/xml/nsIXMLContentSink.h create mode 100644 dom/xml/nsXMLContentSink.cpp create mode 100644 dom/xml/nsXMLContentSink.h create mode 100644 dom/xml/nsXMLElement.cpp create mode 100644 dom/xml/nsXMLElement.h create mode 100644 dom/xml/nsXMLFragmentContentSink.cpp create mode 100644 dom/xml/nsXMLPrettyPrinter.cpp create mode 100644 dom/xml/nsXMLPrettyPrinter.h create mode 100644 dom/xml/resources/XMLPrettyPrint.css create mode 100644 dom/xml/resources/XMLPrettyPrint.xsl create mode 100644 dom/xml/resources/jar.mn create mode 100644 dom/xml/resources/moz.build create mode 100644 dom/xml/test/file_bug293347.xml create mode 100644 dom/xml/test/file_bug293347xslt.xml create mode 100644 dom/xml/test/file_bug343870.xml create mode 100644 dom/xml/test/file_bug691215.xml create mode 100644 dom/xml/test/mochitest.ini create mode 100644 dom/xml/test/old/books/bethlehem.gif create mode 100644 dom/xml/test/old/books/bill.gif create mode 100644 dom/xml/test/old/books/books.js create mode 100644 dom/xml/test/old/books/books.xml create mode 100644 dom/xml/test/old/books/charing.gif create mode 100644 dom/xml/test/old/books/classic.css create mode 100644 dom/xml/test/old/books/common.css create mode 100644 dom/xml/test/old/books/kerouac.gif create mode 100644 dom/xml/test/old/books/list.css create mode 100644 dom/xml/test/old/books/road.gif create mode 100644 dom/xml/test/old/books/welville.gif create mode 100644 dom/xml/test/old/docbook.css create mode 100644 dom/xml/test/old/docbooktest.xml create mode 100644 dom/xml/test/old/flamer.gif create mode 100644 dom/xml/test/old/script.xml create mode 100644 dom/xml/test/old/simple.xml create mode 100644 dom/xml/test/old/toc/book.css create mode 100644 dom/xml/test/old/toc/irslogo.gif create mode 100644 dom/xml/test/old/toc/minus.gif create mode 100644 dom/xml/test/old/toc/plus.gif create mode 100644 dom/xml/test/old/toc/rights.xml create mode 100644 dom/xml/test/old/toc/toc.css create mode 100644 dom/xml/test/old/toc/toc.js create mode 100644 dom/xml/test/old/xlink/auto.xml create mode 100644 dom/xml/test/old/xlink/link.css create mode 100644 dom/xml/test/old/xlink/manual.xml create mode 100644 dom/xml/test/old/xmlbase/xmlbase.css create mode 100644 dom/xml/test/old/xmlbase/xmlbase.xml create mode 100644 dom/xml/test/test_bug232004.xhtml create mode 100644 dom/xml/test/test_bug293347.html create mode 100644 dom/xml/test/test_bug343870.xhtml create mode 100644 dom/xml/test/test_bug355213.xhtml create mode 100644 dom/xml/test/test_bug691215.html (limited to 'dom/xml') diff --git a/dom/xml/CDATASection.cpp b/dom/xml/CDATASection.cpp new file mode 100644 index 0000000000..4858c24af1 --- /dev/null +++ b/dom/xml/CDATASection.cpp @@ -0,0 +1,50 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/dom/CDATASection.h" +#include "mozilla/dom/CDATASectionBinding.h" +#include "mozilla/IntegerPrintfMacros.h" + +namespace mozilla::dom { + +CDATASection::~CDATASection() = default; + +JSObject* CDATASection::WrapNode(JSContext* aCx, + JS::Handle aGivenProto) { + return CDATASection_Binding::Wrap(aCx, this, aGivenProto); +} + +already_AddRefed CDATASection::CloneDataNode( + mozilla::dom::NodeInfo* aNodeInfo, bool aCloneText) const { + RefPtr ni = aNodeInfo; + auto* nim = ni->NodeInfoManager(); + RefPtr it = new (nim) CDATASection(ni.forget()); + if (aCloneText) { + it->mText = mText; + } + + return it.forget(); +} + +#ifdef MOZ_DOM_LIST +void CDATASection::List(FILE* out, int32_t aIndent) const { + int32_t index; + for (index = aIndent; --index >= 0;) fputs(" ", out); + + fprintf(out, "CDATASection refcount=%" PRIuPTR "<", mRefCnt.get()); + + nsAutoString tmp; + ToCString(tmp, 0, mText.GetLength()); + fputs(NS_LossyConvertUTF16toASCII(tmp).get(), out); + + fputs(">\n", out); +} + +void CDATASection::DumpContent(FILE* out, int32_t aIndent, + bool aDumpAll) const {} +#endif + +} // namespace mozilla::dom diff --git a/dom/xml/CDATASection.h b/dom/xml/CDATASection.h new file mode 100644 index 0000000000..ab20a2d21e --- /dev/null +++ b/dom/xml/CDATASection.h @@ -0,0 +1,56 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_CDATASection_h +#define mozilla_dom_CDATASection_h + +#include "mozilla/Attributes.h" +#include "mozilla/dom/Text.h" + +namespace mozilla::dom { + +class CDATASection final : public Text { + private: + void Init() { + MOZ_ASSERT(mNodeInfo->NodeType() == CDATA_SECTION_NODE, + "Bad NodeType in aNodeInfo"); + } + + virtual ~CDATASection(); + + public: + explicit CDATASection(already_AddRefed&& aNodeInfo) + : Text(std::move(aNodeInfo)) { + Init(); + } + + explicit CDATASection(nsNodeInfoManager* aNodeInfoManager) + : Text(aNodeInfoManager->GetNodeInfo(nsGkAtoms::cdataTagName, nullptr, + kNameSpaceID_None, + CDATA_SECTION_NODE)) { + Init(); + } + + // nsISupports + NS_INLINE_DECL_REFCOUNTING_INHERITED(CDATASection, Text) + + // nsINode + already_AddRefed CloneDataNode( + mozilla::dom::NodeInfo* aNodeInfo, bool aCloneText) const override; + +#ifdef MOZ_DOM_LIST + void List(FILE* out, int32_t aIndent) const override; + void DumpContent(FILE* out, int32_t aIndent, bool aDumpAll) const override; +#endif + + protected: + JSObject* WrapNode(JSContext* aCx, + JS::Handle aGivenProto) override; +}; + +} // namespace mozilla::dom + +#endif // mozilla_dom_CDATASection_h diff --git a/dom/xml/ProcessingInstruction.cpp b/dom/xml/ProcessingInstruction.cpp new file mode 100644 index 0000000000..1875487212 --- /dev/null +++ b/dom/xml/ProcessingInstruction.cpp @@ -0,0 +1,107 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsGkAtoms.h" +#include "nsUnicharUtils.h" +#include "mozilla/dom/LinkStyle.h" +#include "mozilla/dom/ProcessingInstruction.h" +#include "mozilla/dom/ProcessingInstructionBinding.h" +#include "mozilla/dom/XMLStylesheetProcessingInstruction.h" +#include "mozilla/IntegerPrintfMacros.h" +#include "nsContentUtils.h" + +already_AddRefed +NS_NewXMLProcessingInstruction(nsNodeInfoManager* aNodeInfoManager, + const nsAString& aTarget, + const nsAString& aData) { + using mozilla::dom::ProcessingInstruction; + using mozilla::dom::XMLStylesheetProcessingInstruction; + + MOZ_ASSERT(aNodeInfoManager, "Missing nodeinfo manager"); + + RefPtr target = NS_Atomize(aTarget); + MOZ_ASSERT(target); + + if (target == nsGkAtoms::xml_stylesheet) { + RefPtr pi = new (aNodeInfoManager) + XMLStylesheetProcessingInstruction(aNodeInfoManager, aData); + return pi.forget(); + } + + RefPtr ni; + ni = aNodeInfoManager->GetNodeInfo( + nsGkAtoms::processingInstructionTagName, nullptr, kNameSpaceID_None, + nsINode::PROCESSING_INSTRUCTION_NODE, target); + + RefPtr instance = + new (aNodeInfoManager) ProcessingInstruction(ni.forget(), aData); + + return instance.forget(); +} + +namespace mozilla::dom { + +ProcessingInstruction::ProcessingInstruction( + already_AddRefed&& aNodeInfo, + const nsAString& aData) + : CharacterData(std::move(aNodeInfo)) { + MOZ_ASSERT(mNodeInfo->NodeType() == nsINode::PROCESSING_INSTRUCTION_NODE, + "Bad NodeType in aNodeInfo"); + + SetTextInternal(0, mText.GetLength(), aData.BeginReading(), aData.Length(), + false); // Don't notify (bug 420429). +} + +ProcessingInstruction::~ProcessingInstruction() = default; + +StyleSheet* ProcessingInstruction::GetSheetForBindings() const { + if (const auto* linkStyle = LinkStyle::FromNode(*this)) { + return linkStyle->GetSheetForBindings(); + } + return nullptr; +} + +JSObject* ProcessingInstruction::WrapNode(JSContext* aCx, + JS::Handle aGivenProto) { + return ProcessingInstruction_Binding::Wrap(aCx, this, aGivenProto); +} + +bool ProcessingInstruction::GetAttrValue(nsAtom* aName, nsAString& aValue) { + nsAutoString data; + + GetData(data); + return nsContentUtils::GetPseudoAttributeValue(data, aName, aValue); +} + +already_AddRefed ProcessingInstruction::CloneDataNode( + mozilla::dom::NodeInfo* aNodeInfo, bool aCloneText) const { + nsAutoString data; + GetData(data); + RefPtr ni = aNodeInfo; + auto* nim = ni->NodeInfoManager(); + return do_AddRef(new (nim) ProcessingInstruction(ni.forget(), data)); +} + +#ifdef MOZ_DOM_LIST +void ProcessingInstruction::List(FILE* out, int32_t aIndent) const { + int32_t index; + for (index = aIndent; --index >= 0;) fputs(" ", out); + + fprintf(out, "Processing instruction refcount=%" PRIuPTR "<", mRefCnt.get()); + + nsAutoString tmp; + ToCString(tmp, 0, mText.GetLength()); + tmp.Insert(nsDependentAtomString(NodeInfo()->GetExtraName()).get(), 0); + fputs(NS_LossyConvertUTF16toASCII(tmp).get(), out); + + fputs(">\n", out); +} + +void ProcessingInstruction::DumpContent(FILE* out, int32_t aIndent, + bool aDumpAll) const {} +#endif + +} // namespace mozilla::dom diff --git a/dom/xml/ProcessingInstruction.h b/dom/xml/ProcessingInstruction.h new file mode 100644 index 0000000000..69902049d4 --- /dev/null +++ b/dom/xml/ProcessingInstruction.h @@ -0,0 +1,74 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_ProcessingInstruction_h +#define mozilla_dom_ProcessingInstruction_h + +#include "mozilla/Attributes.h" +#include "mozilla/dom/CharacterData.h" +#include "nsAString.h" + +class nsIPrincipal; +class nsIURI; + +namespace mozilla { + +class StyleSheet; + +namespace dom { + +class ProcessingInstruction : public CharacterData { + public: + ProcessingInstruction(already_AddRefed&& aNodeInfo, + const nsAString& aData); + + virtual already_AddRefed CloneDataNode( + dom::NodeInfo* aNodeInfo, bool aCloneText) const override; + +#ifdef MOZ_DOM_LIST + virtual void List(FILE* out, int32_t aIndent) const override; + virtual void DumpContent(FILE* out, int32_t aIndent, + bool aDumpAll) const override; +#endif + + // WebIDL API + void GetTarget(nsAString& aTarget) { aTarget = NodeName(); } + // This is the WebIDL API for LinkStyle, even though only + // XMLStylesheetProcessingInstruction actually implements LinkStyle. + StyleSheet* GetSheetForBindings() const; + + NS_IMPL_FROMNODE_HELPER(ProcessingInstruction, IsProcessingInstruction()) + + protected: + virtual ~ProcessingInstruction(); + + /** + * This will parse the content of the PI, to extract the value of the pseudo + * attribute with the name specified in aName. See + * http://www.w3.org/TR/xml-stylesheet/#NT-StyleSheetPI for the specification + * which is used to parse the content of the PI. + * + * @param aName the name of the attribute to get the value for + * @param aValue [out] the value for the attribute with name specified in + * aAttribute. Empty if the attribute isn't present. + */ + bool GetAttrValue(nsAtom* aName, nsAString& aValue); + + JSObject* WrapNode(JSContext*, JS::Handle aGivenProto) override; +}; + +} // namespace dom +} // namespace mozilla + +/** + * aNodeInfoManager must not be null. + */ +already_AddRefed +NS_NewXMLProcessingInstruction(nsNodeInfoManager* aNodeInfoManager, + const nsAString& aTarget, + const nsAString& aData); + +#endif // mozilla_dom_ProcessingInstruction_h diff --git a/dom/xml/XMLDocument.cpp b/dom/xml/XMLDocument.cpp new file mode 100644 index 0000000000..e9c821b7d4 --- /dev/null +++ b/dom/xml/XMLDocument.cpp @@ -0,0 +1,338 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/dom/XMLDocument.h" +#include "nsCharsetSource.h" +#include "nsIXMLContentSink.h" +#include "nsPresContext.h" +#include "nsIContent.h" +#include "nsIDocShell.h" +#include "nsHTMLParts.h" +#include "nsCOMPtr.h" +#include "nsString.h" +#include "nsIURI.h" +#include "nsNetUtil.h" +#include "nsError.h" +#include "nsIPrincipal.h" +#include "nsLayoutCID.h" +#include "mozilla/dom/Attr.h" +#include "nsCExternalHandlerService.h" +#include "nsMimeTypes.h" +#include "nsContentUtils.h" +#include "nsThreadUtils.h" +#include "nsJSUtils.h" +#include "nsCRT.h" +#include "nsComponentManagerUtils.h" +#include "nsContentCreatorFunctions.h" +#include "nsContentPolicyUtils.h" +#include "nsIConsoleService.h" +#include "nsIScriptError.h" +#include "nsHTMLDocument.h" +#include "nsParser.h" +#include "mozilla/BasicEvents.h" +#include "mozilla/EventDispatcher.h" +#include "mozilla/Encoding.h" +#include "mozilla/dom/DocumentType.h" +#include "mozilla/dom/Element.h" +#include "mozilla/dom/DocGroup.h" +#include "mozilla/dom/XMLDocumentBinding.h" +#include "mozilla/dom/DocumentBinding.h" + +using namespace mozilla; +using namespace mozilla::dom; + +// ================================================================== +// = +// ================================================================== + +nsresult NS_NewDOMDocument(Document** aInstancePtrResult, + const nsAString& aNamespaceURI, + const nsAString& aQualifiedName, + DocumentType* aDoctype, nsIURI* aDocumentURI, + nsIURI* aBaseURI, nsIPrincipal* aPrincipal, + bool aLoadedAsData, nsIGlobalObject* aEventObject, + DocumentFlavor aFlavor) { + // Note: can't require that aDocumentURI/aBaseURI/aPrincipal be non-null, + // since at least one caller (XMLHttpRequest) doesn't have decent args to + // pass in. + + nsresult rv; + + *aInstancePtrResult = nullptr; + + nsCOMPtr d; + bool isHTML = false; + bool isXHTML = false; + if (aFlavor == DocumentFlavorSVG) { + rv = NS_NewSVGDocument(getter_AddRefs(d)); + } else if (aFlavor == DocumentFlavorHTML) { + rv = NS_NewHTMLDocument(getter_AddRefs(d)); + isHTML = true; + } else if (aFlavor == DocumentFlavorXML) { + rv = NS_NewXMLDocument(getter_AddRefs(d)); + } else if (aFlavor == DocumentFlavorPlain) { + rv = NS_NewXMLDocument(getter_AddRefs(d), aLoadedAsData, true); + } else if (aDoctype) { + MOZ_ASSERT(aFlavor == DocumentFlavorLegacyGuess); + nsAutoString publicId, name; + aDoctype->GetPublicId(publicId); + if (publicId.IsEmpty()) { + aDoctype->GetName(name); + } + if (name.EqualsLiteral("html") || + publicId.EqualsLiteral("-//W3C//DTD HTML 4.01//EN") || + publicId.EqualsLiteral("-//W3C//DTD HTML 4.01 Frameset//EN") || + publicId.EqualsLiteral("-//W3C//DTD HTML 4.01 Transitional//EN") || + publicId.EqualsLiteral("-//W3C//DTD HTML 4.0//EN") || + publicId.EqualsLiteral("-//W3C//DTD HTML 4.0 Frameset//EN") || + publicId.EqualsLiteral("-//W3C//DTD HTML 4.0 Transitional//EN")) { + rv = NS_NewHTMLDocument(getter_AddRefs(d)); + isHTML = true; + } else if (publicId.EqualsLiteral("-//W3C//DTD XHTML 1.0 Strict//EN") || + publicId.EqualsLiteral( + "-//W3C//DTD XHTML 1.0 Transitional//EN") || + publicId.EqualsLiteral("-//W3C//DTD XHTML 1.0 Frameset//EN")) { + rv = NS_NewHTMLDocument(getter_AddRefs(d)); + isHTML = true; + isXHTML = true; + } else if (publicId.EqualsLiteral("-//W3C//DTD SVG 1.1//EN")) { + rv = NS_NewSVGDocument(getter_AddRefs(d)); + } + // XXX Add support for XUL documents. + else { + rv = NS_NewXMLDocument(getter_AddRefs(d)); + } + } else { + MOZ_ASSERT(aFlavor == DocumentFlavorLegacyGuess); + rv = NS_NewXMLDocument(getter_AddRefs(d)); + } + + if (NS_FAILED(rv)) { + return rv; + } + + if (isHTML) { + d->SetCompatibilityMode(eCompatibility_FullStandards); + d->AsHTMLDocument()->SetIsXHTML(isXHTML); + } + d->SetLoadedAsData(aLoadedAsData, /* aConsiderForMemoryReporting */ true); + d->SetDocumentURI(aDocumentURI); + // Must set the principal first, since SetBaseURI checks it. + d->SetPrincipals(aPrincipal, aPrincipal); + d->SetBaseURI(aBaseURI); + + // We need to set the script handling object after we set the principal such + // that the doc group is assigned correctly. + if (nsCOMPtr sgo = do_QueryInterface(aEventObject)) { + d->SetScriptHandlingObject(sgo); + } else if (aEventObject) { + d->SetScopeObject(aEventObject); + } + + // XMLDocuments and documents "created in memory" get to be UTF-8 by default, + // unlike the legacy HTML mess + d->SetDocumentCharacterSet(UTF_8_ENCODING); + + if (aDoctype) { + ErrorResult result; + d->AppendChild(*aDoctype, result); + // Need to WouldReportJSException() if our callee can throw a JS + // exception (which it can) and we're neither propagating the + // error out nor unconditionally suppressing it. + result.WouldReportJSException(); + if (NS_WARN_IF(result.Failed())) { + return result.StealNSResult(); + } + } + + if (!aQualifiedName.IsEmpty()) { + ErrorResult result; + ElementCreationOptionsOrString options; + options.SetAsString(); + + nsCOMPtr root = + d->CreateElementNS(aNamespaceURI, aQualifiedName, options, result); + if (NS_WARN_IF(result.Failed())) { + return result.StealNSResult(); + } + + d->AppendChild(*root, result); + // Need to WouldReportJSException() if our callee can throw a JS + // exception (which it can) and we're neither propagating the + // error out nor unconditionally suppressing it. + result.WouldReportJSException(); + if (NS_WARN_IF(result.Failed())) { + return result.StealNSResult(); + } + } + + d.forget(aInstancePtrResult); + + return NS_OK; +} + +nsresult NS_NewXMLDocument(Document** aInstancePtrResult, bool aLoadedAsData, + bool aIsPlainDocument) { + RefPtr doc = new XMLDocument(); + + nsresult rv = doc->Init(); + + if (NS_FAILED(rv)) { + *aInstancePtrResult = nullptr; + return rv; + } + + doc->SetLoadedAsData(aLoadedAsData, /* aConsiderForMemoryReporting */ true); + doc->mIsPlainDocument = aIsPlainDocument; + doc.forget(aInstancePtrResult); + + return NS_OK; +} + +namespace mozilla::dom { + +XMLDocument::XMLDocument(const char* aContentType) + : Document(aContentType), + mChannelIsPending(false), + mIsPlainDocument(false), + mSuppressParserErrorElement(false), + mSuppressParserErrorConsoleMessages(false) { + mType = eGenericXML; +} + +nsresult XMLDocument::Init() { + nsresult rv = Document::Init(); + NS_ENSURE_SUCCESS(rv, rv); + + return rv; +} + +void XMLDocument::Reset(nsIChannel* aChannel, nsILoadGroup* aLoadGroup) { + Document::Reset(aChannel, aLoadGroup); +} + +void XMLDocument::ResetToURI(nsIURI* aURI, nsILoadGroup* aLoadGroup, + nsIPrincipal* aPrincipal, + nsIPrincipal* aPartitionedPrincipal) { + if (mChannelIsPending) { + StopDocumentLoad(); + mChannel->CancelWithReason(NS_BINDING_ABORTED, + "XMLDocument::ResetToURI"_ns); + mChannelIsPending = false; + } + + Document::ResetToURI(aURI, aLoadGroup, aPrincipal, aPartitionedPrincipal); +} + +void XMLDocument::SetSuppressParserErrorElement(bool aSuppress) { + mSuppressParserErrorElement = aSuppress; +} + +bool XMLDocument::SuppressParserErrorElement() { + return mSuppressParserErrorElement; +} + +void XMLDocument::SetSuppressParserErrorConsoleMessages(bool aSuppress) { + mSuppressParserErrorConsoleMessages = aSuppress; +} + +bool XMLDocument::SuppressParserErrorConsoleMessages() { + return mSuppressParserErrorConsoleMessages; +} + +nsresult XMLDocument::StartDocumentLoad( + const char* aCommand, nsIChannel* aChannel, nsILoadGroup* aLoadGroup, + nsISupports* aContainer, nsIStreamListener** aDocListener, bool aReset) { + nsresult rv = Document::StartDocumentLoad(aCommand, aChannel, aLoadGroup, + aContainer, aDocListener, aReset); + if (NS_FAILED(rv)) return rv; + + int32_t charsetSource = kCharsetFromDocTypeDefault; + NotNull encoding = UTF_8_ENCODING; + TryChannelCharset(aChannel, charsetSource, encoding, nullptr); + + nsCOMPtr aUrl; + rv = aChannel->GetURI(getter_AddRefs(aUrl)); + if (NS_FAILED(rv)) return rv; + + mParser = new nsParser(); + + nsCOMPtr sink; + + nsCOMPtr docShell; + if (aContainer) { + docShell = do_QueryInterface(aContainer); + NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE); + } + rv = NS_NewXMLContentSink(getter_AddRefs(sink), this, aUrl, docShell, + aChannel); + NS_ENSURE_SUCCESS(rv, rv); + + // Set the parser as the stream listener for the document loader... + rv = CallQueryInterface(mParser, aDocListener); + NS_ENSURE_SUCCESS(rv, rv); + + NS_ASSERTION(mChannel, "How can we not have a channel here?"); + mChannelIsPending = true; + + SetDocumentCharacterSet(encoding); + mParser->SetDocumentCharset(encoding, charsetSource); + mParser->SetCommand(aCommand); + mParser->SetContentSink(sink); + mParser->Parse(aUrl); + + return NS_OK; +} + +void XMLDocument::EndLoad() { + mChannelIsPending = false; + + mSynchronousDOMContentLoaded = mLoadedAsData; + Document::EndLoad(); + if (mSynchronousDOMContentLoaded) { + mSynchronousDOMContentLoaded = false; + Document::SetReadyStateInternal(Document::READYSTATE_COMPLETE); + // Generate a document load event for the case when an XML + // document was loaded as pure data without any presentation + // attached to it. + WidgetEvent event(true, eLoad); + // TODO: Bug 1506441 + EventDispatcher::Dispatch(MOZ_KnownLive(ToSupports(this)), nullptr, &event); + } +} + +/* virtual */ +void XMLDocument::DocAddSizeOfExcludingThis(nsWindowSizes& aWindowSizes) const { + Document::DocAddSizeOfExcludingThis(aWindowSizes); +} + +// Document interface + +nsresult XMLDocument::Clone(dom::NodeInfo* aNodeInfo, nsINode** aResult) const { + NS_ASSERTION(aNodeInfo->NodeInfoManager() == mNodeInfoManager, + "Can't import this document into another document!"); + + RefPtr clone = new XMLDocument(); + nsresult rv = CloneDocHelper(clone); + NS_ENSURE_SUCCESS(rv, rv); + + // State from XMLDocument + clone->mIsPlainDocument = mIsPlainDocument; + + clone.forget(aResult); + return NS_OK; +} + +JSObject* XMLDocument::WrapNode(JSContext* aCx, + JS::Handle aGivenProto) { + if (mIsPlainDocument) { + return Document_Binding::Wrap(aCx, this, aGivenProto); + } + + return XMLDocument_Binding::Wrap(aCx, this, aGivenProto); +} + +} // namespace mozilla::dom diff --git a/dom/xml/XMLDocument.h b/dom/xml/XMLDocument.h new file mode 100644 index 0000000000..54ac3fb9ba --- /dev/null +++ b/dom/xml/XMLDocument.h @@ -0,0 +1,86 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_XMLDocument_h +#define mozilla_dom_XMLDocument_h + +#include "mozilla/Attributes.h" +#include "mozilla/dom/BindingDeclarations.h" +#include "mozilla/dom/Document.h" +#include "nsIScriptContext.h" + +class nsIURI; +class nsIChannel; + +namespace mozilla::dom { + +class XMLDocument : public Document { + public: + explicit XMLDocument(const char* aContentType = "application/xml"); + + NS_INLINE_DECL_REFCOUNTING_INHERITED(XMLDocument, Document) + + virtual void Reset(nsIChannel* aChannel, nsILoadGroup* aLoadGroup) override; + virtual void ResetToURI(nsIURI* aURI, nsILoadGroup* aLoadGroup, + nsIPrincipal* aPrincipal, + nsIPrincipal* aPartitionedPrincipal) override; + + virtual void SetSuppressParserErrorElement(bool aSuppress) override; + virtual bool SuppressParserErrorElement() override; + + virtual void SetSuppressParserErrorConsoleMessages(bool aSuppress) override; + virtual bool SuppressParserErrorConsoleMessages() override; + + virtual nsresult StartDocumentLoad(const char* aCommand, nsIChannel* channel, + nsILoadGroup* aLoadGroup, + nsISupports* aContainer, + nsIStreamListener** aDocListener, + bool aReset = true) override; + + // TODO: Convert this to MOZ_CAN_RUN_SCRIPT (bug 1415230, bug 1535398) + MOZ_CAN_RUN_SCRIPT_BOUNDARY virtual void EndLoad() override; + + virtual nsresult Init() override; + + virtual nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override; + + virtual void DocAddSizeOfExcludingThis( + nsWindowSizes& aWindowSizes) const override; + // DocAddSizeOfIncludingThis is inherited from Document. + + // .location is [Unforgeable], so we have to make it clear that the Document + // version applies to us (it's shadowed by the XPCOM thing on Document). + using Document::GetLocation; + + protected: + virtual ~XMLDocument() = default; + + virtual JSObject* WrapNode(JSContext* aCx, + JS::Handle aGivenProto) override; + + friend nsresult(::NS_NewXMLDocument)(Document**, bool, bool); + + // mChannelIsPending indicates whether we're currently asynchronously loading + // data from mChannel. It's set to true when we first find out about the + // channel (StartDocumentLoad) and set to false in EndLoad or if ResetToURI() + // is called. In the latter case our mChannel is also cancelled. Note that + // if this member is true, mChannel cannot be null. + bool mChannelIsPending; + + // If true. we're really a Document, not an XMLDocument + bool mIsPlainDocument; + + // If true, do not output elements. Per spec, XMLHttpRequest + // shouldn't output them, whereas DOMParser/others should (see bug 918703). + bool mSuppressParserErrorElement; + + // If true, do not log parsing errors to the web console (see bug 884693). + bool mSuppressParserErrorConsoleMessages; +}; + +} // namespace mozilla::dom + +#endif // mozilla_dom_XMLDocument_h diff --git a/dom/xml/XMLStylesheetProcessingInstruction.cpp b/dom/xml/XMLStylesheetProcessingInstruction.cpp new file mode 100644 index 0000000000..9285672bbf --- /dev/null +++ b/dom/xml/XMLStylesheetProcessingInstruction.cpp @@ -0,0 +1,157 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "XMLStylesheetProcessingInstruction.h" + +#include "mozilla/dom/Document.h" +#include "mozilla/dom/ReferrerInfo.h" +#include "nsContentUtils.h" +#include "nsNetUtil.h" + +namespace mozilla::dom { + +// nsISupports implementation + +NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0( + XMLStylesheetProcessingInstruction, ProcessingInstruction) + +NS_IMPL_CYCLE_COLLECTION_CLASS(XMLStylesheetProcessingInstruction) + +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED( + XMLStylesheetProcessingInstruction, ProcessingInstruction) + tmp->LinkStyle::Traverse(cb); +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END + +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED( + XMLStylesheetProcessingInstruction, ProcessingInstruction) + tmp->LinkStyle::Unlink(); +NS_IMPL_CYCLE_COLLECTION_UNLINK_END + +XMLStylesheetProcessingInstruction::~XMLStylesheetProcessingInstruction() = + default; + +// nsIContent + +nsresult XMLStylesheetProcessingInstruction::BindToTree(BindContext& aContext, + nsINode& aParent) { + nsresult rv = ProcessingInstruction::BindToTree(aContext, aParent); + NS_ENSURE_SUCCESS(rv, rv); + + void (XMLStylesheetProcessingInstruction::*update)() = + &XMLStylesheetProcessingInstruction::UpdateStyleSheetInternal; + nsContentUtils::AddScriptRunner(NewRunnableMethod( + "dom::XMLStylesheetProcessingInstruction::BindToTree", this, update)); + + return rv; +} + +void XMLStylesheetProcessingInstruction::UnbindFromTree(bool aNullParent) { + nsCOMPtr oldDoc = GetUncomposedDoc(); + + ProcessingInstruction::UnbindFromTree(aNullParent); + Unused << UpdateStyleSheetInternal(oldDoc, nullptr); +} + +// nsINode + +void XMLStylesheetProcessingInstruction::SetNodeValueInternal( + const nsAString& aNodeValue, ErrorResult& aError) { + CharacterData::SetNodeValueInternal(aNodeValue, aError); + if (!aError.Failed()) { + Unused << UpdateStyleSheetInternal(nullptr, nullptr, ForceUpdate::Yes); + } +} + +// LinkStyle + +void XMLStylesheetProcessingInstruction::GetCharset(nsAString& aCharset) { + if (!GetAttrValue(nsGkAtoms::charset, aCharset)) { + aCharset.Truncate(); + } +} + +void XMLStylesheetProcessingInstruction::OverrideBaseURI(nsIURI* aNewBaseURI) { + mOverriddenBaseURI = aNewBaseURI; +} + +Maybe +XMLStylesheetProcessingInstruction::GetStyleSheetInfo() { + // xml-stylesheet PI is special only in prolog + if (!nsContentUtils::InProlog(this)) { + return Nothing(); + } + + nsAutoString href; + if (!GetAttrValue(nsGkAtoms::href, href)) { + return Nothing(); + } + + nsAutoString data; + GetData(data); + + nsAutoString title; + nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::title, title); + + nsAutoString alternateAttr; + nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::alternate, + alternateAttr); + + bool alternate = alternateAttr.EqualsLiteral("yes"); + if (alternate && title.IsEmpty()) { + // alternates must have title + return Nothing(); + } + + nsAutoString media; + nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::media, media); + + // Make sure the type handling here matches + // nsXMLContentSink::HandleProcessingInstruction + nsAutoString type; + nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::type, type); + + nsAutoString mimeType, notUsed; + nsContentUtils::SplitMimeType(type, mimeType, notUsed); + if (!mimeType.IsEmpty() && !mimeType.LowerCaseEqualsLiteral("text/css")) { + return Nothing(); + } + + Document* doc = OwnerDoc(); + nsIURI* baseURL = + mOverriddenBaseURI ? mOverriddenBaseURI.get() : doc->GetDocBaseURI(); + auto encoding = doc->GetDocumentCharacterSet(); + nsCOMPtr uri; + NS_NewURI(getter_AddRefs(uri), href, encoding, baseURL); + + return Some(SheetInfo{ + *doc, + this, + uri.forget(), + nullptr, + MakeAndAddRef(*doc), + CORS_NONE, + title, + media, + /* integrity = */ u""_ns, + /* nonce = */ u""_ns, + alternate ? HasAlternateRel::Yes : HasAlternateRel::No, + IsInline::No, + IsExplicitlyEnabled::No, + }); +} + +already_AddRefed +XMLStylesheetProcessingInstruction::CloneDataNode( + mozilla::dom::NodeInfo* aNodeInfo, bool aCloneText) const { + nsAutoString data; + GetData(data); + RefPtr ni = aNodeInfo; + auto* nim = ni->NodeInfoManager(); + return do_AddRef(new (nim) + XMLStylesheetProcessingInstruction(ni.forget(), data)); +} + +} // namespace mozilla::dom diff --git a/dom/xml/XMLStylesheetProcessingInstruction.h b/dom/xml/XMLStylesheetProcessingInstruction.h new file mode 100644 index 0000000000..a6b3aa6978 --- /dev/null +++ b/dom/xml/XMLStylesheetProcessingInstruction.h @@ -0,0 +1,84 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_XMLStylesheetProcessingInstruction_h +#define mozilla_dom_XMLStylesheetProcessingInstruction_h + +#include "mozilla/Attributes.h" +#include "mozilla/Unused.h" +#include "mozilla/dom/LinkStyle.h" +#include "mozilla/dom/ProcessingInstruction.h" +#include "nsIURI.h" + +namespace mozilla::dom { + +class XMLStylesheetProcessingInstruction final : public ProcessingInstruction, + public LinkStyle { + public: + XMLStylesheetProcessingInstruction( + already_AddRefed&& aNodeInfo, + const nsAString& aData) + : ProcessingInstruction(std::move(aNodeInfo), aData) {} + + XMLStylesheetProcessingInstruction(nsNodeInfoManager* aNodeInfoManager, + const nsAString& aData) + : ProcessingInstruction( + aNodeInfoManager->GetNodeInfo( + nsGkAtoms::processingInstructionTagName, nullptr, + kNameSpaceID_None, PROCESSING_INSTRUCTION_NODE, + nsGkAtoms::xml_stylesheet), + aData) {} + + // CC + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(XMLStylesheetProcessingInstruction, + ProcessingInstruction) + + // nsINode + virtual void SetNodeValueInternal(const nsAString& aNodeValue, + mozilla::ErrorResult& aError) override; + + // nsIContent + virtual nsresult BindToTree(BindContext&, nsINode& aParent) override; + virtual void UnbindFromTree(bool aNullParent = true) override; + + /** + * Tells this processing instruction to use a different base URI. This is used + * for proper loading of xml-stylesheet processing instructions in XUL + * overlays and is only currently used by nsXMLStylesheetPI. + * + * @param aNewBaseURI the new base URI, nullptr to use the default base URI. + */ + void OverrideBaseURI(nsIURI* aNewBaseURI); + + // LinkStyle + void GetCharset(nsAString& aCharset) override; + + virtual void SetData(const nsAString& aData, + mozilla::ErrorResult& rv) override { + CharacterData::SetData(aData, rv); + if (rv.Failed()) { + return; + } + Unused << UpdateStyleSheetInternal(nullptr, nullptr, ForceUpdate::Yes); + } + + protected: + virtual ~XMLStylesheetProcessingInstruction(); + + nsCOMPtr mOverriddenBaseURI; + + nsIContent& AsContent() final { return *this; } + const LinkStyle* AsLinkStyle() const final { return this; } + Maybe GetStyleSheetInfo() final; + + already_AddRefed CloneDataNode( + mozilla::dom::NodeInfo* aNodeInfo, bool aCloneText) const final; +}; + +} // namespace mozilla::dom + +#endif // mozilla_dom_XMLStylesheetProcessingInstruction_h diff --git a/dom/xml/crashtests/1038887.xhtml b/dom/xml/crashtests/1038887.xhtml new file mode 100644 index 0000000000..18b12083a9 --- /dev/null +++ b/dom/xml/crashtests/1038887.xhtml @@ -0,0 +1 @@ + diff --git a/dom/xml/crashtests/136896-1.xml b/dom/xml/crashtests/136896-1.xml new file mode 100644 index 0000000000..a54f95393f --- /dev/null +++ b/dom/xml/crashtests/136896-1.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + +] +> + +1 + + 60 + abtauchen + 1 + 1 + 10240 + p + + abtauchen.at + abtauchen.com + abtauchen.net + + + + 83 + info + y + n + 10240 + p + + + + + * + info + + + + \ No newline at end of file diff --git a/dom/xml/crashtests/1405878.xml b/dom/xml/crashtests/1405878.xml new file mode 100644 index 0000000000..12677ade93 --- /dev/null +++ b/dom/xml/crashtests/1405878.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/dom/xml/crashtests/1523655.xml b/dom/xml/crashtests/1523655.xml new file mode 100644 index 0000000000..e905e9104d --- /dev/null +++ b/dom/xml/crashtests/1523655.xml @@ -0,0 +1,3 @@ + + + diff --git a/dom/xml/crashtests/185285-1.xml b/dom/xml/crashtests/185285-1.xml new file mode 100644 index 0000000000..9ab44d3356 --- /dev/null +++ b/dom/xml/crashtests/185285-1.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/dom/xml/crashtests/382636-1.xml b/dom/xml/crashtests/382636-1.xml new file mode 100644 index 0000000000..da5110ad05 --- /dev/null +++ b/dom/xml/crashtests/382636-1.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/dom/xml/crashtests/382636-2.svg b/dom/xml/crashtests/382636-2.svg new file mode 100644 index 0000000000..2be0060eed --- /dev/null +++ b/dom/xml/crashtests/382636-2.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/dom/xml/crashtests/382636-3.xhtml b/dom/xml/crashtests/382636-3.xhtml new file mode 100644 index 0000000000..da5110ad05 --- /dev/null +++ b/dom/xml/crashtests/382636-3.xhtml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/dom/xml/crashtests/382636-4.xhtml b/dom/xml/crashtests/382636-4.xhtml new file mode 100644 index 0000000000..e1c65b9030 --- /dev/null +++ b/dom/xml/crashtests/382636-4.xhtml @@ -0,0 +1,5 @@ + + + + + diff --git a/dom/xml/crashtests/420429.xhtml b/dom/xml/crashtests/420429.xhtml new file mode 100644 index 0000000000..e71af4ef21 --- /dev/null +++ b/dom/xml/crashtests/420429.xhtml @@ -0,0 +1,18 @@ + + + + + + + + + diff --git a/dom/xml/crashtests/431703-1.xhtml b/dom/xml/crashtests/431703-1.xhtml new file mode 100644 index 0000000000..622e4455cc --- /dev/null +++ b/dom/xml/crashtests/431703-1.xhtml @@ -0,0 +1,17 @@ + + + + + + + + diff --git a/dom/xml/crashtests/453278-frame.xml b/dom/xml/crashtests/453278-frame.xml new file mode 100644 index 0000000000..7ced674cc5 --- /dev/null +++ b/dom/xml/crashtests/453278-frame.xml @@ -0,0 +1,3 @@ + + + diff --git a/dom/xml/crashtests/453278.html b/dom/xml/crashtests/453278.html new file mode 100644 index 0000000000..f30ea3833e --- /dev/null +++ b/dom/xml/crashtests/453278.html @@ -0,0 +1,9 @@ + + + Bug 453278 - Crash [@ nsContentUtils::TriggerLink] with xlink stuff in display: none iframe + + + + + diff --git a/dom/xml/crashtests/803586.xhtml b/dom/xml/crashtests/803586.xhtml new file mode 100644 index 0000000000..002de07724 --- /dev/null +++ b/dom/xml/crashtests/803586.xhtml @@ -0,0 +1,8 @@ + + + + + + diff --git a/dom/xml/crashtests/994740-1.xhtml b/dom/xml/crashtests/994740-1.xhtml new file mode 100644 index 0000000000..4d71cef27f --- /dev/null +++ b/dom/xml/crashtests/994740-1.xhtml @@ -0,0 +1,15 @@ + + + + + + diff --git a/dom/xml/crashtests/crashtests.list b/dom/xml/crashtests/crashtests.list new file mode 100644 index 0000000000..158342c84d --- /dev/null +++ b/dom/xml/crashtests/crashtests.list @@ -0,0 +1,14 @@ +load 136896-1.xml +load 185285-1.xml +load 382636-1.xml +load 382636-2.svg +load 382636-3.xhtml +load chrome://reftest/content/crashtests/dom/xml/crashtests/382636-4.xhtml # Throws (bug 455856) +load chrome://reftest/content/crashtests/dom/xml/crashtests/420429.xhtml +load 431703-1.xhtml +load 453278.html +load 803586.xhtml +load 994740-1.xhtml +load 1038887.xhtml +load 1405878.xml +load 1523655.xml diff --git a/dom/xml/crashtests/tree.gif b/dom/xml/crashtests/tree.gif new file mode 100644 index 0000000000..360897e910 Binary files /dev/null and b/dom/xml/crashtests/tree.gif differ diff --git a/dom/xml/htmlmathml-f.ent b/dom/xml/htmlmathml-f.ent new file mode 100644 index 0000000000..37b2599769 --- /dev/null +++ b/dom/xml/htmlmathml-f.ent @@ -0,0 +1,2164 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dom/xml/moz.build b/dom/xml/moz.build new file mode 100644 index 0000000000..39fbb901f2 --- /dev/null +++ b/dom/xml/moz.build @@ -0,0 +1,51 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +with Files("**"): + BUG_COMPONENT = ("Core", "XML") + +DIRS += ["resources"] + +MOCHITEST_MANIFESTS += ["test/mochitest.ini"] + +EXPORTS += [ + "nsIXMLContentSink.h", +] + +EXPORTS.mozilla.dom += [ + "CDATASection.h", + "nsXMLElement.h", + "ProcessingInstruction.h", + "XMLDocument.h", + "XMLStylesheetProcessingInstruction.h", +] + +UNIFIED_SOURCES += [ + "CDATASection.cpp", + "nsXMLContentSink.cpp", + "nsXMLElement.cpp", + "nsXMLFragmentContentSink.cpp", + "nsXMLPrettyPrinter.cpp", + "ProcessingInstruction.cpp", + "XMLDocument.cpp", + "XMLStylesheetProcessingInstruction.cpp", +] + +FINAL_LIBRARY = "xul" + +LOCAL_INCLUDES += [ + "/caps", + "/dom/base", + "/dom/html", + "/dom/xslt/base", + "/dom/xul", + "/layout/style", + "/parser/htmlparser", +] + +RESOURCE_FILES.dtd += [ + "htmlmathml-f.ent", +] diff --git a/dom/xml/nsIXMLContentSink.h b/dom/xml/nsIXMLContentSink.h new file mode 100644 index 0000000000..eba9b356f0 --- /dev/null +++ b/dom/xml/nsIXMLContentSink.h @@ -0,0 +1,61 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef nsIXMLContentSink_h___ +#define nsIXMLContentSink_h___ + +#include "nsIContentSink.h" +#include "nsISupports.h" + +class nsIURI; +class nsIChannel; +namespace mozilla::dom { +class Document; +} // namespace mozilla::dom + +#define NS_IXMLCONTENT_SINK_IID \ + { \ + 0x63fedea0, 0x9b0f, 0x4d64, { \ + 0x9b, 0xa5, 0x37, 0xc6, 0x99, 0x73, 0x29, 0x35 \ + } \ + } + +/** + * This interface represents a content sink for generic XML files. + * The goal of this sink is to deal with XML documents that do not + * have pre-built semantics, though it may also be implemented for + * cases in which semantics are hard-wired. + * + * The expectation is that the parser has already performed + * well-formedness and validity checking. + * + * XXX The expectation is that entity expansion will be done by the sink + * itself. This would require, however, that the sink has the ability + * to query the parser for entity replacement text. + * + * XXX This interface does not contain a mechanism for the sink to + * get specific schema/DTD information from the parser. This information + * may be necessary for entity expansion. It is also necessary for + * building the DOM portions that relate to the schema. + * + * XXX This interface does not deal with the presence of an external + * subset. It seems possible that this could be dealt with completely + * at the parser level. + */ + +class nsIXMLContentSink : public nsIContentSink { + public: + NS_DECLARE_STATIC_IID_ACCESSOR(NS_IXMLCONTENT_SINK_IID) + virtual bool IsPrettyPrintXML() const { return false; } + virtual bool IsPrettyPrintHasSpecialRoot() const { return false; } +}; + +NS_DEFINE_STATIC_IID_ACCESSOR(nsIXMLContentSink, NS_IXMLCONTENT_SINK_IID) + +nsresult NS_NewXMLContentSink(nsIXMLContentSink** aInstancePtrResult, + mozilla::dom::Document* aDoc, nsIURI* aURL, + nsISupports* aContainer, nsIChannel* aChannel); + +#endif // nsIXMLContentSink_h___ diff --git a/dom/xml/nsXMLContentSink.cpp b/dom/xml/nsXMLContentSink.cpp new file mode 100644 index 0000000000..4080a10b93 --- /dev/null +++ b/dom/xml/nsXMLContentSink.cpp @@ -0,0 +1,1536 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsCOMPtr.h" +#include "nsXMLContentSink.h" +#include "nsIParser.h" +#include "mozilla/dom/Document.h" +#include "nsIContent.h" +#include "nsIURI.h" +#include "nsNetUtil.h" +#include "nsHTMLParts.h" +#include "nsCRT.h" +#include "mozilla/StyleSheetInlines.h" +#include "mozilla/css/Loader.h" +#include "nsGkAtoms.h" +#include "nsContentUtils.h" +#include "nsDocElementCreatedNotificationRunner.h" +#include "nsIDocShell.h" +#include "nsIScriptContext.h" +#include "nsNameSpaceManager.h" +#include "nsIScriptSecurityManager.h" +#include "nsIContentViewer.h" +#include "prtime.h" +#include "mozilla/Logging.h" +#include "nsRect.h" +#include "nsIScriptElement.h" +#include "nsReadableUtils.h" +#include "nsUnicharUtils.h" +#include "nsIChannel.h" +#include "nsXMLPrettyPrinter.h" +#include "nsNodeInfoManager.h" +#include "nsContentCreatorFunctions.h" +#include "nsIContentPolicy.h" +#include "nsContentPolicyUtils.h" +#include "nsError.h" +#include "nsIScriptGlobalObject.h" +#include "mozAutoDocUpdate.h" +#include "nsMimeTypes.h" +#include "nsHtml5SVGLoadDispatcher.h" +#include "nsTextNode.h" +#include "mozilla/dom/CDATASection.h" +#include "mozilla/dom/Comment.h" +#include "mozilla/dom/DocumentType.h" +#include "mozilla/dom/Element.h" +#include "mozilla/dom/HTMLTemplateElement.h" +#include "mozilla/dom/MutationObservers.h" +#include "mozilla/dom/ProcessingInstruction.h" +#include "mozilla/dom/ScriptLoader.h" +#include "mozilla/dom/txMozillaXSLTProcessor.h" +#include "mozilla/CycleCollectedJSContext.h" +#include "mozilla/LoadInfo.h" +#include "mozilla/UseCounter.h" + +using namespace mozilla; +using namespace mozilla::dom; + +// XXX Open Issues: +// 1) what's not allowed - We need to figure out which HTML tags +// (prefixed with a HTML namespace qualifier) are explicitly not +// allowed (if any). +// 2) factoring code with nsHTMLContentSink - There's some amount of +// common code between this and the HTML content sink. This will +// increase as we support more and more HTML elements. How can code +// from the code be factored? + +nsresult NS_NewXMLContentSink(nsIXMLContentSink** aResult, Document* aDoc, + nsIURI* aURI, nsISupports* aContainer, + nsIChannel* aChannel) { + MOZ_ASSERT(nullptr != aResult, "null ptr"); + if (nullptr == aResult) { + return NS_ERROR_NULL_POINTER; + } + RefPtr it = new nsXMLContentSink(); + + nsresult rv = it->Init(aDoc, aURI, aContainer, aChannel); + NS_ENSURE_SUCCESS(rv, rv); + + it.forget(aResult); + return NS_OK; +} + +nsXMLContentSink::nsXMLContentSink() + : mState(eXMLContentSinkState_InProlog), + mTextLength(0), + mNotifyLevel(0), + mPrettyPrintXML(true), + mPrettyPrintHasSpecialRoot(0), + mPrettyPrintHasFactoredElements(0), + mPrettyPrinting(0), + mPreventScriptExecution(0) { + PodArrayZero(mText); +} + +nsXMLContentSink::~nsXMLContentSink() = default; + +nsresult nsXMLContentSink::Init(Document* aDoc, nsIURI* aURI, + nsISupports* aContainer, nsIChannel* aChannel) { + nsresult rv = nsContentSink::Init(aDoc, aURI, aContainer, aChannel); + NS_ENSURE_SUCCESS(rv, rv); + + aDoc->AddObserver(this); + mIsDocumentObserver = true; + + if (!mDocShell) { + mPrettyPrintXML = false; + } + + mState = eXMLContentSinkState_InProlog; + mDocElement = nullptr; + + return NS_OK; +} + +inline void ImplCycleCollectionTraverse( + nsCycleCollectionTraversalCallback& aCallback, + nsXMLContentSink::StackNode& aField, const char* aName, + uint32_t aFlags = 0) { + ImplCycleCollectionTraverse(aCallback, aField.mContent, aName, aFlags); +} + +inline void ImplCycleCollectionUnlink(nsXMLContentSink::StackNode& aField) { + ImplCycleCollectionUnlink(aField.mContent); +} + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXMLContentSink) + NS_INTERFACE_MAP_ENTRY(nsIContentSink) + NS_INTERFACE_MAP_ENTRY(nsIXMLContentSink) + NS_INTERFACE_MAP_ENTRY(nsIExpatSink) + NS_INTERFACE_MAP_ENTRY(nsITransformObserver) +NS_INTERFACE_MAP_END_INHERITING(nsContentSink) + +NS_IMPL_ADDREF_INHERITED(nsXMLContentSink, nsContentSink) +NS_IMPL_RELEASE_INHERITED(nsXMLContentSink, nsContentSink) + +NS_IMPL_CYCLE_COLLECTION_INHERITED(nsXMLContentSink, nsContentSink, + mCurrentHead, mDocElement, mLastTextNode, + mContentStack, mDocumentChildren) + +// nsIContentSink +NS_IMETHODIMP +nsXMLContentSink::WillParse(void) { return WillParseImpl(); } + +NS_IMETHODIMP +nsXMLContentSink::WillBuildModel(nsDTDMode aDTDMode) { + WillBuildModelImpl(); + + // Notify document that the load is beginning + mDocument->BeginLoad(); + + // Check for correct load-command for maybe prettyprinting + if (mPrettyPrintXML) { + nsAutoCString command; + GetParser()->GetCommand(command); + if (!command.EqualsLiteral("view")) { + mPrettyPrintXML = false; + } + } + + return NS_OK; +} + +bool nsXMLContentSink::CanStillPrettyPrint() { + return mPrettyPrintXML && + (!mPrettyPrintHasFactoredElements || mPrettyPrintHasSpecialRoot); +} + +nsresult nsXMLContentSink::MaybePrettyPrint() { + if (!CanStillPrettyPrint()) { + mPrettyPrintXML = false; + + return NS_OK; + } + + { + // Try to perform a microtask checkpoint; this avoids always breaking + // pretty-printing if webextensions insert new content right after the + // document loads. + nsAutoMicroTask mt; + } + + // stop observing in order to avoid crashing when replacing content + mDocument->RemoveObserver(this); + mIsDocumentObserver = false; + + // Reenable the CSSLoader so that the prettyprinting stylesheets can load + if (mCSSLoader) { + mCSSLoader->SetEnabled(true); + } + + RefPtr printer; + nsresult rv = NS_NewXMLPrettyPrinter(getter_AddRefs(printer)); + NS_ENSURE_SUCCESS(rv, rv); + + bool isPrettyPrinting; + rv = printer->PrettyPrint(mDocument, &isPrettyPrinting); + NS_ENSURE_SUCCESS(rv, rv); + + mPrettyPrinting = isPrettyPrinting; + return NS_OK; +} + +static void CheckXSLTParamPI(ProcessingInstruction* aPi, + nsIDocumentTransformer* aProcessor, + nsINode* aSource) { + nsAutoString target, data; + aPi->GetTarget(target); + + // Check for namespace declarations + if (target.EqualsLiteral("xslt-param-namespace")) { + aPi->GetData(data); + nsAutoString prefix, namespaceAttr; + nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::prefix, prefix); + if (!prefix.IsEmpty() && nsContentUtils::GetPseudoAttributeValue( + data, nsGkAtoms::_namespace, namespaceAttr)) { + aProcessor->AddXSLTParamNamespace(prefix, namespaceAttr); + } + } + + // Check for actual parameters + else if (target.EqualsLiteral("xslt-param")) { + aPi->GetData(data); + nsAutoString name, namespaceAttr, select, value; + nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::name, name); + nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::_namespace, + namespaceAttr); + if (!nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::select, + select)) { + select.SetIsVoid(true); + } + if (!nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::value, + value)) { + value.SetIsVoid(true); + } + if (!name.IsEmpty()) { + aProcessor->AddXSLTParam(name, namespaceAttr, select, value, aSource); + } + } +} + +NS_IMETHODIMP +nsXMLContentSink::DidBuildModel(bool aTerminated) { + if (!mParser) { + // If mParser is null, this parse has already been terminated and must + // not been terminated again. However, Document may still think that + // the parse has not been terminated and call back into here in the case + // where the XML parser has finished but the XSLT transform associated + // with the document has not. + return NS_OK; + } + + FlushTags(); + + DidBuildModelImpl(aTerminated); + + if (mXSLTProcessor) { + // stop observing in order to avoid crashing when replacing content + mDocument->RemoveObserver(this); + mIsDocumentObserver = false; + + ErrorResult rv; + RefPtr source = mDocument->CreateDocumentFragment(); + for (nsIContent* child : mDocumentChildren) { + // XPath data model doesn't have DocumentType nodes. + if (child->NodeType() != nsINode::DOCUMENT_TYPE_NODE) { + source->AppendChild(*child, rv); + if (rv.Failed()) { + return rv.StealNSResult(); + } + } + } + + // Check for xslt-param and xslt-param-namespace PIs + for (nsIContent* child : mDocumentChildren) { + if (auto pi = ProcessingInstruction::FromNode(child)) { + CheckXSLTParamPI(pi, mXSLTProcessor, source); + } else if (child->IsElement()) { + // Only honor PIs in the prolog + break; + } + } + + mXSLTProcessor->SetSourceContentModel(source); + // Since the processor now holds a reference to us we drop our reference + // to it to avoid owning cycles + mXSLTProcessor = nullptr; + } else { + // Kick off layout for non-XSLT transformed documents. + + // Check if we want to prettyprint + MaybePrettyPrint(); + + bool startLayout = true; + + if (mPrettyPrinting) { + NS_ASSERTION(!mPendingSheetCount, "Shouldn't have pending sheets here!"); + + // We're pretty-printing now. See whether we should wait up on + // stylesheet loads + if (mDocument->CSSLoader()->HasPendingLoads()) { + mDocument->CSSLoader()->AddObserver(this); + // wait for those sheets to load + startLayout = false; + } + } + + if (startLayout) { + StartLayout(false); + + ScrollToRef(); + } + + mDocument->RemoveObserver(this); + mIsDocumentObserver = false; + + mDocument->EndLoad(); + + DropParserAndPerfHint(); + } + + return NS_OK; +} + +nsresult nsXMLContentSink::OnDocumentCreated(Document* aSourceDocument, + Document* aResultDocument) { + aResultDocument->SetDocWriteDisabled(true); + + nsCOMPtr contentViewer; + mDocShell->GetContentViewer(getter_AddRefs(contentViewer)); + // Make sure that we haven't loaded a new document into the contentviewer + // after starting the XSLT transform. + if (contentViewer && contentViewer->GetDocument() == aSourceDocument) { + return contentViewer->SetDocumentInternal(aResultDocument, true); + } + return NS_OK; +} + +nsresult nsXMLContentSink::OnTransformDone(Document* aSourceDocument, + nsresult aResult, + Document* aResultDocument) { + MOZ_ASSERT(aResultDocument, + "Don't notify about transform end without a document."); + + mDocumentChildren.Clear(); + + nsCOMPtr contentViewer; + mDocShell->GetContentViewer(getter_AddRefs(contentViewer)); + + RefPtr originalDocument = mDocument; + bool blockingOnload = mIsBlockingOnload; + + // Make sure that we haven't loaded a new document into the contentviewer + // after starting the XSLT transform. + if (contentViewer && (contentViewer->GetDocument() == aSourceDocument || + contentViewer->GetDocument() == aResultDocument)) { + if (NS_FAILED(aResult)) { + // Transform failed. + aResultDocument->SetMayStartLayout(false); + // We have an error document. + contentViewer->SetDocument(aResultDocument); + } + + if (!mRunsToCompletion) { + // This BlockOnload call corresponds to the UnblockOnload call in + // nsContentSink::DropParserAndPerfHint. + aResultDocument->BlockOnload(); + mIsBlockingOnload = true; + } + // Transform succeeded, or it failed and we have an error document to + // display. + mDocument = aResultDocument; + aResultDocument->SetDocWriteDisabled(false); + + // Notify document observers that all the content has been stuck + // into the document. + // XXX do we need to notify for things like PIs? Or just the + // documentElement? + nsIContent* rootElement = mDocument->GetRootElement(); + if (rootElement) { + NS_ASSERTION(mDocument->ComputeIndexOf(rootElement).isSome(), + "rootElement not in doc?"); + mDocument->BeginUpdate(); + MutationObservers::NotifyContentInserted(mDocument, rootElement); + mDocument->EndUpdate(); + } + + // Start the layout process + StartLayout(false); + + ScrollToRef(); + } + + originalDocument->EndLoad(); + if (blockingOnload) { + // This UnblockOnload call corresponds to the BlockOnload call in + // nsContentSink::WillBuildModelImpl. + originalDocument->UnblockOnload(true); + } + + DropParserAndPerfHint(); + + // By this point, the result document has been set in the content viewer. But + // the content viewer does not call Destroy on the original document, so we + // won't end up reporting document use counters. It's possible we should be + // detaching the document from the window, but for now, we call + // ReportDocumentUseCounters on the original document here, to avoid + // assertions in ~Document about not having reported them. + originalDocument->ReportDocumentUseCounters(); + + return NS_OK; +} + +NS_IMETHODIMP +nsXMLContentSink::StyleSheetLoaded(StyleSheet* aSheet, bool aWasDeferred, + nsresult aStatus) { + if (!mPrettyPrinting) { + return nsContentSink::StyleSheetLoaded(aSheet, aWasDeferred, aStatus); + } + + if (!mDocument->CSSLoader()->HasPendingLoads()) { + mDocument->CSSLoader()->RemoveObserver(this); + StartLayout(false); + ScrollToRef(); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsXMLContentSink::WillInterrupt(void) { return WillInterruptImpl(); } + +void nsXMLContentSink::WillResume() { WillResumeImpl(); } + +NS_IMETHODIMP +nsXMLContentSink::SetParser(nsParserBase* aParser) { + MOZ_ASSERT(aParser, "Should have a parser here!"); + mParser = aParser; + return NS_OK; +} + +static bool FindIsAttrValue(const char16_t** aAtts, const char16_t** aResult) { + RefPtr prefix, localName; + for (; *aAtts; aAtts += 2) { + int32_t nameSpaceID; + nsContentUtils::SplitExpatName(aAtts[0], getter_AddRefs(prefix), + getter_AddRefs(localName), &nameSpaceID); + if (nameSpaceID == kNameSpaceID_None && localName == nsGkAtoms::is) { + *aResult = aAtts[1]; + + return true; + } + } + + return false; +} + +nsresult nsXMLContentSink::CreateElement( + const char16_t** aAtts, uint32_t aAttsCount, + mozilla::dom::NodeInfo* aNodeInfo, uint32_t aLineNumber, + uint32_t aColumnNumber, nsIContent** aResult, bool* aAppendContent, + FromParser aFromParser) { + NS_ASSERTION(aNodeInfo, "can't create element without nodeinfo"); + + *aResult = nullptr; + *aAppendContent = true; + nsresult rv = NS_OK; + + RefPtr ni = aNodeInfo; + RefPtr content; + + const char16_t* is = nullptr; + if ((aNodeInfo->NamespaceEquals(kNameSpaceID_XHTML) || + aNodeInfo->NamespaceEquals(kNameSpaceID_XUL)) && + FindIsAttrValue(aAtts, &is)) { + const nsDependentString isStr(is); + rv = NS_NewElement(getter_AddRefs(content), ni.forget(), aFromParser, + &isStr); + } else { + rv = NS_NewElement(getter_AddRefs(content), ni.forget(), aFromParser); + } + + NS_ENSURE_SUCCESS(rv, rv); + + if (aNodeInfo->Equals(nsGkAtoms::script, kNameSpaceID_XHTML) || + aNodeInfo->Equals(nsGkAtoms::script, kNameSpaceID_SVG)) { + nsCOMPtr sele = do_QueryInterface(content); + if (sele) { + sele->SetScriptLineNumber(aLineNumber); + sele->SetScriptColumnNumber(aColumnNumber); + sele->SetCreatorParser(GetParser()); + } else { + MOZ_ASSERT(nsNameSpaceManager::GetInstance()->mSVGDisabled, + "Node didn't QI to script, but SVG wasn't disabled."); + } + } + + // XHTML needs some special attention + if (aNodeInfo->NamespaceEquals(kNameSpaceID_XHTML)) { + mPrettyPrintHasFactoredElements = true; + } else { + // If we care, find out if we just used a special factory. + if (!mPrettyPrintHasFactoredElements && !mPrettyPrintHasSpecialRoot && + mPrettyPrintXML) { + mPrettyPrintHasFactoredElements = + nsNameSpaceManager::GetInstance()->HasElementCreator( + aNodeInfo->NamespaceID()); + } + + if (!aNodeInfo->NamespaceEquals(kNameSpaceID_SVG)) { + content.forget(aResult); + + return NS_OK; + } + } + + if (aNodeInfo->Equals(nsGkAtoms::link, kNameSpaceID_XHTML) || + aNodeInfo->Equals(nsGkAtoms::style, kNameSpaceID_XHTML) || + aNodeInfo->Equals(nsGkAtoms::style, kNameSpaceID_SVG)) { + if (auto* linkStyle = LinkStyle::FromNode(*content)) { + if (aFromParser) { + linkStyle->SetEnableUpdates(false); + } + if (!aNodeInfo->Equals(nsGkAtoms::link, kNameSpaceID_XHTML)) { + linkStyle->SetLineNumber(aFromParser ? aLineNumber : 0); + linkStyle->SetColumnNumber(aFromParser ? aColumnNumber : 0); + } + } + } + + content.forget(aResult); + + return NS_OK; +} + +nsresult nsXMLContentSink::CloseElement(nsIContent* aContent) { + NS_ASSERTION(aContent, "missing element to close"); + + mozilla::dom::NodeInfo* nodeInfo = aContent->NodeInfo(); + + // Some HTML nodes need DoneAddingChildren() called to initialize + // properly (eg form state restoration). + if (nsIContent::RequiresDoneAddingChildren(nodeInfo->NamespaceID(), + nodeInfo->NameAtom())) { + aContent->DoneAddingChildren(HaveNotifiedForCurrentContent()); + } + + if (IsMonolithicContainer(nodeInfo)) { + mInMonolithicContainer--; + } + + if (!nodeInfo->NamespaceEquals(kNameSpaceID_XHTML) && + !nodeInfo->NamespaceEquals(kNameSpaceID_SVG)) { + return NS_OK; + } + + if (nodeInfo->Equals(nsGkAtoms::script, kNameSpaceID_XHTML) || + nodeInfo->Equals(nsGkAtoms::script, kNameSpaceID_SVG)) { + nsCOMPtr sele = do_QueryInterface(aContent); + if (!sele) { + MOZ_ASSERT(nsNameSpaceManager::GetInstance()->mSVGDisabled, + "Node didn't QI to script, but SVG wasn't disabled."); + return NS_OK; + } + + if (mPreventScriptExecution) { + sele->PreventExecution(); + return NS_OK; + } + + // Always check the clock in nsContentSink right after a script + StopDeflecting(); + + // Now tell the script that it's ready to go. This may execute the script + // or return true, or neither if the script doesn't need executing. + bool block = sele->AttemptToExecute(); + if (mParser) { + if (block) { + GetParser()->BlockParser(); + } + + // If the parser got blocked, make sure to return the appropriate rv. + // I'm not sure if this is actually needed or not. + if (!mParser->IsParserEnabled()) { + block = true; + } + } + + return block ? NS_ERROR_HTMLPARSER_BLOCK : NS_OK; + } + + nsresult rv = NS_OK; + if (nodeInfo->Equals(nsGkAtoms::link, kNameSpaceID_XHTML) || + nodeInfo->Equals(nsGkAtoms::style, kNameSpaceID_XHTML) || + nodeInfo->Equals(nsGkAtoms::style, kNameSpaceID_SVG)) { + if (auto* linkStyle = LinkStyle::FromNode(*aContent)) { + linkStyle->SetEnableUpdates(true); + auto updateOrError = + linkStyle->UpdateStyleSheet(mRunsToCompletion ? nullptr : this); + if (updateOrError.isErr()) { + rv = updateOrError.unwrapErr(); + } else if (updateOrError.unwrap().ShouldBlock() && !mRunsToCompletion) { + ++mPendingSheetCount; + mScriptLoader->AddParserBlockingScriptExecutionBlocker(); + } + } + } + + return rv; +} + +nsresult nsXMLContentSink::AddContentAsLeaf(nsIContent* aContent) { + nsresult result = NS_OK; + + if (mState == eXMLContentSinkState_InProlog) { + NS_ASSERTION(mDocument, "Fragments have no prolog"); + mDocumentChildren.AppendElement(aContent); + } else if (mState == eXMLContentSinkState_InEpilog) { + NS_ASSERTION(mDocument, "Fragments have no epilog"); + if (mXSLTProcessor) { + mDocumentChildren.AppendElement(aContent); + } else { + mDocument->AppendChildTo(aContent, false, IgnoreErrors()); + } + } else { + nsCOMPtr parent = GetCurrentContent(); + + if (parent) { + ErrorResult rv; + parent->AppendChildTo(aContent, false, rv); + result = rv.StealNSResult(); + } + } + return result; +} + +// Create an XML parser and an XSL content sink and start parsing +// the XSL stylesheet located at the given URI. +nsresult nsXMLContentSink::LoadXSLStyleSheet(nsIURI* aUrl) { + nsCOMPtr processor = new txMozillaXSLTProcessor(); + mDocument->SetUseCounter(eUseCounter_custom_XSLStylesheet); + + processor->SetTransformObserver(this); + + if (NS_SUCCEEDED(processor->LoadStyleSheet(aUrl, mDocument))) { + mXSLTProcessor.swap(processor); + } + + // Intentionally ignore errors here, we should continue loading the + // XML document whether we're able to load the XSLT stylesheet or + // not. + + return NS_OK; +} + +nsresult nsXMLContentSink::ProcessStyleLinkFromHeader( + const nsAString& aHref, bool aAlternate, const nsAString& aTitle, + const nsAString& aIntegrity, const nsAString& aType, + const nsAString& aMedia, const nsAString& aReferrerPolicy) { + mPrettyPrintXML = false; + + nsAutoCString cmd; + if (mParser) GetParser()->GetCommand(cmd); + if (cmd.EqualsASCII(kLoadAsData)) + return NS_OK; // Do not load stylesheets when loading as data + + bool wasXSLT; + nsresult rv = MaybeProcessXSLTLink(nullptr, aHref, aAlternate, aType, aType, + aMedia, aReferrerPolicy, &wasXSLT); + NS_ENSURE_SUCCESS(rv, rv); + if (wasXSLT) { + // We're done here. + return NS_OK; + } + + // Otherwise fall through to nsContentSink to handle CSS Link headers. + return nsContentSink::ProcessStyleLinkFromHeader( + aHref, aAlternate, aTitle, aIntegrity, aType, aMedia, aReferrerPolicy); +} + +nsresult nsXMLContentSink::MaybeProcessXSLTLink( + ProcessingInstruction* aProcessingInstruction, const nsAString& aHref, + bool aAlternate, const nsAString& aTitle, const nsAString& aType, + const nsAString& aMedia, const nsAString& aReferrerPolicy, bool* aWasXSLT) { + bool wasXSLT = aType.LowerCaseEqualsLiteral(TEXT_XSL) || + aType.LowerCaseEqualsLiteral(APPLICATION_XSLT_XML) || + aType.LowerCaseEqualsLiteral(TEXT_XML) || + aType.LowerCaseEqualsLiteral(APPLICATION_XML); + + if (aWasXSLT) { + *aWasXSLT = wasXSLT; + } + + if (!wasXSLT) { + return NS_OK; + } + + if (aAlternate) { + // don't load alternate XSLT + return NS_OK; + } + // LoadXSLStyleSheet needs a mDocShell. + if (!mDocShell) { + return NS_OK; + } + + nsCOMPtr url; + nsresult rv = NS_NewURI(getter_AddRefs(url), aHref, nullptr, + mDocument->GetDocBaseURI()); + NS_ENSURE_SUCCESS(rv, rv); + + // Do security check + nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager(); + rv = secMan->CheckLoadURIWithPrincipal(mDocument->NodePrincipal(), url, + nsIScriptSecurityManager::ALLOW_CHROME, + mDocument->InnerWindowID()); + NS_ENSURE_SUCCESS(rv, NS_OK); + + nsCOMPtr secCheckLoadInfo = + new net::LoadInfo(mDocument->NodePrincipal(), // loading principal + mDocument->NodePrincipal(), // triggering principal + aProcessingInstruction, + nsILoadInfo::SEC_ONLY_FOR_EXPLICIT_CONTENTSEC_CHECK, + nsIContentPolicy::TYPE_XSLT); + + // Do content policy check + int16_t decision = nsIContentPolicy::ACCEPT; + rv = NS_CheckContentLoadPolicy(url, secCheckLoadInfo, + NS_ConvertUTF16toUTF8(aType), &decision, + nsContentUtils::GetContentPolicy()); + + NS_ENSURE_SUCCESS(rv, rv); + + if (NS_CP_REJECTED(decision)) { + return NS_OK; + } + + return LoadXSLStyleSheet(url); +} + +void nsXMLContentSink::SetDocumentCharset(NotNull aEncoding) { + if (mDocument) { + mDocument->SetDocumentCharacterSet(aEncoding); + } +} + +nsISupports* nsXMLContentSink::GetTarget() { return ToSupports(mDocument); } + +bool nsXMLContentSink::IsScriptExecuting() { return IsScriptExecutingImpl(); } + +nsresult nsXMLContentSink::FlushText(bool aReleaseTextNode) { + nsresult rv = NS_OK; + + if (mTextLength != 0) { + if (mLastTextNode) { + bool notify = HaveNotifiedForCurrentContent(); + // We could probably always increase mInNotification here since + // if AppendText doesn't notify it shouldn't trigger evil code. + // But just in case it does, we don't want to mask any notifications. + if (notify) { + ++mInNotification; + } + rv = mLastTextNode->AppendText(mText, mTextLength, notify); + if (notify) { + --mInNotification; + } + + mTextLength = 0; + } else { + RefPtr textContent = + new (mNodeInfoManager) nsTextNode(mNodeInfoManager); + + mLastTextNode = textContent; + + // Set the text in the text node + textContent->SetText(mText, mTextLength, false); + mTextLength = 0; + + // Add text to its parent + rv = AddContentAsLeaf(textContent); + } + } + + if (aReleaseTextNode) { + mLastTextNode = nullptr; + } + + return rv; +} + +nsIContent* nsXMLContentSink::GetCurrentContent() { + if (mContentStack.Length() == 0) { + return nullptr; + } + return GetCurrentStackNode()->mContent; +} + +nsXMLContentSink::StackNode* nsXMLContentSink::GetCurrentStackNode() { + int32_t count = mContentStack.Length(); + return count != 0 ? &mContentStack[count - 1] : nullptr; +} + +nsresult nsXMLContentSink::PushContent(nsIContent* aContent) { + MOZ_ASSERT(aContent, "Null content being pushed!"); + StackNode* sn = mContentStack.AppendElement(); + NS_ENSURE_TRUE(sn, NS_ERROR_OUT_OF_MEMORY); + + nsIContent* contentToPush = aContent; + + // When an XML parser would append a node to a template element, it + // must instead append it to the template element's template contents. + if (contentToPush->IsHTMLElement(nsGkAtoms::_template)) { + HTMLTemplateElement* templateElement = + static_cast(contentToPush); + contentToPush = templateElement->Content(); + } + + sn->mContent = contentToPush; + sn->mNumFlushed = 0; + return NS_OK; +} + +void nsXMLContentSink::PopContent() { + if (mContentStack.IsEmpty()) { + NS_WARNING("Popping empty stack"); + return; + } + + mContentStack.RemoveLastElement(); +} + +bool nsXMLContentSink::HaveNotifiedForCurrentContent() const { + uint32_t stackLength = mContentStack.Length(); + if (stackLength) { + const StackNode& stackNode = mContentStack[stackLength - 1]; + nsIContent* parent = stackNode.mContent; + return stackNode.mNumFlushed == parent->GetChildCount(); + } + return true; +} + +void nsXMLContentSink::MaybeStartLayout(bool aIgnorePendingSheets) { + // XXXbz if aIgnorePendingSheets is true, what should we do when + // mXSLTProcessor or CanStillPrettyPrint()? + if (mLayoutStarted || mXSLTProcessor || CanStillPrettyPrint()) { + return; + } + StartLayout(aIgnorePendingSheets); +} + +//////////////////////////////////////////////////////////////////////// + +bool nsXMLContentSink::SetDocElement(int32_t aNameSpaceID, nsAtom* aTagName, + nsIContent* aContent) { + if (mDocElement) return false; + + mDocElement = aContent; + + if (mXSLTProcessor) { + mDocumentChildren.AppendElement(aContent); + return true; + } + + if (!mDocumentChildren.IsEmpty()) { + for (nsIContent* child : mDocumentChildren) { + mDocument->AppendChildTo(child, false, IgnoreErrors()); + } + mDocumentChildren.Clear(); + } + + // check for root elements that needs special handling for + // prettyprinting + if (aNameSpaceID == kNameSpaceID_XSLT && + (aTagName == nsGkAtoms::stylesheet || aTagName == nsGkAtoms::transform)) { + mPrettyPrintHasSpecialRoot = true; + if (mPrettyPrintXML) { + // In this case, disable script execution, stylesheet + // loading, and auto XLinks since we plan to prettyprint. + mDocument->ScriptLoader()->SetEnabled(false); + if (mCSSLoader) { + mCSSLoader->SetEnabled(false); + } + } + } + + IgnoredErrorResult rv; + mDocument->AppendChildTo(mDocElement, NotifyForDocElement(), rv); + if (rv.Failed()) { + // If we return false here, the caller will bail out because it won't + // find a parent content node to append to, which is fine. + return false; + } + + return true; +} + +NS_IMETHODIMP +nsXMLContentSink::HandleStartElement(const char16_t* aName, + const char16_t** aAtts, + uint32_t aAttsCount, uint32_t aLineNumber, + uint32_t aColumnNumber) { + return HandleStartElement(aName, aAtts, aAttsCount, aLineNumber, + aColumnNumber, true); +} + +nsresult nsXMLContentSink::HandleStartElement( + const char16_t* aName, const char16_t** aAtts, uint32_t aAttsCount, + uint32_t aLineNumber, uint32_t aColumnNumber, bool aInterruptable) { + MOZ_ASSERT(aAttsCount % 2 == 0, "incorrect aAttsCount"); + // Adjust aAttsCount so it's the actual number of attributes + aAttsCount /= 2; + + nsresult result = NS_OK; + bool appendContent = true; + nsCOMPtr content; + + // XXX Hopefully the parser will flag this before we get + // here. If we're in the epilog, there should be no + // new elements + MOZ_ASSERT(eXMLContentSinkState_InEpilog != mState); + + FlushText(); + DidAddContent(); + + mState = eXMLContentSinkState_InDocumentElement; + + int32_t nameSpaceID; + RefPtr prefix, localName; + nsContentUtils::SplitExpatName(aName, getter_AddRefs(prefix), + getter_AddRefs(localName), &nameSpaceID); + + if (!OnOpenContainer(aAtts, aAttsCount, nameSpaceID, localName, + aLineNumber)) { + return NS_OK; + } + + RefPtr nodeInfo; + nodeInfo = mNodeInfoManager->GetNodeInfo(localName, prefix, nameSpaceID, + nsINode::ELEMENT_NODE); + + result = CreateElement(aAtts, aAttsCount, nodeInfo, aLineNumber, + aColumnNumber, getter_AddRefs(content), &appendContent, + FROM_PARSER_NETWORK); + NS_ENSURE_SUCCESS(result, result); + + // Have to do this before we push the new content on the stack... and have to + // do that before we set attributes, call BindToTree, etc. Ideally we'd push + // on the stack inside CreateElement (which is effectively what the HTML sink + // does), but that's hard with all the subclass overrides going on. + nsCOMPtr parent = GetCurrentContent(); + + result = PushContent(content); + NS_ENSURE_SUCCESS(result, result); + + // Set the attributes on the new content element + result = AddAttributes(aAtts, content->AsElement()); + + if (NS_OK == result) { + // Store the element + if (!SetDocElement(nameSpaceID, localName, content) && appendContent) { + NS_ENSURE_TRUE(parent, NS_ERROR_UNEXPECTED); + + parent->AppendChildTo(content, false, IgnoreErrors()); + } + } + + // Some HTML nodes need DoneCreatingElement() called to initialize + // properly (eg form state restoration). + if (nsIContent::RequiresDoneCreatingElement(nodeInfo->NamespaceID(), + nodeInfo->NameAtom())) { + content->DoneCreatingElement(); + } + + if (nodeInfo->NamespaceID() == kNameSpaceID_XHTML && + nodeInfo->NameAtom() == nsGkAtoms::head && !mCurrentHead) { + mCurrentHead = content; + } + + if (IsMonolithicContainer(nodeInfo)) { + mInMonolithicContainer++; + } + + if (!mXSLTProcessor) { + if (content == mDocElement) { + nsContentUtils::AddScriptRunner( + new nsDocElementCreatedNotificationRunner(mDocument)); + + if (aInterruptable && NS_SUCCEEDED(result) && mParser && + !mParser->IsParserEnabled()) { + return NS_ERROR_HTMLPARSER_BLOCK; + } + } else if (!mCurrentHead) { + // This isn't the root and we're not inside an XHTML . + // Might need to start layout + MaybeStartLayout(false); + } + } + + return aInterruptable && NS_SUCCEEDED(result) ? DidProcessATokenImpl() + : result; +} + +NS_IMETHODIMP +nsXMLContentSink::HandleEndElement(const char16_t* aName) { + return HandleEndElement(aName, true); +} + +nsresult nsXMLContentSink::HandleEndElement(const char16_t* aName, + bool aInterruptable) { + nsresult result = NS_OK; + + // XXX Hopefully the parser will flag this before we get + // here. If we're in the prolog or epilog, there should be + // no close tags for elements. + MOZ_ASSERT(eXMLContentSinkState_InDocumentElement == mState); + + FlushText(); + + StackNode* sn = GetCurrentStackNode(); + if (!sn) { + return NS_ERROR_UNEXPECTED; + } + + nsCOMPtr content; + sn->mContent.swap(content); + uint32_t numFlushed = sn->mNumFlushed; + + PopContent(); + NS_ASSERTION(content, "failed to pop content"); +#ifdef DEBUG + // Check that we're closing the right thing + RefPtr debugNameSpacePrefix, debugTagAtom; + int32_t debugNameSpaceID; + nsContentUtils::SplitExpatName(aName, getter_AddRefs(debugNameSpacePrefix), + getter_AddRefs(debugTagAtom), + &debugNameSpaceID); + // Check if we are closing a template element because template + // elements do not get pushed on the stack, the template + // element content is pushed instead. + bool isTemplateElement = debugTagAtom == nsGkAtoms::_template && + debugNameSpaceID == kNameSpaceID_XHTML; + NS_ASSERTION( + content->NodeInfo()->Equals(debugTagAtom, debugNameSpaceID) || + (debugNameSpaceID == kNameSpaceID_MathML && + content->NodeInfo()->NamespaceID() == kNameSpaceID_disabled_MathML && + content->NodeInfo()->Equals(debugTagAtom)) || + (debugNameSpaceID == kNameSpaceID_SVG && + content->NodeInfo()->NamespaceID() == kNameSpaceID_disabled_SVG && + content->NodeInfo()->Equals(debugTagAtom)) || + isTemplateElement, + "Wrong element being closed"); +#endif + + // Make sure to notify on our kids before we call out to any other code that + // might reenter us and call FlushTags, in a state in which we've already + // popped "content" from the stack but haven't notified on its kids yet. + int32_t stackLen = mContentStack.Length(); + if (mNotifyLevel >= stackLen) { + if (numFlushed < content->GetChildCount()) { + NotifyAppend(content, numFlushed); + } + mNotifyLevel = stackLen - 1; + } + + result = CloseElement(content); + + if (mCurrentHead == content) { + mCurrentHead = nullptr; + } + + if (mDocElement == content) { + // XXXbz for roots that don't want to be appended on open, we + // probably need to deal here.... (and stop appending them on open). + mState = eXMLContentSinkState_InEpilog; + + mDocument->OnParsingCompleted(); + + // We might have had no occasion to start layout yet. Do so now. + MaybeStartLayout(false); + } + + DidAddContent(); + + if (content->IsSVGElement(nsGkAtoms::svg)) { + FlushTags(); + nsCOMPtr event = new nsHtml5SVGLoadDispatcher(content); + if (NS_FAILED(content->OwnerDoc()->Dispatch(TaskCategory::Other, + event.forget()))) { + NS_WARNING("failed to dispatch svg load dispatcher"); + } + } + + return aInterruptable && NS_SUCCEEDED(result) ? DidProcessATokenImpl() + : result; +} + +NS_IMETHODIMP +nsXMLContentSink::HandleComment(const char16_t* aName) { + FlushText(); + + RefPtr comment = new (mNodeInfoManager) Comment(mNodeInfoManager); + comment->SetText(nsDependentString(aName), false); + nsresult rv = AddContentAsLeaf(comment); + DidAddContent(); + + return NS_SUCCEEDED(rv) ? DidProcessATokenImpl() : rv; +} + +NS_IMETHODIMP +nsXMLContentSink::HandleCDataSection(const char16_t* aData, uint32_t aLength) { + // XSLT doesn't differentiate between text and cdata and wants adjacent + // textnodes merged, so add as text. + if (mXSLTProcessor) { + return AddText(aData, aLength); + } + + FlushText(); + + RefPtr cdata = + new (mNodeInfoManager) CDATASection(mNodeInfoManager); + cdata->SetText(aData, aLength, false); + nsresult rv = AddContentAsLeaf(cdata); + DidAddContent(); + + return NS_SUCCEEDED(rv) ? DidProcessATokenImpl() : rv; +} + +NS_IMETHODIMP +nsXMLContentSink::HandleDoctypeDecl(const nsAString& aSubset, + const nsAString& aName, + const nsAString& aSystemId, + const nsAString& aPublicId, + nsISupports* aCatalogData) { + FlushText(); + + NS_ASSERTION(mDocument, "Shouldn't get here from a document fragment"); + + RefPtr name = NS_Atomize(aName); + NS_ENSURE_TRUE(name, NS_ERROR_OUT_OF_MEMORY); + + // Create a new doctype node + RefPtr docType = NS_NewDOMDocumentType( + mNodeInfoManager, name, aPublicId, aSystemId, aSubset); + + MOZ_ASSERT(!aCatalogData, + "Need to add back support for catalog style " + "sheets"); + + mDocumentChildren.AppendElement(docType); + DidAddContent(); + return DidProcessATokenImpl(); +} + +NS_IMETHODIMP +nsXMLContentSink::HandleCharacterData(const char16_t* aData, uint32_t aLength) { + return HandleCharacterData(aData, aLength, true); +} + +nsresult nsXMLContentSink::HandleCharacterData(const char16_t* aData, + uint32_t aLength, + bool aInterruptable) { + nsresult rv = NS_OK; + if (aData && mState != eXMLContentSinkState_InProlog && + mState != eXMLContentSinkState_InEpilog) { + rv = AddText(aData, aLength); + } + return aInterruptable && NS_SUCCEEDED(rv) ? DidProcessATokenImpl() : rv; +} + +NS_IMETHODIMP +nsXMLContentSink::HandleProcessingInstruction(const char16_t* aTarget, + const char16_t* aData) { + FlushText(); + + const nsDependentString target(aTarget); + const nsDependentString data(aData); + + RefPtr node = + NS_NewXMLProcessingInstruction(mNodeInfoManager, target, data); + + auto* linkStyle = LinkStyle::FromNode(*node); + if (linkStyle) { + linkStyle->SetEnableUpdates(false); + mPrettyPrintXML = false; + } + + nsresult rv = AddContentAsLeaf(node); + NS_ENSURE_SUCCESS(rv, rv); + DidAddContent(); + + if (linkStyle) { + // This is an xml-stylesheet processing instruction... but it might not be + // a CSS one if the type is set to something else. + linkStyle->SetEnableUpdates(true); + auto updateOrError = + linkStyle->UpdateStyleSheet(mRunsToCompletion ? nullptr : this); + if (updateOrError.isErr()) { + return updateOrError.unwrapErr(); + } + + auto update = updateOrError.unwrap(); + if (update.WillNotify()) { + // Successfully started a stylesheet load + if (update.ShouldBlock() && !mRunsToCompletion) { + ++mPendingSheetCount; + mScriptLoader->AddParserBlockingScriptExecutionBlocker(); + } + return NS_OK; + } + } + + // Check whether this is a CSS stylesheet PI. Make sure the type + // handling here matches + // XMLStylesheetProcessingInstruction::GetStyleSheetInfo. + nsAutoString type; + nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::type, type); + nsAutoString mimeType, notUsed; + nsContentUtils::SplitMimeType(type, mimeType, notUsed); + + if (mState != eXMLContentSinkState_InProlog || + !target.EqualsLiteral("xml-stylesheet") || mimeType.IsEmpty() || + mimeType.LowerCaseEqualsLiteral("text/css")) { + // Either not a useful stylesheet PI, or a CSS stylesheet PI that + // got handled above by the "ssle" bits. We're done here. + return DidProcessATokenImpl(); + } + + // If it's not a CSS stylesheet PI... + nsAutoString href, title, media; + bool isAlternate = false; + + // If there was no href, we can't do anything with this PI + if (!ParsePIData(data, href, title, media, isAlternate)) { + return DidProcessATokenImpl(); + } + + // processing instructions don't have a referrerpolicy + // pseudo-attribute, so we pass in an empty string + rv = + MaybeProcessXSLTLink(node, href, isAlternate, title, type, media, u""_ns); + return NS_SUCCEEDED(rv) ? DidProcessATokenImpl() : rv; +} + +/* static */ +bool nsXMLContentSink::ParsePIData(const nsString& aData, nsString& aHref, + nsString& aTitle, nsString& aMedia, + bool& aIsAlternate) { + // If there was no href, we can't do anything with this PI + if (!nsContentUtils::GetPseudoAttributeValue(aData, nsGkAtoms::href, aHref)) { + return false; + } + + nsContentUtils::GetPseudoAttributeValue(aData, nsGkAtoms::title, aTitle); + + nsContentUtils::GetPseudoAttributeValue(aData, nsGkAtoms::media, aMedia); + + nsAutoString alternate; + nsContentUtils::GetPseudoAttributeValue(aData, nsGkAtoms::alternate, + alternate); + + aIsAlternate = alternate.EqualsLiteral("yes"); + + return true; +} + +NS_IMETHODIMP +nsXMLContentSink::HandleXMLDeclaration(const char16_t* aVersion, + const char16_t* aEncoding, + int32_t aStandalone) { + mDocument->SetXMLDeclaration(aVersion, aEncoding, aStandalone); + + return DidProcessATokenImpl(); +} + +NS_IMETHODIMP +nsXMLContentSink::ReportError(const char16_t* aErrorText, + const char16_t* aSourceText, + nsIScriptError* aError, bool* _retval) { + MOZ_ASSERT(aError && aSourceText && aErrorText, "Check arguments!!!"); + nsresult rv = NS_OK; + + // The expat driver should report the error. We're just cleaning up the mess. + *_retval = true; + + mPrettyPrintXML = false; + + mState = eXMLContentSinkState_InProlog; + + // XXX need to stop scripts here -- hsivonen + + // stop observing in order to avoid crashing when removing content + mDocument->RemoveObserver(this); + mIsDocumentObserver = false; + + // Clear the current content + mDocumentChildren.Clear(); + while (mDocument->GetLastChild()) { + mDocument->GetLastChild()->Remove(); + } + mDocElement = nullptr; + + // Clear any buffered-up text we have. It's enough to set the length to 0. + // The buffer itself is allocated when we're created and deleted in our + // destructor, so don't mess with it. + mTextLength = 0; + + if (mXSLTProcessor) { + // Get rid of the XSLT processor. + mXSLTProcessor->CancelLoads(); + mXSLTProcessor = nullptr; + } + + // release the nodes on stack + mContentStack.Clear(); + mNotifyLevel = 0; + + // return leaving the document empty if we're asked to not add a + // root node + if (mDocument->SuppressParserErrorElement()) { + return NS_OK; + } + + // prepare to set as the document root + rv = HandleProcessingInstruction( + u"xml-stylesheet", + u"href=\"chrome://global/locale/intl.css\" type=\"text/css\""); + NS_ENSURE_SUCCESS(rv, rv); + + const char16_t* noAtts[] = {0, 0}; + + constexpr auto errorNs = + u"http://www.mozilla.org/newlayout/xml/parsererror.xml"_ns; + + nsAutoString parsererror(errorNs); + parsererror.Append((char16_t)0xFFFF); + parsererror.AppendLiteral("parsererror"); + + rv = HandleStartElement(parsererror.get(), noAtts, 0, (uint32_t)-1, false); + NS_ENSURE_SUCCESS(rv, rv); + + rv = HandleCharacterData(aErrorText, NS_strlen(aErrorText), false); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoString sourcetext(errorNs); + sourcetext.Append((char16_t)0xFFFF); + sourcetext.AppendLiteral("sourcetext"); + + rv = HandleStartElement(sourcetext.get(), noAtts, 0, (uint32_t)-1, false); + NS_ENSURE_SUCCESS(rv, rv); + + rv = HandleCharacterData(aSourceText, NS_strlen(aSourceText), false); + NS_ENSURE_SUCCESS(rv, rv); + + rv = HandleEndElement(sourcetext.get(), false); + NS_ENSURE_SUCCESS(rv, rv); + + rv = HandleEndElement(parsererror.get(), false); + NS_ENSURE_SUCCESS(rv, rv); + + FlushTags(); + + return NS_OK; +} + +nsresult nsXMLContentSink::AddAttributes(const char16_t** aAtts, + Element* aContent) { + // Add tag attributes to the content attributes + RefPtr prefix, localName; + while (*aAtts) { + int32_t nameSpaceID; + nsContentUtils::SplitExpatName(aAtts[0], getter_AddRefs(prefix), + getter_AddRefs(localName), &nameSpaceID); + + // Add attribute to content + aContent->SetAttr(nameSpaceID, localName, prefix, + nsDependentString(aAtts[1]), false); + aAtts += 2; + } + + return NS_OK; +} + +#define NS_ACCUMULATION_BUFFER_SIZE 4096 + +nsresult nsXMLContentSink::AddText(const char16_t* aText, int32_t aLength) { + // Copy data from string into our buffer; flush buffer when it fills up. + int32_t offset = 0; + while (0 != aLength) { + int32_t amount = NS_ACCUMULATION_BUFFER_SIZE - mTextLength; + if (0 == amount) { + nsresult rv = FlushText(false); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + MOZ_ASSERT(mTextLength == 0); + amount = NS_ACCUMULATION_BUFFER_SIZE; + } + + if (amount > aLength) { + amount = aLength; + } + memcpy(&mText[mTextLength], &aText[offset], sizeof(char16_t) * amount); + mTextLength += amount; + offset += amount; + aLength -= amount; + } + + return NS_OK; +} + +void nsXMLContentSink::InitialTranslationCompleted() { StartLayout(false); } + +void nsXMLContentSink::FlushPendingNotifications(FlushType aType) { + // Only flush tags if we're not doing the notification ourselves + // (since we aren't reentrant) + if (!mInNotification) { + if (mIsDocumentObserver) { + // Only flush if we're still a document observer (so that our child + // counts should be correct). + if (aType >= FlushType::ContentAndNotify) { + FlushTags(); + } else { + FlushText(false); + } + } + if (aType >= FlushType::EnsurePresShellInitAndFrames) { + // Make sure that layout has started so that the reflow flush + // will actually happen. + MaybeStartLayout(true); + } + } +} + +/** + * NOTE!! Forked from SinkContext. Please keep in sync. + * + * Flush all elements that have been seen so far such that + * they are visible in the tree. Specifically, make sure + * that they are all added to their respective parents. + * Also, do notification at the top for all content that + * has been newly added so that the frame tree is complete. + */ +nsresult nsXMLContentSink::FlushTags() { + mDeferredFlushTags = false; + uint32_t oldUpdates = mUpdatesInNotification; + + mUpdatesInNotification = 0; + ++mInNotification; + { + // Scope so we call EndUpdate before we decrease mInNotification + mozAutoDocUpdate updateBatch(mDocument, true); + + // Don't release last text node in case we need to add to it again + FlushText(false); + + // Start from the base of the stack (growing downward) and do + // a notification from the node that is closest to the root of + // tree for any content that has been added. + + int32_t stackPos; + int32_t stackLen = mContentStack.Length(); + bool flushed = false; + uint32_t childCount; + nsIContent* content; + + for (stackPos = 0; stackPos < stackLen; ++stackPos) { + content = mContentStack[stackPos].mContent; + childCount = content->GetChildCount(); + + if (!flushed && (mContentStack[stackPos].mNumFlushed < childCount)) { + NotifyAppend(content, mContentStack[stackPos].mNumFlushed); + flushed = true; + } + + mContentStack[stackPos].mNumFlushed = childCount; + } + mNotifyLevel = stackLen - 1; + } + --mInNotification; + + if (mUpdatesInNotification > 1) { + UpdateChildCounts(); + } + + mUpdatesInNotification = oldUpdates; + return NS_OK; +} + +/** + * NOTE!! Forked from SinkContext. Please keep in sync. + */ +void nsXMLContentSink::UpdateChildCounts() { + // Start from the top of the stack (growing upwards) and see if any + // new content has been appended. If so, we recognize that reflows + // have been generated for it and we should make sure that no + // further reflows occur. Note that we have to include stackPos == 0 + // to properly notify on kids of . + int32_t stackLen = mContentStack.Length(); + int32_t stackPos = stackLen - 1; + while (stackPos >= 0) { + StackNode& node = mContentStack[stackPos]; + node.mNumFlushed = node.mContent->GetChildCount(); + + stackPos--; + } + mNotifyLevel = stackLen - 1; +} + +bool nsXMLContentSink::IsMonolithicContainer( + mozilla::dom::NodeInfo* aNodeInfo) { + return ((aNodeInfo->NamespaceID() == kNameSpaceID_XHTML && + (aNodeInfo->NameAtom() == nsGkAtoms::tr || + aNodeInfo->NameAtom() == nsGkAtoms::select || + aNodeInfo->NameAtom() == nsGkAtoms::object)) || + (aNodeInfo->NamespaceID() == kNameSpaceID_MathML && + (aNodeInfo->NameAtom() == nsGkAtoms::math))); +} + +void nsXMLContentSink::ContinueInterruptedParsingIfEnabled() { + if (mParser && mParser->IsParserEnabled()) { + GetParser()->ContinueInterruptedParsing(); + } +} + +void nsXMLContentSink::ContinueInterruptedParsingAsync() { + nsCOMPtr ev = NewRunnableMethod( + "nsXMLContentSink::ContinueInterruptedParsingIfEnabled", this, + &nsXMLContentSink::ContinueInterruptedParsingIfEnabled); + + mDocument->Dispatch(mozilla::TaskCategory::Other, ev.forget()); +} + +nsIParser* nsXMLContentSink::GetParser() { + return static_cast(mParser.get()); +} diff --git a/dom/xml/nsXMLContentSink.h b/dom/xml/nsXMLContentSink.h new file mode 100644 index 0000000000..41acbbc027 --- /dev/null +++ b/dom/xml/nsXMLContentSink.h @@ -0,0 +1,217 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef nsXMLContentSink_h__ +#define nsXMLContentSink_h__ + +#include "mozilla/Attributes.h" +#include "nsContentSink.h" +#include "nsIXMLContentSink.h" +#include "nsIExpatSink.h" +#include "nsIDocumentTransformer.h" +#include "nsTArray.h" +#include "nsCOMPtr.h" +#include "nsCRT.h" +#include "nsCycleCollectionParticipant.h" +#include "nsIDTD.h" +#include "mozilla/dom/FromParser.h" + +class nsIURI; +class nsIContent; +class nsIParser; +class nsTextNode; + +namespace mozilla::dom { +class NodeInfo; +class ProcessingInstruction; +} // namespace mozilla::dom + +enum XMLContentSinkState { + eXMLContentSinkState_InProlog, + eXMLContentSinkState_InDocumentElement, + eXMLContentSinkState_InEpilog +}; + +class nsXMLContentSink : public nsContentSink, + public nsIXMLContentSink, + public nsITransformObserver, + public nsIExpatSink { + public: + struct StackNode { + nsCOMPtr mContent; + uint32_t mNumFlushed; + }; + + nsXMLContentSink(); + + nsresult Init(mozilla::dom::Document* aDoc, nsIURI* aURL, + nsISupports* aContainer, nsIChannel* aChannel); + + // nsISupports + NS_DECL_ISUPPORTS_INHERITED + + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXMLContentSink, nsContentSink) + + NS_DECL_NSIEXPATSINK + + // nsIContentSink + NS_IMETHOD WillParse(void) override; + NS_IMETHOD WillBuildModel(nsDTDMode aDTDMode) override; + NS_IMETHOD DidBuildModel(bool aTerminated) override; + NS_IMETHOD WillInterrupt(void) override; + void WillResume() override; + NS_IMETHOD SetParser(nsParserBase* aParser) override; + virtual void InitialTranslationCompleted() override; + virtual void FlushPendingNotifications(mozilla::FlushType aType) override; + virtual void SetDocumentCharset(NotNull aEncoding) override; + virtual nsISupports* GetTarget() override; + virtual bool IsScriptExecuting() override; + virtual void ContinueInterruptedParsingAsync() override; + bool IsPrettyPrintXML() const override { return mPrettyPrintXML; } + bool IsPrettyPrintHasSpecialRoot() const override { + return mPrettyPrintHasSpecialRoot; + } + + // nsITransformObserver + nsresult OnDocumentCreated(mozilla::dom::Document* aSourceDocument, + mozilla::dom::Document* aResultDocument) override; + nsresult OnTransformDone(mozilla::dom::Document* aSourceDocument, + nsresult aResult, + mozilla::dom::Document* aResultDocument) override; + + // nsICSSLoaderObserver + NS_IMETHOD StyleSheetLoaded(mozilla::StyleSheet* aSheet, bool aWasDeferred, + nsresult aStatus) override; + static bool ParsePIData(const nsString& aData, nsString& aHref, + nsString& aTitle, nsString& aMedia, + bool& aIsAlternate); + + protected: + virtual ~nsXMLContentSink(); + + nsIParser* GetParser(); + + void ContinueInterruptedParsingIfEnabled(); + + // Start layout. If aIgnorePendingSheets is true, this will happen even if + // we still have stylesheet loads pending. Otherwise, we'll wait until the + // stylesheets are all done loading. + virtual void MaybeStartLayout(bool aIgnorePendingSheets); + + virtual nsresult AddAttributes(const char16_t** aNode, + mozilla::dom::Element* aElement); + nsresult AddText(const char16_t* aString, int32_t aLength); + + virtual bool OnOpenContainer(const char16_t** aAtts, uint32_t aAttsCount, + int32_t aNameSpaceID, nsAtom* aTagName, + uint32_t aLineNumber) { + return true; + } + // Set the given content as the root element for the created document + // don't set if root element was already set. + // return TRUE if this call set the root element + virtual bool SetDocElement(int32_t aNameSpaceID, nsAtom* aTagName, + nsIContent* aContent); + virtual bool NotifyForDocElement() { return true; } + virtual nsresult CreateElement(const char16_t** aAtts, uint32_t aAttsCount, + mozilla::dom::NodeInfo* aNodeInfo, + uint32_t aLineNumber, uint32_t aColumnNumber, + nsIContent** aResult, bool* aAppendContent, + mozilla::dom::FromParser aFromParser); + + // aParent is allowed to be null here if this is the root content + // being closed + virtual nsresult CloseElement(nsIContent* aContent); + + virtual nsresult FlushText(bool aReleaseTextNode = true); + + nsresult AddContentAsLeaf(nsIContent* aContent); + + nsIContent* GetCurrentContent(); + StackNode* GetCurrentStackNode(); + nsresult PushContent(nsIContent* aContent); + void PopContent(); + bool HaveNotifiedForCurrentContent() const; + + nsresult FlushTags() override; + + void UpdateChildCounts() override; + + void DidAddContent() { + if (!mXSLTProcessor && IsTimeToNotify()) { + FlushTags(); + } + } + + // nsContentSink override + virtual nsresult ProcessStyleLinkFromHeader( + const nsAString& aHref, bool aAlternate, const nsAString& aTitle, + const nsAString& aIntegrity, const nsAString& aType, + const nsAString& aMedia, const nsAString& aReferrerPolicy) override; + + // Try to handle an XSLT style link. If NS_OK is returned and aWasXSLT is not + // null, *aWasXSLT will be set to whether we processed this link as XSLT. + // + // aProcessingInstruction can be null if this information comes from a Link + // header; otherwise it will be the xml-styleshset XML PI that the loading + // information comes from. + virtual nsresult MaybeProcessXSLTLink( + mozilla::dom::ProcessingInstruction* aProcessingInstruction, + const nsAString& aHref, bool aAlternate, const nsAString& aTitle, + const nsAString& aType, const nsAString& aMedia, + const nsAString& aReferrerPolicy, bool* aWasXSLT = nullptr); + + nsresult LoadXSLStyleSheet(nsIURI* aUrl); + + bool CanStillPrettyPrint(); + + nsresult MaybePrettyPrint(); + + bool IsMonolithicContainer(mozilla::dom::NodeInfo* aNodeInfo); + + nsresult HandleStartElement(const char16_t* aName, const char16_t** aAtts, + uint32_t aAttsCount, uint32_t aLineNumber, + uint32_t aColumnNumber, bool aInterruptable); + nsresult HandleEndElement(const char16_t* aName, bool aInterruptable); + nsresult HandleCharacterData(const char16_t* aData, uint32_t aLength, + bool aInterruptable); + + nsCOMPtr mDocElement; + nsCOMPtr mCurrentHead; // When set, we're in an XHTML + + XMLContentSinkState mState; + + // The length of the valid data in mText. + int32_t mTextLength; + + int32_t mNotifyLevel; + RefPtr mLastTextNode; + + uint8_t mPrettyPrintXML : 1; + uint8_t mPrettyPrintHasSpecialRoot : 1; + uint8_t mPrettyPrintHasFactoredElements : 1; + uint8_t mPrettyPrinting : 1; // True if we called PrettyPrint() and it + // decided we should in fact prettyprint. + // True to call prevent script execution in the fragment mode. + uint8_t mPreventScriptExecution : 1; + + nsTArray mContentStack; + + nsCOMPtr mXSLTProcessor; + + // Holds the children in the prolog until the root element is added, after + // which they're inserted in the document. However, if we're doing an XSLT + // transform this will actually hold all the children of the source document, + // until the transform is finished. After the transform is finished we'll just + // discard the children. + nsTArray> mDocumentChildren; + + static const int NS_ACCUMULATION_BUFFER_SIZE = 4096; + // Our currently accumulated text that we have not flushed to a textnode yet. + char16_t mText[NS_ACCUMULATION_BUFFER_SIZE]; +}; + +#endif // nsXMLContentSink_h__ diff --git a/dom/xml/nsXMLElement.cpp b/dom/xml/nsXMLElement.cpp new file mode 100644 index 0000000000..ef51715d1b --- /dev/null +++ b/dom/xml/nsXMLElement.cpp @@ -0,0 +1,54 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsXMLElement.h" +#include "mozilla/dom/ElementBinding.h" +#include "mozilla/dom/ElementInlines.h" +#include "nsContentUtils.h" // nsAutoScriptBlocker + +using namespace mozilla; +using namespace mozilla::dom; + +nsresult NS_NewXMLElement( + Element** aInstancePtrResult, + already_AddRefed&& aNodeInfo) { + RefPtr nodeInfo(std::move(aNodeInfo)); + auto* nim = nodeInfo->NodeInfoManager(); + RefPtr it = new (nim) nsXMLElement(nodeInfo.forget()); + + it.forget(aInstancePtrResult); + return NS_OK; +} + +JSObject* nsXMLElement::WrapNode(JSContext* aCx, + JS::Handle aGivenProto) { + return Element_Binding::Wrap(aCx, this, aGivenProto); +} + +void nsXMLElement::UnbindFromTree(bool aNullParent) { + nsAtom* property; + switch (GetPseudoElementType()) { + case PseudoStyleType::marker: + property = nsGkAtoms::markerPseudoProperty; + break; + case PseudoStyleType::before: + property = nsGkAtoms::beforePseudoProperty; + break; + case PseudoStyleType::after: + property = nsGkAtoms::afterPseudoProperty; + break; + default: + property = nullptr; + } + if (property) { + MOZ_ASSERT(GetParent()); + MOZ_ASSERT(GetParent()->IsElement()); + GetParent()->RemoveProperty(property); + } + Element::UnbindFromTree(aNullParent); +} + +NS_IMPL_ELEMENT_CLONE(nsXMLElement) diff --git a/dom/xml/nsXMLElement.h b/dom/xml/nsXMLElement.h new file mode 100644 index 0000000000..e401965fff --- /dev/null +++ b/dom/xml/nsXMLElement.h @@ -0,0 +1,35 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef nsXMLElement_h___ +#define nsXMLElement_h___ + +#include "mozilla/Attributes.h" +#include "mozilla/dom/Element.h" +#include "mozilla/dom/DOMRect.h" + +class nsXMLElement : public mozilla::dom::Element { + public: + explicit nsXMLElement(already_AddRefed&& aNodeInfo) + : mozilla::dom::Element(std::move(aNodeInfo)) {} + + // nsISupports + NS_INLINE_DECL_REFCOUNTING_INHERITED(nsXMLElement, mozilla::dom::Element) + + // nsINode interface methods + virtual nsresult Clone(mozilla::dom::NodeInfo*, + nsINode** aResult) const override; + + virtual void UnbindFromTree(bool aNullParent = true) override; + + protected: + virtual ~nsXMLElement() = default; + + virtual JSObject* WrapNode(JSContext* aCx, + JS::Handle aGivenProto) override; +}; + +#endif // nsXMLElement_h___ diff --git a/dom/xml/nsXMLFragmentContentSink.cpp b/dom/xml/nsXMLFragmentContentSink.cpp new file mode 100644 index 0000000000..ddf96793e4 --- /dev/null +++ b/dom/xml/nsXMLFragmentContentSink.cpp @@ -0,0 +1,372 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsCOMPtr.h" +#include "nsXMLContentSink.h" +#include "nsIFragmentContentSink.h" +#include "nsIXMLContentSink.h" +#include "nsContentSink.h" +#include "nsIExpatSink.h" +#include "nsIDTD.h" +#include "mozilla/dom/Document.h" +#include "nsIContent.h" +#include "nsGkAtoms.h" +#include "mozilla/dom/NodeInfo.h" +#include "nsContentCreatorFunctions.h" +#include "nsError.h" +#include "nsIDocShell.h" +#include "nsIScriptError.h" +#include "nsTHashtable.h" +#include "nsHashKeys.h" +#include "nsTArray.h" +#include "nsCycleCollectionParticipant.h" +#include "mozilla/css/Loader.h" +#include "mozilla/dom/DocumentFragment.h" +#include "mozilla/dom/ProcessingInstruction.h" +#include "mozilla/dom/ScriptLoader.h" + +using namespace mozilla::dom; + +class nsXMLFragmentContentSink : public nsXMLContentSink, + public nsIFragmentContentSink { + public: + nsXMLFragmentContentSink(); + + // nsISupports + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXMLFragmentContentSink, + nsXMLContentSink) + + // nsIExpatSink + NS_IMETHOD HandleDoctypeDecl(const nsAString& aSubset, const nsAString& aName, + const nsAString& aSystemId, + const nsAString& aPublicId, + nsISupports* aCatalogData) override; + NS_IMETHOD HandleProcessingInstruction(const char16_t* aTarget, + const char16_t* aData) override; + NS_IMETHOD HandleXMLDeclaration(const char16_t* aVersion, + const char16_t* aEncoding, + int32_t aStandalone) override; + NS_IMETHOD ReportError(const char16_t* aErrorText, + const char16_t* aSourceText, nsIScriptError* aError, + bool* aRetval) override; + + // nsIContentSink + NS_IMETHOD WillBuildModel(nsDTDMode aDTDMode) override; + NS_IMETHOD DidBuildModel(bool aTerminated) override; + virtual void SetDocumentCharset(NotNull aEncoding) override; + virtual nsISupports* GetTarget() override; + NS_IMETHOD DidProcessATokenImpl(); + + // nsIXMLContentSink + + // nsIFragmentContentSink + NS_IMETHOD FinishFragmentParsing(DocumentFragment** aFragment) override; + NS_IMETHOD SetTargetDocument(Document* aDocument) override; + NS_IMETHOD WillBuildContent() override; + NS_IMETHOD DidBuildContent() override; + NS_IMETHOD IgnoreFirstContainer() override; + NS_IMETHOD SetPreventScriptExecution(bool aPreventScriptExecution) override; + + protected: + virtual ~nsXMLFragmentContentSink(); + + virtual bool SetDocElement(int32_t aNameSpaceID, nsAtom* aTagName, + nsIContent* aContent) override; + virtual nsresult CreateElement(const char16_t** aAtts, uint32_t aAttsCount, + mozilla::dom::NodeInfo* aNodeInfo, + uint32_t aLineNumber, uint32_t aColumnNumber, + nsIContent** aResult, bool* aAppendContent, + mozilla::dom::FromParser aFromParser) override; + virtual nsresult CloseElement(nsIContent* aContent) override; + + virtual void MaybeStartLayout(bool aIgnorePendingSheets) override; + + // nsContentSink overrides + virtual nsresult ProcessStyleLinkFromHeader( + const nsAString& aHref, bool aAlternate, const nsAString& aTitle, + const nsAString& aIntegrity, const nsAString& aType, + const nsAString& aMedia, const nsAString& aReferrerPolicy) override; + + // nsXMLContentSink overrides + virtual nsresult MaybeProcessXSLTLink( + ProcessingInstruction* aProcessingInstruction, const nsAString& aHref, + bool aAlternate, const nsAString& aTitle, const nsAString& aType, + const nsAString& aMedia, const nsAString& aReferrerPolicy, + bool* aWasXSLT = nullptr) override; + + nsCOMPtr mTargetDocument; + // the fragment + RefPtr mRoot; + bool mParseError; +}; + +static nsresult NewXMLFragmentContentSinkHelper( + nsIFragmentContentSink** aResult) { + nsXMLFragmentContentSink* it = new nsXMLFragmentContentSink(); + + NS_ADDREF(*aResult = it); + + return NS_OK; +} + +nsresult NS_NewXMLFragmentContentSink(nsIFragmentContentSink** aResult) { + return NewXMLFragmentContentSinkHelper(aResult); +} + +nsXMLFragmentContentSink::nsXMLFragmentContentSink() : mParseError(false) { + mRunsToCompletion = true; +} + +nsXMLFragmentContentSink::~nsXMLFragmentContentSink() = default; + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXMLFragmentContentSink) + NS_INTERFACE_MAP_ENTRY(nsIFragmentContentSink) +NS_INTERFACE_MAP_END_INHERITING(nsXMLContentSink) + +NS_IMPL_ADDREF_INHERITED(nsXMLFragmentContentSink, nsXMLContentSink) +NS_IMPL_RELEASE_INHERITED(nsXMLFragmentContentSink, nsXMLContentSink) + +NS_IMPL_CYCLE_COLLECTION_INHERITED(nsXMLFragmentContentSink, nsXMLContentSink, + mTargetDocument, mRoot) + +NS_IMETHODIMP +nsXMLFragmentContentSink::WillBuildModel(nsDTDMode aDTDMode) { + if (mRoot) { + return NS_OK; + } + + mState = eXMLContentSinkState_InDocumentElement; + + NS_ASSERTION(mTargetDocument, "Need a document!"); + + mRoot = new (mNodeInfoManager) DocumentFragment(mNodeInfoManager); + + return NS_OK; +} + +NS_IMETHODIMP +nsXMLFragmentContentSink::DidBuildModel(bool aTerminated) { + // Drop our reference to the parser to get rid of a circular + // reference. + mParser = nullptr; + + return NS_OK; +} + +void nsXMLFragmentContentSink::SetDocumentCharset( + NotNull aEncoding) { + MOZ_ASSERT_UNREACHABLE("fragments shouldn't set charset"); +} + +nsISupports* nsXMLFragmentContentSink::GetTarget() { + return ToSupports(mTargetDocument); +} + +//////////////////////////////////////////////////////////////////////// + +bool nsXMLFragmentContentSink::SetDocElement(int32_t aNameSpaceID, + nsAtom* aTagName, + nsIContent* aContent) { + // this is a fragment, not a document + return false; +} + +nsresult nsXMLFragmentContentSink::CreateElement( + const char16_t** aAtts, uint32_t aAttsCount, + mozilla::dom::NodeInfo* aNodeInfo, uint32_t aLineNumber, + uint32_t aColumnNumber, nsIContent** aResult, bool* aAppendContent, + FromParser /*aFromParser*/) { + // Claim to not be coming from parser, since we don't do any of the + // fancy CloseElement stuff. + nsresult rv = nsXMLContentSink::CreateElement( + aAtts, aAttsCount, aNodeInfo, aLineNumber, aColumnNumber, aResult, + aAppendContent, NOT_FROM_PARSER); + + // 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 (mContentStack.Length() == 0) { + *aAppendContent = false; + } + + return rv; +} + +nsresult nsXMLFragmentContentSink::CloseElement(nsIContent* aContent) { + // don't do fancy stuff in nsXMLContentSink + if (mPreventScriptExecution && (aContent->IsHTMLElement(nsGkAtoms::script) || + aContent->IsSVGElement(nsGkAtoms::script))) { + nsCOMPtr sele = do_QueryInterface(aContent); + if (sele) { + sele->PreventExecution(); + } else { + NS_ASSERTION(nsNameSpaceManager::GetInstance()->mSVGDisabled, + "Script did QI correctly, but wasn't a disabled SVG!"); + } + } + return NS_OK; +} + +void nsXMLFragmentContentSink::MaybeStartLayout(bool aIgnorePendingSheets) {} + +//////////////////////////////////////////////////////////////////////// + +NS_IMETHODIMP +nsXMLFragmentContentSink::HandleDoctypeDecl(const nsAString& aSubset, + const nsAString& aName, + const nsAString& aSystemId, + const nsAString& aPublicId, + nsISupports* aCatalogData) { + MOZ_ASSERT_UNREACHABLE("fragments shouldn't have doctype declarations"); + + return NS_OK; +} + +NS_IMETHODIMP +nsXMLFragmentContentSink::HandleProcessingInstruction(const char16_t* aTarget, + const char16_t* aData) { + FlushText(); + + const nsDependentString target(aTarget); + const nsDependentString data(aData); + + RefPtr node = + NS_NewXMLProcessingInstruction(mNodeInfoManager, target, data); + + // no special processing here. that should happen when the fragment moves + // into the document + return AddContentAsLeaf(node); +} + +NS_IMETHODIMP +nsXMLFragmentContentSink::HandleXMLDeclaration(const char16_t* aVersion, + const char16_t* aEncoding, + int32_t aStandalone) { + MOZ_ASSERT_UNREACHABLE("fragments shouldn't have XML declarations"); + return NS_OK; +} + +NS_IMETHODIMP +nsXMLFragmentContentSink::ReportError(const char16_t* aErrorText, + const char16_t* aSourceText, + nsIScriptError* aError, bool* _retval) { + MOZ_ASSERT(aError && aSourceText && aErrorText, "Check arguments!!!"); + + // The expat driver should report the error. + *_retval = true; + + mParseError = true; + +#ifdef DEBUG + // Report the error to stderr. + fprintf(stderr, "\n%s\n%s\n\n", NS_LossyConvertUTF16toASCII(aErrorText).get(), + NS_LossyConvertUTF16toASCII(aSourceText).get()); +#endif + + // The following code is similar to the cleanup in + // nsXMLContentSink::ReportError() + mState = eXMLContentSinkState_InProlog; + + // Clear the current content + while (mRoot->GetLastChild()) { + mRoot->GetLastChild()->Remove(); + } + + // Clear any buffered-up text we have. It's enough to set the length to 0. + // The buffer itself is allocated when we're created and deleted in our + // destructor, so don't mess with it. + mTextLength = 0; + + return NS_OK; +} + +nsresult nsXMLFragmentContentSink::ProcessStyleLinkFromHeader( + const nsAString& aHref, bool aAlternate, const nsAString& aTitle, + const nsAString& aIntegrity, const nsAString& aType, + const nsAString& aMedia, const nsAString& aReferrerPolicy) + +{ + MOZ_ASSERT_UNREACHABLE("Shouldn't have headers for a fragment sink"); + return NS_OK; +} + +nsresult nsXMLFragmentContentSink::MaybeProcessXSLTLink( + ProcessingInstruction* aProcessingInstruction, const nsAString& aHref, + bool aAlternate, const nsAString& aTitle, const nsAString& aType, + const nsAString& aMedia, const nsAString& aReferrerPolicy, bool* aWasXSLT) { + MOZ_ASSERT(!aWasXSLT, "Our one caller doesn't care about whether we're XSLT"); + return NS_OK; +} + +//////////////////////////////////////////////////////////////////////// + +NS_IMETHODIMP +nsXMLFragmentContentSink::FinishFragmentParsing(DocumentFragment** aFragment) { + mTargetDocument = nullptr; + mNodeInfoManager = nullptr; + mScriptLoader = nullptr; + mCSSLoader = nullptr; + mContentStack.Clear(); + mDocumentURI = nullptr; + mDocShell = nullptr; + mDocElement = nullptr; + mCurrentHead = nullptr; + if (mParseError) { + // XXX PARSE_ERR from DOM3 Load and Save would be more appropriate + mRoot = nullptr; + mParseError = false; + *aFragment = nullptr; + return NS_ERROR_DOM_SYNTAX_ERR; + } + + mRoot.forget(aFragment); + return NS_OK; +} + +NS_IMETHODIMP +nsXMLFragmentContentSink::SetTargetDocument(Document* aTargetDocument) { + NS_ENSURE_ARG_POINTER(aTargetDocument); + + mTargetDocument = aTargetDocument; + mNodeInfoManager = aTargetDocument->NodeInfoManager(); + + return NS_OK; +} + +NS_IMETHODIMP +nsXMLFragmentContentSink::WillBuildContent() { + PushContent(mRoot); + + return NS_OK; +} + +NS_IMETHODIMP +nsXMLFragmentContentSink::DidBuildContent() { + // 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; +} + +NS_IMETHODIMP +nsXMLFragmentContentSink::DidProcessATokenImpl() { return NS_OK; } + +NS_IMETHODIMP +nsXMLFragmentContentSink::IgnoreFirstContainer() { + MOZ_ASSERT_UNREACHABLE("XML isn't as broken as HTML"); + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsXMLFragmentContentSink::SetPreventScriptExecution(bool aPrevent) { + mPreventScriptExecution = aPrevent; + return NS_OK; +} diff --git a/dom/xml/nsXMLPrettyPrinter.cpp b/dom/xml/nsXMLPrettyPrinter.cpp new file mode 100644 index 0000000000..4a386e92fb --- /dev/null +++ b/dom/xml/nsXMLPrettyPrinter.cpp @@ -0,0 +1,189 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsXMLPrettyPrinter.h" +#include "nsContentUtils.h" +#include "nsICSSDeclaration.h" +#include "nsSyncLoadService.h" +#include "nsPIDOMWindow.h" +#include "nsNetUtil.h" +#include "mozilla/dom/Element.h" +#include "mozilla/dom/ShadowRoot.h" +#include "mozilla/Preferences.h" +#include "mozilla/dom/Document.h" +#include "nsVariant.h" +#include "mozilla/dom/CustomEvent.h" +#include "mozilla/dom/DocumentFragment.h" +#include "mozilla/dom/DocumentL10n.h" +#include "mozilla/dom/ScriptSettings.h" +#include "mozilla/dom/ToJSValue.h" +#include "mozilla/dom/txMozillaXSLTProcessor.h" + +using namespace mozilla; +using namespace mozilla::dom; + +NS_IMPL_ISUPPORTS(nsXMLPrettyPrinter, nsIDocumentObserver, nsIMutationObserver) + +nsXMLPrettyPrinter::nsXMLPrettyPrinter() + : mDocument(nullptr), mUnhookPending(false) {} + +nsXMLPrettyPrinter::~nsXMLPrettyPrinter() { + NS_ASSERTION(!mDocument, "we shouldn't be referencing the document still"); +} + +nsresult nsXMLPrettyPrinter::PrettyPrint(Document* aDocument, + bool* aDidPrettyPrint) { + *aDidPrettyPrint = false; + + // check the pref + if (!Preferences::GetBool("layout.xml.prettyprint", true)) { + return NS_OK; + } + + // Find the root element + RefPtr rootElement = aDocument->GetRootElement(); + NS_ENSURE_TRUE(rootElement, NS_ERROR_UNEXPECTED); + + // nsXMLContentSink should not ask us to pretty print an XML doc that comes + // with a CanAttachShadowDOM() == true root element, but just in case: + if (rootElement->CanAttachShadowDOM()) { + MOZ_DIAGNOSTIC_ASSERT(false, "We shouldn't be getting this root element"); + return NS_ERROR_UNEXPECTED; + } + + // Ok, we should prettyprint. Let's do it! + *aDidPrettyPrint = true; + nsresult rv = NS_OK; + + // Load the XSLT + nsCOMPtr xslUri; + rv = NS_NewURI(getter_AddRefs(xslUri), + "chrome://global/content/xml/XMLPrettyPrint.xsl"_ns); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr xslDocument; + rv = nsSyncLoadService::LoadDocument( + xslUri, nsIContentPolicy::TYPE_XSLT, nsContentUtils::GetSystemPrincipal(), + nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL, nullptr, + aDocument->CookieJarSettings(), true, ReferrerPolicy::_empty, + getter_AddRefs(xslDocument)); + NS_ENSURE_SUCCESS(rv, rv); + + // Transform the document + RefPtr transformer = new txMozillaXSLTProcessor(); + ErrorResult err; + transformer->ImportStylesheet(*xslDocument, err); + if (NS_WARN_IF(err.Failed())) { + return err.StealNSResult(); + } + + RefPtr resultFragment = + transformer->TransformToFragment(*aDocument, *aDocument, err); + if (NS_WARN_IF(err.Failed())) { + return err.StealNSResult(); + } + + // Attach an UA Widget Shadow Root on it. + rootElement->AttachAndSetUAShadowRoot(Element::NotifyUAWidgetSetup::No); + RefPtr shadowRoot = rootElement->GetShadowRoot(); + MOZ_RELEASE_ASSERT(shadowRoot && shadowRoot->IsUAWidget(), + "There should be a UA Shadow Root here."); + + // Append the document fragment to the shadow dom. + shadowRoot->AppendChild(*resultFragment, err); + if (NS_WARN_IF(err.Failed())) { + return err.StealNSResult(); + } + + // Create a DocumentL10n, as the XML document is not allowed to have one. + // Make it sync so that the test for bug 590812 does not require a setTimeout. + RefPtr l10n = DocumentL10n::Create(aDocument, true); + NS_ENSURE_TRUE(l10n, NS_ERROR_UNEXPECTED); + l10n->AddResourceId("dom/XMLPrettyPrint.ftl"_ns); + + // Localize the shadow DOM header + Element* l10nRoot = shadowRoot->GetElementById(u"header"_ns); + NS_ENSURE_TRUE(l10nRoot, NS_ERROR_UNEXPECTED); + l10n->SetRootInfo(l10nRoot); + l10n->ConnectRoot(*l10nRoot, true, err); + if (NS_WARN_IF(err.Failed())) { + return err.StealNSResult(); + } + RefPtr promise = l10n->TranslateRoots(err); + if (NS_WARN_IF(err.Failed())) { + return err.StealNSResult(); + } + + // Observe the document so we know when to switch to "normal" view + aDocument->AddObserver(this); + mDocument = aDocument; + + NS_ADDREF_THIS(); + + return NS_OK; +} + +void nsXMLPrettyPrinter::MaybeUnhook(nsIContent* aContent) { + // If aContent is null, the document-node was modified. + // If it is not null but in the shadow tree or the NACs, + // the change was in the generated content, and it should be ignored. + bool isGeneratedContent = + aContent && + (aContent->IsInNativeAnonymousSubtree() || aContent->IsInShadowTree()); + + if (!isGeneratedContent && !mUnhookPending) { + // Can't blindly to mUnhookPending after AddScriptRunner, + // since AddScriptRunner _could_ in theory run us + // synchronously + mUnhookPending = true; + nsContentUtils::AddScriptRunner(NewRunnableMethod( + "nsXMLPrettyPrinter::Unhook", this, &nsXMLPrettyPrinter::Unhook)); + } +} + +void nsXMLPrettyPrinter::Unhook() { + mDocument->RemoveObserver(this); + nsCOMPtr element = mDocument->GetDocumentElement(); + + if (element) { + // Remove the shadow root + element->UnattachShadow(); + } + + mDocument = nullptr; + + NS_RELEASE_THIS(); +} + +void nsXMLPrettyPrinter::AttributeChanged(Element* aElement, + int32_t aNameSpaceID, + nsAtom* aAttribute, int32_t aModType, + const nsAttrValue* aOldValue) { + MaybeUnhook(aElement); +} + +void nsXMLPrettyPrinter::ContentAppended(nsIContent* aFirstNewContent) { + MaybeUnhook(aFirstNewContent->GetParent()); +} + +void nsXMLPrettyPrinter::ContentInserted(nsIContent* aChild) { + MaybeUnhook(aChild->GetParent()); +} + +void nsXMLPrettyPrinter::ContentRemoved(nsIContent* aChild, + nsIContent* aPreviousSibling) { + MaybeUnhook(aChild->GetParent()); +} + +void nsXMLPrettyPrinter::NodeWillBeDestroyed(nsINode* aNode) { + mDocument = nullptr; + NS_RELEASE_THIS(); +} + +nsresult NS_NewXMLPrettyPrinter(nsXMLPrettyPrinter** aPrinter) { + *aPrinter = new nsXMLPrettyPrinter; + NS_ADDREF(*aPrinter); + return NS_OK; +} diff --git a/dom/xml/nsXMLPrettyPrinter.h b/dom/xml/nsXMLPrettyPrinter.h new file mode 100644 index 0000000000..04835666dd --- /dev/null +++ b/dom/xml/nsXMLPrettyPrinter.h @@ -0,0 +1,59 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef nsXMLPrettyPrinter_h__ +#define nsXMLPrettyPrinter_h__ + +#include "nsStubDocumentObserver.h" +#include "nsCOMPtr.h" + +class nsXMLPrettyPrinter : public nsStubDocumentObserver { + public: + nsXMLPrettyPrinter(); + + NS_DECL_ISUPPORTS + + // nsIMutationObserver + NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED + NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED + NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED + NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED + NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED + + /** + * This will prettyprint the document if the document is loaded in a + * displayed window. + * + * @param aDocument document to prettyprint + * @param [out] aDidPrettyPrint if true, and error not returned, actually + * went ahead with prettyprinting the document. + */ + nsresult PrettyPrint(mozilla::dom::Document* aDocument, + bool* aDidPrettyPrint); + + /** + * Unhook the prettyprinter + */ + void Unhook(); + + private: + virtual ~nsXMLPrettyPrinter(); + + /** + * Signals for unhooking by setting mUnhookPending if the node changed is + * not in the shadow root tree nor in anonymous content. + * + * @param aContent content that has changed + */ + void MaybeUnhook(nsIContent* aContent); + + mozilla::dom::Document* + mDocument; // weak. Set as long as we're observing the document + bool mUnhookPending; +}; + +nsresult NS_NewXMLPrettyPrinter(nsXMLPrettyPrinter** aPrinter); + +#endif // nsXMLPrettyPrinter_h__ diff --git a/dom/xml/resources/XMLPrettyPrint.css b/dom/xml/resources/XMLPrettyPrint.css new file mode 100644 index 0000000000..845833c46f --- /dev/null +++ b/dom/xml/resources/XMLPrettyPrint.css @@ -0,0 +1,58 @@ +@charset "UTF-8"; +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +@import url("resource://content-accessible/viewsource.css"); + +:host { + color-scheme: light dark; +} + +#header { + background-color: #ccc; + border-bottom: 3px solid black; + padding: 0.5em; + margin-bottom: 1em; +} + +@media (prefers-color-scheme: dark) { + #header { + background-color: #333; + border-color: #555; + } +} + +#tree, +.expandable-children { + margin-inline-start: 1em; +} + +.expandable-body { + display: inline-block; +} + +.expandable-body[open] { + display: block; +} + +.expandable-opening { + list-style: '+' outside; +} + +[open] > .expandable-opening { + list-style-type: '−'; +} + +.expandable-opening::marker { + cursor: pointer; + padding-inline-end: 2px; + /* Don't want to inherit the styling from pi and comment elements */ + color: buttontext; + font: initial; +} + +.comment { + font-family: monospace; + white-space: pre; +} diff --git a/dom/xml/resources/XMLPrettyPrint.xsl b/dom/xml/resources/XMLPrettyPrint.xsl new file mode 100644 index 0000000000..b23296cf0d --- /dev/null +++ b/dom/xml/resources/XMLPrettyPrint.xsl @@ -0,0 +1,133 @@ + + + + + + + + + + +
+ + +
+ +
+
+
+ + +
+ < + + + /> +
+
+ + +
+ < + + + > + + + + </ + + > +
+
+ + +
+
+ + < + + + > + + +
+ +
+ + </ + + > + +
+
+ + + + + = + "" + + + + + + + + + +
+ <? + + + + ?> +
+
+ + +
+
+ + <? + + +
+
+ + ?> + +
+
+ + +
+ <!-- + + --> +
+
+ + +
+
+ + <!-- + +
+ +
+
+ + --> + +
+
+ +
diff --git a/dom/xml/resources/jar.mn b/dom/xml/resources/jar.mn new file mode 100644 index 0000000000..14fc365a3e --- /dev/null +++ b/dom/xml/resources/jar.mn @@ -0,0 +1,7 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +toolkit.jar: + content/global/xml/XMLPrettyPrint.css (XMLPrettyPrint.css) + content/global/xml/XMLPrettyPrint.xsl (XMLPrettyPrint.xsl) diff --git a/dom/xml/resources/moz.build b/dom/xml/resources/moz.build new file mode 100644 index 0000000000..d988c0ff9b --- /dev/null +++ b/dom/xml/resources/moz.build @@ -0,0 +1,7 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +JAR_MANIFESTS += ["jar.mn"] diff --git a/dom/xml/test/file_bug293347.xml b/dom/xml/test/file_bug293347.xml new file mode 100644 index 0000000000..d041450e2f --- /dev/null +++ b/dom/xml/test/file_bug293347.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/dom/xml/test/file_bug293347xslt.xml b/dom/xml/test/file_bug293347xslt.xml new file mode 100644 index 0000000000..44df7749e0 --- /dev/null +++ b/dom/xml/test/file_bug293347xslt.xml @@ -0,0 +1,19 @@ + + + + +
+
+ +
+ + +
+
diff --git a/dom/xml/test/file_bug343870.xml b/dom/xml/test/file_bug343870.xml new file mode 100644 index 0000000000..cf9c60544c --- /dev/null +++ b/dom/xml/test/file_bug343870.xml @@ -0,0 +1,6 @@ + + +

+

+

+

diff --git a/dom/xml/test/file_bug691215.xml b/dom/xml/test/file_bug691215.xml new file mode 100644 index 0000000000..37ae932348 --- /dev/null +++ b/dom/xml/test/file_bug691215.xml @@ -0,0 +1,2 @@ + + diff --git a/dom/xml/test/mochitest.ini b/dom/xml/test/mochitest.ini new file mode 100644 index 0000000000..707122eb7b --- /dev/null +++ b/dom/xml/test/mochitest.ini @@ -0,0 +1,14 @@ +[DEFAULT] +support-files = + file_bug293347.xml + file_bug293347xslt.xml + file_bug343870.xml + file_bug691215.xml + +[test_bug232004.xhtml] +[test_bug293347.html] +[test_bug343870.xhtml] +[test_bug355213.xhtml] +[test_bug691215.html] +skip-if = + http3 diff --git a/dom/xml/test/old/books/bethlehem.gif b/dom/xml/test/old/books/bethlehem.gif new file mode 100644 index 0000000000..db41f52fb4 Binary files /dev/null and b/dom/xml/test/old/books/bethlehem.gif differ diff --git a/dom/xml/test/old/books/bill.gif b/dom/xml/test/old/books/bill.gif new file mode 100644 index 0000000000..4b00f890cb Binary files /dev/null and b/dom/xml/test/old/books/bill.gif differ diff --git a/dom/xml/test/old/books/books.js b/dom/xml/test/old/books/books.js new file mode 100644 index 0000000000..cf233a7b93 --- /dev/null +++ b/dom/xml/test/old/books/books.js @@ -0,0 +1,90 @@ +// An inefficient, but effective bubble sort +function sort(collection, key) { + var i, j; + var count = collection.length; + var parent, child; + + for (i = count - 1; i >= 0; i--) { + for (j = 1; j <= i; j++) { + if (collection[j - 1][key] > collection[j][key]) { + // Move the item both in the local array and + // in the tree + child = collection[j]; + parent = child.parentNode; + + collection[j] = collection[j - 1]; + collection[j - 1] = child; + + parent.removeChild(child); + parent.insertBefore(child, collection[j]); + } + } + } +} + +// Set user properties on the nodes in the collection +// based on information found in its children. For example, +// make a property "Author" based on the content of the +// "Author" element found in the childNode list of the node. +// This makes later sorting more efficient +function collectInfo(nodes, propNames) { + var i, j, k; + var ncount = nodes.length; + var pcount = propNames.length; + + for (i = 0; i < ncount; i++) { + var node = nodes[i]; + var childNodes = node.childNodes; + var ccount = childNodes.length; + + for (j = 0; j < ccount; j++) { + var child = childNodes[j]; + + if (child.nodeType == Node.ELEMENT_NODE) { + var tagName = child.tagName; + + for (k = 0; k < pcount; k++) { + var prop = propNames[k]; + if (prop == tagName) { + node[prop] = child.firstChild.data; + } + } + } + } + } +} + +var enabled = true; +function toggleStyleSheet() { + if (enabled) { + document.styleSheets[2].disabled = true; + } else { + document.styleSheets[2].disabled = false; + } + + enabled = !enabled; +} + +// XXX This is a workaround for a bug where +// changing the disabled state of a stylesheet can't +// be done in an event handler. For now, we do it +// in a zero-delay timeout. +function initiateToggle() { + setTimeout(toggleStyleSheet, 0); +} + +var sortableProps = new Array("Author", "Title", "ISBN"); +var books = new Array(); + +// We uppercase the tagName as a workaround for a bug +// that loses the original case of the tag. +var bookset = document.getElementsByTagName("Book"); + +// We need to create a "non-live" array to operate on. Since +// we'll be moving things around in this array, we can't use +// the read-only, live one returned by getElementsByTagName. +for (var i = 0; i < bookset.length; i++) { + books[i] = bookset[i]; +} + +collectInfo(books, sortableProps); diff --git a/dom/xml/test/old/books/books.xml b/dom/xml/test/old/books/books.xml new file mode 100644 index 0000000000..2067487d8d --- /dev/null +++ b/dom/xml/test/old/books/books.xml @@ -0,0 +1,103 @@ + + + + + + + + + +
+ + + + + + + + + + + Amazon.com Search Results for: the keywords include "Road" +
+ + + + + + On the Road + Kerouac, Jack + 0140042598 + +On The Road, the most famous of Jack Kerouac's works, is not only the soul of the Beat movement and literature, but one of the most important novels of the century. Like nearly all of Kerouac's writing, On The Road is thinly fictionalized autobiography, filled with a cast made of Kerouac's real life friends, lovers, and fellow travelers. Narrated by Sal Paradise, one of Kerouac's alter-egos, On the Road is a cross-country bohemian odyssey that not only influenced writing in the years since its 1957 publication but penetrated into the deepest levels of American thought and culture. + + $12.95 + $10.36 + + + + + The Road Ahead + Gates, Bill + 666666666 + +In a study, the founder of Microsoft presents his vision for the future in which he sees the digital technologies of the coming years changing the way we buy, work, learn, and communicate. But he doesn't mention XML! + + $15.95 + $12.76 + + + + + The Road to Wellville + Boyle, T. Coraghessan + 0140167188 + +A snobbish wife and her henpecked husband travel to Dr. Kellogg's spa in turn-of-the-century Battle Creek, where the youth-crazed affluent succumb to quackery. By the author of East is East. + + $12.95 + $10.36 + + + + + AAA Road Atlas 1999 + A. A. A. + 1562512625 + +The definitive road atlas to the United States, Canada and Mexico. + + $9.95 + $9.95 + + + + + Bethlehem Road + Perry, Anne + 0449219143 + +He might be elegant, but there's no mistaking it--the gentleman tied to the lamppost on Westminster Bridge is definitely dead. Before Inspector Thomas Pitt can even speculate on why anyone should want to kill the eminent M.P., Sir Lockwood, a colleague of his, meets the same fate at the same spot. The public is outraged, and clever Charlotte Pitt, Thomas's well-born wife, helps her hard-pressed husband by scouting society's drawing rooms for clues to these appalling crimes. Meanwhile, another victim is being stalked.... + + $6.99 + $5.59 + + + + + 84 Charing Cross Road + Hanff, Helene + 0140143505 + +84, Charing Cross Road is a charming record of bibliophilia, cultural difference, and imaginative sympathy. For 20 years, an outspoken New York writer and a rather more restrained London bookseller carried on an increasingly touching correspondence... + + $9.95 + $7.96 + + + + + + +
diff --git a/dom/xml/test/old/books/charing.gif b/dom/xml/test/old/books/charing.gif new file mode 100644 index 0000000000..9a63fb0b27 Binary files /dev/null and b/dom/xml/test/old/books/charing.gif differ diff --git a/dom/xml/test/old/books/classic.css b/dom/xml/test/old/books/classic.css new file mode 100644 index 0000000000..1ebc92f6e8 --- /dev/null +++ b/dom/xml/test/old/books/classic.css @@ -0,0 +1,78 @@ + + +BookSet { + display: block; +} + +Book { + float: left; + display: block; + width: 300px; + background-color: #f1f1f1; + border: 1px solid #cccccc; + margin-right: 8px; + margin-top: 8px; +} + +BookCover { + display: inline; + float: left; + margin-right: 10px; + padding: 5px; + width: 100px; + height: 140px; +} + +Title { + display: block; + font-weight: bold; + color: blue; + text-decoration: underline; + cursor: pointer; +} + +Author { + display: block; + font-style: italic; +} + +Synopsis { + display: block; + overflow: scroll; + height: 100px; + width: 155px; + padding: 3px; + background-color: #ddddff; +} + + +ListPrice { + display: block; + text-align: right; + padding-right: 15px; + text-decoration: line-through; +} + + +Price { + display: block; + color: rgb(20,100,0); + text-align:right; + padding-right: 15px; + font-weight: bold; +} + + +Price:before { + content: "Our Price: "; +} + +ISBN { + display: block; + font-family: monospace; + font-size: 8pt; +} + + + + diff --git a/dom/xml/test/old/books/common.css b/dom/xml/test/old/books/common.css new file mode 100644 index 0000000000..d63f09585d --- /dev/null +++ b/dom/xml/test/old/books/common.css @@ -0,0 +1,43 @@ +SearchResult { + display: block; + margin-top: 8px; + margin-left: 8px; +} + +Header { + width: 612px; + display: block; +} + +SearchTitle { + display: block; + width: 280px; + border-bottom: thin solid black; + padding-bottom: 6px; + margin-bottom: 12px; +} + +SearchTitle:first-line { + font-family: Verdana, Sans-Serif; + color: #cc6600; + font-size: 14pt; +} + +Toolbar { + font-family: Verdana, Sans-Serif; + float: right; + font-size: 7pt; + display: block; + border: ridge #ddddff 4px; + width: 220px; + margin-right: 0px; + text-align: center; +} + +Label { + font-weight: bold; +} + +input { + margin-top: 2px; +} \ No newline at end of file diff --git a/dom/xml/test/old/books/kerouac.gif b/dom/xml/test/old/books/kerouac.gif new file mode 100644 index 0000000000..df2b371d07 Binary files /dev/null and b/dom/xml/test/old/books/kerouac.gif differ diff --git a/dom/xml/test/old/books/list.css b/dom/xml/test/old/books/list.css new file mode 100644 index 0000000000..3b5d408915 --- /dev/null +++ b/dom/xml/test/old/books/list.css @@ -0,0 +1,61 @@ + +BookSet { + display: block; +} + +Book { + display: list-item; + float: none; + border: none; + background: inherit; +} + +BookCover { + display: none; +} + +Title { + display: block; + font-weight: bold; + color: blue; + text-decoration: underline; + cursor: pointer; +} + +Author { + display: block; + font-style: italic; +} + +Synopsis { + display: none; +} + + +ListPrice { + display: none; + text-align: right; + padding-right: 15px; + text-decoration: line-through; +} + + +Price { + display: block; + color: rgb(20,100,0); + font-weight: bold; + text-align:left; +} + + +Price:before { + content: "Our Price: "; +} + +ISBN { + display: block; + font-family: monospace; + font-size: 8pt; +} + + diff --git a/dom/xml/test/old/books/road.gif b/dom/xml/test/old/books/road.gif new file mode 100644 index 0000000000..5ba7920c7e Binary files /dev/null and b/dom/xml/test/old/books/road.gif differ diff --git a/dom/xml/test/old/books/welville.gif b/dom/xml/test/old/books/welville.gif new file mode 100644 index 0000000000..7ff24a99ec Binary files /dev/null and b/dom/xml/test/old/books/welville.gif differ diff --git a/dom/xml/test/old/docbook.css b/dom/xml/test/old/docbook.css new file mode 100644 index 0000000000..562c8d2133 --- /dev/null +++ b/dom/xml/test/old/docbook.css @@ -0,0 +1,621 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +Book { + display: block; + padding-left: 8px; + padding-top: 8px; + font-family: Courier; + font-size: 10pt; +} + +Abbrev { + display: block; +} + +Affiliation { + font-style: italic; +} + +Appendix Title { + font-weight: bold; + font-family: Arial; + font-size: 24pt; + margin-bottom: 10pt; + display: block; +} + +Para Author { + display: inline; +} + +Author { + display: block; +} + +AuthorGroup { + font-size: 12pt; + margin-top: 25pt; + display: block; + font-weight: bold; +} + +BiblioDiv Title { + font-style: italic; +} + +Blockquote { + display: block; + margin-top: 3pt; + margin-left: 30pt; +} + +Book Title { + font-weight: bold; + font-family: Arial; + font-size: 18pt; + margin-bottom: 10pt; + display: block; +} + +BookInfo { + display: block; + margin-bottom: 30pt; +} + +BridgeHead { + display: block; + font-size: 16pt; + font-weight: bold; + color: teal; +} + +Caution { + font-weight: bold; + color: red; +} + +Caution:before { + content: "Caution:"; +} + +Chapter { + display: block; + margin-bottom: 25pt; +} + +Chapter Title { + font-weight: bold; + font-family: Arial; + font-size: 20pt; + margin-bottom: 10pt; + display: block; +} + +CiteTitle { + font-style: italic; +} + +CmdSynopsis { + display: block; +} + +CO { + display: block; +} + +Command { + font-style: italic; +} + +Comment { + display: block; +} + +ComputerOutput { + font-family: monospace; +} + +Copyright { + display: block; +} + +Para CorpAuthor { + display: inline; +} + +CorpAuthor { + display: block; +} + +Email { + font-style: italic; +} + +Editor { + display: block; +} + +Emphasis { + font-style: italic; +} + +ErrorType { + font-family: monospace; +} + +Example { + display: block; + margin-top: 10pt; + margin-bottom: 10pt; +} + +Example Title { + display: block; + font-weight: bold; + font-size: 14pt; +} + +Figure Title { + font-family: Arial; + font-size: 10pt; + font-style: italic; + font-weight: bold; + display: block; +} + +Filename { + font-style: italic; +} + +Figure { + display: block; + margin-top: 10pt; +} + +FirstTerm { + font-style: italic; +} + +ForeignPhrase { + font-style: italic; +} + +FormalPara { + display: block; +} + +FormalPara Title { + display: block; + font-weight: bold; +} + +FuncSynopsis { + display: block; +} + +FuncSynopsisInfo { + display: block; + white-space: pre; +} + +Function { + font-family: monospace; + white-space: pre; +} + +Glossary { + display: block; +} + +GlossDef { + display: block; + margin-left: 15pt; +} + +GlossList { + display: block; +} + +GlossSee { + display: block; + margin-left: 15pt; +} + +GlossTerm { + display: block; + font-weight: bold; +} + +InformalTable { + display: block; + margin-top: 10pt; + margin-bottom: 10pt; +} + +Interface { + font-family: Arial; +} + +ISBN { + display: block; + font-size: 10pt; +} + +ItemizedList { + display: block; + margin-top: 5pt; + margin-left: 20pt; +} + +LineAnnotation { + font-style: italic; +} + +Link { + color: blue; + text-decoration: underline; +} + +ListItem { + margin-left: 25pt; + display: list-item; +} + +Literal { + font-family: monospace; +} + +LiteralLayout { + white-space: pre; + display: block; +} + +Member { + display: block; + margin-left: 15pt; +} + +OLink { + display: block; + font-size: 12pt; +} + +Option { + font-family: monospace; +} + +OrderedList { + margin-top: 5pt; + margin-left: 20pt; + margin-bottom: 10pt; + display: block; + list-style-type: decimal; +} + +OrderedList Para { + display: block; + margin-top: 15pt; +} + +Para OtherCredit { + display: inline; +} + +OtherCredit { + display: block; +} + +Para { + display: block; + margin-top: 8pt; +} + +Para LiteralLayout { + display: block; + margin-top: 4pt; + margin-left: 10pt; + white-space: pre; +} + +Para Screen { + margin-top: 7pt; + margin-left: 10pt; + margin-bottom: 7pt; + display: block; +} + +Parameter { + font-family: monospace; +} + +Part Title { + font-size: 24pt; + display: block; + font-weight: bold; +} + +Preface { + display: block; + margin-top: 10pt; +} + +Procedure { + display: block; +} + +ProgramListing { + display: block; + white-space: pre; + font-family: monospace; +} + +ProgramListingCO { + display: block; + white-space: pre; + font-family: monospace; +} + +PublisherName { + font-family: Times, New, Roman; + font-size: 20pt; + margin-top: 15pt; + margin-bottom: 15pt; + display: block; +} + +RefEntry { + display: block; +} + +RefEntryTitle { + display: block; + font-size: 20pt; + font-weight: bold; +} + +RefName { + font-weight: bold; +} + +RefNameDiv { + display: block; +} + +RefSect1 { + display: block; + margin-top: 10pt; +} + +RefSect1 Title { + font-size: 14pt; +} + +RefSect1Info { + display: block; + font-size: small; +} + +RefSect2 { + display: block; + margin-top: 10pt; +} + +RefSect2 Title { + font-size: 14pt; +} + +RefSect2Info { + display: block; + font-size: small; +} + +RefSect3 { + display: block; + margin-top: 10pt; +} + +RefSect3 Title { + font-size: 14pt; +} + +RefSect3Info { + display: block; + font-size: small; +} + +RefSynopsisDiv { + display: block; + margin-top: 15pt; +} + +RefSynopsisDiv Title { + display: block; + font-size: 18pt; +} + +Replaceable { + font-family: Arial; + font-style: italic; +} + +Screen { + display: block; + margin-left: 20pt; + margin-bottom: 10pt; + white-space: pre; +} + +ScreenCO { + white-space: pre; +} + +ScreenShot { + white-space: pre; +} + +Sect1 { + display: block; + margin-top: 16pt; +} + +Sect1 Title { + font-family: Arial; + font-size: 20pt; + font-weight: bold; + display: block; +} + +Sect2 { + display: block; + margin-top: 15pt; +} + +Sect2 Title { + font-family: Arial; + font-size: 14pt; + font-weight: bold; + display: block; +} + +Sect3 { + display: block; + margin-top: 15pt; +} + +Sect3 Title { + font-family: Arial; + font-size: 14pt; + font-weight: bold; + display: block; +} + +SegListItem { + display: block; +} + +SegmentedList { + display: block; +} + +SegmentedList Title { + display: block; + font-weight: bold; +} + +Sidebar { + display: block; + margin-top: 15pt; + margin-left: 30pt; + font-family: Arial; + font-size: 9pt; +} + +Step { + display: block; +} + +Step Title { + display: block; + font-style: italic; +} + +Subscript { + font-size: 5pt; + vertical-align: sub; +} + +Subtitle { + font-family: Arial; + font-size: 20pt; + font-weight: bold; + display: block; + text-align: center; +} + +Superscript { + font-size: 5pt; + vertical-align: super; +} + +Synopsis { + display: block; + white-space: pre; +} + +SystemItem { + font-family: monospace; +} + +Table { + display: block; + margin-top: 10pt; +} + +Table Title { + font-family: Arial; + font-size: 10pt; + font-style: italic; + font-weight: bold; +} + +Term { + font-weight: bold; +} + +Title { + font-family: Arial; + font-size: 20pt; + font-weight: bold; + display: block; + text-align: center; +} + +TitleAbbrev { + font-family: Arial; + font-size: 14pt; + font-weight: bold; + display: block; +} + +ULink { + color: blue; + text-decoration: underline; + cursor: pointer; +} + +UserInput { + font-family: monospace; + font-weight: bold; +} + +VariableList Title { + font-weight: bold; + display: block; +} + +VarListEntry { + display: block; + margin-top: 10pt; +} + +VarListEntry Term { + display: block; + font-style: italic; +} + +Warning { + font-weight: bold; + color: fuchsia; +} + +Warning:before { + content: "Warning:"; +} + + +Year { + font-family: serif; + font-weight: bold; +} diff --git a/dom/xml/test/old/docbooktest.xml b/dom/xml/test/old/docbooktest.xml new file mode 100644 index 0000000000..d47c3cb12e --- /dev/null +++ b/dom/xml/test/old/docbooktest.xml @@ -0,0 +1,126 @@ + + + + +SoftQuad +Inc. +

+ + + +

+ Demo Product Documentation +SoftQuad Inc. + <Anchor +Id="SDK3"/>Element Overview +Introduction to Elements +By far the vast majority of objects (apart from text) that authors +encounter when traversing a document are Element nodes. + <Anchor Id="SDK273"/>Element Interfaces + <Anchor Id="SDK274"/>Elements and +Attributes + <Anchor Id="SDK279"/>Introduction to Attributes + +Elements may have attributes associated with them; since the Element +interface inherits from Node, the generic Node interface method +getAttributes may be used to retrieve the set of all +attributes for an element. +There are methods on the Element interface to retrieve either an Attr +object by name or an attribute value by name. In XML, where an attribute value +may contain entity references, an Attr object should be retrieved to examine +the possibly fairly complex sub-tree representing the attribute value. On the +other hand, in HTML, where all attributes have simple string values, methods to +directly access an attribute value can safely be used as a convenience. + +Before you can access an Attribute, you must first gain access to the +associated Element. + <Anchor Id="SDK378"/>Setting the Attribute +Values +Attr objects inherit the Node interface, but since they are not actually +child nodes of the element they describe, the DOM does not consider them part +of the document tree. Thus, the Node attributes parentNode, previousSibling, +and nextSibling have a null value for Attr objects. The DOM takes the view that +attributes are properties of elements rather than having a separate identity +from the elements they are associated with; this should make it more efficient +to implement such features as default attributes associated with all elements +of a given type. Furthermore, Attr nodes may not be immediate children of a +DocumentFragment. However, they can be associated with Element nodes contained +within a DocumentFragment. In short, users and implementors of the DOM need to +be aware that Attr nodes have some things in common with other objects +inheriting the Node interface, but they also are quite distinct. +The attribute's effective value is determined as follows: + +If this attribute has been explicitly assigned any value, that value is +the attribute's effective value +Otherwise, if there is a declaration for this attribute, and that +declaration includes a default value, then that default value is the +attribute's effective value +Otherwise, the attribute does not exist on this element in the structure +model until it has been explicitly added. +In XML, where the value of an attribute can contain entity references, +the child nodes of the Attr node provide a representation in which entity +references are not expanded. These child nodes may be either Text or +EntityReference nodes. Because the attribute type may be unknown, there are no +tokenized attribute values. +The following topics describe DOM attributes: + + +Interface +Attr + + +Interface Element + + <Anchor +Id="SDK48"/>DOM Level 1 Core: Element Functions + setAttribute + setAttribute +Sets the Attributes on the associated Element object +Fundamental +<Anchor Id="SDK85"/>Syntax + OMG IDL +void setAttribute (in +DOMString name, in DOMString +value) raises (DOMException); + <Anchor Id="SDK86"/>Java +public void setAttribute ( +String name, String +value) throws (DOMException); + <Anchor Id="SDK87"/>ECMA Script + + setAttribute (name, value +) +<Anchor Id="SDK88"/>Parameters + name + +(IN) The name of the attribute to create or alter. + value + +(IN) Value to set in string form + <Anchor Id="SDK89"/>Exceptions + +These are the applicable exceptions. + + + +INVALID_CHARACTER_ERR +Raised if the specified name contains an invalid character. + + NO_MODIFICATION_ALLOWED_ERR +Raised if this node is readonly. + + <Anchor +Id="SDK90"/>Remarks + setAttribute adds a new attribute. If an attribute +with that name is already present in the element, its value is changed to be +that of the value parameter. This value is a simple string, it is not parsed as +it is being set. So any markup (such as syntax to be recognized as an entity +reference) is treated as literal text, and needs to be appropriately escaped by +the implementation when it is written out. + In order to assign an attribute value that contains entity references, +the user must create an Attr node plus any Text and EntityReference nodes, +build the appropriate subtree, and use setAttributeNode to +assign it as the value of an attribute. +
diff --git a/dom/xml/test/old/flamer.gif b/dom/xml/test/old/flamer.gif new file mode 100644 index 0000000000..5a05df583f Binary files /dev/null and b/dom/xml/test/old/flamer.gif differ diff --git a/dom/xml/test/old/script.xml b/dom/xml/test/old/script.xml new file mode 100644 index 0000000000..f21d30d973 --- /dev/null +++ b/dom/xml/test/old/script.xml @@ -0,0 +1,67 @@ + + + + + The Book + + Chapter 1. + Yada yada yada. + + +"); + + // get the children + var children = node.childNodes; + var length = children.length; + var count = 0; + while(count < length) { + child = children[count]; + list(child); + count++; + } + dump(""); + } + else { + // close tag + dump("/>"); + } + + + } + // if it's a piece of text just dump the text + else if (type == Node.TEXT_NODE) { + dump(node.data); + } +} + +list(document.documentElement); +dump("\n"); +]]> + + diff --git a/dom/xml/test/old/simple.xml b/dom/xml/test/old/simple.xml new file mode 100644 index 0000000000..c94708c665 --- /dev/null +++ b/dom/xml/test/old/simple.xml @@ -0,0 +1,10 @@ + + + + + The Book + + Chapter 1. + Yada yada yada. + + diff --git a/dom/xml/test/old/toc/book.css b/dom/xml/test/old/toc/book.css new file mode 100644 index 0000000000..778c4244c2 --- /dev/null +++ b/dom/xml/test/old/toc/book.css @@ -0,0 +1,137 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* The book style must be the first style for our JavaScript to work */ +book { + display: block; + padding-left: 2em; + padding-right: 2em; + padding-top: 8px; + font-size: 12pt; + background-color: lightyellow; + font-family: Arial; +} + +book title { + font-weight: bold; + font-size: 24pt; + display: block; + text-align: center; + margin-top: 12pt; + margin-bottom: 3pt; +} + +book subtitle { + display: block; + font-size:12pt; + text-align: center; +} + +book abstract { + display: block; + margin-top: 3pt; +} + +input { + display: block; + margin-left: auto; + margin-right: auto; +} + +chapter { + display: block; +} + +chapter title { + font-weight: bold; + font-size: 16pt; + display: block; + text-align: left; + margin-top: 12pt; + margin-bottom: 3pt; +} + +section { + display: block; +} + +section title { + display: block; + font-size: 10pt; + text-align: left; + margin-top: 12pt; + margin-bottom: 3pt; +} + +contents { + display: block; +} + +para { + display: block; + margin-bottom: auto; + margin-top: auto; + font-size:11pt; +} + +link { + display: inline; + color: blue; + text-decoration: underline; + cursor: pointer; +} + +list { + display: block; + margin-right: 0; + margin-bottom: auto; + margin-top: auto; + list-style-type: disc; + margin-left: 40px; +} + +listitem { + display: list-item; + list-style-position: inside; +} + +emph { + font-style: italic; + font-weight: bold; +} + +ref { + font-style: italic; +} + +heading { + font-weight: bold; +} + +navbar { + font-family: Arial; + font-size: 10pt; + display: block; + float: right; + background-color: #CCE6F3; + color: darkblue; + width: 10em; + margin-right: 0.5em; +} + +navbar title { + font-size: 10pt; + display: block; + background-color: black; + color: white; + margin-bottom:0px; +} + +navbar content { + display: block; + padding: 0.3em; + border: 1px solid black; + font-size: 9pt; +} + diff --git a/dom/xml/test/old/toc/irslogo.gif b/dom/xml/test/old/toc/irslogo.gif new file mode 100644 index 0000000000..daab0ca3ab Binary files /dev/null and b/dom/xml/test/old/toc/irslogo.gif differ diff --git a/dom/xml/test/old/toc/minus.gif b/dom/xml/test/old/toc/minus.gif new file mode 100644 index 0000000000..8adf8d6add Binary files /dev/null and b/dom/xml/test/old/toc/minus.gif differ diff --git a/dom/xml/test/old/toc/plus.gif b/dom/xml/test/old/toc/plus.gif new file mode 100644 index 0000000000..55446e34c9 Binary files /dev/null and b/dom/xml/test/old/toc/plus.gif differ diff --git a/dom/xml/test/old/toc/rights.xml b/dom/xml/test/old/toc/rights.xml new file mode 100644 index 0000000000..520eef3de1 --- /dev/null +++ b/dom/xml/test/old/toc/rights.xml @@ -0,0 +1,292 @@ + + + + + + + +]> + + + + + + Table of contents + + To toggle the Table of Contents, click on this button + + + + + Highlights of 1999 Tax Changes + (Rev. December 1999) + + + + Tax Changes for Individuals + +
+ + Child Tax Credit Increased + + +The maximum child tax credit for each qualifying child will increase from $400 to $500 in 1999. + + +
+
+ + Standard Mileage Rate + + +Beginning April 1, 1999, the optional standard mileage rate for operating your carfor business decreases to 31 cents a mile for each business mile. Until then, the business standard mileage rate of 32 1/2 cents per mile that was in effect for 1998 will continue to apply. + + +
+
+ + Estimated Tax Safe Harbor for Higher Income Individuals + + +For estimated tax payments for tax years beginning in 1999, the safe harbor for higher income individuals (other than farmers and fishermen) has been modified. If your 1998 adjusted gross income was more than $150,000 ($75,000 if you aremarried filing a separate return for 1999), you will have to pay the smaller of 90% of your expected tax for 1999 or 105% (up from 100%) of the tax shown on your 1998 return (provided your 1998 return covered all 12 months) to avoid an estimated tax penalty. + + +For more information on estimated tax, see + Publication 505. + + +
+
+ + Self-Employed Health Insurance Deduction + + +For 1999, the health insurance deduction for the self-employed is increased from 45% to 60% of the amount you pay for medical insurance for yourself and your family. For more information, see chapter 10 in + Publication 535. + + +
+
+ + Social Security and Medicare Taxes + + +For 1999, the employer and employee will continue to pay: + + +1.6.2% each for social security tax (old-age, survivors, and disability insurance), and + + +2.1.45% each for Medicare tax (hospital insurance). + + + + + Wage limits. +For social security tax, the maximum amount of 1999 wages subject to the tax has increased to $72,600. For Medicare tax, all covered 1999 wages are subject to the tax. There is no wage base limit. For information about these taxes, see + Publication 15, Circular E, Employer's Tax Guide. + + +
+
+ + Self-Employment Tax + + +The self-employment tax rate on net earnings remains the same for calendar year1999. This rate, 15.3%, is a total of 12.4% for social security (old-age, survivors, and disability insurance), and 2.9% for Medicare (hospital insurance). + + +The maximum amount subject to the social security part for tax years beginning in 1999 has increased to $72,600. All net earnings of at least $400 are subject to the Medicare part. + + +
+
+
+ + + + Tax Changes for Businesses + +
+ + Social Security and Medicare Taxes + + +For 1999, the employer and employee will continue to pay: + + +6.2% each for social security tax (old-age, survivors, and disability insurance), and + + +1.45% each for Medicare tax (hospital insurance). + + + + +Wage limits. For social security tax, the maximum amount of 1999 wages subject to the tax has increased to $72,600. For Medicare tax, all covered 1999 wages are subject to the tax. There is no wage base limit. For information about these taxes and amounts to withhold, see +Publication 15, Circular E, Employer's TaxGuide. + + +
+
+ + Employment Tax Deposits + + +Under certain circumstances, the IRS can waive the penalty for a first-time depositor's inadvertent failure to timely deposit employment taxes. For deposits required to be made after January 18, 1999, this waiver is expanded to include the first deposit required to be made after a required change in frequency of a taxpayer's deposits. + + +
+
+ + Electronic Deposit of Taxes + + +If you were first required to deposit taxes by electronic funds transfer after June 30, 1997, the IRS will not impose the penalty for not doing so before July 1, 1999. Previously, the IRS had waived the penalty through December 31, 1998. For information about depositing taxes electronically, see Publication 15. + + +
+
+ + 941 TeleFile + + +Beginning with the first quarter of 1998, many employers were able to file Form941 by phone, toll free. If you receive 941 TeleFile with your Form 941 package, check page TEL-1 of the 941 TeleFile Instructions to see if you qualify for this quick, convenient, and easy method of filing. + + +
+
+ + 941 On-Line + + +In 1998, a limited number of employers were allowed to file Form 941 using commercially available software to create the return and then transmitting the return electronically to IRS through a third party. 941 On-Line uses Electronic Data Interchange (EDI) format. In 1999, IRS expects to make the 941 On-Line filing option available nationwide. + + +
+
+ + Self-Employment Tax + + +The self-employment tax rate on net earnings remains the same for calendar year 1999. This rate, 15.3%, is a total of 12.4% for social security (old-age, survivors,and disability insurance), and 2.9% for Medicare (hospital insurance). + + +The maximum amount subject to the social security part for tax years beginning in 1999 has increased to $72,600. All net earnings of at least $400 are subject to the Medicare part. + + +
+
+
+ + + + IRA and other Retirement Plans + +
+ + Hardship Distributions + + +Beginning in 1999, hardship distributions from 401(k) plans and 403(b) plans are not eligible rollover distributions. They cannot be rolled over into a traditional IRA. For more information on traditional IRAs, see Publication 590. + + +
+
+
+ + + + Gift and Estate Taxes + +
+ + New Deduction From Gross Estate + + +For estates of decedents dying after 1997, the executor can elect to deduct the adjusted value of a qualified family-owned business interest, up to a limited amount, from the gross estate. For more information, see section 2057 of the Internal Revenue Code and the instructions for Schedule T, Form 706, United States Estate (and Generation-Skipping Transfer) Tax Return. + + +
+
+ + Suit for Refund + + +Effective July 23, 1998, an executor no longer needs to wait until all the installment payments have been made before filing a suit for refund with a federal district court or the U.S. Court of Federal Claims if the following conditions are met. + + +The estate consists largely of an interest in a closely-held business. + + +The estate elected to make tax payments through the installment method. + + + + +However, all of the following must be true before a suit can be filed. + + +All installment payments due on or before the date the suit is filed have been made. + + +No accelerated installment payments have been made. + + +No Tax Court case is pending with respect to any estate tax liability. + + +The time for petitioning the Tax Court has passed if a notice of deficiency was issued to the estate regarding its liability for estate tax. + + +No proceeding is pending for a declaratory judgment by the Tax Court on whether the estate is eligible to pay tax in installments. + + + + +In addition, the executor must not: + + +Include any previously litigated issues in the current suit for refund, and + + +Discontinue making timely installment payments while the court considers the suit for refund. + + + + +
+
+
+ + + + Excise Tax + +
+ + Air Transportation Taxes + + +For 1999, the tax on the use of international air travel facilities will be $12.20 for both arrivals and departures. In the case of air transportation between the continental United States and Alaska or between Alaska and Hawaii, the use-of-international-facilities tax on departures will be $6.10. + + +
+
+ + Luxury Tax + + +For 1999, the luxury tax on a passenger vehicle is reduced from 7% to 6% of the amount of the sales price that exceeds the base amount. The base amount for 1999 is $36,000. + + +The base amount is increased for electric vehicles and clean-fuel vehicles. See Publication 510 for information on these amounts. + + +
+
+
+ +
diff --git a/dom/xml/test/old/toc/toc.css b/dom/xml/test/old/toc/toc.css new file mode 100644 index 0000000000..99c0c9d327 --- /dev/null +++ b/dom/xml/test/old/toc/toc.css @@ -0,0 +1,77 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +toc { + position:fixed; + top:0; + left:0; + width:12em; + height:100%; + border-right: 1px solid black; + background-color: #CCE6F3; + font-family: Arial; + overflow:auto; + color: darkblue; +} + +toc > title { + display: block; + font-size:12pt; + font-weight: bold; + background-color: black; + color:white; +} + +toclink:visited { + color: purple; +} + +toclink:active { + color: red; +} + +level1 { + display: block; + font-weight:bold; + font-size:12pt; + margin-left: 4px; + margin-bottom: 2px; +} + +level1 > toclink { + list-style-position: inside; + text-decoration: none; + color: darkblue; +} + +level2 { + display: block; + font-size:11pt; + margin-left: 8px; + margin-bottom: 2px; +} + +level2 > toclink { + list-style-position: inside; + text-decoration: none; + color: darkblue; +} + +level3 { + display: list-item; + font-size: 8pt; + margin-left: 12px; + margin-bottom: 2px; +} + +level3 > toclink { + list-style-position: inside; + text-decoration: none; + color: darkblue; +} + +toc img { + margin-right: 1em; +} + diff --git a/dom/xml/test/old/toc/toc.js b/dom/xml/test/old/toc/toc.js new file mode 100644 index 0000000000..b1cfbc4959 --- /dev/null +++ b/dom/xml/test/old/toc/toc.js @@ -0,0 +1,131 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Event handler for display togglers in Table of Contents +function toggleDisplay(event) { + if (event.target.localName != "img") { + return; + } + var img = event.target; + var div = img.nextSibling.nextSibling; + + // Change the display: property of the container to + // hide and show the container. + if (div.style.display == "none") { + div.style.display = "block"; + img.src = "minus.gif"; + } else { + div.style.display = "none"; + img.src = "plus.gif"; + } +} + +// Function that recurses down the tree, looking for +// structural elements. For each structural element, +// a corresponding element is created in the table of +// contents. +var searchTags = new Array("book", "chapter", "section"); +var tocTags = new Array("level1", "level2", "level3"); +function addToToc(root, tocFrame) { + var i; + var newTocFrame = tocFrame; + var newTocElement = null; + var newTocLink = null; + + for (i = 0; i < searchTags.length; i++) { + if (root.tagName == searchTags[i]) { + // If we've found a structural element, create the + // equivalent TOC element. + newTocElement = document.createElement(tocTags[i]); + // Create the toclink element that is a link to the + // corresponding structural element. + newTocLink = document.createElement("toclink"); + newTocLink.setAttributeNS( + "http://www.w3.org/1999/xlink", + "xlink:type", + "simple" + ); + newTocLink.setAttributeNS( + "http://www.w3.org/1999/xlink", + "xlink:href", + "#" + root.getAttribute("id") + ); + newTocLink.setAttributeNS( + "http://www.w3.org/1999/xlink", + "xlink:show", + "replace" + ); + newTocElement.appendChild(newTocLink); + + // Create the image and toggling container in the table of contents + if (i < searchTags.length - 1) { + var img = document.createElementNS( + "http://www.w3.org/1999/xhtml", + "img" + ); + img.src = "minus.gif"; + newTocElement.insertBefore(img, newTocLink); + + newTocFrame = document.createElementNS( + "http://www.w3.org/1999/xhtml", + "div" + ); + newTocElement.appendChild(newTocFrame); + } else { + newTocFrame = null; + } + + tocFrame.appendChild(newTocElement); + + break; + } + } + + // Recurse down through the childNodes list + for (i = 0; i < root.childNodes.length; i++) { + var child = root.childNodes[i]; + if (child.nodeType == Node.ELEMENT_NODE) { + if (newTocLink != null && child.tagName == "title") { + var text = child.firstChild.cloneNode(true); + newTocLink.appendChild(text); + } else { + addToToc(child, newTocFrame); + } + } + } +} + +// Create the root table of contents element (a fixed element) +// and its contents. +function createToc() { + if (!document.getElementsByTagName("toc").length) { + var toc = document.createElement("toc"); + var title = document.createElement("title"); + title.appendChild(document.createTextNode("Table of Contents")); + toc.appendChild(title); + + // Recurse down and build up the document element + addToToc(document.documentElement, toc); + + // Since we've created the toc element as a fixed element, + // insert a rule that shifts over the document element by + // the width of the toc element. + document.styleSheets[0].cssRules[0].style.marginLeft = "12em"; + document.documentElement.appendChild(toc); + + // Attach the event handler for table of contents buttons. + // This will only work for content that is already a part + // of a document, which is why we had to wait until here + // to do this. + toc.addEventListener("mouseup", toggleDisplay, 1); + } else { + // Hide the table of contents. + // This is not very intelligent if we have a static document, we should + // just hide/show the toc via stylesheet mungling + document.documentElement.removeChild( + document.getElementsByTagName("toc")[0] + ); + document.styleSheets[0].cssRules[0].style.marginLeft = "0em"; + } +} diff --git a/dom/xml/test/old/xlink/auto.xml b/dom/xml/test/old/xlink/auto.xml new file mode 100644 index 0000000000..91eb15ff43 --- /dev/null +++ b/dom/xml/test/old/xlink/auto.xml @@ -0,0 +1,16 @@ + + + +

Testing simple XLinks that must fire immediately on load.

+ +Must not open automatically, illegal + +Must open automatically in new window (www.mozilla.org) + +Must open automatically in new window (www.mozillazine.org) + +Must load automatically in same window - "Refresh" (At a glance) + +Must not load automatically, one refresh link fired already (www.netscape.com) +
+ diff --git a/dom/xml/test/old/xlink/link.css b/dom/xml/test/old/xlink/link.css new file mode 100644 index 0000000000..19dc52198d --- /dev/null +++ b/dom/xml/test/old/xlink/link.css @@ -0,0 +1,22 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +@namespace xlink url(http://www.w3.org/1999/xlink); + +root { + display: block; + padding: +5px; +} + +p { + display: block; +} + +mylink { + display: block; + cursor: pointer; + color: blue; + text-decoration: underline; +} + diff --git a/dom/xml/test/old/xlink/manual.xml b/dom/xml/test/old/xlink/manual.xml new file mode 100644 index 0000000000..fd7d49fc17 --- /dev/null +++ b/dom/xml/test/old/xlink/manual.xml @@ -0,0 +1,14 @@ + + + +

Testing manual simple XLinks.

+ +Must not open, illegal + +Must open in new window (www.mozilla.org) + +Must open in same window (www.mozillazine.org) + +Foo +
+ diff --git a/dom/xml/test/old/xmlbase/xmlbase.css b/dom/xml/test/old/xmlbase/xmlbase.css new file mode 100644 index 0000000000..a100186bbc --- /dev/null +++ b/dom/xml/test/old/xmlbase/xmlbase.css @@ -0,0 +1,28 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +@namespace xlink url(http://www.w3.org/1999/xlink); + +title { + font-weight: bold; + display: block; +} + +xlink|link { + color: blue; + text-decoration: underline; + cursor: pointer; + display: inline; + padding-left: +5px; +} + +sect1,sect2,sect3 { + display: block; + padding-left: +20px; +} + +p { + display: block; + padding-left: +5px; +} \ No newline at end of file diff --git a/dom/xml/test/old/xmlbase/xmlbase.xml b/dom/xml/test/old/xmlbase/xmlbase.xml new file mode 100644 index 0000000000..b4cce1dc51 --- /dev/null +++ b/dom/xml/test/old/xmlbase/xmlbase.xml @@ -0,0 +1,82 @@ + + + +Root: no xml:base +a.xml +

Expected: <current path>/a.xml

+ + Sect1: xml:base="http://www.mozilla.org" + b.xml +

Expected: http://www.mozilla.org/b.xml

+ + Sect2: xml:base="/base" + c.xml +

Expected: http://www.mozilla.org/base/c.xml

+ + Sect3: xml:base="" + d.xml +

Expected: http://www.mozilla.org/base/d.xml

+
+ + Sect3: xml:base="/" + d-2.xml +

Expected: http://www.mozilla.org/d-2.xml

+
+ + Sect3: xml:base="/foobar" + e.xml +

Expected: http://www.mozilla.org/foobar/e.xml

+
+ + Sect3: xml:base="ding/dong" + f.xml +

Expected: http://www.mozilla.org/base/ding/dong/f.xml

+
+
+ + Sect2: xml:base="http://www.netscape.com" + g.xml +

Expected: http://www.netscape.com/g.xml

+
+ + Sect2: xml:base="http://www.netscape.com" + http://www.mozilla.org/foobar/h.xml +

Expected: http://www.mozilla.org/foobar/h.xml

+
+ + Sect2: xml:base="http://www.netscape.com" + i.xml, this element has xml:base="wow" +

Expected: http://www.netscape.com/wow/i.xml

+
+
+ + Sect1: xml:base="nothere" + j.xml +

Expected: <current path>/nothere/j.xml

+
+ + Sect1: xml:base="/not" + k.xml +

Expected: file:///not/k.xml

+
+ + Sect1: xml:base="http://foobar.com/ä ö/" + l.xml +

Expected: http://foobar.com/%E4%20%F6/l.xml

+
+ + Sect1: xml:base="http://foobar.com/ /%20/" + m.xml +

Expected: http://foobar.com/%20/%20/m.xml

+
+ + Sect1: xml:base="chrome://navigator" + n.xml +

Expected: |current path|/n.xml because chrome URL is not allowed

+ + Sect2: xml:base="http://www.mozilla.org" + o.xml, this element has xml:base="chrome://navigator" +

Expected: http://www.mozilla.org/o.xml because chrome base is not allowed

+
+
+
\ No newline at end of file diff --git a/dom/xml/test/test_bug232004.xhtml b/dom/xml/test/test_bug232004.xhtml new file mode 100644 index 0000000000..a15129a71e --- /dev/null +++ b/dom/xml/test/test_bug232004.xhtml @@ -0,0 +1,38 @@ + + + + Test for Bug 232004 + + + + + + diff --git a/dom/xml/test/test_bug293347.html b/dom/xml/test/test_bug293347.html new file mode 100644 index 0000000000..6db99bdaa3 --- /dev/null +++ b/dom/xml/test/test_bug293347.html @@ -0,0 +1,33 @@ + + + + + Test for Bug 293347 + + + + +Mozilla Bug 293347 +

+
+
+
+
+ + diff --git a/dom/xml/test/test_bug343870.xhtml b/dom/xml/test/test_bug343870.xhtml new file mode 100644 index 0000000000..7fa625211b --- /dev/null +++ b/dom/xml/test/test_bug343870.xhtml @@ -0,0 +1,39 @@ + + + + Test for Bug 343870 + + + + +Mozilla Bug 343870 +

+ +
+
+
+ + + + diff --git a/dom/xml/test/test_bug355213.xhtml b/dom/xml/test/test_bug355213.xhtml new file mode 100644 index 0000000000..3376a4b8b3 --- /dev/null +++ b/dom/xml/test/test_bug355213.xhtml @@ -0,0 +1,35 @@ + + + + Test for Bug 355213 + + + + +Mozilla Bug 355213 +

+ +
+
+
+ + + diff --git a/dom/xml/test/test_bug691215.html b/dom/xml/test/test_bug691215.html new file mode 100644 index 0000000000..70a5f7b719 --- /dev/null +++ b/dom/xml/test/test_bug691215.html @@ -0,0 +1,53 @@ + + + + + Test for Bug 691215 + + + + +Mozilla Bug 691215 +

+ +
+
+
+ + -- cgit v1.2.3