mirror of
https://github.com/servo/servo.git
synced 2025-08-02 12:10:29 +01:00
Auto merge of #24340 - jdm:image-cache-cors, r=Manishearth
Allow using CORS filtered image responses as WebGL textures More specifically, this makes the "is this image same origin?" check consider the CORS status of the original response, rather than relying on an overly-strict "is this image's response's URL same-origin with a particular global?" check. To do this, we make the image cache double keyed based on the requested URL as well as the requesting origin, and store the CORS status of the eventual response with the final image that eventually gets sent to the HTMLImageElement consumer. --- - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors - [x] These changes fix #24330 and fix #24368 - [x] There are tests for these changes <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/24340) <!-- Reviewable:end -->
This commit is contained in:
commit
75548f40c6
109 changed files with 531 additions and 419 deletions
|
@ -19,11 +19,13 @@ 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};
|
||||
use crate::dom::imagedata::ImageData;
|
||||
use crate::dom::node::{Node, NodeDamage};
|
||||
use crate::dom::paintworkletglobalscope::PaintWorkletGlobalScope;
|
||||
use crate::dom::textmetrics::TextMetrics;
|
||||
use crate::unpremultiplytable::UNPREMULTIPLY_TABLE;
|
||||
use canvas_traits::canvas::{Canvas2dMsg, CanvasId, CanvasMsg};
|
||||
|
@ -44,10 +46,11 @@ 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;
|
||||
use servo_url::ServoUrl;
|
||||
use servo_url::{ImmutableOrigin, ServoUrl};
|
||||
use std::cell::Cell;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
|
@ -126,6 +129,7 @@ pub struct CanvasState {
|
|||
/// The base URL for resolving CSS image URL values.
|
||||
/// Needed because of https://github.com/servo/servo/issues/17625
|
||||
base_url: ServoUrl,
|
||||
origin: ImmutableOrigin,
|
||||
/// Any missing image URLs.
|
||||
missing_image_urls: DomRefCell<Vec<ServoUrl>>,
|
||||
saved_states: DomRefCell<Vec<CanvasContextState>>,
|
||||
|
@ -143,6 +147,14 @@ impl CanvasState {
|
|||
.unwrap();
|
||||
let (ipc_renderer, canvas_id) = receiver.recv().unwrap();
|
||||
debug!("Done.");
|
||||
// Worklets always receive a unique origin. This messes with fetching
|
||||
// cached images in the case of paint worklets, since the image cache
|
||||
// is keyed on the origin requesting the image data.
|
||||
let origin = if global.is::<PaintWorkletGlobalScope>() {
|
||||
global.api_base_url().origin()
|
||||
} else {
|
||||
global.origin().immutable().clone()
|
||||
};
|
||||
CanvasState {
|
||||
ipc_renderer: ipc_renderer,
|
||||
canvas_id: canvas_id,
|
||||
|
@ -152,6 +164,7 @@ impl CanvasState {
|
|||
base_url: global.api_base_url(),
|
||||
missing_image_urls: DomRefCell::new(Vec::new()),
|
||||
saved_states: DomRefCell::new(Vec::new()),
|
||||
origin,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -199,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 |
|
||||
|
@ -218,10 +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,
|
||||
);
|
||||
|
@ -341,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,
|
||||
)
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -423,6 +460,7 @@ impl CanvasState {
|
|||
&self,
|
||||
canvas: Option<&HTMLCanvasElement>,
|
||||
url: ServoUrl,
|
||||
cors_setting: Option<CorsSettings>,
|
||||
sx: f64,
|
||||
sy: f64,
|
||||
sw: Option<f64>,
|
||||
|
@ -433,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();
|
||||
|
||||
|
@ -776,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) => {
|
||||
|
@ -788,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)?,
|
||||
};
|
||||
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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")) {
|
||||
|
|
|
@ -442,12 +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,
|
||||
);
|
||||
|
|
|
@ -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};
|
||||
|
@ -56,11 +58,11 @@ use mime::{self, Mime};
|
|||
use msg::constellation_msg::PipelineId;
|
||||
use net_traits::image::base::{Image, ImageMetadata};
|
||||
use net_traits::image_cache::UsePlaceholder;
|
||||
use net_traits::image_cache::{CanRequestImages, ImageCache, ImageOrMetadataAvailable};
|
||||
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;
|
||||
|
@ -184,6 +186,7 @@ impl FetchResponseListener for ImageContext {
|
|||
fn process_request_eof(&mut self) {}
|
||||
|
||||
fn process_response(&mut self, metadata: Result<FetchMetadata, NetworkError>) {
|
||||
debug!("got {:?} for {:?}", metadata.as_ref().map(|_| ()), self.url);
|
||||
self.image_cache
|
||||
.notify_pending_response(self.id, FetchResponseMsg::ProcessResponse(metadata.clone()));
|
||||
|
||||
|
@ -263,15 +266,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 {
|
||||
|
@ -281,6 +300,8 @@ impl HTMLImageElement {
|
|||
let image_cache = window.image_cache();
|
||||
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,
|
||||
);
|
||||
|
@ -343,6 +364,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
|
||||
|
@ -907,6 +935,8 @@ impl HTMLImageElement {
|
|||
let image_cache = window.image_cache();
|
||||
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,
|
||||
);
|
||||
|
@ -1062,6 +1092,8 @@ impl HTMLImageElement {
|
|||
// Step 14
|
||||
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,
|
||||
);
|
||||
|
@ -1268,6 +1300,10 @@ impl HTMLImageElement {
|
|||
}
|
||||
|
||||
pub fn same_origin(&self, origin: &MutableOrigin) -> bool {
|
||||
if let Some(ref image) = self.current_request.borrow().image {
|
||||
return image.cors_status == CorsStatus::Safe;
|
||||
}
|
||||
|
||||
self.current_request
|
||||
.borrow()
|
||||
.final_url
|
||||
|
|
|
@ -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;
|
||||
|
@ -830,16 +830,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())))
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -159,6 +159,8 @@ impl HTMLVideoElement {
|
|||
let image_cache = window.image_cache();
|
||||
let response = image_cache.find_image_or_metadata(
|
||||
poster_url.clone().into(),
|
||||
window.origin().immutable().clone(),
|
||||
None,
|
||||
UsePlaceholder::No,
|
||||
CanRequestImages::Yes,
|
||||
);
|
||||
|
|
|
@ -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") {
|
||||
|
|
|
@ -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 cors_setting = cors_setting_for_element(image.upcast());
|
||||
|
||||
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 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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue