From 5f8de423f190bbb79a62f804151bc24824fa32d8 Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Fri, 2 Feb 2018 04:16:08 -0500 Subject: Add m-esr52 at 52.6.0 --- dom/xml/CDATASection.cpp | 69 + dom/xml/CDATASection.h | 79 + dom/xml/ProcessingInstruction.cpp | 133 ++ dom/xml/ProcessingInstruction.h | 85 + dom/xml/XMLDocument.cpp | 625 +++++++ dom/xml/XMLDocument.h | 110 ++ dom/xml/XMLStylesheetProcessingInstruction.cpp | 196 +++ dom/xml/XMLStylesheetProcessingInstruction.h | 93 + dom/xml/crashtests/1038887.xhtml | 1 + dom/xml/crashtests/136896-1.xml | 62 + 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.xul | 5 + dom/xml/crashtests/420429.xul | 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 | 12 + dom/xml/crashtests/tree.gif | Bin 0 -> 1140 bytes dom/xml/htmlmathml-f.ent | 2164 ++++++++++++++++++++++++ dom/xml/moz.build | 46 + dom/xml/nsIXMLContentSink.h | 57 + dom/xml/nsXMLContentSink.cpp | 1590 +++++++++++++++++ dom/xml/nsXMLContentSink.h | 204 +++ dom/xml/nsXMLElement.cpp | 32 + dom/xml/nsXMLElement.h | 44 + dom/xml/nsXMLFragmentContentSink.cpp | 431 +++++ dom/xml/nsXMLPrettyPrinter.cpp | 268 +++ dom/xml/nsXMLPrettyPrinter.h | 59 + dom/xml/resources/XMLMonoPrint.css | 11 + dom/xml/resources/XMLPrettyPrint.css | 41 + dom/xml/resources/XMLPrettyPrint.xml | 43 + dom/xml/resources/XMLPrettyPrint.xsl | 137 ++ dom/xml/resources/jar.mn | 9 + dom/xml/resources/moz.build | 7 + dom/xml/test/file_bug293347.xml | 2 + dom/xml/test/file_bug293347xslt.xml | 19 + dom/xml/test/file_bug392338.js | 22 + dom/xml/test/mochitest.ini | 15 + 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 | 97 ++ 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/load/display.css | 298 ++++ dom/xml/test/old/load/display.xml | 9 + dom/xml/test/old/load/load.html | 56 + dom/xml/test/old/load/loadauth.html | 57 + dom/xml/test/old/load/loaddisplay.html | 56 + dom/xml/test/old/load/test.xml | 7 + 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 | 117 ++ 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_bug392338.html | 42 + dom/xml/test/test_bug399502.xhtml | 41 + dom/xml/test/test_bug445330.html | 55 + dom/xml/test/test_bug691215.html | 52 + dom/xml/test/test_viewport.xhtml | 57 + 86 files changed, 9632 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/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.xul create mode 100644 dom/xml/crashtests/420429.xul 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/XMLMonoPrint.css create mode 100644 dom/xml/resources/XMLPrettyPrint.css create mode 100644 dom/xml/resources/XMLPrettyPrint.xml 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_bug392338.js 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/load/display.css create mode 100644 dom/xml/test/old/load/display.xml create mode 100644 dom/xml/test/old/load/load.html create mode 100644 dom/xml/test/old/load/loadauth.html create mode 100644 dom/xml/test/old/load/loaddisplay.html create mode 100644 dom/xml/test/old/load/test.xml 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_bug392338.html create mode 100644 dom/xml/test/test_bug399502.xhtml create mode 100644 dom/xml/test/test_bug445330.html create mode 100644 dom/xml/test/test_bug691215.html create mode 100644 dom/xml/test/test_viewport.xhtml (limited to 'dom/xml') diff --git a/dom/xml/CDATASection.cpp b/dom/xml/CDATASection.cpp new file mode 100644 index 000000000..fcc6a4ade --- /dev/null +++ b/dom/xml/CDATASection.cpp @@ -0,0 +1,69 @@ +/* -*- 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 { +namespace dom { + +CDATASection::~CDATASection() +{ +} + +NS_IMPL_ISUPPORTS_INHERITED(CDATASection, nsGenericDOMDataNode, nsIDOMNode, + nsIDOMCharacterData, nsIDOMText, + nsIDOMCDATASection) + +JSObject* +CDATASection::WrapNode(JSContext *aCx, JS::Handle aGivenProto) +{ + return CDATASectionBinding::Wrap(aCx, this, aGivenProto); +} + +bool +CDATASection::IsNodeOfType(uint32_t aFlags) const +{ + return !(aFlags & ~(eCONTENT | eTEXT | eDATA_NODE)); +} + +nsGenericDOMDataNode* +CDATASection::CloneDataNode(mozilla::dom::NodeInfo *aNodeInfo, bool aCloneText) const +{ + RefPtr ni = aNodeInfo; + CDATASection *it = new CDATASection(ni.forget()); + if (it && aCloneText) { + it->mText = mText; + } + + return it; +} + +#ifdef DEBUG +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 dom +} // namespace mozilla diff --git a/dom/xml/CDATASection.h b/dom/xml/CDATASection.h new file mode 100644 index 000000000..2e99b1abf --- /dev/null +++ b/dom/xml/CDATASection.h @@ -0,0 +1,79 @@ +/* -*- 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 "nsIDOMCDATASection.h" +#include "mozilla/dom/Text.h" + +namespace mozilla { +namespace dom { + +class CDATASection final : public Text, + public nsIDOMCDATASection +{ +private: + void Init() + { + MOZ_ASSERT(mNodeInfo->NodeType() == nsIDOMNode::CDATA_SECTION_NODE, + "Bad NodeType in aNodeInfo"); + } + + virtual ~CDATASection(); + +public: + explicit CDATASection(already_AddRefed aNodeInfo) + : Text(aNodeInfo) + { + Init(); + } + + explicit CDATASection(nsNodeInfoManager* aNodeInfoManager) + : Text(aNodeInfoManager->GetNodeInfo(nsGkAtoms::cdataTagName, + nullptr, kNameSpaceID_None, + nsIDOMNode::CDATA_SECTION_NODE)) + { + Init(); + } + + // nsISupports + NS_DECL_ISUPPORTS_INHERITED + + // nsIDOMNode + NS_FORWARD_NSIDOMNODE_TO_NSINODE + + // nsIDOMCharacterData + NS_FORWARD_NSIDOMCHARACTERDATA(nsGenericDOMDataNode::) + using nsGenericDOMDataNode::SetData; // Prevent hiding overloaded virtual function. + + // nsIDOMText + NS_FORWARD_NSIDOMTEXT(nsGenericDOMDataNode::) + + // nsIDOMCDATASection + // Empty interface + + // nsINode + virtual bool IsNodeOfType(uint32_t aFlags) const override; + + virtual nsGenericDOMDataNode* CloneDataNode(mozilla::dom::NodeInfo *aNodeInfo, + bool aCloneText) const override; + + virtual nsIDOMNode* AsDOMNode() override { return this; } +#ifdef DEBUG + virtual void List(FILE* out, int32_t aIndent) const override; + virtual void DumpContent(FILE* out, int32_t aIndent,bool aDumpAll) const override; +#endif + +protected: + virtual JSObject* WrapNode(JSContext *aCx, JS::Handle aGivenProto) override; +}; + +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_CDATASection_h diff --git a/dom/xml/ProcessingInstruction.cpp b/dom/xml/ProcessingInstruction.cpp new file mode 100644 index 000000000..c341ff4e3 --- /dev/null +++ b/dom/xml/ProcessingInstruction.cpp @@ -0,0 +1,133 @@ +/* -*- 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/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; + + NS_PRECONDITION(aNodeInfoManager, "Missing nodeinfo manager"); + + nsCOMPtr target = NS_Atomize(aTarget); + MOZ_ASSERT(target); + + if (target == nsGkAtoms::xml_stylesheet) { + RefPtr pi = + new XMLStylesheetProcessingInstruction(aNodeInfoManager, aData); + return pi.forget(); + } + + RefPtr ni; + ni = aNodeInfoManager->GetNodeInfo(nsGkAtoms::processingInstructionTagName, + nullptr, kNameSpaceID_None, + nsIDOMNode::PROCESSING_INSTRUCTION_NODE, + target); + + RefPtr instance = + new ProcessingInstruction(ni.forget(), aData); + + return instance.forget(); +} + +namespace mozilla { +namespace dom { + +ProcessingInstruction::ProcessingInstruction(already_AddRefed&& aNodeInfo, + const nsAString& aData) + : nsGenericDOMDataNode(Move(aNodeInfo)) +{ + MOZ_ASSERT(mNodeInfo->NodeType() == nsIDOMNode::PROCESSING_INSTRUCTION_NODE, + "Bad NodeType in aNodeInfo"); + + SetTextInternal(0, mText.GetLength(), + aData.BeginReading(), aData.Length(), + false); // Don't notify (bug 420429). +} + +ProcessingInstruction::~ProcessingInstruction() +{ +} + +NS_IMPL_ISUPPORTS_INHERITED(ProcessingInstruction, nsGenericDOMDataNode, + nsIDOMNode, nsIDOMCharacterData, + nsIDOMProcessingInstruction) + +JSObject* +ProcessingInstruction::WrapNode(JSContext *aCx, JS::Handle aGivenProto) +{ + return ProcessingInstructionBinding::Wrap(aCx, this, aGivenProto); +} + +NS_IMETHODIMP +ProcessingInstruction::GetTarget(nsAString& aTarget) +{ + aTarget = NodeName(); + + return NS_OK; +} + +bool +ProcessingInstruction::GetAttrValue(nsIAtom *aName, nsAString& aValue) +{ + nsAutoString data; + + GetData(data); + return nsContentUtils::GetPseudoAttributeValue(data, aName, aValue); +} + +bool +ProcessingInstruction::IsNodeOfType(uint32_t aFlags) const +{ + return !(aFlags & ~(eCONTENT | ePROCESSING_INSTRUCTION | eDATA_NODE)); +} + +nsGenericDOMDataNode* +ProcessingInstruction::CloneDataNode(mozilla::dom::NodeInfo *aNodeInfo, + bool aCloneText) const +{ + nsAutoString data; + nsGenericDOMDataNode::GetData(data); + RefPtr ni = aNodeInfo; + return new ProcessingInstruction(ni.forget(), data); +} + +#ifdef DEBUG +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 dom +} // namespace mozilla diff --git a/dom/xml/ProcessingInstruction.h b/dom/xml/ProcessingInstruction.h new file mode 100644 index 000000000..ce1a780c9 --- /dev/null +++ b/dom/xml/ProcessingInstruction.h @@ -0,0 +1,85 @@ +/* -*- 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 "nsIDOMProcessingInstruction.h" +#include "nsGenericDOMDataNode.h" +#include "nsAString.h" + +namespace mozilla { +namespace dom { + +class ProcessingInstruction : public nsGenericDOMDataNode, + public nsIDOMProcessingInstruction +{ +public: + ProcessingInstruction(already_AddRefed&& aNodeInfo, + const nsAString& aData); + + // nsISupports + NS_DECL_ISUPPORTS_INHERITED + + // nsIDOMNode + NS_FORWARD_NSIDOMNODE_TO_NSINODE + + // nsIDOMCharacterData + NS_FORWARD_NSIDOMCHARACTERDATA(nsGenericDOMDataNode::) + using nsGenericDOMDataNode::SetData; // Prevent hiding overloaded virtual function. + + // nsIDOMProcessingInstruction + NS_DECL_NSIDOMPROCESSINGINSTRUCTION + + // nsINode + virtual bool IsNodeOfType(uint32_t aFlags) const override; + + virtual nsGenericDOMDataNode* CloneDataNode(mozilla::dom::NodeInfo *aNodeInfo, + bool aCloneText) const override; + +#ifdef DEBUG + virtual void List(FILE* out, int32_t aIndent) const override; + virtual void DumpContent(FILE* out, int32_t aIndent, bool aDumpAll) const override; +#endif + + virtual nsIDOMNode* AsDOMNode() override { return this; } + + // WebIDL API + void GetTarget(nsString& aTarget) + { + aTarget = NodeName(); + } +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(nsIAtom *aName, nsAString& aValue); + + virtual JSObject* WrapNode(JSContext *aCx, 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 000000000..26b88a39b --- /dev/null +++ b/dom/xml/XMLDocument.cpp @@ -0,0 +1,625 @@ +/* -*- 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 "nsParserCIID.h" +#include "nsCharsetSource.h" +#include "nsIXMLContentSink.h" +#include "nsPresContext.h" +#include "nsIContent.h" +#include "nsIContentViewerContainer.h" +#include "nsIContentViewer.h" +#include "nsIDocShell.h" +#include "nsHTMLParts.h" +#include "nsIComponentManager.h" +#include "nsIDOMElement.h" +#include "nsIBaseWindow.h" +#include "nsIDOMWindow.h" +#include "nsIDOMDocumentType.h" +#include "nsCOMPtr.h" +#include "nsXPIDLString.h" +#include "nsIHttpChannelInternal.h" +#include "nsIURI.h" +#include "nsIServiceManager.h" +#include "nsNetUtil.h" +#include "nsError.h" +#include "nsIScriptSecurityManager.h" +#include "nsIPrincipal.h" +#include "nsLayoutCID.h" +#include "mozilla/dom/Attr.h" +#include "nsCExternalHandlerService.h" +#include "nsMimeTypes.h" +#include "mozilla/EventListenerManager.h" +#include "nsContentUtils.h" +#include "nsThreadUtils.h" +#include "nsJSUtils.h" +#include "nsCRT.h" +#include "nsIAuthPrompt.h" +#include "nsContentCreatorFunctions.h" +#include "nsContentPolicyUtils.h" +#include "nsNodeUtils.h" +#include "nsIConsoleService.h" +#include "nsIScriptError.h" +#include "nsIHTMLDocument.h" +#include "mozilla/BasicEvents.h" +#include "mozilla/EventDispatcher.h" +#include "mozilla/dom/Element.h" +#include "mozilla/dom/XMLDocumentBinding.h" +#include "mozilla/dom/DocumentBinding.h" + +using namespace mozilla; +using namespace mozilla::dom; + +// ================================================================== +// = +// ================================================================== + + +nsresult +NS_NewDOMDocument(nsIDOMDocument** aInstancePtrResult, + const nsAString& aNamespaceURI, + const nsAString& aQualifiedName, + nsIDOMDocumentType* 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 == 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) { + nsCOMPtr htmlDoc = do_QueryInterface(d); + NS_ASSERTION(htmlDoc, "HTML Document doesn't implement nsIHTMLDocument?"); + htmlDoc->SetCompatibilityMode(eCompatibility_FullStandards); + htmlDoc->SetIsXHTML(isXHTML); + } + nsDocument* doc = static_cast(d.get()); + doc->SetLoadedAsData(aLoadedAsData); + doc->nsDocument::SetDocumentURI(aDocumentURI); + // Must set the principal first, since SetBaseURI checks it. + doc->SetPrincipal(aPrincipal); + doc->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 + doc->SetDocumentCharacterSet(NS_LITERAL_CSTRING("UTF-8")); + + if (aDoctype) { + nsCOMPtr tmpNode; + rv = doc->AppendChild(aDoctype, getter_AddRefs(tmpNode)); + NS_ENSURE_SUCCESS(rv, rv); + } + + if (!aQualifiedName.IsEmpty()) { + nsCOMPtr root; + rv = doc->CreateElementNS(aNamespaceURI, aQualifiedName, + getter_AddRefs(root)); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr tmpNode; + + rv = doc->AppendChild(root, getter_AddRefs(tmpNode)); + NS_ENSURE_SUCCESS(rv, rv); + } + + *aInstancePtrResult = doc; + NS_ADDREF(*aInstancePtrResult); + + return NS_OK; +} + +nsresult +NS_NewXMLDocument(nsIDocument** aInstancePtrResult, bool aLoadedAsData, + bool aIsPlainDocument) +{ + RefPtr doc = new XMLDocument(); + + nsresult rv = doc->Init(); + + if (NS_FAILED(rv)) { + *aInstancePtrResult = nullptr; + return rv; + } + + doc->SetLoadedAsData(aLoadedAsData); + doc->mIsPlainDocument = aIsPlainDocument; + doc.forget(aInstancePtrResult); + + return NS_OK; +} + +nsresult +NS_NewXBLDocument(nsIDOMDocument** aInstancePtrResult, + nsIURI* aDocumentURI, + nsIURI* aBaseURI, + nsIPrincipal* aPrincipal) +{ + nsresult rv = NS_NewDOMDocument(aInstancePtrResult, + NS_LITERAL_STRING("http://www.mozilla.org/xbl"), + NS_LITERAL_STRING("bindings"), nullptr, + aDocumentURI, aBaseURI, aPrincipal, false, + nullptr, DocumentFlavorLegacyGuess); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr idoc = do_QueryInterface(*aInstancePtrResult); + nsDocument* doc = static_cast(idoc.get()); + doc->SetLoadedAsInteractiveData(true); + doc->SetReadyStateInternal(nsIDocument::READYSTATE_COMPLETE); + + return NS_OK; +} + +namespace mozilla { +namespace dom { + +XMLDocument::XMLDocument(const char* aContentType) + : nsDocument(aContentType), + mAsync(true) +{ + // NOTE! nsDocument::operator new() zeroes out all members, so don't + // bother initializing members to 0. + + mType = eGenericXML; +} + +XMLDocument::~XMLDocument() +{ + // XXX We rather crash than hang + mLoopingForSyncLoad = false; +} + +// QueryInterface implementation for XMLDocument +NS_IMPL_ISUPPORTS_INHERITED(XMLDocument, nsDocument, nsIDOMXMLDocument) + +nsresult +XMLDocument::Init() +{ + nsresult rv = nsDocument::Init(); + NS_ENSURE_SUCCESS(rv, rv); + + return rv; +} + +void +XMLDocument::Reset(nsIChannel* aChannel, nsILoadGroup* aLoadGroup) +{ + nsDocument::Reset(aChannel, aLoadGroup); +} + +void +XMLDocument::ResetToURI(nsIURI *aURI, nsILoadGroup *aLoadGroup, + nsIPrincipal* aPrincipal) +{ + if (mChannelIsPending) { + StopDocumentLoad(); + mChannel->Cancel(NS_BINDING_ABORTED); + mChannelIsPending = false; + } + + nsDocument::ResetToURI(aURI, aLoadGroup, aPrincipal); +} + +bool +XMLDocument::Load(const nsAString& aUrl, ErrorResult& aRv) +{ + bool hasHadScriptObject = true; + nsIScriptGlobalObject* scriptObject = + GetScriptHandlingObject(hasHadScriptObject); + if (!scriptObject && hasHadScriptObject) { + aRv.Throw(NS_ERROR_UNEXPECTED); + return false; + } + + nsCOMPtr callingDoc = GetEntryDocument(); + nsCOMPtr principal = NodePrincipal(); + + // The callingDoc's Principal and doc's Principal should be the same + if (callingDoc && (callingDoc->NodePrincipal() != principal)) { + nsContentUtils::ReportToConsole(nsIScriptError::errorFlag, + NS_LITERAL_CSTRING("DOM"), + callingDoc, + nsContentUtils::eDOM_PROPERTIES, + "XMLDocumentLoadPrincipalMismatch"); + aRv.Throw(NS_ERROR_UNEXPECTED); + return false; + } + + // Reporting a warning on ourselves is rather pointless, because we probably + // have no window id (and hence the warning won't show up in any web console) + // and probably aren't considered a "content document" because we're not + // loaded in a docshell, so won't accumulate telemetry for use counters. Try + // warning on our entry document, if any, since that should have things like + // window ids and associated docshells. + nsIDocument* docForWarning = callingDoc ? callingDoc.get() : this; + if (nsContentUtils::IsCallerChrome()) { + docForWarning->WarnOnceAbout(nsIDocument::eChromeUseOfDOM3LoadMethod); + } else { + docForWarning->WarnOnceAbout(nsIDocument::eUseOfDOM3LoadMethod); + } + + nsIURI *baseURI = mDocumentURI; + nsAutoCString charset; + + if (callingDoc) { + baseURI = callingDoc->GetDocBaseURI(); + charset = callingDoc->GetDocumentCharacterSet(); + } + + // Create a new URI + nsCOMPtr uri; + nsresult rv = NS_NewURI(getter_AddRefs(uri), aUrl, charset.get(), baseURI); + if (NS_FAILED(rv)) { + aRv.Throw(rv); + return false; + } + + if (nsContentUtils::IsSystemPrincipal(principal)) { + // We're called from chrome, check to make sure the URI we're + // about to load is also chrome. + + bool isChrome = false; + if (NS_FAILED(uri->SchemeIs("chrome", &isChrome)) || !isChrome) { + nsAutoCString spec; + if (mDocumentURI) + mDocumentURI->GetSpec(spec); + + nsAutoString error; + error.AssignLiteral("Cross site loading using document.load is no " + "longer supported. Use XMLHttpRequest instead."); + nsCOMPtr errorObject = + do_CreateInstance(NS_SCRIPTERROR_CONTRACTID, &rv); + if (NS_FAILED(rv)) { + aRv.Throw(rv); + return false; + } + + rv = errorObject->InitWithWindowID(error, + NS_ConvertUTF8toUTF16(spec), + EmptyString(), + 0, 0, nsIScriptError::warningFlag, + "DOM", + callingDoc ? + callingDoc->InnerWindowID() : + this->InnerWindowID()); + + if (NS_FAILED(rv)) { + aRv.Throw(rv); + return false; + } + + nsCOMPtr consoleService = + do_GetService(NS_CONSOLESERVICE_CONTRACTID); + if (consoleService) { + consoleService->LogMessage(errorObject); + } + + aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); + return false; + } + } + + // Partial Reset, need to restore principal for security reasons and + // event listener manager so that load listeners etc. will + // remain. This should be done before the security check is done to + // ensure that the document is reset even if the new document can't + // be loaded. Note that we need to hold a strong ref to |principal| + // here, because ResetToURI will null out our node principal before + // setting the new one. + RefPtr elm(mListenerManager); + mListenerManager = nullptr; + + // When we are called from JS we can find the load group for the page, + // and add ourselves to it. This way any pending requests + // will be automatically aborted if the user leaves the page. + + nsCOMPtr loadGroup; + if (callingDoc) { + loadGroup = callingDoc->GetDocumentLoadGroup(); + } + + ResetToURI(uri, loadGroup, principal); + + mListenerManager = elm; + + // Create a channel + nsCOMPtr req = nsContentUtils::SameOriginChecker(); + + nsCOMPtr channel; + // nsIRequest::LOAD_BACKGROUND prevents throbber from becoming active, + // which in turn keeps STOP button from becoming active + rv = NS_NewChannel(getter_AddRefs(channel), + uri, + callingDoc ? callingDoc.get() : + static_cast(this), + nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED, + nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST, + loadGroup, + req, + nsIRequest::LOAD_BACKGROUND); + + if (NS_FAILED(rv)) { + aRv.Throw(rv); + return false; + } + + // TODO Bug 1189945: Remove nsIChannel CorsMode flag and set Request.mode + // based on nsILoadInfo securityFlags instead. This block will be removed + // when Request.mode set correctly. + nsCOMPtr httpChannel = do_QueryInterface(channel); + if (httpChannel) { + httpChannel->SetCorsMode(nsIHttpChannelInternal::CORS_MODE_SAME_ORIGIN); + } + + // StartDocumentLoad asserts that readyState is uninitialized, so + // uninitialize it. SetReadyStateInternal make this transition invisible to + // Web content. But before doing that, assert that the current readyState + // is complete as it should be after the call to ResetToURI() above. + MOZ_ASSERT(GetReadyStateEnum() == nsIDocument::READYSTATE_COMPLETE, + "Bad readyState"); + SetReadyStateInternal(nsIDocument::READYSTATE_UNINITIALIZED); + + // Prepare for loading the XML document "into oneself" + nsCOMPtr listener; + if (NS_FAILED(rv = StartDocumentLoad(kLoadAsData, channel, + loadGroup, nullptr, + getter_AddRefs(listener), + false))) { + NS_ERROR("XMLDocument::Load: Failed to start the document load."); + aRv.Throw(rv); + return false; + } + + // After this point, if we error out of this method we should clear + // mChannelIsPending. + + // Start an asynchronous read of the XML document + rv = channel->AsyncOpen2(listener); + if (NS_FAILED(rv)) { + mChannelIsPending = false; + aRv.Throw(rv); + return false; + } + + if (!mAsync) { + nsCOMPtr thread = do_GetCurrentThread(); + + nsAutoSyncOperation sync(this); + mLoopingForSyncLoad = true; + while (mLoopingForSyncLoad) { + if (!NS_ProcessNextEvent(thread)) + break; + } + + // We set return to true unless there was a parsing error + Element* rootElement = GetRootElement(); + if (!rootElement) { + return false; + } + + if (rootElement->LocalName().EqualsLiteral("parsererror")) { + nsAutoString ns; + rootElement->GetNamespaceURI(ns); + if (ns.EqualsLiteral("http://www.mozilla.org/newlayout/xml/parsererror.xml")) { + return false; + } + } + } + + return true; +} + +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, + nsIContentSink* aSink) +{ + nsresult rv = nsDocument::StartDocumentLoad(aCommand, + aChannel, aLoadGroup, + aContainer, + aDocListener, aReset, aSink); + if (NS_FAILED(rv)) return rv; + + if (nsCRT::strcmp("loadAsInteractiveData", aCommand) == 0) { + mLoadedAsInteractiveData = true; + aCommand = kLoadAsData; // XBL, for example, needs scripts and styles + } + + + int32_t charsetSource = kCharsetFromDocTypeDefault; + nsAutoCString charset(NS_LITERAL_CSTRING("UTF-8")); + TryChannelCharset(aChannel, charsetSource, charset, nullptr); + + nsCOMPtr aUrl; + rv = aChannel->GetURI(getter_AddRefs(aUrl)); + if (NS_FAILED(rv)) return rv; + + static NS_DEFINE_CID(kCParserCID, NS_PARSER_CID); + + mParser = do_CreateInstance(kCParserCID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr sink; + + if (aSink) { + sink = do_QueryInterface(aSink); + } + else { + 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(charset); + mParser->SetDocumentCharset(charset, charsetSource); + mParser->SetCommand(aCommand); + mParser->SetContentSink(sink); + mParser->Parse(aUrl, nullptr, (void *)this); + + return NS_OK; +} + +void +XMLDocument::EndLoad() +{ + mChannelIsPending = false; + mLoopingForSyncLoad = false; + + mSynchronousDOMContentLoaded = (mLoadedAsData || mLoadedAsInteractiveData); + nsDocument::EndLoad(); + if (mSynchronousDOMContentLoaded) { + mSynchronousDOMContentLoaded = false; + nsDocument::SetReadyStateInternal(nsIDocument::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); + EventDispatcher::Dispatch(static_cast(this), nullptr, &event); + } +} + +/* virtual */ void +XMLDocument::DocAddSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const +{ + nsDocument::DocAddSizeOfExcludingThis(aWindowSizes); +} + +// nsIDOMDocument interface + +nsresult +XMLDocument::Clone(mozilla::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->mAsync = mAsync; + clone->mIsPlainDocument = mIsPlainDocument; + + return CallQueryInterface(clone.get(), aResult); +} + +JSObject* +XMLDocument::WrapNode(JSContext *aCx, JS::Handle aGivenProto) +{ + if (mIsPlainDocument) { + return DocumentBinding::Wrap(aCx, this, aGivenProto); + } + + return XMLDocumentBinding::Wrap(aCx, this, aGivenProto); +} + +} // namespace dom +} // namespace mozilla diff --git a/dom/xml/XMLDocument.h b/dom/xml/XMLDocument.h new file mode 100644 index 000000000..a948c1852 --- /dev/null +++ b/dom/xml/XMLDocument.h @@ -0,0 +1,110 @@ +/* -*- 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 "nsDocument.h" +#include "nsIDOMXMLDocument.h" +#include "nsIScriptContext.h" + +class nsIURI; +class nsIChannel; + +namespace mozilla { +namespace dom { + +class XMLDocument : public nsDocument, + public nsIDOMXMLDocument +{ +public: + explicit XMLDocument(const char* aContentType = "application/xml"); + + NS_DECL_ISUPPORTS_INHERITED + + virtual void Reset(nsIChannel* aChannel, nsILoadGroup* aLoadGroup) override; + virtual void ResetToURI(nsIURI *aURI, nsILoadGroup *aLoadGroup, + nsIPrincipal* aPrincipal) 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, + nsIContentSink* aSink = nullptr) override; + + virtual void EndLoad() override; + + // nsIDOMXMLDocument + NS_DECL_NSIDOMXMLDOCUMENT + + virtual nsresult Init() override; + + virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override; + + virtual void DocAddSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const override; + // DocAddSizeOfIncludingThis is inherited from nsIDocument. + + + // WebIDL API + bool Load(const nsAString& aUrl, mozilla::ErrorResult& aRv); + bool Async() const + { + return mAsync; + } + void SetAsync(bool aAsync) + { + mAsync = aAsync; + } + + // .location is [Unforgeable], so we have to make it clear that the + // nsIDocument version applies to us (it's shadowed by the XPCOM thing on + // nsDocument). + using nsIDocument::GetLocation; + // But then we need to also pull in the nsDocument XPCOM version + // because nsXULDocument tries to forward to it. + using nsDocument::GetLocation; + +protected: + virtual ~XMLDocument(); + + virtual JSObject* WrapNode(JSContext *aCx, JS::Handle aGivenProto) override; + + friend nsresult (::NS_NewXMLDocument)(nsIDocument**, bool, bool); + + + // mChannelIsPending indicates whether we're currently asynchronously loading + // data from mChannel (via document.load() or normal load). 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; + bool mAsync; + bool mLoopingForSyncLoad; + + // 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 dom +} // namespace mozilla + +#endif // mozilla_dom_XMLDocument_h diff --git a/dom/xml/XMLStylesheetProcessingInstruction.cpp b/dom/xml/XMLStylesheetProcessingInstruction.cpp new file mode 100644 index 000000000..3d94e179b --- /dev/null +++ b/dom/xml/XMLStylesheetProcessingInstruction.cpp @@ -0,0 +1,196 @@ +/* -*- 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/XMLStylesheetProcessingInstructionBinding.h" +#include "nsContentUtils.h" +#include "nsNetUtil.h" + +namespace mozilla { +namespace dom { + +// nsISupports implementation + +NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(XMLStylesheetProcessingInstruction) + NS_INTERFACE_TABLE_INHERITED(XMLStylesheetProcessingInstruction, nsIDOMNode, + nsIDOMProcessingInstruction, + nsIStyleSheetLinkingElement) +NS_INTERFACE_TABLE_TAIL_INHERITING(ProcessingInstruction) + +NS_IMPL_ADDREF_INHERITED(XMLStylesheetProcessingInstruction, + ProcessingInstruction) +NS_IMPL_RELEASE_INHERITED(XMLStylesheetProcessingInstruction, + ProcessingInstruction) + +NS_IMPL_CYCLE_COLLECTION_CLASS(XMLStylesheetProcessingInstruction) + +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(XMLStylesheetProcessingInstruction, + ProcessingInstruction) + tmp->nsStyleLinkElement::Traverse(cb); +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END + +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(XMLStylesheetProcessingInstruction, + ProcessingInstruction) + tmp->nsStyleLinkElement::Unlink(); +NS_IMPL_CYCLE_COLLECTION_UNLINK_END + + +XMLStylesheetProcessingInstruction::~XMLStylesheetProcessingInstruction() +{ +} + +JSObject* +XMLStylesheetProcessingInstruction::WrapNode(JSContext *aCx, JS::Handle aGivenProto) +{ + return XMLStylesheetProcessingInstructionBinding::Wrap(aCx, this, aGivenProto); +} + +// nsIContent + +nsresult +XMLStylesheetProcessingInstruction::BindToTree(nsIDocument* aDocument, + nsIContent* aParent, + nsIContent* aBindingParent, + bool aCompileEventHandlers) +{ + nsresult rv = ProcessingInstruction::BindToTree(aDocument, aParent, + aBindingParent, + aCompileEventHandlers); + NS_ENSURE_SUCCESS(rv, rv); + + void (XMLStylesheetProcessingInstruction::*update)() = + &XMLStylesheetProcessingInstruction::UpdateStyleSheetInternal; + nsContentUtils::AddScriptRunner(NewRunnableMethod(this, update)); + + return rv; +} + +void +XMLStylesheetProcessingInstruction::UnbindFromTree(bool aDeep, bool aNullParent) +{ + nsCOMPtr oldDoc = GetUncomposedDoc(); + + ProcessingInstruction::UnbindFromTree(aDeep, aNullParent); + UpdateStyleSheetInternal(oldDoc, nullptr); +} + +// nsIDOMNode + +void +XMLStylesheetProcessingInstruction::SetNodeValueInternal(const nsAString& aNodeValue, + ErrorResult& aError) +{ + nsGenericDOMDataNode::SetNodeValueInternal(aNodeValue, aError); + if (!aError.Failed()) { + UpdateStyleSheetInternal(nullptr, nullptr, true); + } +} + +// nsStyleLinkElement + +NS_IMETHODIMP +XMLStylesheetProcessingInstruction::GetCharset(nsAString& aCharset) +{ + return GetAttrValue(nsGkAtoms::charset, aCharset) ? NS_OK : NS_ERROR_FAILURE; +} + +/* virtual */ void +XMLStylesheetProcessingInstruction::OverrideBaseURI(nsIURI* aNewBaseURI) +{ + mOverriddenBaseURI = aNewBaseURI; +} + +already_AddRefed +XMLStylesheetProcessingInstruction::GetStyleSheetURL(bool* aIsInline) +{ + *aIsInline = false; + + nsAutoString href; + if (!GetAttrValue(nsGkAtoms::href, href)) { + return nullptr; + } + + nsIURI *baseURL; + nsAutoCString charset; + nsIDocument *document = OwnerDoc(); + baseURL = mOverriddenBaseURI ? + mOverriddenBaseURI.get() : + document->GetDocBaseURI(); + charset = document->GetDocumentCharacterSet(); + + nsCOMPtr aURI; + NS_NewURI(getter_AddRefs(aURI), href, charset.get(), baseURL); + return aURI.forget(); +} + +void +XMLStylesheetProcessingInstruction::GetStyleSheetInfo(nsAString& aTitle, + nsAString& aType, + nsAString& aMedia, + bool* aIsScoped, + bool* aIsAlternate) +{ + aTitle.Truncate(); + aType.Truncate(); + aMedia.Truncate(); + *aIsScoped = false; + *aIsAlternate = false; + + // xml-stylesheet PI is special only in prolog + if (!nsContentUtils::InProlog(this)) { + return; + } + + nsAutoString data; + GetData(data); + + nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::title, aTitle); + + nsAutoString alternate; + nsContentUtils::GetPseudoAttributeValue(data, + nsGkAtoms::alternate, + alternate); + + // if alternate, does it have title? + if (alternate.EqualsLiteral("yes")) { + if (aTitle.IsEmpty()) { // alternates must have title + return; + } + + *aIsAlternate = true; + } + + nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::media, aMedia); + + nsAutoString type; + nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::type, type); + + nsAutoString mimeType, notUsed; + nsContentUtils::SplitMimeType(type, mimeType, notUsed); + if (!mimeType.IsEmpty() && !mimeType.LowerCaseEqualsLiteral("text/css")) { + aType.Assign(type); + return; + } + + // If we get here we assume that we're loading a css file, so set the + // type to 'text/css' + aType.AssignLiteral("text/css"); + + return; +} + +nsGenericDOMDataNode* +XMLStylesheetProcessingInstruction::CloneDataNode(mozilla::dom::NodeInfo *aNodeInfo, + bool aCloneText) const +{ + nsAutoString data; + nsGenericDOMDataNode::GetData(data); + RefPtr ni = aNodeInfo; + return new XMLStylesheetProcessingInstruction(ni.forget(), data); +} + +} // namespace dom +} // namespace mozilla diff --git a/dom/xml/XMLStylesheetProcessingInstruction.h b/dom/xml/XMLStylesheetProcessingInstruction.h new file mode 100644 index 000000000..818b3392f --- /dev/null +++ b/dom/xml/XMLStylesheetProcessingInstruction.h @@ -0,0 +1,93 @@ +/* -*- 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/dom/ProcessingInstruction.h" +#include "nsIURI.h" +#include "nsStyleLinkElement.h" + +namespace mozilla { +namespace dom { + +class XMLStylesheetProcessingInstruction final +: public ProcessingInstruction +, public nsStyleLinkElement +{ +public: + XMLStylesheetProcessingInstruction(already_AddRefed&& aNodeInfo, + const nsAString& aData) + : ProcessingInstruction(Move(aNodeInfo), aData) + { + } + + XMLStylesheetProcessingInstruction(nsNodeInfoManager* aNodeInfoManager, + const nsAString& aData) + : ProcessingInstruction(aNodeInfoManager->GetNodeInfo( + nsGkAtoms::processingInstructionTagName, + nullptr, kNameSpaceID_None, + nsIDOMNode::PROCESSING_INSTRUCTION_NODE, + nsGkAtoms::xml_stylesheet), aData) + { + } + + virtual JSObject* WrapNode(JSContext *aCx, JS::Handle aGivenProto) override; + + // nsISupports + NS_DECL_ISUPPORTS_INHERITED + + // CC + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(XMLStylesheetProcessingInstruction, + ProcessingInstruction) + + // nsIDOMNode + virtual void SetNodeValueInternal(const nsAString& aNodeValue, + mozilla::ErrorResult& aError) override; + + // nsIContent + virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent, + nsIContent* aBindingParent, + bool aCompileEventHandlers) override; + virtual void UnbindFromTree(bool aDeep = true, + bool aNullParent = true) override; + + // nsIStyleSheetLinkingElement + virtual void OverrideBaseURI(nsIURI* aNewBaseURI) override; + + // nsStyleLinkElement + NS_IMETHOD GetCharset(nsAString& aCharset) override; + + virtual void SetData(const nsAString& aData, mozilla::ErrorResult& rv) override + { + nsGenericDOMDataNode::SetData(aData, rv); + if (rv.Failed()) { + return; + } + UpdateStyleSheetInternal(nullptr, nullptr, true); + } + using ProcessingInstruction::SetData; // Prevent hiding overloaded virtual function. + +protected: + virtual ~XMLStylesheetProcessingInstruction(); + + nsCOMPtr mOverriddenBaseURI; + + already_AddRefed GetStyleSheetURL(bool* aIsInline) override; + void GetStyleSheetInfo(nsAString& aTitle, + nsAString& aType, + nsAString& aMedia, + bool* aIsScoped, + bool* aIsAlternate) override; + virtual nsGenericDOMDataNode* CloneDataNode(mozilla::dom::NodeInfo *aNodeInfo, + bool aCloneText) const override; +}; + +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_XMLStylesheetProcessingInstruction_h diff --git a/dom/xml/crashtests/1038887.xhtml b/dom/xml/crashtests/1038887.xhtml new file mode 100644 index 000000000..18b12083a --- /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 000000000..a54f95393 --- /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/185285-1.xml b/dom/xml/crashtests/185285-1.xml new file mode 100644 index 000000000..9ab44d335 --- /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 000000000..da5110ad0 --- /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 000000000..2be0060ee --- /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 000000000..da5110ad0 --- /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.xul b/dom/xml/crashtests/382636-4.xul new file mode 100644 index 000000000..9907973c0 --- /dev/null +++ b/dom/xml/crashtests/382636-4.xul @@ -0,0 +1,5 @@ + + + + + diff --git a/dom/xml/crashtests/420429.xul b/dom/xml/crashtests/420429.xul new file mode 100644 index 000000000..e71af4ef2 --- /dev/null +++ b/dom/xml/crashtests/420429.xul @@ -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 000000000..622e4455c --- /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 000000000..7ced674cc --- /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 000000000..f30ea3833 --- /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 000000000..002de0772 --- /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 000000000..4d71cef27 --- /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 000000000..f18767d58 --- /dev/null +++ b/dom/xml/crashtests/crashtests.list @@ -0,0 +1,12 @@ +load 136896-1.xml +load 185285-1.xml +load 382636-1.xml +load 382636-2.svg +load 382636-3.xhtml +load 382636-4.xul # Throws (bug 455856) +load 420429.xul +load 431703-1.xhtml +load 453278.html +load 803586.xhtml +load 994740-1.xhtml +load 1038887.xhtml diff --git a/dom/xml/crashtests/tree.gif b/dom/xml/crashtests/tree.gif new file mode 100644 index 000000000..360897e91 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 000000000..299a6bb6c --- /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 000000000..f3af9968d --- /dev/null +++ b/dom/xml/moz.build @@ -0,0 +1,46 @@ +# -*- 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/. + +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/xul', + '/layout/style', +] + +RESOURCE_FILES.dtd += [ + 'htmlmathml-f.ent', +] diff --git a/dom/xml/nsIXMLContentSink.h b/dom/xml/nsIXMLContentSink.h new file mode 100644 index 000000000..19fc7889b --- /dev/null +++ b/dom/xml/nsIXMLContentSink.h @@ -0,0 +1,57 @@ +/* -*- 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 nsIDocument; +class nsIURI; +class nsIChannel; + +#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) + +}; + +NS_DEFINE_STATIC_IID_ACCESSOR(nsIXMLContentSink, NS_IXMLCONTENT_SINK_IID) + +nsresult +NS_NewXMLContentSink(nsIXMLContentSink** aInstancePtrResult, nsIDocument* 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 000000000..7c9d308fd --- /dev/null +++ b/dom/xml/nsXMLContentSink.cpp @@ -0,0 +1,1590 @@ +/* -*- 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 "nsIDocument.h" +#include "nsIDOMDocument.h" +#include "nsIDOMDocumentType.h" +#include "nsIContent.h" +#include "nsIURI.h" +#include "nsNetUtil.h" +#include "nsIDocShell.h" +#include "nsIStyleSheetLinkingElement.h" +#include "nsIDOMComment.h" +#include "nsIDOMCDATASection.h" +#include "DocumentType.h" +#include "nsHTMLParts.h" +#include "nsCRT.h" +#include "mozilla/StyleSheetInlines.h" +#include "mozilla/css/Loader.h" +#include "nsGkAtoms.h" +#include "nsContentUtils.h" +#include "nsIScriptContext.h" +#include "nsNameSpaceManager.h" +#include "nsIServiceManager.h" +#include "nsIScriptSecurityManager.h" +#include "nsIContentViewer.h" +#include "prtime.h" +#include "mozilla/Logging.h" +#include "prmem.h" +#include "nsRect.h" +#include "nsIWebNavigation.h" +#include "nsIScriptElement.h" +#include "nsScriptLoader.h" +#include "nsStyleLinkElement.h" +#include "nsReadableUtils.h" +#include "nsUnicharUtils.h" +#include "nsICookieService.h" +#include "nsIPrompt.h" +#include "nsIChannel.h" +#include "nsIPrincipal.h" +#include "nsXMLPrettyPrinter.h" +#include "nsNodeInfoManager.h" +#include "nsContentCreatorFunctions.h" +#include "nsIContentPolicy.h" +#include "nsContentPolicyUtils.h" +#include "nsError.h" +#include "nsIDOMProcessingInstruction.h" +#include "nsNodeUtils.h" +#include "nsIScriptGlobalObject.h" +#include "nsIHTMLDocument.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/Element.h" +#include "mozilla/dom/HTMLTemplateElement.h" +#include "mozilla/dom/ProcessingInstruction.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, + nsIDocument* aDoc, + nsIURI* aURI, + nsISupports* aContainer, + nsIChannel* aChannel) +{ + NS_PRECONDITION(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() + : mTextLength(0) + , mNotifyLevel(0) + , mPrettyPrintXML(true) + , mPrettyPrintHasSpecialRoot(0) + , mPrettyPrintHasFactoredElements(0) + , mPrettyPrinting(0) + , mPreventScriptExecution(0) +{ + PodArrayZero(mText); +} + +nsXMLContentSink::~nsXMLContentSink() +{ +} + +nsresult +nsXMLContentSink::Init(nsIDocument* 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; +} + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(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_CLASS(nsXMLContentSink) + +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXMLContentSink, + nsContentSink) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCurrentHead) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocElement) + for (uint32_t i = 0, count = tmp->mContentStack.Length(); i < count; i++) { + const StackNode& node = tmp->mContentStack.ElementAt(i); + cb.NoteXPCOMChild(node.mContent); + } + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentChildren) +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END + +// 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; + } + + // 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(nsIDOMProcessingInstruction* aPi, + nsIDocumentTransformer* aProcessor, + nsIDocument* aDocument) +{ + 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()) { + nsCOMPtr doc = do_QueryInterface(aDocument); + aProcessor->AddXSLTParam(name, namespaceAttr, select, value, doc); + } + } +} + +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, nsDocument 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; + } + + DidBuildModelImpl(aTerminated); + + if (mXSLTProcessor) { + // stop observing in order to avoid crashing when replacing content + mDocument->RemoveObserver(this); + mIsDocumentObserver = false; + + // Check for xslt-param and xslt-param-namespace PIs + for (nsIContent* child = mDocument->GetFirstChild(); + child; + child = child->GetNextSibling()) { + if (child->IsNodeOfType(nsINode::ePROCESSING_INSTRUCTION)) { + nsCOMPtr pi = do_QueryInterface(child); + CheckXSLTParamPI(pi, mXSLTProcessor, mDocument); + } + else if (child->IsElement()) { + // Only honor PIs in the prolog + break; + } + } + + mXSLTProcessor->SetSourceContentModel(mDocument, mDocumentChildren); + // 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() && + NS_SUCCEEDED(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; +} + +NS_IMETHODIMP +nsXMLContentSink::OnDocumentCreated(nsIDocument* aResultDocument) +{ + NS_ENSURE_ARG(aResultDocument); + + nsCOMPtr htmlDoc = do_QueryInterface(aResultDocument); + if (htmlDoc) { + htmlDoc->SetDocWriteDisabled(true); + } + + nsCOMPtr contentViewer; + mDocShell->GetContentViewer(getter_AddRefs(contentViewer)); + if (contentViewer) { + return contentViewer->SetDocumentInternal(aResultDocument, true); + } + return NS_OK; +} + +NS_IMETHODIMP +nsXMLContentSink::OnTransformDone(nsresult aResult, + nsIDocument* aResultDocument) +{ + MOZ_ASSERT(aResultDocument, "Don't notify about transform end without a document."); + + mDocumentChildren.Clear(); + + nsCOMPtr domDoc = do_QueryInterface(aResultDocument); + + nsCOMPtr contentViewer; + mDocShell->GetContentViewer(getter_AddRefs(contentViewer)); + + if (NS_FAILED(aResult) && contentViewer) { + // Transform failed. + aResultDocument->SetMayStartLayout(false); + // We have an error document. + contentViewer->SetDOMDocument(domDoc); + } + + nsCOMPtr originalDocument = mDocument; + // Transform succeeded, or it failed and we have an error document to display. + mDocument = aResultDocument; + nsCOMPtr htmlDoc = do_QueryInterface(mDocument); + if (htmlDoc) { + htmlDoc->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->IndexOf(rootElement) != -1, + "rootElement not in doc?"); + mDocument->BeginUpdate(UPDATE_CONTENT_MODEL); + nsNodeUtils::ContentInserted(mDocument, rootElement, + mDocument->IndexOf(rootElement)); + mDocument->EndUpdate(UPDATE_CONTENT_MODEL); + } + + // Start the layout process + StartLayout(false); + + ScrollToRef(); + + originalDocument->EndLoad(); + + return NS_OK; +} + +NS_IMETHODIMP +nsXMLContentSink::StyleSheetLoaded(StyleSheet* aSheet, + bool aWasAlternate, + nsresult aStatus) +{ + if (!mPrettyPrinting) { + return nsContentSink::StyleSheetLoaded(aSheet, aWasAlternate, aStatus); + } + + if (!mDocument->CSSLoader()->HasPendingLoads()) { + mDocument->CSSLoader()->RemoveObserver(this); + StartLayout(false); + ScrollToRef(); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsXMLContentSink::WillInterrupt(void) +{ + return WillInterruptImpl(); +} + +NS_IMETHODIMP +nsXMLContentSink::WillResume(void) +{ + return WillResumeImpl(); +} + +NS_IMETHODIMP +nsXMLContentSink::SetParser(nsParserBase* aParser) +{ + NS_PRECONDITION(aParser, "Should have a parser here!"); + mParser = aParser; + return NS_OK; +} + +nsresult +nsXMLContentSink::CreateElement(const char16_t** aAtts, uint32_t aAttsCount, + mozilla::dom::NodeInfo* aNodeInfo, uint32_t aLineNumber, + 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; + 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); + sele->SetScriptLineNumber(aLineNumber); + sele->SetCreatorParser(GetParser()); + } + + // 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 = + nsContentUtils::NameSpaceManager()-> + 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)) { + nsCOMPtr ssle(do_QueryInterface(content)); + if (ssle) { + ssle->InitStyleLinkElement(false); + if (aFromParser) { + ssle->SetEnableUpdates(false); + } + if (!aNodeInfo->Equals(nsGkAtoms::link, kNameSpaceID_XHTML)) { + ssle->SetLineNumber(aFromParser ? aLineNumber : 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 ((nodeInfo->NamespaceID() == kNameSpaceID_XHTML && + (nodeInfo->NameAtom() == nsGkAtoms::select || + nodeInfo->NameAtom() == nsGkAtoms::textarea || + nodeInfo->NameAtom() == nsGkAtoms::video || + nodeInfo->NameAtom() == nsGkAtoms::audio || + nodeInfo->NameAtom() == nsGkAtoms::object || + nodeInfo->NameAtom() == nsGkAtoms::applet)) + || nodeInfo->NameAtom() == nsGkAtoms::title + ) { + 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 (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 the parser got blocked, make sure to return the appropriate rv. + // I'm not sure if this is actually needed or not. + if (mParser && !mParser->IsParserEnabled()) { + // XXX The HTML sink doesn't call BlockParser here, why do we? + GetParser()->BlockParser(); + block = true; + } + + return block ? NS_ERROR_HTMLPARSER_BLOCK : NS_OK; + } + + nsresult rv = NS_OK; + if (nodeInfo->Equals(nsGkAtoms::meta, kNameSpaceID_XHTML) && + // Need to check here to make sure this meta tag does not set + // mPrettyPrintXML to false when we have a special root! + (!mPrettyPrintXML || !mPrettyPrintHasSpecialRoot)) { + rv = ProcessMETATag(aContent); + } + else if (nodeInfo->Equals(nsGkAtoms::link, kNameSpaceID_XHTML) || + nodeInfo->Equals(nsGkAtoms::style, kNameSpaceID_XHTML) || + nodeInfo->Equals(nsGkAtoms::style, kNameSpaceID_SVG)) { + nsCOMPtr ssle(do_QueryInterface(aContent)); + if (ssle) { + ssle->SetEnableUpdates(true); + bool willNotify; + bool isAlternate; + rv = ssle->UpdateStyleSheet(mRunsToCompletion ? nullptr : this, + &willNotify, + &isAlternate); + if (NS_SUCCEEDED(rv) && willNotify && !isAlternate && !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); + } + } else { + nsCOMPtr parent = GetCurrentContent(); + + if (parent) { + result = parent->AppendChildTo(aContent, false); + } + } + 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 = + do_CreateInstance("@mozilla.org/document-transformer;1?type=xslt"); + if (!processor) { + // No XSLT processor available, continue normal document loading + return NS_OK; + } + + 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::ProcessStyleLink(nsIContent* aElement, + const nsSubstring& aHref, + bool aAlternate, + const nsSubstring& aTitle, + const nsSubstring& aType, + const nsSubstring& aMedia) +{ + nsresult rv = NS_OK; + mPrettyPrintXML = false; + + nsAutoCString cmd; + if (mParser) + GetParser()->GetCommand(cmd); + if (cmd.EqualsASCII(kLoadAsData)) + return NS_OK; // Do not load stylesheets when loading as data + + NS_ConvertUTF16toUTF8 type(aType); + if (type.EqualsIgnoreCase(TEXT_XSL) || + type.EqualsIgnoreCase(APPLICATION_XSLT_XML) || + type.EqualsIgnoreCase(TEXT_XML) || + type.EqualsIgnoreCase(APPLICATION_XML)) { + if (aAlternate) { + // don't load alternate XSLT + return NS_OK; + } + // LoadXSLStyleSheet needs a mDocShell. + if (!mDocShell) + return NS_OK; + + nsCOMPtr url; + 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); + NS_ENSURE_SUCCESS(rv, NS_OK); + + // Do content policy check + int16_t decision = nsIContentPolicy::ACCEPT; + rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_XSLT, + url, + mDocument->NodePrincipal(), + aElement, + type, + nullptr, + &decision, + nsContentUtils::GetContentPolicy(), + nsContentUtils::GetSecurityManager()); + + NS_ENSURE_SUCCESS(rv, rv); + + if (NS_CP_REJECTED(decision)) { + return NS_OK; + } + + return LoadXSLStyleSheet(url); + } + + // Let nsContentSink deal with css. + rv = nsContentSink::ProcessStyleLink(aElement, aHref, aAlternate, + aTitle, aType, aMedia); + + // nsContentSink::ProcessStyleLink handles the bookkeeping here wrt + // pending sheets. + + return rv; +} + +NS_IMETHODIMP +nsXMLContentSink::SetDocumentCharset(nsACString& aCharset) +{ + if (mDocument) { + mDocument->SetDocumentCharacterSet(aCharset); + } + + return NS_OK; +} + +nsISupports * +nsXMLContentSink::GetTarget() +{ + return 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 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; +} + +StackNode* +nsXMLContentSink::GetCurrentStackNode() +{ + int32_t count = mContentStack.Length(); + return count != 0 ? &mContentStack[count-1] : nullptr; +} + + +nsresult +nsXMLContentSink::PushContent(nsIContent *aContent) +{ + NS_PRECONDITION(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() +{ + int32_t count = mContentStack.Length(); + + if (count == 0) { + NS_WARNING("Popping empty stack"); + return; + } + + mContentStack.RemoveElementAt(count - 1); +} + +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, + nsIAtom* 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); + } + mDocumentChildren.Clear(); + } + + // check for root elements that needs special handling for + // prettyprinting + if ((aNameSpaceID == kNameSpaceID_XBL && + aTagName == nsGkAtoms::bindings) || + (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); + } + } + } + + nsresult rv = mDocument->AppendChildTo(mDocElement, NotifyForDocElement()); + if (NS_FAILED(rv)) { + // 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; + } + + if (aTagName == nsGkAtoms::html && + aNameSpaceID == kNameSpaceID_XHTML) { + ProcessOfflineManifest(aContent); + } + + return true; +} + +NS_IMETHODIMP +nsXMLContentSink::HandleStartElement(const char16_t *aName, + const char16_t **aAtts, + uint32_t aAttsCount, + uint32_t aLineNumber) +{ + return HandleStartElement(aName, aAtts, aAttsCount, aLineNumber, + true); +} + +nsresult +nsXMLContentSink::HandleStartElement(const char16_t *aName, + const char16_t **aAtts, + uint32_t aAttsCount, + uint32_t aLineNumber, + bool aInterruptable) +{ + NS_PRECONDITION(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; + nsCOMPtr 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, + nsIDOMNode::ELEMENT_NODE); + + result = CreateElement(aAtts, aAttsCount, nodeInfo, aLineNumber, + 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); + + if (NS_OK == result) { + // Store the element + if (!SetDocElement(nameSpaceID, localName, content) && appendContent) { + NS_ENSURE_TRUE(parent, NS_ERROR_UNEXPECTED); + + parent->AppendChildTo(content, false); + } + } + + // Some HTML nodes need DoneCreatingElement() called to initialize + // properly (eg form state restoration). + if (nodeInfo->NamespaceID() == kNameSpaceID_XHTML) { + if (nodeInfo->NameAtom() == nsGkAtoms::input || + nodeInfo->NameAtom() == nsGkAtoms::button || + nodeInfo->NameAtom() == nsGkAtoms::menuitem || + nodeInfo->NameAtom() == nsGkAtoms::audio || + nodeInfo->NameAtom() == nsGkAtoms::video) { + content->DoneCreatingElement(); + } else if (nodeInfo->NameAtom() == nsGkAtoms::head && !mCurrentHead) { + mCurrentHead = content; + } + } + + if (IsMonolithicContainer(nodeInfo)) { + mInMonolithicContainer++; + } + + if (!mXSLTProcessor) { + if (content == mDocElement) { + NotifyDocElementCreated(mDocument); + } 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 + nsCOMPtr 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)) || + isTemplateElement, "Wrong element being closed"); +#endif + + 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; + + // We might have had no occasion to start layout yet. Do so now. + MaybeStartLayout(false); + } + + int32_t stackLen = mContentStack.Length(); + if (mNotifyLevel >= stackLen) { + if (numFlushed < content->GetChildCount()) { + NotifyAppend(content, numFlushed); + } + mNotifyLevel = stackLen - 1; + } + DidAddContent(); + + if (content->IsSVGElement(nsGkAtoms::svg)) { + FlushTags(); + nsCOMPtr event = new nsHtml5SVGLoadDispatcher(content); + if (NS_FAILED(NS_DispatchToMainThread(event))) { + 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 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 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(); + + nsresult rv = NS_OK; + + NS_ASSERTION(mDocument, "Shouldn't get here from a document fragment"); + + nsCOMPtr name = NS_Atomize(aName); + NS_ENSURE_TRUE(name, NS_ERROR_OUT_OF_MEMORY); + + // Create a new doctype node + nsCOMPtr docType; + rv = NS_NewDOMDocumentType(getter_AddRefs(docType), mNodeInfoManager, + name, aPublicId, aSystemId, aSubset); + if (NS_FAILED(rv) || !docType) { + return rv; + } + + MOZ_ASSERT(!aCatalogData, "Need to add back support for catalog style " + "sheets"); + + nsCOMPtr content = do_QueryInterface(docType); + NS_ASSERTION(content, "doctype isn't content?"); + + mDocumentChildren.AppendElement(content); + 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); + + nsCOMPtr node = + NS_NewXMLProcessingInstruction(mNodeInfoManager, target, data); + + nsCOMPtr ssle(do_QueryInterface(node)); + if (ssle) { + ssle->InitStyleLinkElement(false); + ssle->SetEnableUpdates(false); + mPrettyPrintXML = false; + } + + nsresult rv = AddContentAsLeaf(node); + NS_ENSURE_SUCCESS(rv, rv); + DidAddContent(); + + if (ssle) { + // This is an xml-stylesheet processing instruction... but it might not be + // a CSS one if the type is set to something else. + ssle->SetEnableUpdates(true); + bool willNotify; + bool isAlternate; + rv = ssle->UpdateStyleSheet(mRunsToCompletion ? nullptr : this, + &willNotify, + &isAlternate); + NS_ENSURE_SUCCESS(rv, rv); + + if (willNotify) { + // Successfully started a stylesheet load + if (!isAlternate && !mRunsToCompletion) { + ++mPendingSheetCount; + mScriptLoader->AddParserBlockingScriptExecutionBlocker(); + } + + return NS_OK; + } + } + + // If it's not a CSS stylesheet PI... + nsAutoString type; + nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::type, type); + + if (mState != eXMLContentSinkState_InProlog || + !target.EqualsLiteral("xml-stylesheet") || + type.IsEmpty() || + type.LowerCaseEqualsLiteral("text/css")) { + return DidProcessATokenImpl(); + } + + 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(); + } + + rv = ProcessStyleLink(node, href, isAlternate, title, type, media); + 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) +{ + NS_PRECONDITION(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(); + nsCOMPtr node(do_QueryInterface(mDocument)); + if (node) { + for (;;) { + nsCOMPtr child, dummy; + node->GetLastChild(getter_AddRefs(child)); + if (!child) + break; + node->RemoveChild(child, getter_AddRefs(dummy)); + } + } + 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 }; + + NS_NAMED_LITERAL_STRING(errorNs, + "http://www.mozilla.org/newlayout/xml/parsererror.xml"); + + 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, + nsIContent* aContent) +{ + // Add tag attributes to the content attributes + nsCOMPtr 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::FlushPendingNotifications(mozFlushType 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 >= Flush_ContentAndNotify) { + FlushTags(); + } + else { + FlushText(false); + } + } + if (aType >= Flush_InterruptibleLayout) { + // 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; + bool oldBeganUpdate = mBeganUpdate; + uint32_t oldUpdates = mUpdatesInNotification; + + mUpdatesInNotification = 0; + ++mInNotification; + { + // Scope so we call EndUpdate before we decrease mInNotification + mozAutoDocUpdate updateBatch(mDocument, UPDATE_CONTENT_MODEL, true); + mBeganUpdate = 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; + mBeganUpdate = oldBeganUpdate; + + 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->NameAtom() == nsGkAtoms::applet)) || + (aNodeInfo->NamespaceID() == kNameSpaceID_MathML && + (aNodeInfo->NameAtom() == nsGkAtoms::math)) + ); +} + +void +nsXMLContentSink::ContinueInterruptedParsingIfEnabled() +{ + if (mParser && mParser->IsParserEnabled()) { + GetParser()->ContinueInterruptedParsing(); + } +} + +void +nsXMLContentSink::ContinueInterruptedParsingAsync() +{ + nsCOMPtr ev = NewRunnableMethod(this, + &nsXMLContentSink::ContinueInterruptedParsingIfEnabled); + + NS_DispatchToCurrentThread(ev); +} + +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 000000000..5e9880b08 --- /dev/null +++ b/dom/xml/nsXMLContentSink.h @@ -0,0 +1,204 @@ +/* -*- 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 nsIDocument; +class nsIURI; +class nsIContent; +class nsIParser; + +namespace mozilla { +namespace dom { +class NodeInfo; +} // namespace dom +} // namespace mozilla + +typedef enum { + eXMLContentSinkState_InProlog, + eXMLContentSinkState_InDocumentElement, + eXMLContentSinkState_InEpilog +} XMLContentSinkState; + +struct StackNode { + nsCOMPtr mContent; + uint32_t mNumFlushed; +}; + +class nsXMLContentSink : public nsContentSink, + public nsIXMLContentSink, + public nsITransformObserver, + public nsIExpatSink +{ +public: + nsXMLContentSink(); + + nsresult Init(nsIDocument* aDoc, + nsIURI* aURL, + nsISupports* aContainer, + nsIChannel* aChannel); + + // nsISupports + NS_DECL_ISUPPORTS_INHERITED + + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(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; + NS_IMETHOD WillResume(void) override; + NS_IMETHOD SetParser(nsParserBase* aParser) override; + virtual void FlushPendingNotifications(mozFlushType aType) override; + NS_IMETHOD SetDocumentCharset(nsACString& aCharset) override; + virtual nsISupports *GetTarget() override; + virtual bool IsScriptExecuting() override; + virtual void ContinueInterruptedParsingAsync() override; + + // nsITransformObserver + NS_IMETHOD OnDocumentCreated(nsIDocument *aResultDocument) override; + NS_IMETHOD OnTransformDone(nsresult aResult, nsIDocument *aResultDocument) override; + + // nsICSSLoaderObserver + NS_IMETHOD StyleSheetLoaded(mozilla::StyleSheet* aSheet, + bool aWasAlternate, + 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, nsIContent* aContent); + nsresult AddText(const char16_t* aString, int32_t aLength); + + virtual bool OnOpenContainer(const char16_t **aAtts, + uint32_t aAttsCount, + int32_t aNameSpaceID, + nsIAtom* 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, + nsIAtom *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, + 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 ProcessStyleLink(nsIContent* aElement, + const nsSubstring& aHref, + bool aAlternate, + const nsSubstring& aTitle, + const nsSubstring& aType, + const nsSubstring& aMedia) override; + + 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, + 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; + nsCOMPtr 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 000000000..45163a1c4 --- /dev/null +++ b/dom/xml/nsXMLElement.cpp @@ -0,0 +1,32 @@ +/* -*- 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::dom; + +nsresult +NS_NewXMLElement(Element** aInstancePtrResult, + already_AddRefed&& aNodeInfo) +{ + nsXMLElement* it = new nsXMLElement(aNodeInfo); + NS_ADDREF(*aInstancePtrResult = it); + return NS_OK; +} + +NS_IMPL_ISUPPORTS_INHERITED(nsXMLElement, Element, + nsIDOMNode, nsIDOMElement) + +JSObject* +nsXMLElement::WrapNode(JSContext *aCx, JS::Handle aGivenProto) +{ + return ElementBinding::Wrap(aCx, this, aGivenProto); +} + +NS_IMPL_ELEMENT_CLONE(nsXMLElement) diff --git a/dom/xml/nsXMLElement.h b/dom/xml/nsXMLElement.h new file mode 100644 index 000000000..d16b82f39 --- /dev/null +++ b/dom/xml/nsXMLElement.h @@ -0,0 +1,44 @@ +/* -*- 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 "nsIDOMElement.h" +#include "mozilla/dom/ElementInlines.h" +#include "mozilla/dom/DOMRect.h" + +class nsXMLElement : public mozilla::dom::Element, + public nsIDOMElement +{ +public: + explicit nsXMLElement(already_AddRefed& aNodeInfo) + : mozilla::dom::Element(aNodeInfo) + { + } + + // nsISupports + NS_DECL_ISUPPORTS_INHERITED + + // nsIDOMNode + NS_FORWARD_NSIDOMNODE_TO_NSINODE + + // nsIDOMElement + NS_FORWARD_NSIDOMELEMENT_TO_GENERIC + + // nsINode interface methods + virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override; + + virtual nsIDOMNode* AsDOMNode() override { return this; } + +protected: + virtual ~nsXMLElement() {} + + 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 000000000..7fa815c84 --- /dev/null +++ b/dom/xml/nsXMLFragmentContentSink.cpp @@ -0,0 +1,431 @@ +/* -*- 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 "nsIDocument.h" +#include "nsIDOMDocumentFragment.h" +#include "nsIContent.h" +#include "nsGkAtoms.h" +#include "mozilla/dom/NodeInfo.h" +#include "nsContentCreatorFunctions.h" +#include "nsError.h" +#include "nsIConsoleService.h" +#include "nsIScriptError.h" +#include "nsTHashtable.h" +#include "nsHashKeys.h" +#include "nsTArray.h" +#include "nsCycleCollectionParticipant.h" +#include "nsIDocShell.h" +#include "nsScriptLoader.h" +#include "mozilla/css/Loader.h" +#include "mozilla/dom/DocumentFragment.h" +#include "mozilla/dom/ProcessingInstruction.h" + +using namespace mozilla::dom; + +class nsXMLFragmentContentSink : public nsXMLContentSink, + public nsIFragmentContentSink +{ +public: + nsXMLFragmentContentSink(); + + NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW + + // nsISupports + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(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; + NS_IMETHOD SetDocumentCharset(nsACString& aCharset) override; + virtual nsISupports* GetTarget() override; + NS_IMETHOD DidProcessATokenImpl(); + + // nsIXMLContentSink + + // nsIFragmentContentSink + NS_IMETHOD FinishFragmentParsing(nsIDOMDocumentFragment** aFragment) override; + NS_IMETHOD SetTargetDocument(nsIDocument* 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, + nsIAtom* aTagName, + nsIContent* aContent) override; + virtual nsresult CreateElement(const char16_t** aAtts, uint32_t aAttsCount, + mozilla::dom::NodeInfo* aNodeInfo, uint32_t aLineNumber, + 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 ProcessStyleLink(nsIContent* aElement, + const nsSubstring& aHref, + bool aAlternate, + const nsSubstring& aTitle, + const nsSubstring& aType, + const nsSubstring& aMedia) override; + nsresult LoadXSLStyleSheet(nsIURI* aUrl); + void StartLayout(); + + nsCOMPtr mTargetDocument; + // the fragment + nsCOMPtr 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() +{ +} + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(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_CLASS(nsXMLFragmentContentSink) + +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXMLFragmentContentSink, + nsXMLContentSink) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTargetDocument) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRoot) +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END + +NS_IMETHODIMP +nsXMLFragmentContentSink::WillBuildModel(nsDTDMode aDTDMode) +{ + if (mRoot) { + return NS_OK; + } + + mState = eXMLContentSinkState_InDocumentElement; + + NS_ASSERTION(mTargetDocument, "Need a document!"); + + mRoot = new 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; +} + +NS_IMETHODIMP +nsXMLFragmentContentSink::SetDocumentCharset(nsACString& aCharset) +{ + NS_NOTREACHED("fragments shouldn't set charset"); + return NS_OK; +} + +nsISupports * +nsXMLFragmentContentSink::GetTarget() +{ + return mTargetDocument; +} + +//////////////////////////////////////////////////////////////////////// + +bool +nsXMLFragmentContentSink::SetDocElement(int32_t aNameSpaceID, + nsIAtom* 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, + 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, + 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); + NS_ASSERTION(sele, "script did QI correctly!"); + sele->PreventExecution(); + } + return NS_OK; +} + +void +nsXMLFragmentContentSink::MaybeStartLayout(bool aIgnorePendingSheets) +{ + return; +} + +//////////////////////////////////////////////////////////////////////// + +NS_IMETHODIMP +nsXMLFragmentContentSink::HandleDoctypeDecl(const nsAString & aSubset, + const nsAString & aName, + const nsAString & aSystemId, + const nsAString & aPublicId, + nsISupports* aCatalogData) +{ + NS_NOTREACHED("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) +{ + NS_NOTREACHED("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) +{ + NS_PRECONDITION(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 + nsCOMPtr node(do_QueryInterface(mRoot)); + if (node) { + for (;;) { + nsCOMPtr child, dummy; + node->GetLastChild(getter_AddRefs(child)); + if (!child) + break; + node->RemoveChild(child, getter_AddRefs(dummy)); + } + } + + // 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::ProcessStyleLink(nsIContent* aElement, + const nsSubstring& aHref, + bool aAlternate, + const nsSubstring& aTitle, + const nsSubstring& aType, + const nsSubstring& aMedia) +{ + // don't process until moved to document + return NS_OK; +} + +nsresult +nsXMLFragmentContentSink::LoadXSLStyleSheet(nsIURI* aUrl) +{ + NS_NOTREACHED("fragments shouldn't have XSL style sheets"); + return NS_ERROR_UNEXPECTED; +} + +void +nsXMLFragmentContentSink::StartLayout() +{ + NS_NOTREACHED("fragments shouldn't layout"); +} + +//////////////////////////////////////////////////////////////////////// + +NS_IMETHODIMP +nsXMLFragmentContentSink::FinishFragmentParsing(nsIDOMDocumentFragment** aFragment) +{ + *aFragment = nullptr; + 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; + return NS_ERROR_DOM_SYNTAX_ERR; + } else if (mRoot) { + nsresult rv = CallQueryInterface(mRoot, aFragment); + mRoot = nullptr; + return rv; + } else { + return NS_OK; + } +} + +NS_IMETHODIMP +nsXMLFragmentContentSink::SetTargetDocument(nsIDocument* 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() +{ + NS_NOTREACHED("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 000000000..2e086dde0 --- /dev/null +++ b/dom/xml/nsXMLPrettyPrinter.cpp @@ -0,0 +1,268 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* 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 "nsIDOMDocumentXBL.h" +#include "nsIObserver.h" +#include "nsIXSLTProcessor.h" +#include "nsSyncLoadService.h" +#include "nsPIDOMWindow.h" +#include "nsIDOMElement.h" +#include "nsIServiceManager.h" +#include "nsNetUtil.h" +#include "mozilla/dom/Element.h" +#include "nsIDOMDocumentFragment.h" +#include "nsBindingManager.h" +#include "nsXBLService.h" +#include "nsIScriptSecurityManager.h" +#include "mozilla/Preferences.h" +#include "nsIDocument.h" +#include "nsVariant.h" +#include "mozilla/dom/CustomEvent.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(nsIDocument* aDocument, + bool* aDidPrettyPrint) +{ + *aDidPrettyPrint = false; + + // Check for iframe with display:none. Such iframes don't have presshells + if (!aDocument->GetShell()) { + return NS_OK; + } + + // check if we're in an invisible iframe + nsPIDOMWindowOuter *internalWin = aDocument->GetWindow(); + nsCOMPtr frameElem; + if (internalWin) { + frameElem = internalWin->GetFrameElementInternal(); + } + + if (frameElem) { + nsCOMPtr computedStyle; + if (nsIDocument* frameOwnerDoc = frameElem->OwnerDoc()) { + nsPIDOMWindowOuter* window = frameOwnerDoc->GetDefaultView(); + if (window) { + nsCOMPtr innerWindow = + window->GetCurrentInnerWindow(); + + ErrorResult dummy; + computedStyle = innerWindow->GetComputedStyle(*frameElem, + EmptyString(), + dummy); + dummy.SuppressException(); + } + } + + if (computedStyle) { + nsAutoString visibility; + computedStyle->GetPropertyValue(NS_LITERAL_STRING("visibility"), + visibility); + if (!visibility.EqualsLiteral("visible")) { + + return NS_OK; + } + } + } + + // check the pref + if (!Preferences::GetBool("layout.xml.prettyprint", true)) { + return NS_OK; + } + + // 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), + NS_LITERAL_CSTRING("chrome://global/content/xml/XMLPrettyPrint.xsl")); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr xslDocument; + rv = nsSyncLoadService::LoadDocument(xslUri, nsIContentPolicy::TYPE_XSLT, + nsContentUtils::GetSystemPrincipal(), + nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL, + nullptr, true, mozilla::net::RP_Default, + getter_AddRefs(xslDocument)); + NS_ENSURE_SUCCESS(rv, rv); + + // Transform the document + nsCOMPtr transformer = + do_CreateInstance("@mozilla.org/document-transformer;1?type=xslt", &rv); + NS_ENSURE_SUCCESS(rv, rv); + + rv = transformer->ImportStylesheet(xslDocument); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr resultFragment; + nsCOMPtr sourceDocument = do_QueryInterface(aDocument); + rv = transformer->TransformToFragment(sourceDocument, sourceDocument, + getter_AddRefs(resultFragment)); + NS_ENSURE_SUCCESS(rv, rv); + + // + // Apply the prettprint XBL binding. + // + // We take some shortcuts here. In particular, we don't bother invoking the + // contstructor (since the binding has no constructor), and we don't bother + // calling LoadBindingDocument because it's a chrome:// URI and thus will get + // sync loaded no matter what. + // + + // Grab the XBL service. + nsXBLService* xblService = nsXBLService::GetInstance(); + NS_ENSURE_TRUE(xblService, NS_ERROR_NOT_AVAILABLE); + + // Compute the binding URI. + nsCOMPtr bindingUri; + rv = NS_NewURI(getter_AddRefs(bindingUri), + NS_LITERAL_STRING("chrome://global/content/xml/XMLPrettyPrint.xml#prettyprint")); + NS_ENSURE_SUCCESS(rv, rv); + + // Compute the bound element. + nsCOMPtr rootCont = aDocument->GetRootElement(); + NS_ENSURE_TRUE(rootCont, NS_ERROR_UNEXPECTED); + + // Grab the system principal. + nsCOMPtr sysPrincipal; + nsContentUtils::GetSecurityManager()-> + GetSystemPrincipal(getter_AddRefs(sysPrincipal)); + + // Load the bindings. + RefPtr unused; + bool ignored; + rv = xblService->LoadBindings(rootCont, bindingUri, sysPrincipal, + getter_AddRefs(unused), &ignored); + NS_ENSURE_SUCCESS(rv, rv); + + // Fire an event at the bound element to pass it |resultFragment|. + RefPtr event = + NS_NewDOMCustomEvent(rootCont, nullptr, nullptr); + MOZ_ASSERT(event); + nsCOMPtr resultFragmentVariant = new nsVariant(); + rv = resultFragmentVariant->SetAsISupports(resultFragment); + MOZ_ASSERT(NS_SUCCEEDED(rv)); + rv = event->InitCustomEvent(NS_LITERAL_STRING("prettyprint-dom-created"), + /* bubbles = */ false, /* cancelable = */ false, + /* detail = */ resultFragmentVariant); + NS_ENSURE_SUCCESS(rv, rv); + event->SetTrusted(true); + bool dummy; + rv = rootCont->DispatchEvent(event, &dummy); + NS_ENSURE_SUCCESS(rv, rv); + + // 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 there either aContent is null (the document-node was modified) or + // there isn't a binding parent we know it's non-anonymous content. + if ((!aContent || !aContent->GetBindingParent()) && !mUnhookPending) { + // Can't blindly to mUnhookPending after AddScriptRunner, + // since AddScriptRunner _could_ in theory run us + // synchronously + mUnhookPending = true; + nsContentUtils::AddScriptRunner( + NewRunnableMethod(this, &nsXMLPrettyPrinter::Unhook)); + } +} + +void +nsXMLPrettyPrinter::Unhook() +{ + mDocument->RemoveObserver(this); + nsCOMPtr element = mDocument->GetDocumentElement(); + + if (element) { + mDocument->BindingManager()->ClearBinding(element); + } + + mDocument = nullptr; + + NS_RELEASE_THIS(); +} + +void +nsXMLPrettyPrinter::AttributeChanged(nsIDocument* aDocument, + Element* aElement, + int32_t aNameSpaceID, + nsIAtom* aAttribute, + int32_t aModType, + const nsAttrValue* aOldValue) +{ + MaybeUnhook(aElement); +} + +void +nsXMLPrettyPrinter::ContentAppended(nsIDocument* aDocument, + nsIContent* aContainer, + nsIContent* aFirstNewContent, + int32_t aNewIndexInContainer) +{ + MaybeUnhook(aContainer); +} + +void +nsXMLPrettyPrinter::ContentInserted(nsIDocument* aDocument, + nsIContent* aContainer, + nsIContent* aChild, + int32_t aIndexInContainer) +{ + MaybeUnhook(aContainer); +} + +void +nsXMLPrettyPrinter::ContentRemoved(nsIDocument* aDocument, + nsIContent* aContainer, + nsIContent* aChild, + int32_t aIndexInContainer, + nsIContent* aPreviousSibling) +{ + MaybeUnhook(aContainer); +} + +void +nsXMLPrettyPrinter::NodeWillBeDestroyed(const 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 000000000..0f1f2f23a --- /dev/null +++ b/dom/xml/nsXMLPrettyPrinter.h @@ -0,0 +1,59 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* 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 nsIDocument; + +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(nsIDocument* aDocument, bool* aDidPrettyPrint); + + /** + * Unhook the prettyprinter + */ + void Unhook(); +private: + virtual ~nsXMLPrettyPrinter(); + + /** + * Signals for unhooking by setting mUnhookPending if the node changed is + * non-anonymous content. + * + * @param aContent content that has changed + */ + void MaybeUnhook(nsIContent* aContent); + + nsIDocument* 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/XMLMonoPrint.css b/dom/xml/resources/XMLMonoPrint.css new file mode 100644 index 000000000..598daba22 --- /dev/null +++ b/dom/xml/resources/XMLMonoPrint.css @@ -0,0 +1,11 @@ +@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("chrome://global/content/xml/XMLPrettyPrint.css"); + +#top > .expander-open { + font-family: monospace; + white-space: pre; +} diff --git a/dom/xml/resources/XMLPrettyPrint.css b/dom/xml/resources/XMLPrettyPrint.css new file mode 100644 index 000000000..efc7ab5e5 --- /dev/null +++ b/dom/xml/resources/XMLPrettyPrint.css @@ -0,0 +1,41 @@ +@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://gre-resources/viewsource.css"); + +#header { + background-color: #ccc; + border-bottom: 3px solid black; + padding: 0.5em; + margin-bottom: 1em; +} + +.expander-content { + padding-left: 1em; +} + +.expander { + cursor: pointer; + -moz-user-select: none; + text-align: center; + vertical-align: top; + width: 1em; + display: inline-block; + margin-left: -1em; +} + +#top > .expander-open, #top > .expander-closed { + margin-left: 1em; +} + +.expander-closed > .expander-content { + display: none; +} + +.comment { + font-family: monospace; + white-space: pre; +} + diff --git a/dom/xml/resources/XMLPrettyPrint.xml b/dom/xml/resources/XMLPrettyPrint.xml new file mode 100644 index 000000000..522d37210 --- /dev/null +++ b/dom/xml/resources/XMLPrettyPrint.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dom/xml/resources/XMLPrettyPrint.xsl b/dom/xml/resources/XMLPrettyPrint.xsl new file mode 100644 index 000000000..bdd9b7287 --- /dev/null +++ b/dom/xml/resources/XMLPrettyPrint.xsl @@ -0,0 +1,137 @@ + + + + + %prettyPrintDTD; + + %globalDTD; +]> + + + + + + + + + + + + + +
+ < + + + /> +
+
+ + +
+ < + + + > + + + + </ + + > +
+
+ + +
+ + + < + + + > + +
+ + </ + + > +
+
+ + + + + = + "" + + + + + + + + + +
+ <? + + + + ?> +
+
+ + +
+ + + + <? + + +
+ + ?> + +
+
+ + +
+ <!-- + + --> +
+
+ + +
+ + + + <!-- + +
+ +
+ + --> + +
+
+ + +
+
+ +
diff --git a/dom/xml/resources/jar.mn b/dom/xml/resources/jar.mn new file mode 100644 index 000000000..4ad311385 --- /dev/null +++ b/dom/xml/resources/jar.mn @@ -0,0 +1,9 @@ +# 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/XMLMonoPrint.css (XMLMonoPrint.css) + content/global/xml/XMLPrettyPrint.xml (XMLPrettyPrint.xml) + 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 000000000..eb4454d28 --- /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'] \ No newline at end of file diff --git a/dom/xml/test/file_bug293347.xml b/dom/xml/test/file_bug293347.xml new file mode 100644 index 000000000..d041450e2 --- /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 000000000..44df7749e --- /dev/null +++ b/dom/xml/test/file_bug293347xslt.xml @@ -0,0 +1,19 @@ + + + + +
+
+ +
+ + +
+
diff --git a/dom/xml/test/file_bug392338.js b/dom/xml/test/file_bug392338.js new file mode 100644 index 000000000..1a433353b --- /dev/null +++ b/dom/xml/test/file_bug392338.js @@ -0,0 +1,22 @@ +Components.utils.import("resource://gre/modules/Services.jsm"); + +var modifyObserver = { + observe: function(subject, topic, data) { + if (topic == 'http-on-modify-request') { + var testOk = false; + try { + // We should be able to QI the request to an nsIChannel, then get + // the notificationCallbacks without throwing an exception. + var ir = subject.QueryInterface(Components.interfaces.nsIChannel).notificationCallbacks; + + // The notificationCallbacks should be an nsIInterfaceRequestor. + testOk = ir.toString().indexOf(Components.interfaces.nsIInterfaceRequestor) != -1; + } catch (e) { + } + sendAsyncMessage('modify-request-completed', testOk); + Services.obs.removeObserver(modifyObserver, 'http-on-modify-request'); + } + } +}; + +Services.obs.addObserver(modifyObserver, 'http-on-modify-request', false); diff --git a/dom/xml/test/mochitest.ini b/dom/xml/test/mochitest.ini new file mode 100644 index 000000000..f58f36f36 --- /dev/null +++ b/dom/xml/test/mochitest.ini @@ -0,0 +1,15 @@ +[DEFAULT] +support-files = + file_bug293347.xml + file_bug293347xslt.xml + file_bug392338.js + +[test_bug232004.xhtml] +[test_bug293347.html] +[test_bug343870.xhtml] +[test_bug355213.xhtml] +[test_bug392338.html] +[test_bug399502.xhtml] +[test_bug445330.html] +[test_bug691215.html] +[test_viewport.xhtml] diff --git a/dom/xml/test/old/books/bethlehem.gif b/dom/xml/test/old/books/bethlehem.gif new file mode 100644 index 000000000..db41f52fb 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 000000000..4b00f890c 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 000000000..3e4a01d11 --- /dev/null +++ b/dom/xml/test/old/books/books.js @@ -0,0 +1,97 @@ + +// 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 000000000..2067487d8 --- /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 000000000..9a63fb0b2 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 000000000..1ebc92f6e --- /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 000000000..d63f09585 --- /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 000000000..df2b371d0 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 000000000..3b5d40891 --- /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 000000000..5ba7920c7 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 000000000..7ff24a99e 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 000000000..562c8d213 --- /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 000000000..d47c3cb12 --- /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 000000000..5a05df583 Binary files /dev/null and b/dom/xml/test/old/flamer.gif differ diff --git a/dom/xml/test/old/load/display.css b/dom/xml/test/old/load/display.css new file mode 100644 index 000000000..c5470194b --- /dev/null +++ b/dom/xml/test/old/load/display.css @@ -0,0 +1,298 @@ +/** + * A CSS test file for display.xml + * + * This file is intentionally long to make parsing + * it last a little longer. + */ + +/*********************************************** + * S O M E C O M M E N T S * + **********************************************/ +doc { + display: block; +} + +/*********************************************** + * S O M E C O M M E N T S * + **********************************************/ +foo { + display: block; +} + +/*********************************************** + * S O M E C O M M E N T S * + **********************************************/ +d { + display: block; + color: red; +} + +/*********************************************** + * S O M E C O M M E N T S * + **********************************************/ +f1 { + display: block; + color: red; + text-decoration: underline; +} + +/*********************************************** + * S O M E C O M M E N T S * + **********************************************/ +f2 { + display: block; + color: red; + text-decoration: underline; +} + +/*********************************************** + * S O M E C O M M E N T S * + **********************************************/ +f3 { + display: block; + color: red; + text-decoration: underline; +} + +/*********************************************** + * S O M E C O M M E N T S * + **********************************************/ +f4 { + display: block; + color: red; + text-decoration: underline; +} + +/*********************************************** + * S O M E C O M M E N T S * + **********************************************/ +f5 { + display: block; + color: red; + text-decoration: underline; +} + +/*********************************************** + * S O M E C O M M E N T S * + **********************************************/ +f6 { + display: block; + color: red; + text-decoration: underline; +} + +/*********************************************** + * S O M E C O M M E N T S * + **********************************************/ +f7 { + display: block; + color: red; + text-decoration: underline; +} + +/*********************************************** + * S O M E C O M M E N T S * + **********************************************/ +f8 { + display: block; + color: red; + text-decoration: underline; +} + +/*********************************************** + * S O M E C O M M E N T S * + **********************************************/ +f9 { + display: block; + color: red; + text-decoration: underline; +} + +/*********************************************** + * S O M E C O M M E N T S * + **********************************************/ +f10 { + display: block; + color: red; + text-decoration: underline; +} + +/*********************************************** + * S O M E C O M M E N T S * + **********************************************/ +f11 { + display: block; + color: red; + text-decoration: underline; +} + +/*********************************************** + * S O M E C O M M E N T S * + **********************************************/ +f12 { + display: block; + color: red; + text-decoration: underline; +} + +/*********************************************** + * S O M E C O M M E N T S * + **********************************************/ +f13 { + display: block; + color: red; + text-decoration: underline; +} + +/*********************************************** + * S O M E C O M M E N T S * + **********************************************/ +f14 { + display: block; + color: red; + text-decoration: underline; +} + +/*********************************************** + * S O M E C O M M E N T S * + **********************************************/ +f15 { + display: block; + color: red; + text-decoration: underline; +} + +/*********************************************** + * S O M E C O M M E N T S * + **********************************************/ +f21 { + display: block; + color: red; + text-decoration: underline; +} + +/*********************************************** + * S O M E C O M M E N T S * + **********************************************/ +f22 { + display: block; + color: red; + text-decoration: underline; +} + +/*********************************************** + * S O M E C O M M E N T S * + **********************************************/ +f23 { + display: block; + color: red; + text-decoration: underline; +} + +/*********************************************** + * S O M E C O M M E N T S * + **********************************************/ +f24 { + display: block; + color: red; + text-decoration: underline; +} + +/*********************************************** + * S O M E C O M M E N T S * + **********************************************/ +f25 { + display: block; + color: red; + text-decoration: underline; +} + +/*********************************************** + * S O M E C O M M E N T S * + **********************************************/ +f26 { + display: block; + color: red; + text-decoration: underline; +} + +/*********************************************** + * S O M E C O M M E N T S * + **********************************************/ +f27 { + display: block; + color: red; + text-decoration: underline; +} + +/*********************************************** + * S O M E C O M M E N T S * + **********************************************/ +f28 { + display: block; + color: red; + text-decoration: underline; +} + +/*********************************************** + * S O M E C O M M E N T S * + **********************************************/ +f29 { + display: block; + color: red; + text-decoration: underline; +} + +/*********************************************** + * S O M E C O M M E N T S * + **********************************************/ +f210 { + display: block; + color: red; + text-decoration: underline; +} + +/*********************************************** + * S O M E C O M M E N T S * + **********************************************/ +f211 { + display: block; + color: red; + text-decoration: underline; +} + +/*********************************************** + * S O M E C O M M E N T S * + **********************************************/ +f212 { + display: block; + color: red; + text-decoration: underline; +} + +/*********************************************** + * S O M E C O M M E N T S * + **********************************************/ +f213 { + display: block; + color: red; + text-decoration: underline; +} + +/*********************************************** + * S O M E C O M M E N T S * + **********************************************/ +f214 { + display: block; + color: red; + text-decoration: underline; +} + +/*********************************************** + * S O M E C O M M E N T S * + **********************************************/ +f215 { + display: block; + color: red; + text-decoration: underline; +} diff --git a/dom/xml/test/old/load/display.xml b/dom/xml/test/old/load/display.xml new file mode 100644 index 000000000..25a0e3026 --- /dev/null +++ b/dom/xml/test/old/load/display.xml @@ -0,0 +1,9 @@ + + + +]> + + One Two + Three + \ No newline at end of file diff --git a/dom/xml/test/old/load/load.html b/dom/xml/test/old/load/load.html new file mode 100644 index 000000000..f385ade42 --- /dev/null +++ b/dom/xml/test/old/load/load.html @@ -0,0 +1,56 @@ + + +Synchronized document.load() test + + + + +

Synchronized document.load() test

+ +
XML document serialized +
@@No result@@
+
+
Event information +
@@No result@@
+
+ + + + diff --git a/dom/xml/test/old/load/loadauth.html b/dom/xml/test/old/load/loadauth.html new file mode 100644 index 000000000..8f638525d --- /dev/null +++ b/dom/xml/test/old/load/loadauth.html @@ -0,0 +1,57 @@ + + +Synchronized document.load() test + + + + +

Synchronized document.load() test

+ +
XML document serialized +
@@No result@@
+
+
Event information +
@@No result@@
+
+ + + + diff --git a/dom/xml/test/old/load/loaddisplay.html b/dom/xml/test/old/load/loaddisplay.html new file mode 100644 index 000000000..9da8167a7 --- /dev/null +++ b/dom/xml/test/old/load/loaddisplay.html @@ -0,0 +1,56 @@ + + +Synchronized document.load() test + + + + +

Synchronized document.load() test

+ +
XML document serialized +
@@No result@@
+
+
Event information +
@@No result@@
+
+ + + + diff --git a/dom/xml/test/old/load/test.xml b/dom/xml/test/old/load/test.xml new file mode 100644 index 000000000..1c877acb4 --- /dev/null +++ b/dom/xml/test/old/load/test.xml @@ -0,0 +1,7 @@ + + +]> + +

Text from sample XML document.

+
\ No newline at end of file diff --git a/dom/xml/test/old/script.xml b/dom/xml/test/old/script.xml new file mode 100644 index 000000000..f21d30d97 --- /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 000000000..c94708c66 --- /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 000000000..778c4244c --- /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 000000000..daab0ca3a 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 000000000..8adf8d6ad 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 000000000..55446e34c 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 000000000..520eef3de --- /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 000000000..99c0c9d32 --- /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 000000000..9825dbe5f --- /dev/null +++ b/dom/xml/test/old/toc/toc.js @@ -0,0 +1,117 @@ +/* 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 == 0) { + 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 000000000..91eb15ff4 --- /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 000000000..19dc52198 --- /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 000000000..fd7d49fc1 --- /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 000000000..a100186bb --- /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 000000000..b4cce1dc5 --- /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 000000000..9f8d1e4b7 --- /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 000000000..859914b90 --- /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 000000000..35c604394 --- /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 000000000..11f8817c4 --- /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_bug392338.html b/dom/xml/test/test_bug392338.html new file mode 100644 index 000000000..024d7453b --- /dev/null +++ b/dom/xml/test/test_bug392338.html @@ -0,0 +1,42 @@ + + + + + Test for Bug 392338 + + + + +Mozilla Bug 392338 +

+ +
+
+
+ + + diff --git a/dom/xml/test/test_bug399502.xhtml b/dom/xml/test/test_bug399502.xhtml new file mode 100644 index 000000000..3f835cc0b --- /dev/null +++ b/dom/xml/test/test_bug399502.xhtml @@ -0,0 +1,41 @@ + + + + + Test for Bug 399502 + + + + +Mozilla Bug 399502 +

+ +
+
+
+ + + diff --git a/dom/xml/test/test_bug445330.html b/dom/xml/test/test_bug445330.html new file mode 100644 index 000000000..137b20ba3 --- /dev/null +++ b/dom/xml/test/test_bug445330.html @@ -0,0 +1,55 @@ + + + + + Test for Bug 445330 + + + + +Mozilla Bug 445330 +

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

+ +
+
+
+ + diff --git a/dom/xml/test/test_viewport.xhtml b/dom/xml/test/test_viewport.xhtml new file mode 100644 index 000000000..de4ef7135 --- /dev/null +++ b/dom/xml/test/test_viewport.xhtml @@ -0,0 +1,57 @@ + + + + + + + Test for Viewport META Tag Parsing + + + + +Mozilla Bug 436083 +
+
+
+ + -- cgit v1.2.3