Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP : Using the entry settings object in CanvasRenderingContext2d::is_origin_clean #15887

Closed
wants to merge 1 commit into from

Conversation

@sendilkumarn
Copy link
Contributor

sendilkumarn commented Mar 9, 2017


  • ./mach build -d does not report any errors
  • ./mach test-tidy does not report any errors
  • These changes fix #15409

This change is Reviewable

@highfive
Copy link

highfive commented Mar 9, 2017

Heads up! This PR modifies the following files:

  • @fitzgen: components/script/dom/canvasrenderingcontext2d.rs
  • @KiChjang: components/script/dom/canvasrenderingcontext2d.rs
@highfive
Copy link

highfive commented Mar 9, 2017

warning Warning warning

  • These commits modify script code, but no tests are modified. Please consider adding a test!
@sendilkumarn sendilkumarn force-pushed the sendilkumarn:canvas2d branch 2 times, most recently from a691976 to 19da53e Mar 10, 2017
url.origin() == node.owner_doc().url().origin()
match image.GetCrossOrigin() {
None => {
match image.get_url() {

This comment has been minimized.

@wafflespeanut

wafflespeanut Mar 14, 2017

Member

I think this could be better written with map and unwrap_or like,

image.get_url().map(|url| ...).unwrap_or(true)

This comment has been minimized.

@sendilkumarn

sendilkumarn Mar 14, 2017

Author Contributor

TIL 👍 @wafflespeanut

@wafflespeanut
Copy link
Member

wafflespeanut commented Mar 14, 2017

Please make sure that this has a proper commit message in the end.

r? @Ms2ger

@highfive highfive assigned Ms2ger and unassigned pcwalton Mar 14, 2017
@sendilkumarn sendilkumarn changed the title Using Origin of entry settings Using the entry settings object in CanvasRenderingContext2d::is_origin_clean Mar 14, 2017
@sendilkumarn sendilkumarn force-pushed the sendilkumarn:canvas2d branch from 19da53e to d563147 Mar 14, 2017
@Ms2ger
Copy link
Contributor

Ms2ger commented Mar 14, 2017

r? @jdm

I don't know the img code well enough to figure out how to match it to the spec.

@highfive highfive assigned jdm and unassigned Ms2ger Mar 14, 2017
Copy link
Member

jdm left a comment

The HTMLImageElement and image cache implementations will require changes in order to properly support this change. I'll describe the necessary changes in a subsequent comment.

// 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()
match image.GetCrossOrigin() {

This comment has been minimized.

@jdm

jdm Mar 17, 2017

Member

Unfortunately this is not enough. We should add a origin method to HTMLImageElement that returns Option<Origin> and use that for the comparison, ignoring anything related to GetCrossOrigin in this particular code.

This comment has been minimized.

@jdm

jdm Apr 25, 2017

Member

This change is still missing.

@jdm
Copy link
Member

jdm commented Mar 17, 2017

We have a couple missing pieces here:

  • we need to make the image element store the origin of the actual URL that was associated with the original image request
  • the image cache needs to store the final URL that was used
  • the image cache's API needs to provide the URL along with the final image data

The image cache receives the FetchMetadata value associated with the image response in ImageCache::handle_progress (in the ProcessResponse branch) but ignores it. We will need to extract the appropriate Metadata value from this and store the final_url value in the image cache. The ImageResponder API will need to be modified to support sending the url along with the ImageResponse value, and the code in HTMLImageElement that in interacts with this API (ImageResponseHandlerRunnable and process_image_response) will need to account for this. Once we have the URL, we can store it and return a meaningful value for the new origin method that I've requested.

@sendilkumarn
Copy link
Contributor Author

sendilkumarn commented Mar 20, 2017

@jdm I think this also changes few methods in windows.rs. Can mind to help on this ?

@jdm
Copy link
Member

jdm commented Mar 20, 2017

@sendilkumarn Could you be more specific? What help are you looking for?

@sendilkumarn
Copy link
Contributor Author

sendilkumarn commented Mar 20, 2017

I can fetch the response in ProcessResponse and use the same to fetch the url for final_url.
Also changed the image responder api to accomodate final url as one of the parameter.

ImageResponseHandlerRunnable and process_image_response i am not quite sure what has to be changed.

@jdm
Copy link
Member

jdm commented Mar 20, 2017

process_image_response needs to store the origin of the final URL in the current image request, so that the new origin method can return it.

@sendilkumarn sendilkumarn changed the title Using the entry settings object in CanvasRenderingContext2d::is_origin_clean WIP : Using the entry settings object in CanvasRenderingContext2d::is_origin_clean Mar 22, 2017
@sendilkumarn
Copy link
Contributor Author

sendilkumarn commented Mar 22, 2017

@jdm I am clueless and missing a link here. 😞
How to get final URL in process_image_response ?

@bors-servo
Copy link
Contributor

bors-servo commented Mar 27, 2017

The latest upstream changes (presumably #16048) made this pull request unmergeable. Please resolve the merge conflicts.

@jdm
Copy link
Member

jdm commented May 2, 2017

Additionally, I have made a pull request that modifies the tests in tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/ to expose our current implementation's flaws. The changes in this PR should cause those tests to start passing, so it would be worth verifying that that is the case :)

@sendilkumarn sendilkumarn force-pushed the sendilkumarn:canvas2d branch from c4c9318 to c18e217 May 3, 2017
@sendilkumarn sendilkumarn force-pushed the sendilkumarn:canvas2d branch from c18e217 to 43658ac May 3, 2017
bors-servo added a commit that referenced this pull request May 15, 2017
…frey,jgraham

Make cross-origin canvas drawing tests use a same-origin redirect.

These tests either pass or maintain existing known failures in Firefox and Chrome, and expose the problem in our current implementation that #15887 is addressing.

<!-- 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/16699)
<!-- Reviewable:end -->
@jdm
Copy link
Member

jdm commented May 16, 2017

@bors-servo
Copy link
Contributor

bors-servo commented May 16, 2017

Trying commit 43658ac with merge 3f0cedc...

bors-servo added a commit that referenced this pull request May 16, 2017
WIP : Using the entry settings object in CanvasRenderingContext2d::is_origin_clean

<!-- Please describe your changes on the following line: -->

---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: -->
- [x] `./mach build -d` does not report any errors
- [x] `./mach test-tidy` does not report any errors
- [x] These changes fix #15409

<!-- 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/15887)
<!-- Reviewable:end -->
@bors-servo
Copy link
Contributor

bors-servo commented May 16, 2017

💔 Test failed - linux-rel-wpt

@jdm
Copy link
Member

jdm commented May 16, 2017

There are a lot of failures like this:

  ▶ CRASH [expected ERROR] /referrer-policy/no-referrer-when-downgrade/http-rp/same-origin/http-https/img-tag/upgrade-protocol.no-redirect.http.html
  │ 
  │ VMware, Inc.
  │ Gallium 0.4 on softpipe
  │ 3.3 (Core Profile) Mesa 12.0.1
  │ Image's origin is missing (thread ScriptThread PipelineId { namespace_id: PipelineNamespaceId(0), index: PipelineIndex(1) }, at /checkout/src/libcore/option.rs:794)
  │ stack backtrace:
  │    0:     0x7f93dd87f55c - backtrace::backtrace::trace::haa53f4880ff627c6
  │    1:     0x7f93dd87fa22 - backtrace::capture::Backtrace::new::h5f3de869c0349b3d
  │    2:     0x7f93dc377f05 - servo::main::{{closure}}::hc2262116bcc3d90c
  │    3:     0x7f93de3a626a - std::panicking::rust_panic_with_hook
  │                         at /checkout/src/libstd/panicking.rs:550
  │    4:     0x7f93de3a60b4 - std::panicking::begin_panic<collections::string::String>
  │                         at /checkout/src/libstd/panicking.rs:511
  │    5:     0x7f93de3a6039 - std::panicking::begin_panic_fmt
  │                         at /checkout/src/libstd/panicking.rs:495
  │    6:     0x7f93de3a5fc7 - std::panicking::rust_begin_panic
  │                         at /checkout/src/libstd/panicking.rs:471
  │    7:     0x7f93de3d1cad - core::panicking::panic_fmt
  │                         at /checkout/src/libcore/panicking.rs:69
  │    8:     0x7f93de3d1d1d - core::option::expect_failed
  │                         at /checkout/src/libcore/option.rs:794
  │    9:     0x7f93dc96f663 - script::dom::canvasrenderingcontext2d::CanvasRenderingContext2D::is_origin_clean::ha981bbaf7851015a
  │   10:     0x7f93dc97020b - script::dom::canvasrenderingcontext2d::CanvasRenderingContext2D::draw_image::h7fd357714a01cd83
  │   11:     0x7f93dc6c04ae - std::panicking::try::do_call::h5297a332a63507f4
  │   12:     0x7f93de3ad38a - panic_unwind::__rust_maybe_catch_panic
  │                         at /checkout/src/libpanic_unwind/lib.rs:98
  │   13:     0x7f93dcc6f157 - script::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasRenderingContext2DBinding::drawImage::h6015f19ace437be4
  │   14:     0x7f93dced0b34 - CallJitMethodOp
  │   15:     0x7f93dc93e26c - script::dom::bindings::utils::generic_call::h86cbfedc7c4ee9ad
  │   16:     0x7f93dd22ca40 - CallJSNative
  │                         at /home/servo/.cargo/git/checkouts/mozjs-fa11ffc7d4f1cc2d/834ce35/mozjs/js/src/jscntxtinlines.h:232
  │                          - 2js23InternalCallOrConstructEP9JSContextRKN2JS8CallArgsENS_14MaybeConstruct
  │                         at /home/servo/.cargo/git/checkouts/mozjs-fa11ffc7d4f1cc2d/834ce35/mozjs/js/src/vm/Interpreter.cpp:453
  │   17:     0x7f93dd21f3be - CallFromStack
  │                         at /home/servo/.cargo/git/checkouts/mozjs-fa11ffc7d4f1cc2d/834ce35/mozjs/js/src/vm/Interpreter.cpp:504
  │                          - Interpret
  │                         at /home/servo/.cargo/git/checkouts/mozjs-fa11ffc7d4f1cc2d/834ce35/mozjs/js/src/vm/Interpreter.cpp:2873
  │   18:     0x7f93dd22c60b - 2js9RunScriptEP9JSContextRNS_8RunState
  │                         at /home/servo/.cargo/git/checkouts/mozjs-fa11ffc7d4f1cc2d/834ce35/mozjs/js/src/vm/Interpreter.cpp:399
  │   19:     0x7f93dd22c7e8 - 2js23InternalCallOrConstructEP9JSContextRKN2JS8CallArgsENS_14MaybeConstruct
  │                         at /home/servo/.cargo/git/checkouts/mozjs-fa11ffc7d4f1cc2d/834ce35/mozjs/js/src/vm/Interpreter.cpp:471
  │   20:     0x7f93dd22cbf4 - 2js4CallEP9JSContextN2JS6HandleINS2_5ValueEEES5_RKNS_13AnyInvokeArgsENS2_13MutableHandleIS4_E
  │                         at /home/servo/.cargo/git/checkouts/mozjs-fa11ffc7d4f1cc2d/834ce35/mozjs/js/src/vm/Interpreter.cpp:517
  │   21:     0x7f93dd0c32e0 - _Z20JS_CallFunctionValueP9JSContextN2JS6HandleIP8JSObjectEENS2_INS1_5ValueEEERKNS1_16HandleValueArrayENS1_13MutableHandleIS6_EE
  │                         at /home/servo/.cargo/git/checkouts/mozjs-fa11ffc7d4f1cc2d/834ce35/mozjs/js/src/jsapi.cpp:2781
  │   22:     0x7f93dccd969d - script::dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull::Call::h256624740c59fe56
  │   23:     0x7f93dc9fde76 - script::dom::eventtarget::CompiledEventListener::call_or_handle_event::h7009b025b13671b7
  │   24:     0x7f93dc9f6c11 - script::dom::event::invoke::hbb25d04970be2cbd
  │   25:     0x7f93dc9f5ba1 - script::dom::event::Event::dispatch::h3b48c68010618af2
  │   26:     0x7f93dca0037e - script::dom::eventtarget::EventTarget::fire_event_with_params::hfe32e25e500f72b6
  │   27:     0x7f93dca5345f - script::dom::htmlimageelement::HTMLImageElement::process_image_response::ha5ced91d751b9672
  │   28:     0x7f93dca5197e - <script::dom::htmlimageelement::ImageResponseHandlerRunnable as script::script_thread::Runnable>::handler::h1f3dc49cfd7ef48e
  │   29:     0x7f93dcb8d95f - <script::script_thread::CancellableRunnable<T> as script::script_thread::Runnable>::handler::h10035bca36729c1c
  │   30:     0x7f93dcbab31d - script::script_thread::ScriptThread::handle_msg_from_script::h0dbdd55b53278d41
  │   31:     0x7f93dcba20d1 - script::script_thread::ScriptThread::handle_msgs::{{closure}}::h9e655a1ef871076f
  │   32:     0x7f93dcb9d152 - script::script_thread::ScriptThread::handle_msgs::h45f8388d7e815d4f
  │   33:     0x7f93dc632b97 - std::sys_common::backtrace::__rust_begin_short_backtrace::h159e20038beb8f87
  │   34:     0x7f93dc670a15 - std::panicking::try::do_call::h20908c8b38fdf297
  │   35:     0x7f93de3ad38a - panic_unwind::__rust_maybe_catch_panic
  │                         at /checkout/src/libpanic_unwind/lib.rs:98
  │   36:     0x7f93dc8482c3 - <F as alloc::boxed::FnBox<A>>::call_box::he85ee2aa097e69b3
  │   37:     0x7f93de3a4de5 - alloc::boxed::{{impl}}::call_once<(),()>
  │                         at /checkout/src/liballoc/boxed.rs:658
  │                          - std::sys_common::thread::start_thread
  │                         at /checkout/src/libstd/sys_common/thread.rs:21
  │                          - std::sys::imp::thread::{{impl}}::new::thread_start
  │                         at /checkout/src/libstd/sys/unix/thread.rs:84
  │   38:     0x7f93da291183 - start_thread
  │   39:     0x7f93d9da8bec - clone
  │   40:                0x0 - <unknown>
  │ ERROR:servo: Image's origin is missing
  └ Pipeline failed in hard-fail mode.  Crashing!
@jdm
Copy link
Member

jdm commented May 16, 2017

Also, it is now possible to run ./mach test-wpt tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/ and the new tests added in #16699 should pass. If they don't, there's something wrong with these changes.

cleanup

cors-settings

linting fixes

moved to more SS

fixing comments

improved

fixing comments

adding servourl to net_traits metadataAvail and Loaded

linting fixes

fixing comments

refactoring and adding image url

fixing canvas2d method

linting fixes
@sendilkumarn
Copy link
Contributor Author

sendilkumarn commented May 16, 2017

@jdm The test cases don't report any error [Edited] I will rebase the pull

@jdm
Copy link
Member

jdm commented May 17, 2017

I looked into both problems and figured out the solutions. The "Image's origin is missing" panics happen because it turns out that we don't always send MetadataAvailable messages. In this case, the code to determine image width/height does not recognize BMP images, so the message was never sent and the image element never was provided with a final URL.

The second problem was the canvas element tests continuing to fail with these changes. I discovered that #16699 had a mistake, and the addCrossOriginRedirectedYellowImage function never actually added the image to the DOM. The tests passed as expected after fixing that. This is the final diff of changes that I added to your changes in #16913:

diff --git a/components/layout/context.rs b/components/layout/context.rs
index d425388..3a4fac9 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)
@@ -194,7 +194,7 @@ impl<'a> LayoutContext<'a> {
                     Some(image_info)
                 }
             }
-            None | Some(ImageOrMetadataAvailable::MetadataAvailable(_, _)) => None,
+            None | Some(ImageOrMetadataAvailable::MetadataAvailable(_)) => None,
         }
     }
 }
diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs
index a896c30..52171dc 100644
--- a/components/layout/fragment.rs
+++ b/components/layout/fragment.rs
@@ -378,10 +378,10 @@ 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, _url)) => {
+            Some(ImageOrMetadataAvailable::MetadataAvailable(m)) => {
                 (None, Some(m))
             }
             None => {
diff --git a/components/net/image_cache.rs b/components/net/image_cache.rs
index f7b8c94..b8467e5 100644
--- a/components/net/image_cache.rs
+++ b/components/net/image_cache.rs
@@ -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();
@@ -196,15 +195,13 @@ enum CacheResult<'a> {
 struct CompletedLoad {
     image_response: ImageResponse,
     id: PendingImageId,
-    final_url: ServoUrl,
 }
 
 impl CompletedLoad {
-    fn new(image_response: ImageResponse, id: PendingImageId, final_url: ServoUrl) -> CompletedLoad {
+    fn new(image_response: ImageResponse, id: PendingImageId) -> CompletedLoad {
         CompletedLoad {
             image_response: image_response,
             id: id,
-            final_url: final_url,
         }
     }
 }
@@ -325,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,
 }
@@ -361,14 +361,15 @@ 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,
         };
 
-        let url = pending_load.final_url.clone();
-        let completed_load = CompletedLoad::new(image_response.clone(), key, url.unwrap());
+        let completed_load = CompletedLoad::new(image_response.clone(), key);
         self.completed_loads.insert(pending_load.url.into(), completed_load);
 
         for listener in pending_load.listeners {
@@ -384,13 +385,13 @@ 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(_, _), _) => {
+                (&ImageResponse::MetadataLoaded(_), _) => {
                     Err(ImageState::LoadError)
                 }
             }
@@ -415,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,
             }))
         }
