diff options
author | Josh Matthews <josh@joshmatthews.net> | 2019-10-03 17:36:02 -0400 |
---|---|---|
committer | Josh Matthews <josh@joshmatthews.net> | 2019-10-04 15:08:40 -0400 |
commit | 1df8d57dc6adcf56c22b45053b3d2eca904d17d3 (patch) | |
tree | ce2ba8d6672925a95d551a0ece8ee9e279332e3e /components/script | |
parent | 583536c9406e685405d5b28da99dd8cab94c7d66 (diff) | |
download | servo-1df8d57dc6adcf56c22b45053b3d2eca904d17d3.tar.gz servo-1df8d57dc6adcf56c22b45053b3d2eca904d17d3.zip |
Support CORS attributes for image elements.
Diffstat (limited to 'components/script')
-rw-r--r-- | components/script/dom/canvasrenderingcontext2d.rs | 48 | ||||
-rw-r--r-- | components/script/dom/element.rs | 12 | ||||
-rw-r--r-- | components/script/dom/eventsource.rs | 24 | ||||
-rw-r--r-- | components/script/dom/htmlanchorelement.rs | 8 | ||||
-rw-r--r-- | components/script/dom/htmlcanvaselement.rs | 8 | ||||
-rw-r--r-- | components/script/dom/htmlimageelement.rs | 38 | ||||
-rw-r--r-- | components/script/dom/htmlmediaelement.rs | 15 | ||||
-rw-r--r-- | components/script/dom/htmlscriptelement.rs | 20 | ||||
-rw-r--r-- | components/script/dom/htmlvideoelement.rs | 1 | ||||
-rw-r--r-- | components/script/dom/servoparser/prefetch.rs | 23 | ||||
-rw-r--r-- | components/script/dom/webglrenderingcontext.rs | 17 | ||||
-rw-r--r-- | components/script/fetch.rs | 31 | ||||
-rw-r--r-- | components/script/stylesheet_loader.rs | 21 |
13 files changed, 172 insertions, 94 deletions
diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 380b9a8312a..c964422c27c 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -19,6 +19,7 @@ use crate::dom::bindings::root::{Dom, DomRoot, LayoutDom}; use crate::dom::bindings::str::DOMString; use crate::dom::canvasgradient::{CanvasGradient, CanvasGradientStyle, ToFillOrStrokeStyle}; use crate::dom::canvaspattern::CanvasPattern; +use crate::dom::element::cors_setting_for_element; use crate::dom::element::Element; use crate::dom::globalscope::GlobalScope; use crate::dom::htmlcanvaselement::{CanvasContext, HTMLCanvasElement}; @@ -45,6 +46,7 @@ use net_traits::image_cache::ImageOrMetadataAvailable; use net_traits::image_cache::ImageResponse; use net_traits::image_cache::ImageState; use net_traits::image_cache::UsePlaceholder; +use net_traits::request::CorsSettings; use pixels::PixelFormat; use profile_traits::ipc as profiled_ipc; use script_traits::ScriptMsg; @@ -210,8 +212,12 @@ impl CanvasState { } } - fn fetch_image_data(&self, url: ServoUrl) -> Option<(Vec<u8>, Size2D<u32>)> { - let img = match self.request_image_from_cache(url) { + fn fetch_image_data( + &self, + url: ServoUrl, + cors_setting: Option<CorsSettings>, + ) -> Option<(Vec<u8>, Size2D<u32>)> { + let img = match self.request_image_from_cache(url, cors_setting) { ImageResponse::Loaded(img, _) => img, ImageResponse::PlaceholderLoaded(_, _) | ImageResponse::None | @@ -229,11 +235,15 @@ impl CanvasState { Some((image_data, image_size)) } - #[inline] - fn request_image_from_cache(&self, url: ServoUrl) -> ImageResponse { + fn request_image_from_cache( + &self, + url: ServoUrl, + cors_setting: Option<CorsSettings>, + ) -> ImageResponse { let response = self.image_cache.find_image_or_metadata( url.clone(), self.origin.clone(), + cors_setting, UsePlaceholder::No, CanRequestImages::No, ); @@ -353,13 +363,28 @@ impl CanvasState { // If the image argument is an HTMLImageElement object that is in the broken state, // then throw an InvalidStateError exception let url = image.get_url().ok_or(Error::InvalidState)?; - self.fetch_and_draw_image_data(htmlcanvas, url, sx, sy, sw, sh, dx, dy, dw, dh) + let cors_setting = cors_setting_for_element(image.upcast()); + self.fetch_and_draw_image_data( + htmlcanvas, + url, + cors_setting, + sx, + sy, + sw, + sh, + dx, + dy, + dw, + dh, + ) }, CanvasImageSource::CSSStyleValue(ref value) => { let url = value .get_url(self.base_url.clone()) .ok_or(Error::InvalidState)?; - self.fetch_and_draw_image_data(htmlcanvas, url, sx, sy, sw, sh, dx, dy, dw, dh) + self.fetch_and_draw_image_data( + htmlcanvas, url, None, sx, sy, sw, sh, dx, dy, dw, dh, + ) }, }; @@ -435,6 +460,7 @@ impl CanvasState { &self, canvas: Option<&HTMLCanvasElement>, url: ServoUrl, + cors_setting: Option<CorsSettings>, sx: f64, sy: f64, sw: Option<f64>, @@ -445,7 +471,9 @@ impl CanvasState { dh: Option<f64>, ) -> ErrorResult { debug!("Fetching image {}.", url); - let (mut image_data, image_size) = self.fetch_image_data(url).ok_or(Error::InvalidState)?; + let (mut image_data, image_size) = self + .fetch_image_data(url, cors_setting) + .ok_or(Error::InvalidState)?; pixels::rgba8_premultiply_inplace(&mut image_data); let image_size = image_size.to_f64(); @@ -788,7 +816,9 @@ impl CanvasState { // then throw an InvalidStateError exception image .get_url() - .and_then(|url| self.fetch_image_data(url)) + .and_then(|url| { + self.fetch_image_data(url, cors_setting_for_element(image.upcast())) + }) .ok_or(Error::InvalidState)? }, CanvasImageSource::HTMLCanvasElement(ref canvas) => { @@ -800,7 +830,7 @@ impl CanvasState { }, CanvasImageSource::CSSStyleValue(ref value) => value .get_url(self.base_url.clone()) - .and_then(|url| self.fetch_image_data(url)) + .and_then(|url| self.fetch_image_data(url, None)) .ok_or(Error::InvalidState)?, }; diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index 4b16db4699e..baf4fcd0878 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -35,7 +35,7 @@ use crate::dom::create::create_element; use crate::dom::customelementregistry::{ CallbackReaction, CustomElementDefinition, CustomElementReaction, CustomElementState, }; -use crate::dom::document::{Document, LayoutDocumentHelpers}; +use crate::dom::document::{determine_policy_for_token, Document, LayoutDocumentHelpers}; use crate::dom::documentfragment::DocumentFragment; use crate::dom::domrect::DOMRect; use crate::dom::domtokenlist::DOMTokenList; @@ -97,6 +97,7 @@ use js::jsapi::Heap; use js::jsval::JSVal; use msg::constellation_msg::InputMethodType; use net_traits::request::CorsSettings; +use net_traits::ReferrerPolicy; use ref_filter_map::ref_filter_map; use script_layout_interface::message::ReflowGoal; use selectors::attr::{AttrSelectorOperation, CaseSensitivity, NamespaceConstraint}; @@ -3606,7 +3607,14 @@ pub fn set_cross_origin_attribute(element: &Element, value: Option<DOMString>) { } } -pub fn cors_setting_for_element(element: &Element) -> Option<CorsSettings> { +pub(crate) fn referrer_policy_for_element(element: &Element) -> Option<ReferrerPolicy> { + element + .get_attribute_by_name(DOMString::from_string(String::from("referrerpolicy"))) + .and_then(|attribute: DomRoot<Attr>| determine_policy_for_token(&attribute.Value())) + .or_else(|| document_from_node(element).get_referrer_policy()) +} + +pub(crate) fn cors_setting_for_element(element: &Element) -> Option<CorsSettings> { reflect_cross_origin_attribute(element).map_or(None, |attr| match &*attr { "anonymous" => Some(CorsSettings::Anonymous), "use-credentials" => Some(CorsSettings::UseCredentials), diff --git a/components/script/dom/eventsource.rs b/components/script/dom/eventsource.rs index 02283a3c190..92eb2c2f414 100644 --- a/components/script/dom/eventsource.rs +++ b/components/script/dom/eventsource.rs @@ -18,7 +18,7 @@ use crate::dom::eventtarget::EventTarget; use crate::dom::globalscope::GlobalScope; use crate::dom::messageevent::MessageEvent; use crate::dom::performanceresourcetiming::InitiatorType; -use crate::fetch::FetchCanceller; +use crate::fetch::{create_a_potential_CORS_request, FetchCanceller}; use crate::network_listener::{self, NetworkListener, PreInvoke, ResourceTimingListener}; use crate::task_source::{TaskSource, TaskSourceName}; use crate::timers::OneshotTimerCallback; @@ -31,8 +31,7 @@ use ipc_channel::router::ROUTER; use js::conversions::ToJSValConvertible; use js::jsval::UndefinedValue; use mime::{self, Mime}; -use net_traits::request::{CacheMode, CorsSettings, CredentialsMode}; -use net_traits::request::{RequestBuilder, RequestMode}; +use net_traits::request::{CacheMode, CorsSettings, Destination, RequestBuilder}; use net_traits::{CoreResourceMsg, FetchChannels, FetchMetadata}; use net_traits::{FetchResponseListener, FetchResponseMsg, NetworkError}; use net_traits::{ResourceFetchTiming, ResourceTimingType}; @@ -516,17 +515,14 @@ impl EventSource { }; // Step 8 // TODO: Step 9 set request's client settings - let mut request = RequestBuilder::new(url_record) - .origin(global.origin().immutable().clone()) - .pipeline_id(Some(global.pipeline_id())) - // https://html.spec.whatwg.org/multipage/#create-a-potential-cors-request - .use_url_credentials(true) - .mode(RequestMode::CorsMode) - .credentials_mode(if cors_attribute_state == CorsSettings::Anonymous { - CredentialsMode::CredentialsSameOrigin - } else { - CredentialsMode::Include - }); + let mut request = create_a_potential_CORS_request( + url_record, + Destination::None, + Some(cors_attribute_state), + Some(true), + ) + .origin(global.origin().immutable().clone()) + .pipeline_id(Some(global.pipeline_id())); // Step 10 // TODO(eijebong): Replace once typed headers allow it diff --git a/components/script/dom/htmlanchorelement.rs b/components/script/dom/htmlanchorelement.rs index cb197a054f3..c5b3fb51362 100644 --- a/components/script/dom/htmlanchorelement.rs +++ b/components/script/dom/htmlanchorelement.rs @@ -3,7 +3,6 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use crate::dom::activation::Activatable; -use crate::dom::attr::Attr; use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::codegen::Bindings::AttrBinding::AttrMethods; use crate::dom::bindings::codegen::Bindings::HTMLAnchorElementBinding; @@ -14,10 +13,9 @@ use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::refcounted::Trusted; use crate::dom::bindings::root::{DomRoot, MutNullableDom}; use crate::dom::bindings::str::{DOMString, USVString}; -use crate::dom::document::determine_policy_for_token; use crate::dom::document::Document; use crate::dom::domtokenlist::DOMTokenList; -use crate::dom::element::Element; +use crate::dom::element::{referrer_policy_for_element, Element}; use crate::dom::event::Event; use crate::dom::eventtarget::EventTarget; use crate::dom::globalscope::GlobalScope; @@ -669,9 +667,7 @@ pub fn follow_hyperlink(subject: &Element, hyperlink_suffix: Option<String>) { }; // Step 12. - let referrer_policy = subject - .get_attribute_by_name(DOMString::from_string(String::from("referrerpolicy"))) - .and_then(|attribute: DomRoot<Attr>| (determine_policy_for_token(&attribute.Value()))); + let referrer_policy = referrer_policy_for_element(subject); // Step 13 let referrer = match subject.get_attribute(&ns!(), &local_name!("rel")) { diff --git a/components/script/dom/htmlcanvaselement.rs b/components/script/dom/htmlcanvaselement.rs index eb62d920ca9..9e638539995 100644 --- a/components/script/dom/htmlcanvaselement.rs +++ b/components/script/dom/htmlcanvaselement.rs @@ -442,13 +442,19 @@ pub mod utils { use crate::dom::window::Window; use net_traits::image_cache::CanRequestImages; use net_traits::image_cache::{ImageOrMetadataAvailable, ImageResponse, UsePlaceholder}; + use net_traits::request::CorsSettings; use servo_url::ServoUrl; - pub fn request_image_from_cache(window: &Window, url: ServoUrl) -> ImageResponse { + pub fn request_image_from_cache( + window: &Window, + url: ServoUrl, + cors_setting: Option<CorsSettings>, + ) -> ImageResponse { let image_cache = window.image_cache(); let response = image_cache.find_image_or_metadata( url.into(), window.origin().immutable().clone(), + cors_setting, UsePlaceholder::No, CanRequestImages::No, ); diff --git a/components/script/dom/htmlimageelement.rs b/components/script/dom/htmlimageelement.rs index 95f00a2b007..a8dcfca5b92 100644 --- a/components/script/dom/htmlimageelement.rs +++ b/components/script/dom/htmlimageelement.rs @@ -20,6 +20,7 @@ use crate::dom::bindings::reflector::DomObject; use crate::dom::bindings::root::{DomRoot, LayoutDom, MutNullableDom}; use crate::dom::bindings::str::{DOMString, USVString}; use crate::dom::document::Document; +use crate::dom::element::{cors_setting_for_element, referrer_policy_for_element}; use crate::dom::element::{reflect_cross_origin_attribute, set_cross_origin_attribute}; use crate::dom::element::{AttributeMutation, Element, RawLayoutElementHelpers}; use crate::dom::event::Event; @@ -40,6 +41,7 @@ use crate::dom::performanceresourcetiming::InitiatorType; use crate::dom::values::UNSIGNED_LONG_MAX; use crate::dom::virtualmethods::VirtualMethods; use crate::dom::window::Window; +use crate::fetch::create_a_potential_CORS_request; use crate::image_listener::{add_cache_listener_for_element, ImageCacheListener}; use crate::microtask::{Microtask, MicrotaskRunnable}; use crate::network_listener::{self, NetworkListener, PreInvoke, ResourceTimingListener}; @@ -58,9 +60,9 @@ use net_traits::image::base::{Image, ImageMetadata}; use net_traits::image_cache::UsePlaceholder; use net_traits::image_cache::{CanRequestImages, CorsStatus, ImageCache, ImageOrMetadataAvailable}; use net_traits::image_cache::{ImageResponder, ImageResponse, ImageState, PendingImageId}; -use net_traits::request::RequestBuilder; +use net_traits::request::{CorsSettings, Destination, Initiator, RequestBuilder}; use net_traits::{FetchMetadata, FetchResponseListener, FetchResponseMsg, NetworkError}; -use net_traits::{ResourceFetchTiming, ResourceTimingType}; +use net_traits::{ReferrerPolicy, ResourceFetchTiming, ResourceTimingType}; use num_traits::ToPrimitive; use servo_url::origin::ImmutableOrigin; use servo_url::origin::MutableOrigin; @@ -263,15 +265,31 @@ impl PreInvoke for ImageContext { } } +#[derive(PartialEq)] +pub(crate) enum FromPictureOrSrcSet { + Yes, + No, +} + +// https://html.spec.whatwg.org/multipage/#update-the-image-data steps 17-20 // This function is also used to prefetch an image in `script::dom::servoparser::prefetch`. pub(crate) fn image_fetch_request( img_url: ServoUrl, origin: ImmutableOrigin, pipeline_id: PipelineId, + cors_setting: Option<CorsSettings>, + referrer_policy: Option<ReferrerPolicy>, + from_picture_or_srcset: FromPictureOrSrcSet, ) -> RequestBuilder { - RequestBuilder::new(img_url) - .origin(origin) - .pipeline_id(Some(pipeline_id)) + let mut request = + create_a_potential_CORS_request(img_url, Destination::Image, cors_setting, None) + .origin(origin) + .pipeline_id(Some(pipeline_id)) + .referrer_policy(referrer_policy); + if from_picture_or_srcset == FromPictureOrSrcSet::Yes { + request = request.initiator(Initiator::ImageSet); + } + request } impl HTMLImageElement { @@ -282,6 +300,7 @@ impl HTMLImageElement { let response = image_cache.find_image_or_metadata( img_url.clone().into(), window.origin().immutable().clone(), + cors_setting_for_element(self.upcast()), UsePlaceholder::Yes, CanRequestImages::Yes, ); @@ -344,6 +363,13 @@ impl HTMLImageElement { img_url.clone(), document.origin().immutable().clone(), document.global().pipeline_id(), + cors_setting_for_element(self.upcast()), + referrer_policy_for_element(self.upcast()), + if Self::uses_srcset_or_picture(self.upcast()) { + FromPictureOrSrcSet::Yes + } else { + FromPictureOrSrcSet::No + }, ); // This is a background load because the load blocker already fulfills the @@ -909,6 +935,7 @@ impl HTMLImageElement { let response = image_cache.find_image_or_metadata( img_url.clone().into(), window.origin().immutable().clone(), + cors_setting_for_element(self.upcast()), UsePlaceholder::No, CanRequestImages::No, ); @@ -1065,6 +1092,7 @@ impl HTMLImageElement { let response = image_cache.find_image_or_metadata( img_url.clone().into(), window.origin().immutable().clone(), + cors_setting_for_element(self.upcast()), UsePlaceholder::No, CanRequestImages::Yes, ); diff --git a/components/script/dom/htmlmediaelement.rs b/components/script/dom/htmlmediaelement.rs index e3cb0dfb5b2..fb14f32c789 100644 --- a/components/script/dom/htmlmediaelement.rs +++ b/components/script/dom/htmlmediaelement.rs @@ -58,7 +58,7 @@ use crate::dom::url::URL; use crate::dom::videotrack::VideoTrack; use crate::dom::videotracklist::VideoTrackList; use crate::dom::virtualmethods::VirtualMethods; -use crate::fetch::FetchCanceller; +use crate::fetch::{create_a_potential_CORS_request, FetchCanceller}; use crate::microtask::{Microtask, MicrotaskRunnable}; use crate::network_listener::{self, NetworkListener, PreInvoke, ResourceTimingListener}; use crate::script_thread::ScriptThread; @@ -74,7 +74,7 @@ use ipc_channel::router::ROUTER; use media::{glplayer_channel, GLPlayerMsg, GLPlayerMsgForward}; use net_traits::image::base::Image; use net_traits::image_cache::ImageResponse; -use net_traits::request::{CredentialsMode, Destination, Referrer, RequestBuilder, RequestMode}; +use net_traits::request::{Destination, Referrer}; use net_traits::{CoreResourceMsg, FetchChannels, FetchMetadata, FetchResponseListener, Metadata}; use net_traits::{NetworkError, ResourceFetchTiming, ResourceTimingType}; use script_layout_interface::HTMLMediaData; @@ -822,16 +822,9 @@ impl HTMLMediaElement { None => self.blob_url.borrow().as_ref().unwrap().clone(), }; - let request = RequestBuilder::new(url.clone()) + let cors_setting = cors_setting_for_element(self.upcast()); + let request = create_a_potential_CORS_request(url.clone(), destination, cors_setting, None) .headers(headers) - .destination(destination) - .credentials_mode(CredentialsMode::Include) - // https://html.spec.whatwg.org/multipage/#create-a-potential-cors-request - .mode(match cors_setting_for_element(self.upcast::<Element>()) { - Some(_) => RequestMode::CorsMode, - None => RequestMode::NoCors, - }) - .use_url_credentials(true) .origin(document.origin().immutable().clone()) .pipeline_id(Some(self.global().pipeline_id())) .referrer(Some(Referrer::ReferrerUrl(document.url()))) diff --git a/components/script/dom/htmlscriptelement.rs b/components/script/dom/htmlscriptelement.rs index 4d2cf061804..1bd0101c03d 100644 --- a/components/script/dom/htmlscriptelement.rs +++ b/components/script/dom/htmlscriptelement.rs @@ -25,6 +25,7 @@ use crate::dom::node::{document_from_node, window_from_node}; use crate::dom::node::{BindContext, ChildrenMutation, CloneChildrenFlag, Node}; use crate::dom::performanceresourcetiming::InitiatorType; use crate::dom::virtualmethods::VirtualMethods; +use crate::fetch::create_a_potential_CORS_request; use crate::network_listener::{self, NetworkListener, PreInvoke, ResourceTimingListener}; use dom_struct::dom_struct; use encoding_rs::Encoding; @@ -33,9 +34,7 @@ use ipc_channel::ipc; use ipc_channel::router::ROUTER; use js::jsval::UndefinedValue; use msg::constellation_msg::PipelineId; -use net_traits::request::{ - CorsSettings, CredentialsMode, Destination, Referrer, RequestBuilder, RequestMode, -}; +use net_traits::request::{CorsSettings, Destination, Referrer, RequestBuilder}; use net_traits::ReferrerPolicy; use net_traits::{FetchMetadata, FetchResponseListener, Metadata, NetworkError}; use net_traits::{ResourceFetchTiming, ResourceTimingType}; @@ -306,20 +305,7 @@ pub(crate) fn script_fetch_request( referrer_policy: Option<ReferrerPolicy>, integrity_metadata: String, ) -> RequestBuilder { - RequestBuilder::new(url) - .destination(Destination::Script) - // https://html.spec.whatwg.org/multipage/#create-a-potential-cors-request - // Step 1 - .mode(match cors_setting { - Some(_) => RequestMode::CorsMode, - None => RequestMode::NoCors, - }) - // https://html.spec.whatwg.org/multipage/#create-a-potential-cors-request - // Step 3-4 - .credentials_mode(match cors_setting { - Some(CorsSettings::Anonymous) => CredentialsMode::CredentialsSameOrigin, - _ => CredentialsMode::Include, - }) + create_a_potential_CORS_request(url, Destination::Script, cors_setting, None) .origin(origin) .pipeline_id(Some(pipeline_id)) .referrer(Some(referrer)) diff --git a/components/script/dom/htmlvideoelement.rs b/components/script/dom/htmlvideoelement.rs index 4a1816b5cd4..9b7fc13fcb1 100644 --- a/components/script/dom/htmlvideoelement.rs +++ b/components/script/dom/htmlvideoelement.rs @@ -133,6 +133,7 @@ impl HTMLVideoElement { let response = image_cache.find_image_or_metadata( poster_url.clone().into(), window.origin().immutable().clone(), + None, UsePlaceholder::No, CanRequestImages::Yes, ); diff --git a/components/script/dom/servoparser/prefetch.rs b/components/script/dom/servoparser/prefetch.rs index a2977cc15b1..716be8b0f51 100644 --- a/components/script/dom/servoparser/prefetch.rs +++ b/components/script/dom/servoparser/prefetch.rs @@ -4,8 +4,8 @@ use crate::dom::bindings::reflector::DomObject; use crate::dom::bindings::trace::JSTraceable; -use crate::dom::document::Document; -use crate::dom::htmlimageelement::image_fetch_request; +use crate::dom::document::{determine_policy_for_token, Document}; +use crate::dom::htmlimageelement::{image_fetch_request, FromPictureOrSrcSet}; use crate::dom::htmlscriptelement::script_fetch_request; use crate::stylesheet_loader::stylesheet_fetch_request; use html5ever::buffer_queue::BufferQueue; @@ -123,7 +123,14 @@ impl TokenSink for PrefetchSink { (TagKind::StartTag, local_name!("img")) if self.prefetching => { if let Some(url) = self.get_url(tag, local_name!("src")) { debug!("Prefetch {} {}", tag.name, url); - let request = image_fetch_request(url, self.origin.clone(), self.pipeline_id); + let request = image_fetch_request( + url, + self.origin.clone(), + self.pipeline_id, + self.get_cors_settings(tag, local_name!("crossorigin")), + self.get_referrer_policy(tag, LocalName::from("referrerpolicy")), + FromPictureOrSrcSet::No, + ); let _ = self .resource_threads .send(CoreResourceMsg::Fetch(request, FetchChannels::Prefetch)); @@ -137,6 +144,8 @@ impl TokenSink for PrefetchSink { debug!("Prefetch {} {}", tag.name, url); let cors_setting = self.get_cors_settings(tag, local_name!("crossorigin")); + let referrer_policy = + self.get_referrer_policy(tag, LocalName::from("referrerpolicy")); let integrity_metadata = self .get_attr(tag, local_name!("integrity")) .map(|attr| String::from(&attr.value)) @@ -147,7 +156,7 @@ impl TokenSink for PrefetchSink { self.origin.clone(), self.pipeline_id, self.referrer.clone(), - self.referrer_policy, + referrer_policy, integrity_metadata, ); let _ = self @@ -191,6 +200,12 @@ impl PrefetchSink { ServoUrl::parse_with_base(Some(base), &attr.value).ok() } + fn get_referrer_policy(&self, tag: &Tag, name: LocalName) -> Option<ReferrerPolicy> { + self.get_attr(tag, name) + .and_then(|attr| determine_policy_for_token(&*attr.value)) + .or(self.referrer_policy) + } + fn get_cors_settings(&self, tag: &Tag, name: LocalName) -> Option<CorsSettings> { let crossorigin = self.get_attr(tag, name)?; if crossorigin.value.eq_ignore_ascii_case("anonymous") { diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs index 46b9c72c6ca..9aa8bfe053a 100644 --- a/components/script/dom/webglrenderingcontext.rs +++ b/components/script/dom/webglrenderingcontext.rs @@ -19,6 +19,7 @@ use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector}; use crate::dom::bindings::root::{Dom, DomOnceCell, DomRoot, LayoutDom, MutNullableDom}; use crate::dom::bindings::str::DOMString; +use crate::dom::element::cors_setting_for_element; use crate::dom::event::{Event, EventBubbles, EventCancelable}; use crate::dom::htmlcanvaselement::utils as canvas_utils; use crate::dom::htmlcanvaselement::HTMLCanvasElement; @@ -576,13 +577,15 @@ impl WebGLRenderingContext { }; let window = window_from_node(&*self.canvas); - - let img = match canvas_utils::request_image_from_cache(&window, img_url) { - ImageResponse::Loaded(img, _) => img, - ImageResponse::PlaceholderLoaded(_, _) | - ImageResponse::None | - ImageResponse::MetadataLoaded(_) => return Ok(None), - }; + let cors_setting = cors_setting_for_element(image.upcast()); + + let img = + match canvas_utils::request_image_from_cache(&window, img_url, cors_setting) { + ImageResponse::Loaded(img, _) => img, + ImageResponse::PlaceholderLoaded(_, _) | + ImageResponse::None | + ImageResponse::MetadataLoaded(_) => return Ok(None), + }; let size = Size2D::new(img.width, img.height); diff --git a/components/script/fetch.rs b/components/script/fetch.rs index 0b093c5501d..8c31f24f260 100644 --- a/components/script/fetch.rs +++ b/components/script/fetch.rs @@ -26,7 +26,9 @@ use crate::network_listener::{ use crate::task_source::TaskSourceName; use ipc_channel::ipc; use ipc_channel::router::ROUTER; -use net_traits::request::RequestBuilder; +use net_traits::request::{ + CorsSettings, CredentialsMode, Destination, RequestBuilder, RequestMode, +}; use net_traits::request::{Request as NetTraitsRequest, ServiceWorkersMode}; use net_traits::CoreResourceMsg::Fetch as NetTraitsFetch; use net_traits::{CoreResourceMsg, CoreResourceThread, FetchResponseMsg}; @@ -124,6 +126,7 @@ fn request_init_from_request(request: NetTraitsRequest) -> RequestBuilder { integrity_metadata: "".to_owned(), url_list: vec![], parser_metadata: request.parser_metadata, + initiator: request.initiator, } } @@ -339,3 +342,29 @@ pub fn load_whole_resource( } } } + +/// https://html.spec.whatwg.org/multipage/#create-a-potential-cors-request +pub(crate) fn create_a_potential_CORS_request( + url: ServoUrl, + destination: Destination, + cors_setting: Option<CorsSettings>, + same_origin_fallback: Option<bool>, +) -> RequestBuilder { + RequestBuilder::new(url) + // https://html.spec.whatwg.org/multipage/#create-a-potential-cors-request + // Step 1 + .mode(match cors_setting { + Some(_) => RequestMode::CorsMode, + None if same_origin_fallback == Some(true) => RequestMode::SameOrigin, + None => RequestMode::NoCors, + }) + // https://html.spec.whatwg.org/multipage/#create-a-potential-cors-request + // Step 3-4 + .credentials_mode(match cors_setting { + Some(CorsSettings::Anonymous) => CredentialsMode::CredentialsSameOrigin, + _ => CredentialsMode::Include, + }) + // Step 5 + .destination(destination) + .use_url_credentials(true) +} diff --git a/components/script/stylesheet_loader.rs b/components/script/stylesheet_loader.rs index 258286dd6ea..82b5bbdf532 100644 --- a/components/script/stylesheet_loader.rs +++ b/components/script/stylesheet_loader.rs @@ -16,6 +16,7 @@ use crate::dom::htmllinkelement::{HTMLLinkElement, RequestGenerationId}; use crate::dom::node::{containing_shadow_root, document_from_node, window_from_node}; use crate::dom::performanceresourcetiming::InitiatorType; use crate::dom::shadowroot::ShadowRoot; +use crate::fetch::create_a_potential_CORS_request; use crate::network_listener::{self, NetworkListener, PreInvoke, ResourceTimingListener}; use cssparser::SourceLocation; use encoding_rs::UTF_8; @@ -23,9 +24,7 @@ use ipc_channel::ipc; use ipc_channel::router::ROUTER; use mime::{self, Mime}; use msg::constellation_msg::PipelineId; -use net_traits::request::{ - CorsSettings, CredentialsMode, Destination, Referrer, RequestBuilder, RequestMode, -}; +use net_traits::request::{CorsSettings, Destination, Referrer, RequestBuilder}; use net_traits::{ FetchMetadata, FetchResponseListener, FilteredMetadata, Metadata, NetworkError, ReferrerPolicy, }; @@ -335,6 +334,7 @@ impl<'a> StylesheetLoader<'a> { } // This function is also used to prefetch a stylesheet in `script::dom::servoparser::prefetch`. +// https://html.spec.whatwg.org/multipage/#default-fetch-and-process-the-linked-resource pub(crate) fn stylesheet_fetch_request( url: ServoUrl, cors_setting: Option<CorsSettings>, @@ -344,20 +344,7 @@ pub(crate) fn stylesheet_fetch_request( referrer_policy: Option<ReferrerPolicy>, integrity_metadata: String, ) -> RequestBuilder { - RequestBuilder::new(url) - .destination(Destination::Style) - // https://html.spec.whatwg.org/multipage/#create-a-potential-cors-request - // Step 1 - .mode(match cors_setting { - Some(_) => RequestMode::CorsMode, - None => RequestMode::NoCors, - }) - // https://html.spec.whatwg.org/multipage/#create-a-potential-cors-request - // Step 3-4 - .credentials_mode(match cors_setting { - Some(CorsSettings::Anonymous) => CredentialsMode::CredentialsSameOrigin, - _ => CredentialsMode::Include, - }) + create_a_potential_CORS_request(url, Destination::Style, cors_setting, None) .origin(origin) .pipeline_id(Some(pipeline_id)) .referrer(Some(referrer)) |