DOMImplementation.cpp (7278B)
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/. */ 6 7 #include "mozilla/dom/DOMImplementation.h" 8 9 #include "mozilla/ContentEvents.h" 10 #include "mozilla/dom/DOMImplementationBinding.h" 11 #include "mozilla/dom/Document.h" 12 #include "mozilla/dom/DocumentType.h" 13 #include "nsContentCreatorFunctions.h" 14 #include "nsContentUtils.h" 15 #include "nsTextNode.h" 16 17 namespace mozilla::dom { 18 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) 23 NS_INTERFACE_MAP_END 24 25 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(DOMImplementation, mOwner) 26 27 NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMImplementation) 28 NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMImplementation) 29 30 DOMImplementation::DOMImplementation(Document* aOwner, 31 nsIGlobalObject* aScriptObject, 32 nsIURI* aDocumentURI, nsIURI* aBaseURI) 33 : mOwner(aOwner), 34 mScriptObject(do_GetWeakReference(aScriptObject)), 35 mDocumentURI(aDocumentURI), 36 mBaseURI(aBaseURI) { 37 MOZ_ASSERT(aOwner); 38 } 39 40 DOMImplementation::~DOMImplementation() = default; 41 42 JSObject* DOMImplementation::WrapObject(JSContext* aCx, 43 JS::Handle<JSObject*> aGivenProto) { 44 return DOMImplementation_Binding::Wrap(aCx, this, aGivenProto); 45 } 46 47 already_AddRefed<DocumentType> DOMImplementation::CreateDocumentType( 48 const nsAString& aQualifiedName, const nsAString& aPublicId, 49 const nsAString& aSystemId, ErrorResult& aRv) { 50 if (!mOwner) { 51 aRv.Throw(NS_ERROR_UNEXPECTED); 52 return nullptr; 53 } 54 55 aRv = nsContentUtils::CheckQName(aQualifiedName); 56 if (aRv.Failed()) { 57 return nullptr; 58 } 59 60 RefPtr<nsAtom> name = NS_Atomize(aQualifiedName); 61 if (!name) { 62 aRv.Throw(NS_ERROR_OUT_OF_MEMORY); 63 return nullptr; 64 } 65 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(); 70 } 71 72 nsresult DOMImplementation::CreateDocument(const nsAString& aNamespaceURI, 73 const nsAString& aQualifiedName, 74 DocumentType* aDoctype, 75 Document** aDocument) { 76 *aDocument = nullptr; 77 78 nsresult rv; 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); 84 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; 90 } 91 } 92 93 nsCOMPtr<nsIGlobalObject> scriptHandlingObject = 94 do_QueryReferent(mScriptObject); 95 96 NS_ENSURE_STATE(!mScriptObject || scriptHandlingObject); 97 98 nsCOMPtr<Document> doc; 99 100 rv = NS_NewDOMDocument(getter_AddRefs(doc), aNamespaceURI, aQualifiedName, 101 aDoctype, mDocumentURI, mBaseURI, 102 mOwner->NodePrincipal(), LoadedAsData::AsData, 103 scriptHandlingObject, DocumentFlavor::XML); 104 NS_ENSURE_SUCCESS(rv, rv); 105 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. 109 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); 114 } else { 115 doc->SetContentType("application/xml"_ns); 116 } 117 118 doc->SetReadyStateInternal(Document::READYSTATE_COMPLETE); 119 120 doc.forget(aDocument); 121 return NS_OK; 122 } 123 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(); 131 } 132 133 nsresult DOMImplementation::CreateHTMLDocument(const nsAString& aTitle, 134 Document** aDocument) { 135 *aDocument = nullptr; 136 137 NS_ENSURE_STATE(mOwner); 138 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 143 u""_ns, // aPublicId 144 u""_ns, // aSystemId 145 VoidString()); // aInternalSubset 146 147 nsCOMPtr<nsIGlobalObject> scriptHandlingObject = 148 do_QueryReferent(mScriptObject); 149 150 NS_ENSURE_STATE(!mScriptObject || scriptHandlingObject); 151 152 nsCOMPtr<Document> doc; 153 nsresult rv = NS_NewDOMDocument( 154 getter_AddRefs(doc), u""_ns, u""_ns, doctype, mDocumentURI, mBaseURI, 155 mOwner->NodePrincipal(), LoadedAsData::AsData, scriptHandlingObject, 156 DocumentFlavor::LegacyGuess); 157 NS_ENSURE_SUCCESS(rv, rv); 158 159 ErrorResult error; 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(); 165 } 166 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(); 172 } 173 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(); 180 } 181 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(); 189 } 190 } 191 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(); 197 } 198 199 doc->SetReadyStateInternal(Document::READYSTATE_COMPLETE); 200 201 doc.forget(aDocument); 202 return NS_OK; 203 } 204 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(); 211 } 212 213 } // namespace mozilla::dom