aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbors-servo <metajack+bors@gmail.com>2015-03-30 12:40:12 -0600
committerbors-servo <metajack+bors@gmail.com>2015-03-30 12:40:12 -0600
commit1e282d55d7e36f0e488a395b90e961e9200c3817 (patch)
tree80200f6e523e054df6ef74e65c66216759971e10
parent46d4ef81674d1de4b9066185c7e63c32b04c167e (diff)
parentcdebb3ca543bb7f8d0bd71d8387925f5d8439f75 (diff)
downloadservo-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.rs94
-rw-r--r--components/servo/lib.rs6
-rw-r--r--ports/gonk/src/lib.rs6
-rw-r--r--resources/rippy.jpgbin0 -> 35425 bytes
-rw-r--r--tests/ref/basic.list1
-rw-r--r--tests/ref/no-image-ref.html1
-rw-r--r--tests/ref/no-image.html1
-rw-r--r--tests/ref/rippy.jpgbin0 -> 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
new file mode 100644
index 00000000000..a94649ae3f2
--- /dev/null
+++ b/resources/rippy.jpg
Binary files differ
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
new file mode 100644
index 00000000000..a94649ae3f2
--- /dev/null
+++ b/tests/ref/rippy.jpg
Binary files differ