diff options
author | SendilKumar N <sendilkumarn@live.com> | 2017-03-09 20:30:01 +0800 |
---|---|---|
committer | Josh Matthews <josh@joshmatthews.net> | 2017-05-19 09:38:50 -0400 |
commit | 5acee23f5d46b40c35491de22592a58a9ef5a45b (patch) | |
tree | 960083d54ce4929c486cff1e04713ca16cf99a6a | |
parent | d855c929ef32e8f7d4bc15ba726e8eb5f8ad8e05 (diff) | |
download | servo-5acee23f5d46b40c35491de22592a58a9ef5a45b.tar.gz servo-5acee23f5d46b40c35491de22592a58a9ef5a45b.zip |
Use the origin of the actual image response when determining if a canvas is origin clean.
22 files changed, 79 insertions, 92 deletions
diff --git a/components/layout/context.rs b/components/layout/context.rs index 8acbc3b254a..3a4fac939cd 100644 --- a/components/layout/context.rs +++ b/components/layout/context.rs @@ -183,7 +183,7 @@ impl<'a> LayoutContext<'a> { } match self.get_or_request_image_or_meta(node, url.clone(), use_placeholder) { - Some(ImageOrMetadataAvailable::ImageAvailable(image)) => { + Some(ImageOrMetadataAvailable::ImageAvailable(image, _)) => { let image_info = WebRenderImageInfo::from_image(&*image); if image_info.key.is_none() { Some(image_info) diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs index c4dfefcc696..52171dcdfa5 100644 --- a/components/layout/fragment.rs +++ b/components/layout/fragment.rs @@ -378,7 +378,7 @@ impl ImageFragmentInfo { }); let (image, metadata) = match image_or_metadata { - Some(ImageOrMetadataAvailable::ImageAvailable(i)) => { + Some(ImageOrMetadataAvailable::ImageAvailable(i, _)) => { (Some(i.clone()), Some(ImageMetadata { height: i.height, width: i.width } )) } Some(ImageOrMetadataAvailable::MetadataAvailable(m)) => { diff --git a/components/net/image_cache.rs b/components/net/image_cache.rs index 9dcbf331cf4..b8467e5a461 100644 --- a/components/net/image_cache.rs +++ b/components/net/image_cache.rs @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use immeta::load_from_buf; -use net_traits::{FetchResponseMsg, NetworkError}; +use net_traits::{FetchMetadata, FetchResponseMsg, NetworkError}; use net_traits::image::base::{Image, ImageMetadata, PixelFormat, load_from_memory}; use net_traits::image_cache::{CanRequestImages, ImageCache, ImageResponder}; use net_traits::image_cache::{ImageOrMetadataAvailable, ImageResponse, ImageState}; @@ -15,6 +15,7 @@ use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::fs::File; use std::io::{self, Read}; use std::mem; +use std::path::PathBuf; use std::sync::{Arc, Mutex}; use std::thread; use webrender_traits; @@ -51,10 +52,8 @@ fn decode_bytes_sync(key: LoadKey, bytes: &[u8]) -> DecoderMsg { } } -fn get_placeholder_image(webrender_api: &webrender_traits::RenderApi) -> io::Result<Arc<Image>> { - let mut placeholder_path = try!(resources_dir_path()); - placeholder_path.push("rippy.png"); - let mut file = try!(File::open(&placeholder_path)); +fn get_placeholder_image(webrender_api: &webrender_traits::RenderApi, path: &PathBuf) -> io::Result<Arc<Image>> { + let mut file = try!(File::open(path)); let mut image_data = vec![]; try!(file.read_to_end(&mut image_data)); let mut image = load_from_memory(&image_data).unwrap(); @@ -289,6 +288,8 @@ struct PendingLoad { // The url being loaded. Do not forget that this may be several Mb // if we are loading a data: url. url: ServoUrl, + + final_url: Option<ServoUrl>, } impl PendingLoad { @@ -299,6 +300,7 @@ impl PendingLoad { result: None, listeners: vec!(), url: url, + final_url: None, } } @@ -320,6 +322,9 @@ struct ImageCacheStore { // The placeholder image used when an image fails to load placeholder_image: Option<Arc<Image>>, + // The URL used for the placeholder image + placeholder_url: ServoUrl, + // Webrender API instance. webrender_api: webrender_traits::RenderApi, } @@ -356,9 +361,11 @@ impl ImageCacheStore { LoadResult::PlaceholderLoaded(..) | LoadResult::None => {} } + let url = pending_load.final_url.clone(); let image_response = match load_result { - LoadResult::Loaded(image) => ImageResponse::Loaded(Arc::new(image)), - LoadResult::PlaceholderLoaded(image) => ImageResponse::PlaceholderLoaded(image), + LoadResult::Loaded(image) => ImageResponse::Loaded(Arc::new(image), url.unwrap()), + LoadResult::PlaceholderLoaded(image) => + ImageResponse::PlaceholderLoaded(image, self.placeholder_url.clone()), LoadResult::None => ImageResponse::None, }; @@ -378,11 +385,11 @@ impl ImageCacheStore { -> Option<Result<ImageOrMetadataAvailable, ImageState>> { self.completed_loads.get(url).map(|completed_load| { match (&completed_load.image_response, placeholder) { - (&ImageResponse::Loaded(ref image), _) | - (&ImageResponse::PlaceholderLoaded(ref image), UsePlaceholder::Yes) => { - Ok(ImageOrMetadataAvailable::ImageAvailable(image.clone())) + (&ImageResponse::Loaded(ref image, ref url), _) | + (&ImageResponse::PlaceholderLoaded(ref image, ref url), UsePlaceholder::Yes) => { + Ok(ImageOrMetadataAvailable::ImageAvailable(image.clone(), url.clone())) } - (&ImageResponse::PlaceholderLoaded(_), UsePlaceholder::No) | + (&ImageResponse::PlaceholderLoaded(_, _), UsePlaceholder::No) | (&ImageResponse::None, _) | (&ImageResponse::MetadataLoaded(_), _) => { Err(ImageState::LoadError) @@ -409,11 +416,16 @@ pub struct ImageCacheImpl { impl ImageCache for ImageCacheImpl { fn new(webrender_api: webrender_traits::RenderApi) -> ImageCacheImpl { debug!("New image cache"); + + let mut placeholder_path = resources_dir_path().expect("Can't figure out resources path."); + placeholder_path.push("rippy.png"); + ImageCacheImpl { store: Arc::new(Mutex::new(ImageCacheStore { pending_loads: AllPendingLoads::new(), completed_loads: HashMap::new(), - placeholder_image: get_placeholder_image(&webrender_api).ok(), + placeholder_image: get_placeholder_image(&webrender_api, &placeholder_path).ok(), + placeholder_url: ServoUrl::from_file_path(&placeholder_path).unwrap(), webrender_api: webrender_api, })) } @@ -496,7 +508,21 @@ impl ImageCache for ImageCacheImpl { match (action, id) { (FetchResponseMsg::ProcessRequestBody, _) | (FetchResponseMsg::ProcessRequestEOF, _) => return, - (FetchResponseMsg::ProcessResponse(_response), _) => {} + (FetchResponseMsg::ProcessResponse(response), _) => { + let mut store = self.store.lock().unwrap(); + let pending_load = store.pending_loads.get_by_key_mut(&id).unwrap(); + let metadata = match response { + Ok(meta) => { + Some(match meta { + FetchMetadata::Unfiltered(m) => m, + FetchMetadata::Filtered { unsafe_, .. } => unsafe_, + }) + }, + Err(_) => None, + }; + let final_url = metadata.as_ref().map(|m| m.final_url.clone()); + pending_load.final_url = final_url; + } (FetchResponseMsg::ProcessResponseChunk(data), _) => { debug!("Got some data for {:?}", id); let mut store = self.store.lock().unwrap(); @@ -509,7 +535,8 @@ impl ImageCache for ImageCacheImpl { let img_metadata = ImageMetadata { width: dimensions.width, height: dimensions.height }; for listener in &pending_load.listeners { - listener.respond(ImageResponse::MetadataLoaded(img_metadata.clone())); + listener.respond( + ImageResponse::MetadataLoaded(img_metadata.clone())); } pending_load.metadata = Some(img_metadata); } diff --git a/components/net_traits/image_cache.rs b/components/net_traits/image_cache.rs index c275e553b24..99f8d576d71 100644 --- a/components/net_traits/image_cache.rs +++ b/components/net_traits/image_cache.rs @@ -25,7 +25,7 @@ pub enum CanRequestImages { /// Indicating either entire image or just metadata availability #[derive(Clone, Deserialize, Serialize, HeapSizeOf)] pub enum ImageOrMetadataAvailable { - ImageAvailable(Arc<Image>), + ImageAvailable(Arc<Image>, ServoUrl), MetadataAvailable(ImageMetadata), } @@ -63,11 +63,11 @@ impl ImageResponder { #[derive(Clone, Deserialize, Serialize, HeapSizeOf)] pub enum ImageResponse { /// The requested image was loaded. - Loaded(Arc<Image>), + Loaded(Arc<Image>, ServoUrl), /// The request image metadata was loaded. MetadataLoaded(ImageMetadata), /// The requested image failed to load, so a placeholder was loaded instead. - PlaceholderLoaded(Arc<Image>), + PlaceholderLoaded(Arc<Image>, ServoUrl), /// Neither the requested image nor the placeholder could be loaded. None, } diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index a5ec8d233b6..348ec08aced 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -32,7 +32,7 @@ use dom::htmlcanvaselement::HTMLCanvasElement; use dom::htmlcanvaselement::utils as canvas_utils; use dom::htmlimageelement::HTMLImageElement; use dom::imagedata::ImageData; -use dom::node::{Node, NodeDamage, window_from_node}; +use dom::node::{document_from_node, Node, NodeDamage, window_from_node}; use dom_struct::dom_struct; use euclid::matrix2d::Matrix2D; use euclid::point::Point2D; @@ -228,16 +228,11 @@ impl CanvasRenderingContext2D { } HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::CanvasRenderingContext2D(image) => image.origin_is_clean(), - HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::HTMLImageElement(image) => - match image.get_url() { - None => true, - Some(url) => { - // TODO(zbarsky): we should check the origin of the image against - // the entry settings object, but for now check it against the canvas' doc. - let node: &Node = &*self.canvas.upcast(); - url.origin() == node.owner_doc().url().origin() - } - } + HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::HTMLImageElement(image) => { + let image_origin = image.get_origin().expect("Image's origin is missing"); + let document = document_from_node(&*self.canvas); + document.url().clone().origin() == image_origin + } } } @@ -429,8 +424,8 @@ impl CanvasRenderingContext2D { }; let img = match self.request_image_from_cache(url) { - ImageResponse::Loaded(img) => img, - ImageResponse::PlaceholderLoaded(_) | + ImageResponse::Loaded(img, _) => img, + ImageResponse::PlaceholderLoaded(_, _) | ImageResponse::None | ImageResponse::MetadataLoaded(_) => { return None; diff --git a/components/script/dom/htmlcanvaselement.rs b/components/script/dom/htmlcanvaselement.rs index 6dd10aa3c82..c8956c1620b 100644 --- a/components/script/dom/htmlcanvaselement.rs +++ b/components/script/dom/htmlcanvaselement.rs @@ -371,8 +371,8 @@ pub mod utils { UsePlaceholder::No, CanRequestImages::No); match response { - Ok(ImageOrMetadataAvailable::ImageAvailable(image)) => - ImageResponse::Loaded(image), + Ok(ImageOrMetadataAvailable::ImageAvailable(image, url)) => + ImageResponse::Loaded(image, url), _ => ImageResponse::None, } } diff --git a/components/script/dom/htmlimageelement.rs b/components/script/dom/htmlimageelement.rs index b706288a2cf..e38b615f9ad 100644 --- a/components/script/dom/htmlimageelement.rs +++ b/components/script/dom/htmlimageelement.rs @@ -48,6 +48,7 @@ use network_listener::{NetworkListener, PreInvoke}; use num_traits::ToPrimitive; use script_thread::Runnable; use servo_url::ServoUrl; +use servo_url::origin::ImmutableOrigin; use std::cell::Cell; use std::default::Default; use std::i32; @@ -73,6 +74,7 @@ struct ImageRequest { #[ignore_heap_size_of = "Arc"] image: Option<Arc<Image>>, metadata: Option<ImageMetadata>, + final_url: Option<ServoUrl>, } #[dom_struct] pub struct HTMLImageElement { @@ -215,8 +217,8 @@ impl HTMLImageElement { UsePlaceholder::Yes, CanRequestImages::Yes); match response { - Ok(ImageOrMetadataAvailable::ImageAvailable(image)) => { - self.process_image_response(ImageResponse::Loaded(image)); + Ok(ImageOrMetadataAvailable::ImageAvailable(image, url)) => { + self.process_image_response(ImageResponse::Loaded(image, url)); } Ok(ImageOrMetadataAvailable::MetadataAvailable(m)) => { @@ -273,7 +275,8 @@ impl HTMLImageElement { fn process_image_response(&self, image: ImageResponse) { let (image, metadata, trigger_image_load, trigger_image_error) = match image { - ImageResponse::Loaded(image) | ImageResponse::PlaceholderLoaded(image) => { + ImageResponse::Loaded(image, url) | ImageResponse::PlaceholderLoaded(image, url) => { + self.current_request.borrow_mut().final_url = Some(url); (Some(image.clone()), Some(ImageMetadata { height: image.height, width: image.width }), true, @@ -378,6 +381,7 @@ impl HTMLImageElement { image: None, metadata: None, blocker: None, + final_url: None, }), pending_request: DOMRefCell::new(ImageRequest { state: State::Unavailable, @@ -386,6 +390,7 @@ impl HTMLImageElement { image: None, metadata: None, blocker: None, + final_url: None, }), form_owner: Default::default(), generation: Default::default(), @@ -441,6 +446,14 @@ impl HTMLImageElement { useMapElements.map(|mapElem| mapElem.get_area_elements()) } + + pub fn get_origin(&self) -> Option<ImmutableOrigin> { + match self.current_request.borrow_mut().final_url { + Some(ref url) => Some(url.origin()), + None => None + } + } + } pub trait LayoutHTMLImageElementHelpers { diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs index 1826a877331..09f997241c6 100644 --- a/components/script/dom/webglrenderingcontext.rs +++ b/components/script/dom/webglrenderingcontext.rs @@ -465,8 +465,8 @@ 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::Loaded(img, _) => img, + ImageResponse::PlaceholderLoaded(_, _) | ImageResponse::None | ImageResponse::MetadataLoaded(_) => return Err(()), }; diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index 65d1a591adc..037892bb8f2 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -386,8 +386,8 @@ impl Window { } match response.response { ImageResponse::MetadataLoaded(_) => {} - ImageResponse::Loaded(_) | - ImageResponse::PlaceholderLoaded(_) | + ImageResponse::Loaded(_, _) | + ImageResponse::PlaceholderLoaded(_, _) | ImageResponse::None => { nodes.remove(); } } self.add_pending_reflow(); diff --git a/tests/wpt/metadata/MANIFEST.json b/tests/wpt/metadata/MANIFEST.json index deefe0473fb..191c2a3d1c1 100644 --- a/tests/wpt/metadata/MANIFEST.json +++ b/tests/wpt/metadata/MANIFEST.json @@ -399550,7 +399550,7 @@ "support" ], "common/canvas-tests.js": [ - "2db347399bee84e76c01a15ca5c0c3006fcd4d4e", + "329e3ae1cfde2ee0525302e6a3260faed3885f28", "support" ], "common/css-red.txt": [ diff --git a/tests/wpt/metadata/html/semantics/embedded-content/the-canvas-element/security.drawImage.canvas.redirect.html.ini b/tests/wpt/metadata/html/semantics/embedded-content/the-canvas-element/security.drawImage.canvas.redirect.html.ini deleted file mode 100644 index b2b00f6801d..00000000000 --- a/tests/wpt/metadata/html/semantics/embedded-content/the-canvas-element/security.drawImage.canvas.redirect.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[security.drawImage.canvas.redirect.html] - type: testharness - [drawImage of unclean canvas makes the canvas origin-unclean] - expected: FAIL - diff --git a/tests/wpt/metadata/html/semantics/embedded-content/the-canvas-element/security.drawImage.image.redirect.html.ini b/tests/wpt/metadata/html/semantics/embedded-content/the-canvas-element/security.drawImage.image.redirect.html.ini deleted file mode 100644 index 65a70479323..00000000000 --- a/tests/wpt/metadata/html/semantics/embedded-content/the-canvas-element/security.drawImage.image.redirect.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[security.drawImage.image.redirect.html] - type: testharness - [drawImage of different-origin image makes the canvas origin-unclean] - expected: FAIL - diff --git a/tests/wpt/metadata/html/semantics/embedded-content/the-canvas-element/security.pattern.canvas.fillStyle.redirect.html.ini b/tests/wpt/metadata/html/semantics/embedded-content/the-canvas-element/security.pattern.canvas.fillStyle.redirect.html.ini deleted file mode 100644 index 12ca9a579a9..00000000000 --- a/tests/wpt/metadata/html/semantics/embedded-content/the-canvas-element/security.pattern.canvas.fillStyle.redirect.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[security.pattern.canvas.fillStyle.redirect.html] - type: testharness - [Setting fillStyle to a pattern of an unclean canvas makes the canvas origin-unclean] - expected: FAIL - diff --git a/tests/wpt/metadata/html/semantics/embedded-content/the-canvas-element/security.pattern.canvas.strokeStyle.redirect.html.ini b/tests/wpt/metadata/html/semantics/embedded-content/the-canvas-element/security.pattern.canvas.strokeStyle.redirect.html.ini deleted file mode 100644 index 5e139d2b9c8..00000000000 --- a/tests/wpt/metadata/html/semantics/embedded-content/the-canvas-element/security.pattern.canvas.strokeStyle.redirect.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[security.pattern.canvas.strokeStyle.redirect.html] - type: testharness - [Setting strokeStyle to a pattern of an unclean canvas makes the canvas origin-unclean] - expected: FAIL - diff --git a/tests/wpt/metadata/html/semantics/embedded-content/the-canvas-element/security.pattern.canvas.timing.redirect.html.ini b/tests/wpt/metadata/html/semantics/embedded-content/the-canvas-element/security.pattern.canvas.timing.redirect.html.ini deleted file mode 100644 index 0a85486c6a3..00000000000 --- a/tests/wpt/metadata/html/semantics/embedded-content/the-canvas-element/security.pattern.canvas.timing.redirect.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[security.pattern.canvas.timing.redirect.html] - type: testharness - [Pattern safety depends on whether the source was origin-clean, not on whether it still is clean] - expected: FAIL - diff --git a/tests/wpt/metadata/html/semantics/embedded-content/the-canvas-element/security.pattern.create.redirect.html.ini b/tests/wpt/metadata/html/semantics/embedded-content/the-canvas-element/security.pattern.create.redirect.html.ini deleted file mode 100644 index 5ad342fe0a0..00000000000 --- a/tests/wpt/metadata/html/semantics/embedded-content/the-canvas-element/security.pattern.create.redirect.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[security.pattern.create.redirect.html] - type: testharness - [Creating an unclean pattern does not make the canvas origin-unclean] - expected: FAIL - diff --git a/tests/wpt/metadata/html/semantics/embedded-content/the-canvas-element/security.pattern.cross.redirect.html.ini b/tests/wpt/metadata/html/semantics/embedded-content/the-canvas-element/security.pattern.cross.redirect.html.ini deleted file mode 100644 index 0fc3910276c..00000000000 --- a/tests/wpt/metadata/html/semantics/embedded-content/the-canvas-element/security.pattern.cross.redirect.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[security.pattern.cross.redirect.html] - type: testharness - [Using an unclean pattern makes the target canvas origin-unclean, not the pattern canvas] - expected: FAIL - diff --git a/tests/wpt/metadata/html/semantics/embedded-content/the-canvas-element/security.pattern.image.fillStyle.redirect.html.ini b/tests/wpt/metadata/html/semantics/embedded-content/the-canvas-element/security.pattern.image.fillStyle.redirect.html.ini deleted file mode 100644 index 51192c8c09c..00000000000 --- a/tests/wpt/metadata/html/semantics/embedded-content/the-canvas-element/security.pattern.image.fillStyle.redirect.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[security.pattern.image.fillStyle.redirect.html] - type: testharness - [Setting fillStyle to a pattern of a different-origin image makes the canvas origin-unclean] - expected: FAIL - diff --git a/tests/wpt/metadata/html/semantics/embedded-content/the-canvas-element/security.pattern.image.strokeStyle.redirect.html.ini b/tests/wpt/metadata/html/semantics/embedded-content/the-canvas-element/security.pattern.image.strokeStyle.redirect.html.ini deleted file mode 100644 index d64cf011f63..00000000000 --- a/tests/wpt/metadata/html/semantics/embedded-content/the-canvas-element/security.pattern.image.strokeStyle.redirect.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[security.pattern.image.strokeStyle.redirect.html] - type: testharness - [Setting strokeStyle to a pattern of a different-origin image makes the canvas origin-unclean] - expected: FAIL - diff --git a/tests/wpt/metadata/html/semantics/embedded-content/the-canvas-element/security.reset.redirect.html.ini b/tests/wpt/metadata/html/semantics/embedded-content/the-canvas-element/security.reset.redirect.html.ini deleted file mode 100644 index 749f89f2b41..00000000000 --- a/tests/wpt/metadata/html/semantics/embedded-content/the-canvas-element/security.reset.redirect.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[security.reset.redirect.html] - type: testharness - [Resetting the canvas state does not reset the origin-clean flag] - expected: FAIL - diff --git a/tests/wpt/mozilla/meta/mozilla/adopted_node_is_same_origin_domain.html.ini b/tests/wpt/mozilla/meta/mozilla/adopted_node_is_same_origin_domain.html.ini index 3c4d9edc50f..829514a8656 100644 --- a/tests/wpt/mozilla/meta/mozilla/adopted_node_is_same_origin_domain.html.ini +++ b/tests/wpt/mozilla/meta/mozilla/adopted_node_is_same_origin_domain.html.ini @@ -2,3 +2,4 @@ type: testharness [Adopting a node should make it same-origin-domain.] expected: FAIL + diff --git a/tests/wpt/web-platform-tests/common/canvas-tests.js b/tests/wpt/web-platform-tests/common/canvas-tests.js index b41ba339e79..bf13d4a349c 100644 --- a/tests/wpt/web-platform-tests/common/canvas-tests.js +++ b/tests/wpt/web-platform-tests/common/canvas-tests.js @@ -101,4 +101,5 @@ function addCrossOriginRedirectYellowImage() img.className = "resource"; img.src = get_host_info().HTTP_ORIGIN + "/common/redirect.py?location=" + get_host_info().HTTP_REMOTE_ORIGIN + "/images/yellow.png"; + document.body.appendChild(img); } |