1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "mozilla/dom/XMLDocument.h"
8 #include "nsCharsetSource.h"
9 #include "nsIXMLContentSink.h"
10 #include "nsPresContext.h"
11 #include "nsIContent.h"
12 #include "nsIDocShell.h"
13 #include "nsHTMLParts.h"
17 #include "nsNetUtil.h"
19 #include "nsIPrincipal.h"
20 #include "nsLayoutCID.h"
21 #include "mozilla/dom/Attr.h"
22 #include "nsCExternalHandlerService.h"
23 #include "nsMimeTypes.h"
24 #include "nsContentUtils.h"
25 #include "nsThreadUtils.h"
26 #include "nsJSUtils.h"
28 #include "nsComponentManagerUtils.h"
29 #include "nsContentCreatorFunctions.h"
30 #include "nsContentPolicyUtils.h"
31 #include "nsIConsoleService.h"
32 #include "nsIScriptError.h"
33 #include "nsHTMLDocument.h"
35 #include "mozilla/BasicEvents.h"
36 #include "mozilla/EventDispatcher.h"
37 #include "mozilla/Encoding.h"
38 #include "mozilla/dom/DocumentType.h"
39 #include "mozilla/dom/Element.h"
40 #include "mozilla/dom/DocGroup.h"
41 #include "mozilla/dom/XMLDocumentBinding.h"
42 #include "mozilla/dom/DocumentBinding.h"
44 using namespace mozilla
;
45 using namespace mozilla::dom
;
47 // ==================================================================
49 // ==================================================================
51 nsresult
NS_NewDOMDocument(Document
** aInstancePtrResult
,
52 const nsAString
& aNamespaceURI
,
53 const nsAString
& aQualifiedName
,
54 DocumentType
* aDoctype
, nsIURI
* aDocumentURI
,
55 nsIURI
* aBaseURI
, nsIPrincipal
* aPrincipal
,
56 bool aLoadedAsData
, nsIGlobalObject
* aEventObject
,
57 DocumentFlavor aFlavor
) {
58 // Note: can't require that aDocumentURI/aBaseURI/aPrincipal be non-null,
59 // since at least one caller (XMLHttpRequest) doesn't have decent args to
64 *aInstancePtrResult
= nullptr;
69 if (aFlavor
== DocumentFlavorSVG
) {
70 rv
= NS_NewSVGDocument(getter_AddRefs(d
));
71 } else if (aFlavor
== DocumentFlavorHTML
) {
72 rv
= NS_NewHTMLDocument(getter_AddRefs(d
));
74 } else if (aFlavor
== DocumentFlavorXML
) {
75 rv
= NS_NewXMLDocument(getter_AddRefs(d
));
76 } else if (aFlavor
== DocumentFlavorPlain
) {
77 rv
= NS_NewXMLDocument(getter_AddRefs(d
), aLoadedAsData
, true);
78 } else if (aDoctype
) {
79 MOZ_ASSERT(aFlavor
== DocumentFlavorLegacyGuess
);
80 nsAutoString publicId
, name
;
81 aDoctype
->GetPublicId(publicId
);
82 if (publicId
.IsEmpty()) {
83 aDoctype
->GetName(name
);
85 if (name
.EqualsLiteral("html") ||
86 publicId
.EqualsLiteral("-//W3C//DTD HTML 4.01//EN") ||
87 publicId
.EqualsLiteral("-//W3C//DTD HTML 4.01 Frameset//EN") ||
88 publicId
.EqualsLiteral("-//W3C//DTD HTML 4.01 Transitional//EN") ||
89 publicId
.EqualsLiteral("-//W3C//DTD HTML 4.0//EN") ||
90 publicId
.EqualsLiteral("-//W3C//DTD HTML 4.0 Frameset//EN") ||
91 publicId
.EqualsLiteral("-//W3C//DTD HTML 4.0 Transitional//EN")) {
92 rv
= NS_NewHTMLDocument(getter_AddRefs(d
));
94 } else if (publicId
.EqualsLiteral("-//W3C//DTD XHTML 1.0 Strict//EN") ||
95 publicId
.EqualsLiteral(
96 "-//W3C//DTD XHTML 1.0 Transitional//EN") ||
97 publicId
.EqualsLiteral("-//W3C//DTD XHTML 1.0 Frameset//EN")) {
98 rv
= NS_NewHTMLDocument(getter_AddRefs(d
));
101 } else if (publicId
.EqualsLiteral("-//W3C//DTD SVG 1.1//EN")) {
102 rv
= NS_NewSVGDocument(getter_AddRefs(d
));
104 // XXX Add support for XUL documents.
106 rv
= NS_NewXMLDocument(getter_AddRefs(d
));
109 MOZ_ASSERT(aFlavor
== DocumentFlavorLegacyGuess
);
110 rv
= NS_NewXMLDocument(getter_AddRefs(d
));
118 d
->SetCompatibilityMode(eCompatibility_FullStandards
);
119 d
->AsHTMLDocument()->SetIsXHTML(isXHTML
);
121 d
->SetLoadedAsData(aLoadedAsData
, /* aConsiderForMemoryReporting */ true);
122 d
->SetDocumentURI(aDocumentURI
);
123 // Must set the principal first, since SetBaseURI checks it.
124 d
->SetPrincipals(aPrincipal
, aPrincipal
);
125 d
->SetBaseURI(aBaseURI
);
127 // We need to set the script handling object after we set the principal such
128 // that the doc group is assigned correctly.
129 if (nsCOMPtr
<nsIScriptGlobalObject
> sgo
= do_QueryInterface(aEventObject
)) {
130 d
->SetScriptHandlingObject(sgo
);
131 } else if (aEventObject
) {
132 d
->SetScopeObject(aEventObject
);
135 // XMLDocuments and documents "created in memory" get to be UTF-8 by default,
136 // unlike the legacy HTML mess
137 d
->SetDocumentCharacterSet(UTF_8_ENCODING
);
141 d
->AppendChild(*aDoctype
, result
);
142 // Need to WouldReportJSException() if our callee can throw a JS
143 // exception (which it can) and we're neither propagating the
144 // error out nor unconditionally suppressing it.
145 result
.WouldReportJSException();
146 if (NS_WARN_IF(result
.Failed())) {
147 return result
.StealNSResult();
151 if (!aQualifiedName
.IsEmpty()) {
153 ElementCreationOptionsOrString options
;
154 Unused
<< options
.SetAsString();
156 nsCOMPtr
<Element
> root
=
157 d
->CreateElementNS(aNamespaceURI
, aQualifiedName
, options
, result
);
158 if (NS_WARN_IF(result
.Failed())) {
159 return result
.StealNSResult();
162 d
->AppendChild(*root
, result
);
163 // Need to WouldReportJSException() if our callee can throw a JS
164 // exception (which it can) and we're neither propagating the
165 // error out nor unconditionally suppressing it.
166 result
.WouldReportJSException();
167 if (NS_WARN_IF(result
.Failed())) {
168 return result
.StealNSResult();
172 d
.forget(aInstancePtrResult
);
177 nsresult
NS_NewXMLDocument(Document
** aInstancePtrResult
, bool aLoadedAsData
,
178 bool aIsPlainDocument
) {
179 RefPtr
<XMLDocument
> doc
= new XMLDocument();
181 nsresult rv
= doc
->Init();
184 *aInstancePtrResult
= nullptr;
188 doc
->SetLoadedAsData(aLoadedAsData
, /* aConsiderForMemoryReporting */ true);
189 doc
->mIsPlainDocument
= aIsPlainDocument
;
190 doc
.forget(aInstancePtrResult
);
195 namespace mozilla::dom
{
197 XMLDocument::XMLDocument(const char* aContentType
)
198 : Document(aContentType
),
199 mChannelIsPending(false),
200 mIsPlainDocument(false),
201 mSuppressParserErrorElement(false),
202 mSuppressParserErrorConsoleMessages(false) {
206 nsresult
XMLDocument::Init() {
207 nsresult rv
= Document::Init();
208 NS_ENSURE_SUCCESS(rv
, rv
);
213 void XMLDocument::Reset(nsIChannel
* aChannel
, nsILoadGroup
* aLoadGroup
) {
214 Document::Reset(aChannel
, aLoadGroup
);
217 void XMLDocument::ResetToURI(nsIURI
* aURI
, nsILoadGroup
* aLoadGroup
,
218 nsIPrincipal
* aPrincipal
,
219 nsIPrincipal
* aPartitionedPrincipal
) {
220 if (mChannelIsPending
) {
222 mChannel
->CancelWithReason(NS_BINDING_ABORTED
,
223 "XMLDocument::ResetToURI"_ns
);
224 mChannelIsPending
= false;
227 Document::ResetToURI(aURI
, aLoadGroup
, aPrincipal
, aPartitionedPrincipal
);
230 void XMLDocument::SetSuppressParserErrorElement(bool aSuppress
) {
231 mSuppressParserErrorElement
= aSuppress
;
234 bool XMLDocument::SuppressParserErrorElement() {
235 return mSuppressParserErrorElement
;
238 void XMLDocument::SetSuppressParserErrorConsoleMessages(bool aSuppress
) {
239 mSuppressParserErrorConsoleMessages
= aSuppress
;
242 bool XMLDocument::SuppressParserErrorConsoleMessages() {
243 return mSuppressParserErrorConsoleMessages
;
246 nsresult
XMLDocument::StartDocumentLoad(
247 const char* aCommand
, nsIChannel
* aChannel
, nsILoadGroup
* aLoadGroup
,
248 nsISupports
* aContainer
, nsIStreamListener
** aDocListener
, bool aReset
) {
249 nsresult rv
= Document::StartDocumentLoad(aCommand
, aChannel
, aLoadGroup
,
250 aContainer
, aDocListener
, aReset
);
251 if (NS_FAILED(rv
)) return rv
;
253 int32_t charsetSource
= kCharsetFromDocTypeDefault
;
254 NotNull
<const Encoding
*> encoding
= UTF_8_ENCODING
;
255 TryChannelCharset(aChannel
, charsetSource
, encoding
, nullptr);
257 nsCOMPtr
<nsIURI
> aUrl
;
258 rv
= aChannel
->GetURI(getter_AddRefs(aUrl
));
259 if (NS_FAILED(rv
)) return rv
;
261 mParser
= new nsParser();
263 nsCOMPtr
<nsIXMLContentSink
> sink
;
265 nsCOMPtr
<nsIDocShell
> docShell
;
267 docShell
= do_QueryInterface(aContainer
);
268 NS_ENSURE_TRUE(docShell
, NS_ERROR_FAILURE
);
270 rv
= NS_NewXMLContentSink(getter_AddRefs(sink
), this, aUrl
, docShell
,
272 NS_ENSURE_SUCCESS(rv
, rv
);
274 // Set the parser as the stream listener for the document loader...
275 rv
= CallQueryInterface(mParser
, aDocListener
);
276 NS_ENSURE_SUCCESS(rv
, rv
);
278 NS_ASSERTION(mChannel
, "How can we not have a channel here?");
279 mChannelIsPending
= true;
281 SetDocumentCharacterSet(encoding
);
282 mParser
->SetDocumentCharset(encoding
, charsetSource
);
283 mParser
->SetCommand(aCommand
);
284 mParser
->SetContentSink(sink
);
285 mParser
->Parse(aUrl
);
290 void XMLDocument::EndLoad() {
291 mChannelIsPending
= false;
293 mSynchronousDOMContentLoaded
= mLoadedAsData
;
295 if (mSynchronousDOMContentLoaded
) {
296 mSynchronousDOMContentLoaded
= false;
297 Document::SetReadyStateInternal(Document::READYSTATE_COMPLETE
);
298 // Generate a document load event for the case when an XML
299 // document was loaded as pure data without any presentation
301 WidgetEvent
event(true, eLoad
);
303 EventDispatcher::Dispatch(MOZ_KnownLive(ToSupports(this)), nullptr, &event
);
308 void XMLDocument::DocAddSizeOfExcludingThis(nsWindowSizes
& aWindowSizes
) const {
309 Document::DocAddSizeOfExcludingThis(aWindowSizes
);
312 // Document interface
314 nsresult
XMLDocument::Clone(dom::NodeInfo
* aNodeInfo
, nsINode
** aResult
) const {
315 NS_ASSERTION(aNodeInfo
->NodeInfoManager() == mNodeInfoManager
,
316 "Can't import this document into another document!");
318 RefPtr
<XMLDocument
> clone
= new XMLDocument();
319 nsresult rv
= CloneDocHelper(clone
);
320 NS_ENSURE_SUCCESS(rv
, rv
);
322 // State from XMLDocument
323 clone
->mIsPlainDocument
= mIsPlainDocument
;
325 clone
.forget(aResult
);
329 JSObject
* XMLDocument::WrapNode(JSContext
* aCx
,
330 JS::Handle
<JSObject
*> aGivenProto
) {
331 if (mIsPlainDocument
) {
332 return Document_Binding::Wrap(aCx
, this, aGivenProto
);
335 return XMLDocument_Binding::Wrap(aCx
, this, aGivenProto
);
338 } // namespace mozilla::dom