servo: Merge #10543 - Implement image request concept for HTMLImageElement. Implement HTMLI… (from jdm:imageload); r=jdm
authorakhan7 <akhan7@ncsu.edu>
Wed, 13 Apr 2016 00:34:58 +0500
changeset 338492 aad87eb69ddb28977f9f846b268b2088fbe4f423
parent 338491 8ebe1b758ee1af13d4e9cc8a600a4d1ebe3b8402
child 338493 77c88d178004c8b7bed588d82be6bb95b3886375
push id31307
push usergszorc@mozilla.com
push dateSat, 04 Feb 2017 00:59:06 +0000
treeherdermozilla-central@94079d43835f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjdm
servo: Merge #10543 - Implement image request concept for HTMLImageElement. Implement HTMLI… (from jdm:imageload); r=jdm …mageElement.currentSrc. Source-Repo: https://github.com/servo/servo Source-Revision: 85f4e5828548f2f25b2d75cb2853b896a0854ab3
servo/components/script/dom/htmlimageelement.rs
servo/components/script/dom/webidls/HTMLImageElement.webidl
--- a/servo/components/script/dom/htmlimageelement.rs
+++ b/servo/components/script/dom/htmlimageelement.rs
@@ -16,39 +16,54 @@ use dom::bindings::js::{LayoutJS, Root};
 use dom::bindings::refcounted::Trusted;
 use dom::document::Document;
 use dom::element::{AttributeMutation, Element, RawLayoutElementHelpers};
 use dom::eventtarget::EventTarget;
 use dom::htmlelement::HTMLElement;
 use dom::node::{Node, NodeDamage, document_from_node, window_from_node};
 use dom::values::UNSIGNED_LONG_MAX;
 use dom::virtualmethods::VirtualMethods;
+use heapsize::HeapSizeOf;
 use ipc_channel::ipc;
 use ipc_channel::router::ROUTER;
 use net_traits::image::base::{Image, ImageMetadata};
 use net_traits::image_cache_thread::{ImageResponder, ImageResponse};
 use script_runtime::ScriptThreadEventCategory::UpdateReplacedElement;
 use script_runtime::{CommonScriptMsg, ScriptChan};
 use script_thread::Runnable;
 use std::sync::Arc;
 use string_cache::Atom;
 use url::Url;
 use util::str::{DOMString, LengthOrPercentageOrAuto};
 
+#[derive(JSTraceable, HeapSizeOf)]
+#[allow(dead_code)]
+enum State {
+    Unavailable,
+    PartiallyAvailable,
+    CompletelyAvailable,
+    Broken,
+}
+#[derive(JSTraceable, HeapSizeOf)]
+struct ImageRequest {
+    state: State,
+    url: Option<Url>,
+    image: Option<Arc<Image>>,
+    metadata: Option<ImageMetadata>,
+}
 #[dom_struct]
 pub struct HTMLImageElement {
     htmlelement: HTMLElement,
-    url: DOMRefCell<Option<Url>>,
-    image: DOMRefCell<Option<Arc<Image>>>,
-    metadata: DOMRefCell<Option<ImageMetadata>>,
+    current_request: DOMRefCell<ImageRequest>,
+    pending_request: DOMRefCell<ImageRequest>,
 }
 
 impl HTMLImageElement {
     pub fn get_url(&self) -> Option<Url>{
-        self.url.borrow().clone()
+        self.current_request.borrow().url.clone()
     }
 }
 
 
 struct ImageResponseHandlerRunnable {
     element: Trusted<HTMLImageElement>,
     image: ImageResponse,
 }
@@ -72,18 +87,18 @@ impl Runnable for ImageResponseHandlerRu
             ImageResponse::Loaded(image) | ImageResponse::PlaceholderLoaded(image) => {
                 (Some(image.clone()), Some(ImageMetadata { height: image.height, width: image.width } ), true)
             }
             ImageResponse::MetadataLoaded(meta) => {
                 (None, Some(meta), false)
             }
             ImageResponse::None => (None, None, true)
         };
