Skip to content

Commit 81d01d3

Browse files
sebsebmcTG199
authored andcommitted
fix: meta referrer updating to follow spec (servo#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 <[email protected]>
1 parent 2eb13bb commit 81d01d3

File tree

5 files changed

+28
-46
lines changed

5 files changed

+28
-46
lines changed

components/script/dom/htmlheadelement.rs

Lines changed: 1 addition & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use js::rust::HandleObject;
1010
use crate::dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
1111
use crate::dom::bindings::inheritance::Castable;
1212
use crate::dom::bindings::root::DomRoot;
13-
use crate::dom::document::{Document, determine_policy_for_token};
13+
use crate::dom::document::Document;
1414
use crate::dom::element::Element;
1515
use crate::dom::htmlelement::HTMLElement;
1616
use crate::dom::htmlmetaelement::HTMLMetaElement;
@@ -54,37 +54,6 @@ impl HTMLHeadElement {
5454
n
5555
}
5656

57-
/// <https://html.spec.whatwg.org/multipage/#meta-referrer>
58-
pub(crate) fn set_document_referrer(&self) {
59-
let doc = self.owner_document();
60-
61-
if doc.GetHead().as_deref() != Some(self) {
62-
return;
63-
}
64-
65-
let node = self.upcast::<Node>();
66-
let candidates = node
67-
.traverse_preorder(ShadowIncluding::No)
68-
.filter_map(DomRoot::downcast::<Element>)
69-
.filter(|elem| elem.is::<HTMLMetaElement>())
70-
.filter(|elem| elem.get_name() == Some(atom!("referrer")))
71-
.filter(|elem| {
72-
elem.get_attribute(&ns!(), &local_name!("content"))
73-
.is_some()
74-
});
75-
76-
for meta in candidates {
77-
if let Some(ref content) = meta.get_attribute(&ns!(), &local_name!("content")) {
78-
let content = content.value();
79-
let content_val = content.trim();
80-
if !content_val.is_empty() {
81-
doc.set_referrer_policy(determine_policy_for_token(content_val));
82-
return;
83-
}
84-
}
85-
}
86-
}
87-
8857
/// <https://html.spec.whatwg.org/multipage/#attr-meta-http-equiv-content-security-policy>
8958
pub(crate) fn set_content_security_policy(&self) {
9059
let doc = self.owner_document();

components/script/dom/htmlmetaelement.rs

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use std::time::Duration;
88

99
use constellation_traits::NavigationHistoryBehavior;
1010
use dom_struct::dom_struct;
11-
use html5ever::{LocalName, Prefix};
11+
use html5ever::{LocalName, Prefix, local_name, namespace_url, ns};
1212
use js::rust::HandleObject;
1313
use regex::bytes::Regex;
1414
use servo_url::ServoUrl;
@@ -21,7 +21,7 @@ use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
2121
use crate::dom::bindings::inheritance::Castable;
2222
use crate::dom::bindings::root::DomRoot;
2323
use crate::dom::bindings::str::DOMString;
24-
use crate::dom::document::{DeclarativeRefresh, Document};
24+
use crate::dom::document::{DeclarativeRefresh, Document, determine_policy_for_token};
2525
use crate::dom::element::{AttributeMutation, Element};
2626
use crate::dom::htmlelement::HTMLElement;
2727
use crate::dom::htmlheadelement::HTMLHeadElement;
@@ -115,9 +115,31 @@ impl HTMLMetaElement {
115115

116116
/// <https://html.spec.whatwg.org/multipage/#meta-referrer>
117117
fn apply_referrer(&self) {
118-
if let Some(parent) = self.upcast::<Node>().GetParentElement() {
119-
if let Some(head) = parent.downcast::<HTMLHeadElement>() {
120-
head.set_document_referrer();
118+
let doc = self.owner_document();
119+
// From spec: For historical reasons, unlike other standard metadata names, the processing model for referrer
120+
// is not responsive to element removals, and does not use tree order. Only the most-recently-inserted or
121+
// most-recently-modified meta element in this state has an effect.
122+
// 1. If element is not in a document tree, then return.
123+
let meta_node = self.upcast::<Node>();
124+
if !meta_node.is_in_a_document_tree() {
125+
return;
126+
}
127+
128+
// 2. If element does not have a name attribute whose value is an ASCII case-insensitive match for "referrer",
129+
// then return.
130+
if self.upcast::<Element>().get_name() != Some(atom!("referrer")) {
131+
return;
132+
}
133+
134+
// 3. If element does not have a content attribute, or that attribute's value is the empty string, then return.
135+
let content = self
136+
.upcast::<Element>()
137+
.get_attribute(&ns!(), &local_name!("content"));
138+
if let Some(attr) = content {
139+
let attr = attr.value();
140+
let attr_val = attr.trim();
141+
if !attr_val.is_empty() {
142+
doc.set_referrer_policy(determine_policy_for_token(attr_val));
121143
}
122144
}
123145
}

tests/wpt/meta/referrer-policy/generic/first-meta-changed-after-second-added.http.html.ini

Lines changed: 0 additions & 3 deletions
This file was deleted.

tests/wpt/meta/referrer-policy/generic/meta-referrer-outofhead-fetch.http.html.ini

Lines changed: 0 additions & 3 deletions
This file was deleted.

tests/wpt/meta/referrer-policy/generic/meta-referrer-removed-2.http.html.ini

Lines changed: 0 additions & 3 deletions
This file was deleted.

0 commit comments

Comments
 (0)