michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "mozilla/dom/DOMImplementation.h" michael@0: michael@0: #include "mozilla/ContentEvents.h" michael@0: #include "mozilla/dom/DOMImplementationBinding.h" michael@0: #include "nsContentCreatorFunctions.h" michael@0: #include "nsContentUtils.h" michael@0: #include "nsDOMClassInfoID.h" michael@0: #include "nsIDOMDocument.h" michael@0: #include "DocumentType.h" michael@0: #include "nsTextNode.h" michael@0: michael@0: namespace mozilla { michael@0: namespace dom { michael@0: michael@0: // QueryInterface implementation for DOMImplementation michael@0: NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMImplementation) michael@0: NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY michael@0: NS_INTERFACE_MAP_ENTRY(nsIDOMDOMImplementation) michael@0: NS_INTERFACE_MAP_ENTRY(nsISupports) michael@0: NS_INTERFACE_MAP_END michael@0: michael@0: NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(DOMImplementation, mOwner) michael@0: michael@0: NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMImplementation) michael@0: NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMImplementation) michael@0: michael@0: JSObject* michael@0: DOMImplementation::WrapObject(JSContext* aCx) michael@0: { michael@0: return DOMImplementationBinding::Wrap(aCx, this); michael@0: } michael@0: michael@0: bool michael@0: DOMImplementation::HasFeature(const nsAString& aFeature, michael@0: const nsAString& aVersion) michael@0: { michael@0: return nsContentUtils::InternalIsSupported( michael@0: static_cast(this), michael@0: aFeature, aVersion); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: DOMImplementation::HasFeature(const nsAString& aFeature, michael@0: const nsAString& aVersion, michael@0: bool* aReturn) michael@0: { michael@0: *aReturn = HasFeature(aFeature, aVersion); michael@0: return NS_OK; michael@0: } michael@0: michael@0: already_AddRefed michael@0: DOMImplementation::CreateDocumentType(const nsAString& aQualifiedName, michael@0: const nsAString& aPublicId, michael@0: const nsAString& aSystemId, michael@0: ErrorResult& aRv) michael@0: { michael@0: if (!mOwner) { michael@0: aRv.Throw(NS_ERROR_UNEXPECTED); michael@0: return nullptr; michael@0: } michael@0: michael@0: aRv = nsContentUtils::CheckQName(aQualifiedName); michael@0: if (aRv.Failed()) { michael@0: return nullptr; michael@0: } michael@0: michael@0: nsCOMPtr name = do_GetAtom(aQualifiedName); michael@0: if (!name) { michael@0: aRv.Throw(NS_ERROR_OUT_OF_MEMORY); michael@0: return nullptr; michael@0: } michael@0: michael@0: // Indicate that there is no internal subset (not just an empty one) michael@0: nsRefPtr docType = michael@0: NS_NewDOMDocumentType(mOwner->NodeInfoManager(), name, aPublicId, michael@0: aSystemId, NullString(), aRv); michael@0: return docType.forget(); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: DOMImplementation::CreateDocumentType(const nsAString& aQualifiedName, michael@0: const nsAString& aPublicId, michael@0: const nsAString& aSystemId, michael@0: nsIDOMDocumentType** aReturn) michael@0: { michael@0: ErrorResult rv; michael@0: *aReturn = michael@0: CreateDocumentType(aQualifiedName, aPublicId, aSystemId, rv).take(); michael@0: return rv.ErrorCode(); michael@0: } michael@0: michael@0: nsresult michael@0: DOMImplementation::CreateDocument(const nsAString& aNamespaceURI, michael@0: const nsAString& aQualifiedName, michael@0: nsIDOMDocumentType* aDoctype, michael@0: nsIDocument** aDocument, michael@0: nsIDOMDocument** aDOMDocument) michael@0: { michael@0: *aDocument = nullptr; michael@0: *aDOMDocument = nullptr; michael@0: michael@0: nsresult rv; michael@0: if (!aQualifiedName.IsEmpty()) { michael@0: const nsAFlatString& qName = PromiseFlatString(aQualifiedName); michael@0: const char16_t *colon; michael@0: rv = nsContentUtils::CheckQName(qName, true, &colon); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: if (colon && michael@0: (DOMStringIsNull(aNamespaceURI) || michael@0: (Substring(qName.get(), colon).EqualsLiteral("xml") && michael@0: !aNamespaceURI.EqualsLiteral("http://www.w3.org/XML/1998/namespace")))) { michael@0: return NS_ERROR_DOM_NAMESPACE_ERR; michael@0: } michael@0: } michael@0: michael@0: nsCOMPtr scriptHandlingObject = michael@0: do_QueryReferent(mScriptObject); michael@0: michael@0: NS_ENSURE_STATE(!mScriptObject || scriptHandlingObject); michael@0: michael@0: nsCOMPtr document; michael@0: michael@0: rv = NS_NewDOMDocument(getter_AddRefs(document), michael@0: aNamespaceURI, aQualifiedName, aDoctype, michael@0: mDocumentURI, mBaseURI, michael@0: mOwner->NodePrincipal(), michael@0: true, scriptHandlingObject, michael@0: DocumentFlavorLegacyGuess); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: // When DOMImplementation's createDocument method is invoked with michael@0: // namespace set to HTML Namespace use the registry of the associated michael@0: // document to the new instance. michael@0: nsCOMPtr doc = do_QueryInterface(document); michael@0: if (aNamespaceURI.EqualsLiteral("http://www.w3.org/1999/xhtml")) { michael@0: doc->UseRegistryFromDocument(mOwner); michael@0: } michael@0: michael@0: doc->SetReadyStateInternal(nsIDocument::READYSTATE_COMPLETE); michael@0: michael@0: doc.forget(aDocument); michael@0: document.forget(aDOMDocument); michael@0: return NS_OK; michael@0: } michael@0: michael@0: already_AddRefed michael@0: DOMImplementation::CreateDocument(const nsAString& aNamespaceURI, michael@0: const nsAString& aQualifiedName, michael@0: nsIDOMDocumentType* aDoctype, michael@0: ErrorResult& aRv) michael@0: { michael@0: nsCOMPtr document; michael@0: nsCOMPtr domDocument; michael@0: aRv = CreateDocument(aNamespaceURI, aQualifiedName, aDoctype, michael@0: getter_AddRefs(document), getter_AddRefs(domDocument)); michael@0: return document.forget(); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: DOMImplementation::CreateDocument(const nsAString& aNamespaceURI, michael@0: const nsAString& aQualifiedName, michael@0: nsIDOMDocumentType* aDoctype, michael@0: nsIDOMDocument** aReturn) michael@0: { michael@0: nsCOMPtr document; michael@0: return CreateDocument(aNamespaceURI, aQualifiedName, aDoctype, michael@0: getter_AddRefs(document), aReturn); michael@0: } michael@0: michael@0: nsresult michael@0: DOMImplementation::CreateHTMLDocument(const nsAString& aTitle, michael@0: nsIDocument** aDocument, michael@0: nsIDOMDocument** aDOMDocument) michael@0: { michael@0: *aDocument = nullptr; michael@0: *aDOMDocument = nullptr; michael@0: michael@0: NS_ENSURE_STATE(mOwner); michael@0: michael@0: nsCOMPtr doctype; michael@0: // Indicate that there is no internal subset (not just an empty one) michael@0: nsresult rv = NS_NewDOMDocumentType(getter_AddRefs(doctype), michael@0: mOwner->NodeInfoManager(), michael@0: nsGkAtoms::html, // aName michael@0: EmptyString(), // aPublicId michael@0: EmptyString(), // aSystemId michael@0: NullString()); // aInternalSubset michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: michael@0: nsCOMPtr scriptHandlingObject = michael@0: do_QueryReferent(mScriptObject); michael@0: michael@0: NS_ENSURE_STATE(!mScriptObject || scriptHandlingObject); michael@0: michael@0: nsCOMPtr document; michael@0: rv = NS_NewDOMDocument(getter_AddRefs(document), michael@0: EmptyString(), EmptyString(), michael@0: doctype, mDocumentURI, mBaseURI, michael@0: mOwner->NodePrincipal(), michael@0: true, scriptHandlingObject, michael@0: DocumentFlavorLegacyGuess); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: nsCOMPtr doc = do_QueryInterface(document); michael@0: michael@0: nsCOMPtr root; michael@0: rv = doc->CreateElem(NS_LITERAL_STRING("html"), nullptr, kNameSpaceID_XHTML, michael@0: getter_AddRefs(root)); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: rv = doc->AppendChildTo(root, false); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: nsCOMPtr head; michael@0: rv = doc->CreateElem(NS_LITERAL_STRING("head"), nullptr, kNameSpaceID_XHTML, michael@0: getter_AddRefs(head)); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: rv = root->AppendChildTo(head, false); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: if (!DOMStringIsNull(aTitle)) { michael@0: nsCOMPtr title; michael@0: rv = doc->CreateElem(NS_LITERAL_STRING("title"), nullptr, michael@0: kNameSpaceID_XHTML, getter_AddRefs(title)); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: rv = head->AppendChildTo(title, false); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: nsRefPtr titleText = new nsTextNode(doc->NodeInfoManager()); michael@0: rv = titleText->SetText(aTitle, false); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: rv = title->AppendChildTo(titleText, false); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: } michael@0: michael@0: nsCOMPtr body; michael@0: rv = doc->CreateElem(NS_LITERAL_STRING("body"), nullptr, kNameSpaceID_XHTML, michael@0: getter_AddRefs(body)); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: rv = root->AppendChildTo(body, false); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: // When the createHTMLDocument method is invoked, michael@0: // use the registry of the associated document to the new instance. michael@0: doc->UseRegistryFromDocument(mOwner); michael@0: michael@0: doc->SetReadyStateInternal(nsIDocument::READYSTATE_COMPLETE); michael@0: michael@0: doc.forget(aDocument); michael@0: document.forget(aDOMDocument); michael@0: return NS_OK; michael@0: } michael@0: michael@0: already_AddRefed michael@0: DOMImplementation::CreateHTMLDocument(const Optional& aTitle, michael@0: ErrorResult& aRv) michael@0: { michael@0: nsCOMPtr document; michael@0: nsCOMPtr domDocument; michael@0: aRv = CreateHTMLDocument(aTitle.WasPassed() ? aTitle.Value() michael@0: : NullString(), michael@0: getter_AddRefs(document), michael@0: getter_AddRefs(domDocument)); michael@0: return document.forget(); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: DOMImplementation::CreateHTMLDocument(const nsAString& aTitle, michael@0: nsIDOMDocument** aReturn) michael@0: { michael@0: nsCOMPtr document; michael@0: return CreateHTMLDocument(aTitle, getter_AddRefs(document), aReturn); michael@0: } michael@0: michael@0: } // namespace dom michael@0: } // namespace mozilla