diff options
author | bors-servo <metajack+bors@gmail.com> | 2015-03-30 12:40:12 -0600 |
---|---|---|
committer | bors-servo <metajack+bors@gmail.com> | 2015-03-30 12:40:12 -0600 |
commit | 1e282d55d7e36f0e488a395b90e961e9200c3817 (patch) | |
tree | 80200f6e523e054df6ef74e65c66216759971e10 | |
parent | 46d4ef81674d1de4b9066185c7e63c32b04c167e (diff) | |
parent | cdebb3ca543bb7f8d0bd71d8387925f5d8439f75 (diff) | |
download | servo-1e282d55d7e36f0e488a395b90e961e9200c3817.tar.gz servo-1e282d55d7e36f0e488a395b90e961e9200c3817.zip |
auto merge of #5366 : Adenilson/servo/loadPlaceholder01, r=jdm
I decided to use the old Netscape broken image link icon (later we may
replace the image asset for something more trendier).
-rw-r--r-- | components/net/image_cache_task.rs | 94 | ||||
-rw-r--r-- | components/servo/lib.rs | 6 | ||||
-rw-r--r-- | ports/gonk/src/lib.rs | 6 | ||||
-rw-r--r-- | resources/rippy.jpg | bin | 0 -> 35425 bytes | |||
-rw-r--r-- | tests/ref/basic.list | 1 | ||||
-rw-r--r-- | tests/ref/no-image-ref.html | 1 | ||||
-rw-r--r-- | tests/ref/no-image.html | 1 | ||||
-rw-r--r-- | tests/ref/rippy.jpg | bin | 0 -> 35425 bytes |
8 files changed, 77 insertions, 32 deletions
diff --git a/components/net/image_cache_task.rs b/components/net/image_cache_task.rs index 4719a305485..e881e80dd41 100644 --- a/components/net/image_cache_task.rs +++ b/components/net/image_cache_task.rs @@ -15,6 +15,7 @@ use std::mem::replace; use std::sync::{Arc, Mutex}; use std::sync::mpsc::{channel, Receiver, Sender}; use url::Url; +use util::resource_files::resources_dir_path; use util::task::spawn_named; use util::taskpool::TaskPool; @@ -75,7 +76,8 @@ pub struct ImageCacheTask { impl ImageCacheTask { pub fn new(resource_task: ResourceTask, task_pool: TaskPool, - time_profiler_chan: time::ProfilerChan) -> ImageCacheTask { + time_profiler_chan: time::ProfilerChan, + load_placeholder: LoadPlaceholder) -> ImageCacheTask { let (chan, port) = channel(); let chan_clone = chan.clone(); @@ -89,8 +91,9 @@ impl ImageCacheTask { need_exit: None, task_pool: task_pool, time_profiler_chan: time_profiler_chan, + placeholder_data: Arc::new(vec!()), }; - cache.run(); + cache.run(load_placeholder); }); ImageCacheTask { @@ -99,12 +102,13 @@ impl ImageCacheTask { } pub fn new_sync(resource_task: ResourceTask, task_pool: TaskPool, - time_profiler_chan: time::ProfilerChan) -> ImageCacheTask { + time_profiler_chan: time::ProfilerChan, + load_placeholder: LoadPlaceholder) -> ImageCacheTask { let (chan, port) = channel(); spawn_named("ImageCacheTask (sync)".to_owned(), move || { let inner_cache = ImageCacheTask::new(resource_task, task_pool, - time_profiler_chan); + time_profiler_chan, load_placeholder); loop { let msg: Msg = port.recv().unwrap(); @@ -142,6 +146,8 @@ struct ImageCache { need_exit: Option<Sender<()>>, task_pool: TaskPool, time_profiler_chan: time::ProfilerChan, + // Default image used when loading fails. + placeholder_data: Arc<Vec<u8>>, } #[derive(Clone)] @@ -160,8 +166,32 @@ enum AfterPrefetch { DoNotDecode } +pub enum LoadPlaceholder { + Preload, + Ignore +} + impl ImageCache { - pub fn run(&mut self) { + // Used to preload the default placeholder. + fn init(&mut self) { + let mut placeholder_url = resources_dir_path(); + // TODO (Savago): replace for a prettier one. + placeholder_url.push("rippy.jpg"); + let image = load_image_data(Url::from_file_path(&*placeholder_url).unwrap(), self.resource_task.clone(), &self.placeholder_data); + + match image { + Err(..) => debug!("image_cache_task: failed loading the placeholder."), + Ok(image_data) => self.placeholder_data = Arc::new(image_data), + } + } + + pub fn run(&mut self, load_placeholder: LoadPlaceholder) { + // We have to load the placeholder before running. + match load_placeholder { + LoadPlaceholder::Preload => self.init(), + LoadPlaceholder::Ignore => debug!("image_cache_task: use old behavior."), + } + let mut store_chan: Option<Sender<()>> = None; let mut store_prefetched_chan: Option<Sender<()>> = None; @@ -245,12 +275,12 @@ impl ImageCache { let to_cache = self.chan.clone(); let resource_task = self.resource_task.clone(); let url_clone = url.clone(); - + let placeholder = self.placeholder_data.clone(); spawn_named("ImageCacheTask (prefetch)".to_owned(), move || { let url = url_clone; debug!("image_cache_task: started fetch for {}", url.serialize()); - let image = load_image_data(url.clone(), resource_task.clone()); + let image = load_image_data(url.clone(), resource_task.clone(), &placeholder); to_cache.send(Msg::StorePrefetchedImageData(url.clone(), image)).unwrap(); debug!("image_cache_task: ended fetch for {}", url.serialize()); }); @@ -446,9 +476,9 @@ impl ImageCacheTask { } } -fn load_image_data(url: Url, resource_task: ResourceTask) -> Result<Vec<u8>, ()> { +fn load_image_data(url: Url, resource_task: ResourceTask, placeholder: &[u8]) -> Result<Vec<u8>, ()> { let (response_chan, response_port) = channel(); - resource_task.send(resource_task::ControlMsg::Load(LoadData::new(url, response_chan))).unwrap(); + resource_task.send(resource_task::ControlMsg::Load(LoadData::new(url.clone(), response_chan))).unwrap(); let mut image_data = vec!(); @@ -462,7 +492,19 @@ fn load_image_data(url: Url, resource_task: ResourceTask) -> Result<Vec<u8>, ()> return Ok(image_data); } Done(Err(..)) => { - return Err(()); + // Failure to load the requested image will return the + // placeholder instead. In case it failed to load at init(), + // we still recover and return Err() but nothing will be drawn. + if placeholder.len() != 0 { + debug!("image_cache_task: failed to load {:?}, use placeholder instead.", url); + // Clean in case there was an error after started loading the image. + image_data.clear(); + image_data.push_all(&placeholder); + return Ok(image_data); + } else { + debug!("image_cache_task: invalid placeholder."); + return Err(()); + } } } } @@ -595,7 +637,7 @@ mod tests { fn should_exit_on_request() { let mock_resource_task = mock_resource_task(box DoesNothing); - let image_cache_task = ImageCacheTask::new(mock_resource_task.clone(), TaskPool::new(4), profiler()); + let image_cache_task = ImageCacheTask::new(mock_resource_task.clone(), TaskPool::new(4), profiler(), LoadPlaceholder::Ignore); image_cache_task.exit(); mock_resource_task.send(resource_task::ControlMsg::Exit); @@ -606,7 +648,7 @@ mod tests { fn should_panic_if_unprefetched_image_is_requested() { let mock_resource_task = mock_resource_task(box DoesNothing); - let image_cache_task = ImageCacheTask::new(mock_resource_task.clone(), TaskPool::new(4), profiler()); + let image_cache_task = ImageCacheTask::new(mock_resource_task.clone(), TaskPool::new(4), profiler(), LoadPlaceholder::Preload); let url = Url::parse("file:///").unwrap(); let (chan, port) = channel(); @@ -620,7 +662,7 @@ mod tests { let mock_resource_task = mock_resource_task(box JustSendOK { url_requested_chan: url_requested_chan}); - let image_cache_task = ImageCacheTask::new(mock_resource_task.clone(), TaskPool::new(4), profiler()); + let image_cache_task = ImageCacheTask::new(mock_resource_task.clone(), TaskPool::new(4), profiler(), LoadPlaceholder::Preload); let url = Url::parse("file:///").unwrap(); image_cache_task.send(Prefetch(url)); @@ -635,7 +677,7 @@ mod tests { let mock_resource_task = mock_resource_task(box JustSendOK { url_requested_chan: url_requested_chan}); - let image_cache_task = ImageCacheTask::new(mock_resource_task.clone(), TaskPool::new(4), profiler()); + let image_cache_task = ImageCacheTask::new(mock_resource_task.clone(), TaskPool::new(4), profiler(), LoadPlaceholder::Ignore); let url = Url::parse("file:///").unwrap(); image_cache_task.send(Prefetch(url.clone())); @@ -655,7 +697,7 @@ mod tests { let mock_resource_task = mock_resource_task(box WaitSendTestImage{wait_port: wait_port}); - let image_cache_task = ImageCacheTask::new(mock_resource_task.clone(), TaskPool::new(4), profiler()); + let image_cache_task = ImageCacheTask::new(mock_resource_task.clone(), TaskPool::new(4), profiler(), LoadPlaceholder::Ignore); let url = Url::parse("file:///").unwrap(); image_cache_task.send(Prefetch(url.clone())); @@ -672,7 +714,7 @@ mod tests { fn should_return_decoded_image_data_if_data_has_arrived() { let mock_resource_task = mock_resource_task(box SendTestImage); - let image_cache_task = ImageCacheTask::new(mock_resource_task.clone(), TaskPool::new(4), profiler()); + let image_cache_task = ImageCacheTask::new(mock_resource_task.clone(), TaskPool::new(4), profiler(), LoadPlaceholder::Preload); let url = Url::parse("file:///").unwrap(); let join_port = image_cache_task.wait_for_store(); @@ -698,7 +740,7 @@ mod tests { fn should_return_decoded_image_data_for_multiple_requests() { let mock_resource_task = mock_resource_task(box SendTestImage); - let image_cache_task = ImageCacheTask::new(mock_resource_task.clone(), TaskPool::new(4), profiler()); + let image_cache_task = ImageCacheTask::new(mock_resource_task.clone(), TaskPool::new(4), profiler(), LoadPlaceholder::Preload); let url = Url::parse("file:///").unwrap(); let join_port = image_cache_task.wait_for_store(); @@ -752,7 +794,7 @@ mod tests { } }); - let image_cache_task = ImageCacheTask::new(mock_resource_task.clone(), TaskPool::new(4), profiler()); + let image_cache_task = ImageCacheTask::new(mock_resource_task.clone(), TaskPool::new(4), profiler(), LoadPlaceholder::Ignore); let url = Url::parse("file:///").unwrap(); image_cache_task.send(Prefetch(url.clone())); @@ -804,7 +846,7 @@ mod tests { } }); - let image_cache_task = ImageCacheTask::new(mock_resource_task.clone(), TaskPool::new(4), profiler()); + let image_cache_task = ImageCacheTask::new(mock_resource_task.clone(), TaskPool::new(4), profiler(), LoadPlaceholder::Ignore); let url = Url::parse("file:///").unwrap(); image_cache_task.send(Prefetch(url.clone())); @@ -833,7 +875,7 @@ mod tests { fn should_return_failed_if_image_bin_cannot_be_fetched() { let mock_resource_task = mock_resource_task(box SendTestImageErr); - let image_cache_task = ImageCacheTask::new(mock_resource_task.clone(), TaskPool::new(4), profiler()); + let image_cache_task = ImageCacheTask::new(mock_resource_task.clone(), TaskPool::new(4), profiler(), LoadPlaceholder::Preload); let url = Url::parse("file:///").unwrap(); let join_port = image_cache_task.wait_for_store_prefetched(); @@ -859,7 +901,7 @@ mod tests { fn should_return_failed_for_multiple_get_image_requests_if_image_bin_cannot_be_fetched() { let mock_resource_task = mock_resource_task(box SendTestImageErr); - let image_cache_task = ImageCacheTask::new(mock_resource_task.clone(), TaskPool::new(4), profiler()); + let image_cache_task = ImageCacheTask::new(mock_resource_task.clone(), TaskPool::new(4), profiler(), LoadPlaceholder::Preload); let url = Url::parse("file:///").unwrap(); let join_port = image_cache_task.wait_for_store_prefetched(); @@ -893,7 +935,7 @@ mod tests { fn should_return_failed_if_image_decode_fails() { let mock_resource_task = mock_resource_task(box SendBogusImage); - let image_cache_task = ImageCacheTask::new(mock_resource_task.clone(), TaskPool::new(4), profiler()); + let image_cache_task = ImageCacheTask::new(mock_resource_task.clone(), TaskPool::new(4), profiler(), LoadPlaceholder::Preload); let url = Url::parse("file:///").unwrap(); let join_port = image_cache_task.wait_for_store(); @@ -921,7 +963,7 @@ mod tests { fn should_return_image_on_wait_if_image_is_already_loaded() { let mock_resource_task = mock_resource_task(box SendTestImage); - let image_cache_task = ImageCacheTask::new(mock_resource_task.clone(), TaskPool::new(4), profiler()); + let image_cache_task = ImageCacheTask::new(mock_resource_task.clone(), TaskPool::new(4), profiler(), LoadPlaceholder::Preload); let url = Url::parse("file:///").unwrap(); let join_port = image_cache_task.wait_for_store(); @@ -949,7 +991,7 @@ mod tests { let mock_resource_task = mock_resource_task(box WaitSendTestImage {wait_port: wait_port}); - let image_cache_task = ImageCacheTask::new(mock_resource_task.clone(), TaskPool::new(4), profiler()); + let image_cache_task = ImageCacheTask::new(mock_resource_task.clone(), TaskPool::new(4), profiler(), LoadPlaceholder::Ignore); let url = Url::parse("file:///").unwrap(); image_cache_task.send(Prefetch(url.clone())); @@ -975,7 +1017,7 @@ mod tests { let mock_resource_task = mock_resource_task(box WaitSendTestImageErr{wait_port: wait_port}); - let image_cache_task = ImageCacheTask::new(mock_resource_task.clone(), TaskPool::new(4), profiler()); + let image_cache_task = ImageCacheTask::new(mock_resource_task.clone(), TaskPool::new(4), profiler(), LoadPlaceholder::Ignore); let url = Url::parse("file:///").unwrap(); image_cache_task.send(Prefetch(url.clone())); @@ -999,7 +1041,7 @@ mod tests { fn sync_cache_should_wait_for_images() { let mock_resource_task = mock_resource_task(box SendTestImage); - let image_cache_task = ImageCacheTask::new_sync(mock_resource_task.clone(), TaskPool::new(4), profiler()); + let image_cache_task = ImageCacheTask::new_sync(mock_resource_task.clone(), TaskPool::new(4), profiler(), LoadPlaceholder::Preload); let url = Url::parse("file:///").unwrap(); image_cache_task.send(Prefetch(url.clone())); diff --git a/components/servo/lib.rs b/components/servo/lib.rs index 1afdbf8dca5..b197ad30e6f 100644 --- a/components/servo/lib.rs +++ b/components/servo/lib.rs @@ -33,7 +33,7 @@ use msg::constellation_msg::ConstellationChan; use script::dom::bindings::codegen::RegisterBindings; #[cfg(not(test))] -use net::image_cache_task::ImageCacheTask; +use net::image_cache_task::{ImageCacheTask, LoadPlaceholder}; #[cfg(not(test))] use net::resource_task::new_resource_task; #[cfg(not(test))] @@ -84,10 +84,10 @@ impl Browser { // image. let image_cache_task = if opts.output_file.is_some() { ImageCacheTask::new_sync(resource_task.clone(), shared_task_pool, - time_profiler_chan.clone()) + time_profiler_chan.clone(), LoadPlaceholder::Preload) } else { ImageCacheTask::new(resource_task.clone(), shared_task_pool, - time_profiler_chan.clone()) + time_profiler_chan.clone(), LoadPlaceholder::Preload) }; let font_cache_task = FontCacheTask::new(resource_task.clone()); diff --git a/ports/gonk/src/lib.rs b/ports/gonk/src/lib.rs index 46c12ef0cba..ca01f431ae0 100644 --- a/ports/gonk/src/lib.rs +++ b/ports/gonk/src/lib.rs @@ -38,7 +38,7 @@ use msg::constellation_msg::ConstellationChan; use script::dom::bindings::codegen::RegisterBindings; #[cfg(not(test))] -use net::image_cache_task::ImageCacheTask; +use net::image_cache_task::{ImageCacheTask, LoadPlaceholder}; #[cfg(not(test))] use net::storage_task::StorageTaskFactory; #[cfg(not(test))] @@ -89,10 +89,10 @@ impl Browser { // image. let image_cache_task = if opts.output_file.is_some() { ImageCacheTask::new_sync(resource_task.clone(), shared_task_pool, - time_profiler_chan.clone()) + time_profiler_chan.clone(), LoadPlaceholder::Preload) } else { ImageCacheTask::new(resource_task.clone(), shared_task_pool, - time_profiler_chan.clone()) + time_profiler_chan.clone(), LoadPlaceholder::Preload) }; let font_cache_task = FontCacheTask::new(resource_task.clone()); let storage_task = StorageTaskFactory::new(); diff --git a/resources/rippy.jpg b/resources/rippy.jpg Binary files differnew file mode 100644 index 00000000000..a94649ae3f2 --- /dev/null +++ b/resources/rippy.jpg diff --git a/tests/ref/basic.list b/tests/ref/basic.list index 3d322ac5d8c..c66e6750ad5 100644 --- a/tests/ref/basic.list +++ b/tests/ref/basic.list @@ -193,6 +193,7 @@ flaky_cpu == linebreak_simple_a.html linebreak_simple_b.html == multiple_css_class_a.html multiple_css_class_b.html == negative_margin_uncle_a.html negative_margin_uncle_b.html == negative_margins_a.html negative_margins_b.html +== no-image.html no-image-ref.html == noscript.html noscript_ref.html != noteq_attr_exists_selector.html attr_exists_selector_ref.html == nth_child_pseudo_a.html nth_child_pseudo_b.html diff --git a/tests/ref/no-image-ref.html b/tests/ref/no-image-ref.html new file mode 100644 index 00000000000..40ce07f789e --- /dev/null +++ b/tests/ref/no-image-ref.html @@ -0,0 +1 @@ +<img width="100px" height="100px" src="rippy.jpg"> diff --git a/tests/ref/no-image.html b/tests/ref/no-image.html new file mode 100644 index 00000000000..972206b12f1 --- /dev/null +++ b/tests/ref/no-image.html @@ -0,0 +1 @@ +<img width="100px" height="100px" src="i-feel-a-disturbance-in-the-force.wtf"> diff --git a/tests/ref/rippy.jpg b/tests/ref/rippy.jpg Binary files differnew file mode 100644 index 00000000000..a94649ae3f2 --- /dev/null +++ b/tests/ref/rippy.jpg |