-        *element_ref.image.borrow_mut() = image;
-        *element_ref.metadata.borrow_mut() = metadata;
+        element_ref.current_request.borrow_mut().image = image;
+        element_ref.current_request.borrow_mut().metadata = metadata;
 
         // Mark the node dirty
         let document = document_from_node(&*element);
         element.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
 
         // Fire image.onload
         if trigger_image_load {
             element.upcast::<EventTarget>().fire_simple_event("load");
@@ -99,24 +114,24 @@ impl HTMLImageElement {
     /// Makes the local `image` member match the status of the `src` attribute and starts
     /// prefetching the image. This method must be called after `src` is changed.
     fn update_image(&self, value: Option<(DOMString, Url)>) {
         let document = document_from_node(self);
         let window = document.window();
         let image_cache = window.image_cache_thread();
         match value {
             None => {
-                *self.url.borrow_mut() = None;
-                *self.image.borrow_mut() = None;
+                self.current_request.borrow_mut().url = None;
+                self.current_request.borrow_mut().image = None;
             }
             Some((src, base_url)) => {
                 let img_url = base_url.join(&src);
                 // FIXME: handle URL parse errors more gracefully.
                 let img_url = img_url.unwrap();
-                *self.url.borrow_mut() = Some(img_url.clone());
+                self.current_request.borrow_mut().url = Some(img_url.clone());
 
                 let trusted_node = Trusted::new(self, window.networking_task_source());
                 let (responder_sender, responder_receiver) = ipc::channel().unwrap();
                 let script_chan = window.networking_task_source();
                 let wrapper = window.get_runnable_wrapper();
                 ROUTER.add_route(responder_receiver.to_opaque(), box move |message| {
                     // Return the image via a message to the script thread, which marks the element
                     // as dirty and triggers a reflow.
@@ -129,23 +144,31 @@ impl HTMLImageElement {
                 });
 
                 image_cache.request_image_and_metadata(img_url,
                                           window.image_cache_chan(),
                                           Some(ImageResponder::new(responder_sender)));
             }
         }
     }
-
     fn new_inherited(localName: Atom, prefix: Option<DOMString>, document: &Document) -> HTMLImageElement {
         HTMLImageElement {
             htmlelement: HTMLElement::new_inherited(localName, prefix, document),
-            url: DOMRefCell::new(None),
-            image: DOMRefCell::new(None),
-            metadata: DOMRefCell::new(None),
+            current_request: DOMRefCell::new(ImageRequest {
+                state: State::Unavailable,
+                url: None,
+                image: None,
+                metadata: None
+            }),
+            pending_request: DOMRefCell::new(ImageRequest {
+                state: State::Unavailable,
+                url: None,
+                image: None,
+                metadata: None
+            }),
         }
     }
 
     #[allow(unrooted_must_root)]
     pub fn new(localName: Atom,
                prefix: Option<DOMString>,
                document: &Document) -> Root<HTMLImageElement> {
         let element = HTMLImageElement::new_inherited(localName, prefix, document);
@@ -177,22 +200,22 @@ pub trait LayoutHTMLImageElementHelpers 
 
     fn get_width(&self) -> LengthOrPercentageOrAuto;
     fn get_height(&self) -> LengthOrPercentageOrAuto;
 }
 
 impl LayoutHTMLImageElementHelpers for LayoutJS<HTMLImageElement> {
     #[allow(unsafe_code)]
     unsafe fn image(&self) -> Option<Arc<Image>> {
-        (*self.unsafe_get()).image.borrow_for_layout().clone()
+        (*self.unsafe_get()).current_request.borrow_for_layout().image.clone()
     }
 
     #[allow(unsafe_code)]
     unsafe fn image_url(&self) -> Option<Url> {
-        (*self.unsafe_get()).url.borrow_for_layout().clone()
+        (*self.unsafe_get()).current_request.borrow_for_layout().url.clone()
     }
 
     #[allow(unsafe_code)]
     fn get_width(&self) -> LengthOrPercentageOrAuto {
         unsafe {
             (*self.upcast::<Element>().unsafe_get())
                 .get_attr_for_layout(&ns!(), &atom!("width"))
                 .map(AttrValue::as_dimension)
@@ -219,16 +242,21 @@ impl HTMLImageElementMethods for HTMLIma
     // https://html.spec.whatwg.org/multipage/#dom-img-alt
     make_setter!(SetAlt, "alt");
 
     // https://html.spec.whatwg.org/multipage/#dom-img-src
     make_url_getter!(Src, "src");
     // https://html.spec.whatwg.org/multipage/#dom-img-src
     make_setter!(SetSrc, "src");
 
+    // https://html.spec.whatwg.org/multipage/#dom-img-crossOrigin
+    make_enumerated_getter!(CrossOrigin, "crossorigin", "anonymous", ("use-credentials"));
+    // https://html.spec.whatwg.org/multipage/#dom-img-crossOrigin
+    make_setter!(SetCrossOrigin, "crossorigin");
+
     // https://html.spec.whatwg.org/multipage/#dom-img-usemap
     make_getter!(UseMap, "usemap");
     // https://html.spec.whatwg.org/multipage/#dom-img-usemap
     make_setter!(SetUseMap, "usemap");
 
     // https://html.spec.whatwg.org/multipage/#dom-img-ismap
     make_bool_getter!(IsMap, "ismap");
     // https://html.spec.whatwg.org/multipage/#dom-img-ismap
@@ -255,40 +283,49 @@ impl HTMLImageElementMethods for HTMLIma
 
     // https://html.spec.whatwg.org/multipage/#dom-img-height
     fn SetHeight(&self, value: u32) {
         image_dimension_setter(self.upcast(), atom!("height"), value);
     }
 
     // https://html.spec.whatwg.org/multipage/#dom-img-naturalwidth
     fn NaturalWidth(&self) -> u32 {
-        let metadata = self.metadata.borrow();
+        let ref metadata = self.current_request.borrow().metadata;
 
         match *metadata {
             Some(ref metadata) => metadata.width,
             None => 0,
         }
     }
 
     // https://html.spec.whatwg.org/multipage/#dom-img-naturalheight
     fn NaturalHeight(&self) -> u32 {
-        let metadata = self.metadata.borrow();
+        let ref metadata = self.current_request.borrow().metadata;
 
         match *metadata {
             Some(ref metadata) => metadata.height,
             None => 0,
         }
     }
 
     // https://html.spec.whatwg.org/multipage/#dom-img-complete
     fn Complete(&self) -> bool {
-        let image = self.image.borrow();
+        let ref image = self.current_request.borrow().image;
         image.is_some()
     }
 
+    // https://html.spec.whatwg.org/multipage/#dom-img-currentsrc
+    fn CurrentSrc(&self) -> DOMString {
+        let ref url = self.current_request.borrow().url;
+        match *url {
+            Some(ref url) => DOMString::from(url.serialize()),
+            None => DOMString::from(""),
+        }
+    }
+
     // https://html.spec.whatwg.org/multipage/#dom-img-name
     make_getter!(Name, "name");
 
     // https://html.spec.whatwg.org/multipage/#dom-img-name
     make_atomic_setter!(SetName, "name");
 
     // https://html.spec.whatwg.org/multipage/#dom-img-align
     make_getter!(Align, "align");
--- a/servo/components/script/dom/webidls/HTMLImageElement.webidl
+++ b/servo/components/script/dom/webidls/HTMLImageElement.webidl
@@ -4,25 +4,25 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 // https://html.spec.whatwg.org/multipage/#htmlimageelement
 [NamedConstructor=Image(optional unsigned long width, optional unsigned long height)]
 interface HTMLImageElement : HTMLElement {
            attribute DOMString alt;
            attribute DOMString src;
   //         attribute DOMString srcset;
-  //         attribute DOMString crossOrigin;
+           attribute DOMString crossOrigin;
            attribute DOMString useMap;
            attribute boolean isMap;
            attribute unsigned long width;
            attribute unsigned long height;
   readonly attribute unsigned long naturalWidth;
   readonly attribute unsigned long naturalHeight;
   readonly attribute boolean complete;
-
+  readonly attribute DOMString currentSrc;
   // also has obsolete members
 };
 
 // https://html.spec.whatwg.org/multipage/#HTMLImageElement-partial
 partial interface HTMLImageElement {
            attribute DOMString name;
   //         attribute DOMString lowsrc;
            attribute DOMString align;