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/DOMImplementation.h"
9 #include "mozilla/ContentEvents.h"
10 #include "mozilla/dom/DOMImplementationBinding.h"
11 #include "nsContentCreatorFunctions.h"
12 #include "nsContentUtils.h"
13 #include "mozilla/dom/Document.h"
14 #include "mozilla/dom/DocumentType.h"
15 #include "nsTextNode.h"
17 namespace mozilla::dom
{
19 // QueryInterface implementation for DOMImplementation
20 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMImplementation
)
21 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
22 NS_INTERFACE_MAP_ENTRY(nsISupports
)
25 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(DOMImplementation
, mOwner
)
27 NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMImplementation
)
28 NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMImplementation
)
30 DOMImplementation::DOMImplementation(Document
* aOwner
,
31 nsIGlobalObject
* aScriptObject
,
32 nsIURI
* aDocumentURI
, nsIURI
* aBaseURI
)
34 mScriptObject(do_GetWeakReference(aScriptObject
)),
35 mDocumentURI(aDocumentURI
),
40 DOMImplementation::~DOMImplementation() = default;
42 JSObject
* DOMImplementation::WrapObject(JSContext
* aCx
,
43 JS::Handle
<JSObject
*> aGivenProto
) {
44 return DOMImplementation_Binding::Wrap(aCx
, this, aGivenProto
);
47 already_AddRefed
<DocumentType
> DOMImplementation::CreateDocumentType(
48 const nsAString
& aQualifiedName
, const nsAString
& aPublicId
,
49 const nsAString
& aSystemId
, ErrorResult
& aRv
) {
51 aRv
.Throw(NS_ERROR_UNEXPECTED
);
55 aRv
= nsContentUtils::CheckQName(aQualifiedName
);
60 RefPtr
<nsAtom
> name
= NS_Atomize(aQualifiedName
);
62 aRv
.Throw(NS_ERROR_OUT_OF_MEMORY
);
66 // Indicate that there is no internal subset (not just an empty one)
67 RefPtr
<DocumentType
> docType
= NS_NewDOMDocumentType(
68 mOwner
->NodeInfoManager(), name
, aPublicId
, aSystemId
, VoidString());
69 return docType
.forget();
72 nsresult
DOMImplementation::CreateDocument(const nsAString
& aNamespaceURI
,
73 const nsAString
& aQualifiedName
,
74 DocumentType
* aDoctype
,
75 Document
** aDocument
) {
79 if (!aQualifiedName
.IsEmpty()) {
80 const nsString
& qName
= PromiseFlatString(aQualifiedName
);
81 const char16_t
* colon
;
82 rv
= nsContentUtils::CheckQName(qName
, true, &colon
);
83 NS_ENSURE_SUCCESS(rv
, rv
);
85 if (colon
&& (DOMStringIsNull(aNamespaceURI
) ||
86 (Substring(qName
.get(), colon
).EqualsLiteral("xml") &&
87 !aNamespaceURI
.EqualsLiteral(
88 "http://www.w3.org/XML/1998/namespace")))) {
89 return NS_ERROR_DOM_NAMESPACE_ERR
;
93 nsCOMPtr
<nsIGlobalObject
> scriptHandlingObject
=
94 do_QueryReferent(mScriptObject
);
96 NS_ENSURE_STATE(!mScriptObject
|| scriptHandlingObject
);
98 nsCOMPtr
<Document
> doc
;
100 rv
= NS_NewDOMDocument(getter_AddRefs(doc
), aNamespaceURI
, aQualifiedName
,
101 aDoctype
, mDocumentURI
, mBaseURI
,
102 mOwner
->NodePrincipal(), true, scriptHandlingObject
,
104 NS_ENSURE_SUCCESS(rv
, rv
);
106 // When DOMImplementation's createDocument method is invoked with
107 // namespace set to HTML Namespace use the registry of the associated
108 // document to the new instance.
110 if (aNamespaceURI
.EqualsLiteral("http://www.w3.org/1999/xhtml")) {
111 doc
->SetContentType("application/xhtml+xml"_ns
);
112 } else if (aNamespaceURI
.EqualsLiteral("http://www.w3.org/2000/svg")) {
113 doc
->SetContentType("image/svg+xml"_ns
);
115 doc
->SetContentType("application/xml"_ns
);
118 doc
->SetReadyStateInternal(Document::READYSTATE_COMPLETE
);
120 doc
.forget(aDocument
);
124 already_AddRefed
<Document
> DOMImplementation::CreateDocument(
125 const nsAString
& aNamespaceURI
, const nsAString
& aQualifiedName
,
126 DocumentType
* aDoctype
, ErrorResult
& aRv
) {
127 nsCOMPtr
<Document
> document
;
128 aRv
= CreateDocument(aNamespaceURI
, aQualifiedName
, aDoctype
,
129 getter_AddRefs(document
));
130 return document
.forget();
133 nsresult
DOMImplementation::CreateHTMLDocument(const nsAString
& aTitle
,
134 Document
** aDocument
) {
135 *aDocument
= nullptr;
137 NS_ENSURE_STATE(mOwner
);
139 // Indicate that there is no internal subset (not just an empty one)
140 RefPtr
<DocumentType
> doctype
=
141 NS_NewDOMDocumentType(mOwner
->NodeInfoManager(),
142 nsGkAtoms::html
, // aName
145 VoidString()); // aInternalSubset
147 nsCOMPtr
<nsIGlobalObject
> scriptHandlingObject
=
148 do_QueryReferent(mScriptObject
);
150 NS_ENSURE_STATE(!mScriptObject
|| scriptHandlingObject
);
152 nsCOMPtr
<Document
> doc
;
154 NS_NewDOMDocument(getter_AddRefs(doc
), u
""_ns
, u
""_ns
, doctype
,
155 mDocumentURI
, mBaseURI
, mOwner
->NodePrincipal(), true,
156 scriptHandlingObject
, DocumentFlavorLegacyGuess
);
157 NS_ENSURE_SUCCESS(rv
, rv
);
160 nsCOMPtr
<Element
> root
=
161 doc
->CreateElem(u
"html"_ns
, nullptr, kNameSpaceID_XHTML
);
162 doc
->AppendChildTo(root
, false, error
);
163 if (error
.Failed()) {
164 return error
.StealNSResult();
167 nsCOMPtr
<Element
> head
=
168 doc
->CreateElem(u
"head"_ns
, nullptr, kNameSpaceID_XHTML
);
169 root
->AppendChildTo(head
, false, error
);
170 if (error
.Failed()) {
171 return error
.StealNSResult();
174 if (!DOMStringIsNull(aTitle
)) {
175 nsCOMPtr
<Element
> title
=
176 doc
->CreateElem(u
"title"_ns
, nullptr, kNameSpaceID_XHTML
);
177 head
->AppendChildTo(title
, false, error
);
178 if (error
.Failed()) {
179 return error
.StealNSResult();
182 RefPtr
<nsTextNode
> titleText
=
183 new (doc
->NodeInfoManager()) nsTextNode(doc
->NodeInfoManager());
184 rv
= titleText
->SetText(aTitle
, false);
185 NS_ENSURE_SUCCESS(rv
, rv
);
186 title
->AppendChildTo(titleText
, false, error
);
187 if (error
.Failed()) {
188 return error
.StealNSResult();
192 nsCOMPtr
<Element
> body
=
193 doc
->CreateElem(u
"body"_ns
, nullptr, kNameSpaceID_XHTML
);
194 root
->AppendChildTo(body
, false, error
);
195 if (error
.Failed()) {
196 return error
.StealNSResult();
199 doc
->SetReadyStateInternal(Document::READYSTATE_COMPLETE
);
201 doc
.forget(aDocument
);
205 already_AddRefed
<Document
> DOMImplementation::CreateHTMLDocument(
206 const Optional
<nsAString
>& aTitle
, ErrorResult
& aRv
) {
207 nsCOMPtr
<Document
> document
;
208 aRv
= CreateHTMLDocument(aTitle
.WasPassed() ? aTitle
.Value() : VoidString(),
209 getter_AddRefs(document
));
210 return document
.forget();
213 } // namespace mozilla::dom