@@ -450,8 +456,7 @@ impl ImageCache for ImageCacheImpl {
                     }
                     (&None, &Some(ref meta)) => {
                         debug!("Metadata available for {} ({:?})", url, key);
-                        return Ok(ImageOrMetadataAvailable::MetadataAvailable(meta.clone(),
-                            pl.final_url.clone().unwrap()))
+                        return Ok(ImageOrMetadataAvailable::MetadataAvailable(meta.clone()))
                     }
                     (&Some(Err(_)), _) | (&None, &None) => {
                         debug!("{} ({:?}) is still pending", url, key);
@@ -486,7 +491,7 @@ impl ImageCache for ImageCacheImpl {
         let mut store = self.store.lock().unwrap();
         if let Some(load) = store.pending_loads.get_by_key_mut(&id) {
             if let Some(ref metadata) = load.metadata {
-                listener.respond(ImageResponse::MetadataLoaded(metadata.clone(), load.final_url.clone().unwrap()));
+                listener.respond(ImageResponse::MetadataLoaded(metadata.clone()));
             }
             load.add_listener(listener);
             return;
@@ -531,8 +536,7 @@ impl ImageCache for ImageCacheImpl {
                                                            height: dimensions.height };
                         for listener in &pending_load.listeners {
                             listener.respond(
-                                ImageResponse::MetadataLoaded(img_metadata.clone(),
-                                    pending_load.final_url.clone().unwrap()));
+                                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 bdda678..99f8d57 100644
--- a/components/net_traits/image_cache.rs
+++ b/components/net_traits/image_cache.rs
@@ -25,8 +25,8 @@ pub enum CanRequestImages {
 /// Indicating either entire image or just metadata availability
 #[derive(Clone, Deserialize, Serialize, HeapSizeOf)]
 pub enum ImageOrMetadataAvailable {
-    ImageAvailable(Arc<Image>),
-    MetadataAvailable(ImageMetadata, ServoUrl),
+    ImageAvailable(Arc<Image>, ServoUrl),
+    MetadataAvailable(ImageMetadata),
 }
 
 /// This is optionally passed to the image cache when requesting
@@ -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, ServoUrl),
+    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 88ef4cb..1936728 100644
--- a/components/script/dom/canvasrenderingcontext2d.rs
+++ b/components/script/dom/canvasrenderingcontext2d.rs
@@ -425,10 +425,10 @@ 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(_, _) => {
+            ImageResponse::MetadataLoaded(_) => {
                 return None;
             }
         };
diff --git a/components/script/dom/htmlcanvaselement.rs b/components/script/dom/htmlcanvaselement.rs
index 6dd10aa..c8956c1 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 31d6686..e38b615 100644
--- a/components/script/dom/htmlimageelement.rs
+++ b/components/script/dom/htmlimageelement.rs
@@ -217,12 +217,12 @@ 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, img_url)) => {
-                self.process_image_response(ImageResponse::MetadataLoaded(m, img_url));
+            Ok(ImageOrMetadataAvailable::MetadataAvailable(m)) => {
+                self.process_image_response(ImageResponse::MetadataLoaded(m));
             }
 
             Err(ImageState::Pending(id)) => {
@@ -275,14 +275,14 @@ 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,
                  false)
             }
-            ImageResponse::MetadataLoaded(meta, url) => {
-                self.current_request.borrow_mut().final_url = Some(url);
+            ImageResponse::MetadataLoaded(meta) => {
                 (None, Some(meta), false, false)
             }
             ImageResponse::None => (None, None, false, true)
diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs
index 42bdd13..09f9972 100644
--- a/components/script/dom/webglrenderingcontext.rs
+++ b/components/script/dom/webglrenderingcontext.rs
@@ -465,9 +465,9 @@ 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(_, _)
+                    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 84d0b16..037892b 100644
--- a/components/script/dom/window.rs
+++ b/components/script/dom/window.rs
@@ -385,9 +385,9 @@ impl Window {
             node.dirty(NodeDamage::OtherNodeDamage);
         }
         match response.response {
-            ImageResponse::MetadataLoaded(_, _) => {}
-            ImageResponse::Loaded(_) |
-            ImageResponse::PlaceholderLoaded(_) |
+            ImageResponse::MetadataLoaded(_) => {}
+            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 deefe04..191c2a3 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/web-platform-tests/common/canvas-tests.js b/tests/wpt/web-platform-tests/common/canvas-tests.js
index b41ba33..bf13d4a 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);
 }

In particular, I moved the final URL out of MetadataAvailable and into the ImageAvailable/PlaceholderAvailable messages, which are always sent to the image cache consumers.

@jdm
Copy link
Member

jdm commented May 17, 2017

Closing in favour of #16913. Thanks for working on this!

@jdm jdm closed this May 17, 2017
bors-servo added a commit that referenced this pull request May 19, 2017
Make canvas origin clean checks use origin of image response

Adapted from #15887.

---
- [X] `./mach build -d` does not report any errors
- [X] `./mach test-tidy` does not report any errors
- [X] These changes fix #15409
- [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/16913)
<!-- Reviewable:end -->
bors-servo added a commit that referenced this pull request May 19, 2017
Make canvas origin clean checks use origin of image response

Adapted from #15887.

---
- [X] `./mach build -d` does not report any errors
- [X] `./mach test-tidy` does not report any errors
- [X] These changes fix #15409
- [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/16913)
<!-- Reviewable:end -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked issues

Successfully merging this pull request may close these issues.

7 participants
You can’t perform that action at this time.