aboutsummaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
authorSebastian C <sebsebmc@gmail.com>2025-04-07 17:29:12 -0500
committerGitHub <noreply@github.com>2025-04-07 22:29:12 +0000
commit9bdc46d66b68ceac79d026118d9602a8e4c20118 (patch)
treece7d22e830de53a21d7f78d1dfee3d2bca714b78 /components
parentbfbe464eba0a3b7944f00f8a2bdedc3ff28f12ce (diff)
downloadservo-9bdc46d66b68ceac79d026118d9602a8e4c20118.tar.gz
servo-9bdc46d66b68ceac79d026118d9602a8e4c20118.zip
fix: meta referrer updating to follow spec (#36390)
Previously the referrer policy used tree order but the spec only cares about the most-recently-updated or most-recently-added meta referrer. Testing: change has existing WPT tests --------- Signed-off-by: Sebastian C <sebsebmc@gmail.com>
Diffstat (limited to 'components')
-rw-r--r--components/script/dom/htmlheadelement.rs33
-rw-r--r--components/script/dom/htmlmetaelement.rs32
2 files changed, 28 insertions, 37 deletions
diff --git a/components/script/dom/htmlheadelement.rs b/components/script/dom/htmlheadelement.rs
index 51b2c025982..b4845fc949c 100644
--- a/components/script/dom/htmlheadelement.rs
+++ b/components/script/dom/htmlheadelement.rs
@@ -10,7 +10,7 @@ use js::rust::HandleObject;
use crate::dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::root::DomRoot;
-use crate::dom::document::{Document, determine_policy_for_token};
+use crate::dom::document::Document;
use crate::dom::element::Element;
use crate::dom::htmlelement::HTMLElement;
use crate::dom::htmlmetaelement::HTMLMetaElement;
@@ -54,37 +54,6 @@ impl HTMLHeadElement {
n
}
- /// <https://html.spec.whatwg.org/multipage/#meta-referrer>
- pub(crate) fn set_document_referrer(&self) {
- let doc = self.owner_document();
-
- if doc.GetHead().as_deref() != Some(self) {
- return;
- }
-
- let node = self.upcast::<Node>();
- let candidates = node
- .traverse_preorder(ShadowIncluding::No)
- .filter_map(DomRoot::downcast::<Element>)
- .filter(|elem| elem.is::<HTMLMetaElement>())
- .filter(|elem| elem.get_name() == Some(atom!("referrer")))
- .filter(|elem| {
- elem.get_attribute(&ns!(), &local_name!("content"))
- .is_some()
- });
-
- for meta in candidates {
- if let Some(ref content) = meta.get_attribute(&ns!(), &local_name!("content")) {
- let content = content.value();
- let content_val = content.trim();
- if !content_val.is_empty() {
- doc.set_referrer_policy(determine_policy_for_token(content_val));
- return;
- }
- }
- }
- }
-
/// <https://html.spec.whatwg.org/multipage/#attr-meta-http-equiv-content-security-policy>
pub(crate) fn set_content_security_policy(&self) {
let doc = self.owner_document();
diff --git a/components/script/dom/htmlmetaelement.rs b/components/script/dom/htmlmetaelement.rs
index fd95ac1abbf..ac4dcbf0db6 100644
--- a/components/script/dom/htmlmetaelement.rs
+++ b/components/script/dom/htmlmetaelement.rs
@@ -8,7 +8,7 @@ use std::time::Duration;
use constellation_traits::NavigationHistoryBehavior;
use dom_struct::dom_struct;
-use html5ever::{LocalName, Prefix};
+use html5ever::{LocalName, Prefix, local_name, namespace_url, ns};
use js::rust::HandleObject;
use regex::bytes::Regex;
use servo_url::ServoUrl;
@@ -21,7 +21,7 @@ use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::root::DomRoot;
use crate::dom::bindings::str::DOMString;
-use crate::dom::document::{DeclarativeRefresh, Document};
+use crate::dom::document::{DeclarativeRefresh, Document, determine_policy_for_token};
use crate::dom::element::{AttributeMutation, Element};
use crate::dom::htmlelement::HTMLElement;
use crate::dom::htmlheadelement::HTMLHeadElement;
@@ -115,9 +115,31 @@ impl HTMLMetaElement {
/// <https://html.spec.whatwg.org/multipage/#meta-referrer>
fn apply_referrer(&self) {
- if let Some(parent) = self.upcast::<Node>().GetParentElement() {
- if let Some(head) = parent.downcast::<HTMLHeadElement>() {
- head.set_document_referrer();
+ let doc = self.owner_document();
+ // From spec: For historical reasons, unlike other standard metadata names, the processing model for referrer
+ // is not responsive to element removals, and does not use tree order. Only the most-recently-inserted or
+ // most-recently-modified meta element in this state has an effect.
+ // 1. If element is not in a document tree, then return.
+ let meta_node = self.upcast::<Node>();
+ if !meta_node.is_in_a_document_tree() {
+ return;
+ }
+
+ // 2. If element does not have a name attribute whose value is an ASCII case-insensitive match for "referrer",
+ // then return.
+ if self.upcast::<Element>().get_name() != Some(atom!("referrer")) {
+ return;
+ }
+
+ // 3. If element does not have a content attribute, or that attribute's value is the empty string, then return.
+ let content = self
+ .upcast::<Element>()
+ .get_attribute(&ns!(), &local_name!("content"));
+ if let Some(attr) = content {
+ let attr = attr.value();
+ let attr_val = attr.trim();
+ if !attr_val.is_empty() {
+ doc.set_referrer_policy(determine_policy_for_token(attr_val));
}
}
}