diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index 0086bf518f4..5cb0ddf6e28 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -5428,17 +5428,18 @@ impl TaskOnce for ElementPerformFullscreenExit { } } +/// pub(crate) fn reflect_cross_origin_attribute(element: &Element) -> Option { - let attr = element.get_attribute(&ns!(), &local_name!("crossorigin")); - - if let Some(mut val) = attr.map(|v| v.Value()) { - val.make_ascii_lowercase(); - if val == "anonymous" || val == "use-credentials" { - return Some(val); - } - return Some(DOMString::from("anonymous")); - } - None + element + .get_attribute(&ns!(), &local_name!("crossorigin")) + .map(|attribute| { + let value = attribute.value().to_ascii_lowercase(); + if value == "anonymous" || value == "use-credentials" { + DOMString::from(value) + } else { + DOMString::from("anonymous") + } + }) } pub(crate) fn set_cross_origin_attribute( @@ -5454,38 +5455,38 @@ pub(crate) fn set_cross_origin_attribute( } } +/// pub(crate) fn reflect_referrer_policy_attribute(element: &Element) -> DOMString { - let attr = - element.get_attribute_by_name(DOMString::from_string(String::from("referrerpolicy"))); - - if let Some(mut val) = attr.map(|v| v.Value()) { - val.make_ascii_lowercase(); - if val == "no-referrer" || - val == "no-referrer-when-downgrade" || - val == "same-origin" || - val == "origin" || - val == "strict-origin" || - val == "origin-when-cross-origin" || - val == "strict-origin-when-cross-origin" || - val == "unsafe-url" - { - return val; - } - } - DOMString::new() + element + .get_attribute(&ns!(), &local_name!("referrerpolicy")) + .map(|attribute| { + let value = attribute.value().to_ascii_lowercase(); + if value == "no-referrer" || + value == "no-referrer-when-downgrade" || + value == "same-origin" || + value == "origin" || + value == "strict-origin" || + value == "origin-when-cross-origin" || + value == "strict-origin-when-cross-origin" || + value == "unsafe-url" + { + DOMString::from(value) + } else { + DOMString::new() + } + }) + .unwrap_or_default() } pub(crate) fn referrer_policy_for_element(element: &Element) -> ReferrerPolicy { element - .get_attribute_by_name(DOMString::from_string(String::from("referrerpolicy"))) - .map(|attribute: DomRoot| determine_policy_for_token(attribute.Value().str())) + .get_attribute(&ns!(), &local_name!("referrerpolicy")) + .map(|attribute| determine_policy_for_token(&attribute.value())) .unwrap_or(element.owner_document().get_referrer_policy()) } pub(crate) fn cors_setting_for_element(element: &Element) -> Option { - reflect_cross_origin_attribute(element).and_then(|attr| match attr.str() { - "anonymous" => Some(CorsSettings::Anonymous), - "use-credentials" => Some(CorsSettings::UseCredentials), - _ => unreachable!(), - }) + element + .get_attribute(&ns!(), &local_name!("crossorigin")) + .map(|attribute| CorsSettings::from_enumerated_attribute(&attribute.value())) } diff --git a/components/script/dom/html/htmlimageelement.rs b/components/script/dom/html/htmlimageelement.rs index aa1fd130a81..1502e9753bf 100644 --- a/components/script/dom/html/htmlimageelement.rs +++ b/components/script/dom/html/htmlimageelement.rs @@ -22,7 +22,7 @@ use net_traits::image_cache::{ Image, ImageCache, ImageCacheResult, ImageLoadListener, ImageOrMetadataAvailable, ImageResponse, PendingImageId, UsePlaceholder, }; -use net_traits::request::{Destination, Initiator, RequestId}; +use net_traits::request::{CorsSettings, Destination, Initiator, RequestId}; use net_traits::{ FetchMetadata, FetchResponseListener, FetchResponseMsg, NetworkError, ReferrerPolicy, ResourceFetchTiming, ResourceTimingType, @@ -1603,22 +1603,6 @@ fn parse_a_sizes_attribute(value: &str) -> SourceSizeList { SourceSizeList::parse(&context, &mut parser) } -fn get_correct_referrerpolicy_from_raw_token(token: &DOMString) -> DOMString { - if token.is_empty() { - // Empty token is treated as the default referrer policy inside determine_policy_for_token, - // so it should remain unchanged. - DOMString::new() - } else { - let policy = determine_policy_for_token(token.str()); - - if policy == ReferrerPolicy::EmptyString { - return DOMString::new(); - } - - DOMString::from_string(policy.to_string()) - } -} - #[allow(non_snake_case)] impl HTMLImageElementMethods for HTMLImageElement { // https://html.spec.whatwg.org/multipage/#dom-image @@ -1784,24 +1768,8 @@ impl HTMLImageElementMethods for HTMLImageElement { reflect_referrer_policy_attribute(self.upcast::()) } - // https://html.spec.whatwg.org/multipage/#dom-img-referrerpolicy - fn SetReferrerPolicy(&self, value: DOMString, can_gc: CanGc) { - let referrerpolicy_attr_name = local_name!("referrerpolicy"); - let element = self.upcast::(); - let previous_correct_attribute_value = get_correct_referrerpolicy_from_raw_token( - &element.get_string_attribute(&referrerpolicy_attr_name), - ); - let correct_value_or_empty_string = get_correct_referrerpolicy_from_raw_token(&value); - if previous_correct_attribute_value != correct_value_or_empty_string { - // Setting the attribute to the same value will update the image. - // We don't want to start an update if referrerpolicy is set to the same value. - element.set_string_attribute( - &referrerpolicy_attr_name, - correct_value_or_empty_string, - can_gc, - ); - } - } + // + make_setter!(SetReferrerPolicy, "referrerpolicy"); /// fn Decode(&self, can_gc: CanGc) -> Rc { @@ -1874,9 +1842,51 @@ impl VirtualMethods for HTMLImageElement { &local_name!("src") | &local_name!("srcset") | &local_name!("width") | - &local_name!("crossorigin") | - &local_name!("sizes") | - &local_name!("referrerpolicy") => self.update_the_image_data(can_gc), + &local_name!("sizes") => { + // + // The element's src, srcset, width, or sizes attributes are set, changed, or + // removed. + self.update_the_image_data(can_gc); + }, + &local_name!("crossorigin") => { + // + // The element's crossorigin attribute's state is changed. + let cross_origin_state_changed = match mutation { + AttributeMutation::Removed | AttributeMutation::Set(None) => true, + AttributeMutation::Set(Some(old_value)) => { + let new_cors_setting = + CorsSettings::from_enumerated_attribute(&attr.value()); + let old_cors_setting = CorsSettings::from_enumerated_attribute(old_value); + + new_cors_setting != old_cors_setting + }, + }; + + if cross_origin_state_changed { + self.update_the_image_data(can_gc); + } + }, + &local_name!("referrerpolicy") => { + // + // The element's referrerpolicy attribute's state is changed. + let referrer_policy_state_changed = match mutation { + AttributeMutation::Removed | AttributeMutation::Set(None) => { + let referrer_policy = determine_policy_for_token(&attr.value()); + + referrer_policy != ReferrerPolicy::EmptyString + }, + AttributeMutation::Set(Some(old_value)) => { + let new_referrer_policy = determine_policy_for_token(&attr.value()); + let old_referrer_policy = determine_policy_for_token(old_value); + + new_referrer_policy != old_referrer_policy + }, + }; + + if referrer_policy_state_changed { + self.update_the_image_data(can_gc); + } + }, _ => {}, } } diff --git a/components/script_bindings/codegen/Bindings.conf b/components/script_bindings/codegen/Bindings.conf index 6a7ac7dbfb0..2b96a6ffa1d 100644 --- a/components/script_bindings/codegen/Bindings.conf +++ b/components/script_bindings/codegen/Bindings.conf @@ -394,7 +394,7 @@ DOMInterfaces = { }, 'HTMLImageElement': { - 'canGc': ['RequestSubmit', 'ReportValidity', 'Reset','SetRel', 'Decode', 'SetCrossOrigin', 'SetWidth', 'SetHeight', 'SetReferrerPolicy'], + 'canGc': ['RequestSubmit', 'ReportValidity', 'Reset','SetRel', 'Decode', 'SetCrossOrigin', 'SetWidth', 'SetHeight'], }, 'HTMLInputElement': { diff --git a/components/shared/net/request.rs b/components/shared/net/request.rs index 5fafa8ada00..3947e58ce54 100644 --- a/components/shared/net/request.rs +++ b/components/shared/net/request.rs @@ -137,6 +137,17 @@ pub enum CorsSettings { UseCredentials, } +impl CorsSettings { + /// + pub fn from_enumerated_attribute(value: &str) -> CorsSettings { + match value.to_ascii_lowercase().as_str() { + "anonymous" => CorsSettings::Anonymous, + "use-credentials" => CorsSettings::UseCredentials, + _ => CorsSettings::Anonymous, + } + } +} + /// [Parser Metadata](https://fetch.spec.whatwg.org/#concept-request-parser-metadata) #[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)] pub enum ParserMetadata { diff --git a/tests/wpt/meta/html/dom/reflection-embedded.html.ini b/tests/wpt/meta/html/dom/reflection-embedded.html.ini index 679057f2794..aed03a46f56 100644 --- a/tests/wpt/meta/html/dom/reflection-embedded.html.ini +++ b/tests/wpt/meta/html/dom/reflection-embedded.html.ini @@ -503,168 +503,6 @@ [img.srcset: IDL set to object "test-valueOf"] expected: FAIL - [img.referrerPolicy: IDL set to ""] - expected: FAIL - - [img.referrerPolicy: IDL set to " \\0\\x01\\x02\\x03\\x04\\x05\\x06\\x07 \\b\\t\\n\\v\\f\\r\\x0e\\x0f \\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17 \\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f foo "] - expected: FAIL - - [img.referrerPolicy: IDL set to undefined] - expected: FAIL - - [img.referrerPolicy: IDL set to 7] - expected: FAIL - - [img.referrerPolicy: IDL set to 1.5] - expected: FAIL - - [img.referrerPolicy: IDL set to "5%"] - expected: FAIL - - [img.referrerPolicy: IDL set to "+100"] - expected: FAIL - - [img.referrerPolicy: IDL set to ".5"] - expected: FAIL - - [img.referrerPolicy: IDL set to true] - expected: FAIL - - [img.referrerPolicy: IDL set to false] - expected: FAIL - - [img.referrerPolicy: IDL set to object "[object Object\]"] - expected: FAIL - - [img.referrerPolicy: IDL set to NaN] - expected: FAIL - - [img.referrerPolicy: IDL set to Infinity] - expected: FAIL - - [img.referrerPolicy: IDL set to -Infinity] - expected: FAIL - - [img.referrerPolicy: IDL set to "\\0"] - expected: FAIL - - [img.referrerPolicy: IDL set to object "test-toString"] - expected: FAIL - - [img.referrerPolicy: IDL set to object "test-valueOf"] - expected: FAIL - - [img.referrerPolicy: IDL set to "xno-referrer"] - expected: FAIL - - [img.referrerPolicy: IDL set to "no-referrer\\0"] - expected: FAIL - - [img.referrerPolicy: IDL set to "o-referrer"] - expected: FAIL - - [img.referrerPolicy: IDL set to "NO-REFERRER"] - expected: FAIL - - [img.referrerPolicy: IDL set to "xno-referrer-when-downgrade"] - expected: FAIL - - [img.referrerPolicy: IDL set to "no-referrer-when-downgrade\\0"] - expected: FAIL - - [img.referrerPolicy: IDL set to "o-referrer-when-downgrade"] - expected: FAIL - - [img.referrerPolicy: IDL set to "NO-REFERRER-WHEN-DOWNGRADE"] - expected: FAIL - - [img.referrerPolicy: IDL set to "xsame-origin"] - expected: FAIL - - [img.referrerPolicy: IDL set to "same-origin\\0"] - expected: FAIL - - [img.referrerPolicy: IDL set to "ame-origin"] - expected: FAIL - - [img.referrerPolicy: IDL set to "SAME-ORIGIN"] - expected: FAIL - - [img.referrerPolicy: IDL set to "ſame-origin"] - expected: FAIL - - [img.referrerPolicy: IDL set to "xorigin"] - expected: FAIL - - [img.referrerPolicy: IDL set to "origin\\0"] - expected: FAIL - - [img.referrerPolicy: IDL set to "rigin"] - expected: FAIL - - [img.referrerPolicy: IDL set to "ORIGIN"] - expected: FAIL - - [img.referrerPolicy: IDL set to "xstrict-origin"] - expected: FAIL - - [img.referrerPolicy: IDL set to "strict-origin\\0"] - expected: FAIL - - [img.referrerPolicy: IDL set to "trict-origin"] - expected: FAIL - - [img.referrerPolicy: IDL set to "STRICT-ORIGIN"] - expected: FAIL - - [img.referrerPolicy: IDL set to "ſtrict-origin"] - expected: FAIL - - [img.referrerPolicy: IDL set to "xorigin-when-cross-origin"] - expected: FAIL - - [img.referrerPolicy: IDL set to "origin-when-cross-origin\\0"] - expected: FAIL - - [img.referrerPolicy: IDL set to "rigin-when-cross-origin"] - expected: FAIL - - [img.referrerPolicy: IDL set to "ORIGIN-WHEN-CROSS-ORIGIN"] - expected: FAIL - - [img.referrerPolicy: IDL set to "origin-when-croſſ-origin"] - expected: FAIL - - [img.referrerPolicy: IDL set to "xstrict-origin-when-cross-origin"] - expected: FAIL - - [img.referrerPolicy: IDL set to "strict-origin-when-cross-origin\\0"] - expected: FAIL - - [img.referrerPolicy: IDL set to "trict-origin-when-cross-origin"] - expected: FAIL - - [img.referrerPolicy: IDL set to "STRICT-ORIGIN-WHEN-CROSS-ORIGIN"] - expected: FAIL - - [img.referrerPolicy: IDL set to "ſtrict-origin-when-croſſ-origin"] - expected: FAIL - - [img.referrerPolicy: IDL set to "xunsafe-url"] - expected: FAIL - - [img.referrerPolicy: IDL set to "unsafe-url\\0"] - expected: FAIL - - [img.referrerPolicy: IDL set to "nsafe-url"] - expected: FAIL - - [img.referrerPolicy: IDL set to "UNSAFE-URL"] - expected: FAIL - - [img.referrerPolicy: IDL set to "unſafe-url"] - expected: FAIL - [img.decoding: typeof IDL attribute] expected: FAIL diff --git a/tests/wpt/meta/html/semantics/embedded-content/the-img-element/relevant-mutations.html.ini b/tests/wpt/meta/html/semantics/embedded-content/the-img-element/relevant-mutations.html.ini deleted file mode 100644 index 089c3ea5915..00000000000 --- a/tests/wpt/meta/html/semantics/embedded-content/the-img-element/relevant-mutations.html.ini +++ /dev/null @@ -1,9 +0,0 @@ -[relevant-mutations.html] - [crossorigin state not changed: empty to anonymous] - expected: FAIL - - [crossorigin state not changed: use-credentials to USE-CREDENTIALS] - expected: FAIL - - [crossorigin state not changed: anonymous to foobar] - expected: FAIL