summaryrefslogtreecommitdiffstats
path: root/dom/html/HTMLMetaElement.cpp
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /dom/html/HTMLMetaElement.cpp
parentInitial commit. (diff)
downloadfirefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz
firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dom/html/HTMLMetaElement.cpp')
-rw-r--r--dom/html/HTMLMetaElement.cpp194
1 files changed, 194 insertions, 0 deletions
diff --git a/dom/html/HTMLMetaElement.cpp b/dom/html/HTMLMetaElement.cpp
new file mode 100644
index 0000000000..719a2b14f4
--- /dev/null
+++ b/dom/html/HTMLMetaElement.cpp
@@ -0,0 +1,194 @@
+/* -*- 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/AsyncEventDispatcher.h"
+#include "mozilla/dom/BindContext.h"
+#include "mozilla/dom/HTMLMetaElement.h"
+#include "mozilla/dom/HTMLMetaElementBinding.h"
+#include "mozilla/dom/nsCSPService.h"
+#include "mozilla/dom/nsCSPUtils.h"
+#include "mozilla/dom/ViewportMetaData.h"
+#include "mozilla/Logging.h"
+#include "mozilla/StaticPrefs_security.h"
+#include "nsContentUtils.h"
+#include "nsSandboxFlags.h"
+#include "nsStyleConsts.h"
+#include "nsIXMLContentSink.h"
+
+static mozilla::LazyLogModule gMetaElementLog("nsMetaElement");
+#define LOG(msg) MOZ_LOG(gMetaElementLog, mozilla::LogLevel::Debug, msg)
+#define LOG_ENABLED() MOZ_LOG_TEST(gMetaElementLog, mozilla::LogLevel::Debug)
+
+NS_IMPL_NS_NEW_HTML_ELEMENT(Meta)
+
+namespace mozilla::dom {
+
+HTMLMetaElement::HTMLMetaElement(
+ already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
+ : nsGenericHTMLElement(std::move(aNodeInfo)) {}
+
+HTMLMetaElement::~HTMLMetaElement() = default;
+
+NS_IMPL_ELEMENT_CLONE(HTMLMetaElement)
+
+void HTMLMetaElement::SetMetaReferrer(Document* aDocument) {
+ if (!aDocument || !AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
+ nsGkAtoms::referrer, eIgnoreCase)) {
+ return;
+ }
+ nsAutoString content;
+ GetContent(content);
+
+ Element* headElt = aDocument->GetHeadElement();
+ if (headElt && IsInclusiveDescendantOf(headElt)) {
+ content = nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(
+ content);
+ aDocument->UpdateReferrerInfoFromMeta(content, false);
+ }
+}
+
+nsresult HTMLMetaElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue,
+ nsIPrincipal* aSubjectPrincipal,
+ bool aNotify) {
+ if (aNameSpaceID == kNameSpaceID_None) {
+ Document* document = GetUncomposedDoc();
+ if (aName == nsGkAtoms::content) {
+ if (document && AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
+ nsGkAtoms::viewport, eIgnoreCase)) {
+ ProcessViewportContent(document);
+ }
+ CreateAndDispatchEvent(document, u"DOMMetaChanged"_ns);
+ } else if (document && aName == nsGkAtoms::name) {
+ if (aValue && aValue->Equals(nsGkAtoms::viewport, eIgnoreCase)) {
+ ProcessViewportContent(document);
+ } else if (aOldValue &&
+ aOldValue->Equals(nsGkAtoms::viewport, eIgnoreCase)) {
+ DiscardViewportContent(document);
+ }
+ CreateAndDispatchEvent(document, u"DOMMetaChanged"_ns);
+ }
+ // Update referrer policy when it got changed from JS
+ SetMetaReferrer(document);
+ }
+
+ return nsGenericHTMLElement::AfterSetAttr(
+ aNameSpaceID, aName, aValue, aOldValue, aSubjectPrincipal, aNotify);
+}
+
+nsresult HTMLMetaElement::BindToTree(BindContext& aContext, nsINode& aParent) {
+ nsresult rv = nsGenericHTMLElement::BindToTree(aContext, aParent);
+ NS_ENSURE_SUCCESS(rv, rv);
+ if (!IsInUncomposedDoc()) {
+ return rv;
+ }
+ Document& doc = aContext.OwnerDoc();
+
+ bool shouldProcessMeta = true;
+ // We don't want to call ProcessMETATag when we are pretty print
+ // the document
+ if (doc.IsXMLDocument()) {
+ if (nsCOMPtr<nsIXMLContentSink> xmlSink =
+ do_QueryInterface(doc.GetCurrentContentSink())) {
+ if (xmlSink->IsPrettyPrintXML() &&
+ xmlSink->IsPrettyPrintHasSpecialRoot()) {
+ shouldProcessMeta = false;
+ }
+ }
+ }
+
+ if (shouldProcessMeta) {
+ doc.ProcessMETATag(this);
+ }
+
+ if (AttrValueIs(kNameSpaceID_None, nsGkAtoms::name, nsGkAtoms::viewport,
+ eIgnoreCase)) {
+ ProcessViewportContent(&doc);
+ }
+
+ if (AttrValueIs(kNameSpaceID_None, nsGkAtoms::httpEquiv, nsGkAtoms::headerCSP,
+ eIgnoreCase)) {
+ // only accept <meta http-equiv="Content-Security-Policy" content=""> if it
+ // appears in the <head> element.
+ Element* headElt = doc.GetHeadElement();
+ if (headElt && IsInclusiveDescendantOf(headElt)) {
+ nsAutoString content;
+ GetContent(content);
+
+ if (LOG_ENABLED()) {
+ nsAutoCString documentURIspec;
+ if (nsIURI* documentURI = doc.GetDocumentURI()) {
+ documentURI->GetAsciiSpec(documentURIspec);
+ }
+
+ LOG(
+ ("HTMLMetaElement %p sets CSP '%s' on document=%p, "
+ "document-uri=%s",
+ this, NS_ConvertUTF16toUTF8(content).get(), &doc,
+ documentURIspec.get()));
+ }
+ CSP_ApplyMetaCSPToDoc(doc, content);
+ }
+ }
+
+ // Referrer Policy spec requires a <meta name="referrer" tag to be in the
+ // <head> element.
+ SetMetaReferrer(&doc);
+ CreateAndDispatchEvent(&doc, u"DOMMetaAdded"_ns);
+ return rv;
+}
+
+void HTMLMetaElement::UnbindFromTree(bool aNullParent) {
+ nsCOMPtr<Document> oldDoc = GetUncomposedDoc();
+ if (oldDoc && AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
+ nsGkAtoms::viewport, eIgnoreCase)) {
+ DiscardViewportContent(oldDoc);
+ }
+ CreateAndDispatchEvent(oldDoc, u"DOMMetaRemoved"_ns);
+ nsGenericHTMLElement::UnbindFromTree(aNullParent);
+}
+
+void HTMLMetaElement::CreateAndDispatchEvent(Document* aDoc,
+ const nsAString& aEventName) {
+ if (!aDoc) return;
+
+ RefPtr<AsyncEventDispatcher> asyncDispatcher = new AsyncEventDispatcher(
+ this, aEventName, CanBubble::eYes, ChromeOnlyDispatch::eYes);
+ asyncDispatcher->RunDOMEventWhenSafe();
+}
+
+JSObject* HTMLMetaElement::WrapNode(JSContext* aCx,
+ JS::Handle<JSObject*> aGivenProto) {
+ return HTMLMetaElement_Binding::Wrap(aCx, this, aGivenProto);
+}
+
+void HTMLMetaElement::ProcessViewportContent(Document* aDocument) {
+ if (!HasAttr(kNameSpaceID_None, nsGkAtoms::content)) {
+ // Call Document::RemoveMetaViewportElement for cases that the content
+ // attribute is removed.
+ // NOTE: RemoveMetaViewportElement enumerates all existing meta viewport
+ // tags in the case where this element hasn't been there, i.e. this element
+ // is newly added to the document, but it should be fine because a document
+ // unlikely has a bunch of meta viewport tags.
+ aDocument->RemoveMetaViewportElement(this);
+ return;
+ }
+
+ nsAutoString content;
+ GetContent(content);
+
+ aDocument->SetHeaderData(nsGkAtoms::viewport, content);
+
+ ViewportMetaData data(content);
+ aDocument->AddMetaViewportElement(this, std::move(data));
+}
+
+void HTMLMetaElement::DiscardViewportContent(Document* aDocument) {
+ aDocument->RemoveMetaViewportElement(this);
+}
+
+} // namespace mozilla::dom