mirror of
https://github.com/servo/servo.git
synced 2025-07-23 15:23:42 +01:00
Send response for image requests progressively to image cache.
This commit is contained in:
parent
21118f0a8a
commit
0d2ec852ac
5 changed files with 59 additions and 58 deletions
|
@ -396,8 +396,11 @@ impl ImageCache {
|
||||||
// TODO(#15501): look for opportunities to clean up cache if this send fails.
|
// TODO(#15501): look for opportunities to clean up cache if this send fails.
|
||||||
let _ = consumer.send(result);
|
let _ = consumer.send(result);
|
||||||
}
|
}
|
||||||
ImageCacheCommand::StoreDecodeImage(id, image_vector) => {
|
ImageCacheCommand::StoreDecodeImage(id, data) => {
|
||||||
self.store_decode_image(id, image_vector);
|
self.handle_progress(ResourceLoadInfo {
|
||||||
|
action: data,
|
||||||
|
key: id
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -409,7 +412,7 @@ impl ImageCache {
|
||||||
match (msg.action, msg.key) {
|
match (msg.action, msg.key) {
|
||||||
(FetchResponseMsg::ProcessRequestBody, _) |
|
(FetchResponseMsg::ProcessRequestBody, _) |
|
||||||
(FetchResponseMsg::ProcessRequestEOF, _) => return,
|
(FetchResponseMsg::ProcessRequestEOF, _) => return,
|
||||||
(FetchResponseMsg::ProcessResponse(_), _) => {}
|
(FetchResponseMsg::ProcessResponse(_response), _) => {}
|
||||||
(FetchResponseMsg::ProcessResponseChunk(data), _) => {
|
(FetchResponseMsg::ProcessResponseChunk(data), _) => {
|
||||||
let pending_load = self.pending_loads.get_by_key_mut(&msg.key).unwrap();
|
let pending_load = self.pending_loads.get_by_key_mut(&msg.key).unwrap();
|
||||||
pending_load.bytes.extend_from_slice(&data);
|
pending_load.bytes.extend_from_slice(&data);
|
||||||
|
@ -581,21 +584,6 @@ impl ImageCache {
|
||||||
None => Err(ImageState::LoadError),
|
None => Err(ImageState::LoadError),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn store_decode_image(&mut self,
|
|
||||||
id: PendingImageId,
|
|
||||||
loaded_bytes: Vec<u8>) {
|
|
||||||
let action = FetchResponseMsg::ProcessResponseChunk(loaded_bytes);
|
|
||||||
self.handle_progress(ResourceLoadInfo {
|
|
||||||
action: action,
|
|
||||||
key: id,
|
|
||||||
});
|
|
||||||
let action = FetchResponseMsg::ProcessResponseEOF(Ok(()));
|
|
||||||
self.handle_progress(ResourceLoadInfo {
|
|
||||||
action: action,
|
|
||||||
key: id,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new image cache.
|
/// Create a new image cache.
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use FetchResponseMsg;
|
||||||
use image::base::{Image, ImageMetadata};
|
use image::base::{Image, ImageMetadata};
|
||||||
use ipc_channel::ipc::{self, IpcSender};
|
use ipc_channel::ipc::{self, IpcSender};
|
||||||
use servo_url::ServoUrl;
|
use servo_url::ServoUrl;
|
||||||
|
@ -89,7 +90,7 @@ pub enum ImageCacheCommand {
|
||||||
|
|
||||||
/// Instruct the cache to store this data as a newly-complete network request and continue
|
/// Instruct the cache to store this data as a newly-complete network request and continue
|
||||||
/// decoding the result into pixel data
|
/// decoding the result into pixel data
|
||||||
StoreDecodeImage(PendingImageId, Vec<u8>),
|
StoreDecodeImage(PendingImageId, FetchResponseMsg),
|
||||||
|
|
||||||
/// Clients must wait for a response before shutting down the ResourceThread
|
/// Clients must wait for a response before shutting down the ResourceThread
|
||||||
Exit(IpcSender<()>),
|
Exit(IpcSender<()>),
|
||||||
|
@ -151,9 +152,9 @@ impl ImageCacheThread {
|
||||||
self.chan.send(msg).expect("Image cache thread is not available");
|
self.chan.send(msg).expect("Image cache thread is not available");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Decode the given image bytes and cache the result for the given pending ID.
|
/// Inform the image cache about a response for a pending request.
|
||||||
pub fn store_complete_image_bytes(&self, id: PendingImageId, image_data: Vec<u8>) {
|
pub fn notify_pending_response(&self, id: PendingImageId, data: FetchResponseMsg) {
|
||||||
let msg = ImageCacheCommand::StoreDecodeImage(id, image_data);
|
let msg = ImageCacheCommand::StoreDecodeImage(id, data);
|
||||||
self.chan.send(msg).expect("Image cache thread is not available");
|
self.chan.send(msg).expect("Image cache thread is not available");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -192,7 +192,7 @@ pub trait FetchTaskTarget {
|
||||||
fn process_response_eof(&mut self, response: &Response);
|
fn process_response_eof(&mut self, response: &Response);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Clone, Serialize, Deserialize)]
|
||||||
pub enum FilteredMetadata {
|
pub enum FilteredMetadata {
|
||||||
Basic(Metadata),
|
Basic(Metadata),
|
||||||
Cors(Metadata),
|
Cors(Metadata),
|
||||||
|
@ -200,7 +200,7 @@ pub enum FilteredMetadata {
|
||||||
OpaqueRedirect
|
OpaqueRedirect
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Clone, Serialize, Deserialize)]
|
||||||
pub enum FetchMetadata {
|
pub enum FetchMetadata {
|
||||||
Unfiltered(Metadata),
|
Unfiltered(Metadata),
|
||||||
Filtered {
|
Filtered {
|
||||||
|
|
|
@ -36,10 +36,11 @@ use euclid::point::Point2D;
|
||||||
use html5ever_atoms::LocalName;
|
use html5ever_atoms::LocalName;
|
||||||
use ipc_channel::ipc;
|
use ipc_channel::ipc;
|
||||||
use ipc_channel::router::ROUTER;
|
use ipc_channel::router::ROUTER;
|
||||||
use net_traits::{FetchResponseListener, FetchMetadata, Metadata, NetworkError};
|
use net_traits::{FetchResponseListener, FetchMetadata, NetworkError, FetchResponseMsg};
|
||||||
use net_traits::image::base::{Image, ImageMetadata};
|
use net_traits::image::base::{Image, ImageMetadata};
|
||||||
use net_traits::image_cache_thread::{ImageResponder, ImageResponse, PendingImageId, ImageState};
|
use net_traits::image_cache_thread::{ImageResponder, ImageResponse, PendingImageId, ImageState};
|
||||||
use net_traits::image_cache_thread::{UsePlaceholder, ImageOrMetadataAvailable, CanRequestImages};
|
use net_traits::image_cache_thread::{UsePlaceholder, ImageOrMetadataAvailable, CanRequestImages};
|
||||||
|
use net_traits::image_cache_thread::ImageCacheThread;
|
||||||
use net_traits::request::{RequestInit, Type as RequestType};
|
use net_traits::request::{RequestInit, Type as RequestType};
|
||||||
use network_listener::{NetworkListener, PreInvoke};
|
use network_listener::{NetworkListener, PreInvoke};
|
||||||
use num_traits::ToPrimitive;
|
use num_traits::ToPrimitive;
|
||||||
|
@ -112,8 +113,6 @@ impl Runnable for ImageRequestRunnable {
|
||||||
|
|
||||||
let context = Arc::new(Mutex::new(ImageContext {
|
let context = Arc::new(Mutex::new(ImageContext {
|
||||||
elem: trusted_node,
|
elem: trusted_node,
|
||||||
data: vec!(),
|
|
||||||
metadata: None,
|
|
||||||
url: this.img_url.clone(),
|
url: this.img_url.clone(),
|
||||||
status: Ok(()),
|
status: Ok(()),
|
||||||
id: this.id,
|
id: this.id,
|
||||||
|
@ -200,10 +199,6 @@ impl Runnable for ImageResponseHandlerRunnable {
|
||||||
struct ImageContext {
|
struct ImageContext {
|
||||||
/// The element that initiated the request.
|
/// The element that initiated the request.
|
||||||
elem: Trusted<HTMLImageElement>,
|
elem: Trusted<HTMLImageElement>,
|
||||||
/// The response body received to date.
|
|
||||||
data: Vec<u8>,
|
|
||||||
/// The response metadata received to date.
|
|
||||||
metadata: Option<Metadata>,
|
|
||||||
/// The initial URL requested.
|
/// The initial URL requested.
|
||||||
url: ServoUrl,
|
url: ServoUrl,
|
||||||
/// Indicates whether the request failed, and why
|
/// Indicates whether the request failed, and why
|
||||||
|
@ -212,21 +207,31 @@ struct ImageContext {
|
||||||
id: PendingImageId,
|
id: PendingImageId,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ImageContext {
|
||||||
|
fn image_cache(&self) -> ImageCacheThread {
|
||||||
|
let elem = self.elem.root();
|
||||||
|
window_from_node(&*elem).image_cache_thread().clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl FetchResponseListener for ImageContext {
|
impl FetchResponseListener for ImageContext {
|
||||||
fn process_request_body(&mut self) {}
|
fn process_request_body(&mut self) {}
|
||||||
fn process_request_eof(&mut self) {}
|
fn process_request_eof(&mut self) {}
|
||||||
|
|
||||||
fn process_response(&mut self, metadata: Result<FetchMetadata, NetworkError>) {
|
fn process_response(&mut self, metadata: Result<FetchMetadata, NetworkError>) {
|
||||||
self.metadata = metadata.ok().map(|meta| match meta {
|
self.image_cache().notify_pending_response(
|
||||||
FetchMetadata::Unfiltered(m) => m,
|
self.id,
|
||||||
FetchMetadata::Filtered { unsafe_, .. } => unsafe_
|
FetchResponseMsg::ProcessResponse(metadata.clone()));
|
||||||
|
|
||||||
|
let metadata = metadata.ok().map(|meta| {
|
||||||
|
match meta {
|
||||||
|
FetchMetadata::Unfiltered(m) => m,
|
||||||
|
FetchMetadata::Filtered { unsafe_, .. } => unsafe_
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let status_code = self.metadata.as_ref().and_then(|m| {
|
let status_code = metadata.as_ref().and_then(|m| {
|
||||||
match m.status {
|
m.status.as_ref().map(|&(code, _)| code)
|
||||||
Some((c, _)) => Some(c),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}).unwrap_or(0);
|
}).unwrap_or(0);
|
||||||
|
|
||||||
self.status = match status_code {
|
self.status = match status_code {
|
||||||
|
@ -236,18 +241,20 @@ impl FetchResponseListener for ImageContext {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_response_chunk(&mut self, mut payload: Vec<u8>) {
|
fn process_response_chunk(&mut self, payload: Vec<u8>) {
|
||||||
if self.status.is_ok() {
|
if self.status.is_ok() {
|
||||||
self.data.append(&mut payload);
|
self.image_cache().notify_pending_response(
|
||||||
|
self.id,
|
||||||
|
FetchResponseMsg::ProcessResponseChunk(payload));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_response_eof(&mut self, _response: Result<(), NetworkError>) {
|
fn process_response_eof(&mut self, response: Result<(), NetworkError>) {
|
||||||
let elem = self.elem.root();
|
let elem = self.elem.root();
|
||||||
let document = document_from_node(&*elem);
|
let document = document_from_node(&*elem);
|
||||||
let window = document.window();
|
let image_cache = self.image_cache();
|
||||||
let image_cache = window.image_cache_thread();
|
image_cache.notify_pending_response(self.id,
|
||||||
image_cache.store_complete_image_bytes(self.id, self.data.clone());
|
FetchResponseMsg::ProcessResponseEOF(response));
|
||||||
document.finish_load(LoadType::Image(self.url.clone()));
|
document.finish_load(LoadType::Image(self.url.clone()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,8 +59,8 @@ use js::jsapi::{JS_GC, JS_GetRuntime};
|
||||||
use js::jsval::UndefinedValue;
|
use js::jsval::UndefinedValue;
|
||||||
use js::rust::Runtime;
|
use js::rust::Runtime;
|
||||||
use msg::constellation_msg::{FrameType, PipelineId};
|
use msg::constellation_msg::{FrameType, PipelineId};
|
||||||
|
use net_traits::{FetchResponseMsg, NetworkError};
|
||||||
use net_traits::{ResourceThreads, ReferrerPolicy, FetchResponseListener, FetchMetadata};
|
use net_traits::{ResourceThreads, ReferrerPolicy, FetchResponseListener, FetchMetadata};
|
||||||
use net_traits::NetworkError;
|
|
||||||
use net_traits::image_cache_thread::{ImageResponder, ImageResponse};
|
use net_traits::image_cache_thread::{ImageResponder, ImageResponse};
|
||||||
use net_traits::image_cache_thread::{PendingImageResponse, ImageCacheThread, PendingImageId};
|
use net_traits::image_cache_thread::{PendingImageResponse, ImageCacheThread, PendingImageId};
|
||||||
use net_traits::request::{Type as RequestType, RequestInit as FetchRequestInit};
|
use net_traits::request::{Type as RequestType, RequestInit as FetchRequestInit};
|
||||||
|
@ -1207,7 +1207,7 @@ impl Window {
|
||||||
let node = from_untrusted_node_address(js_runtime.rt(), image.node);
|
let node = from_untrusted_node_address(js_runtime.rt(), image.node);
|
||||||
|
|
||||||
if let PendingImageState::Unrequested(ref url) = image.state {
|
if let PendingImageState::Unrequested(ref url) = image.state {
|
||||||
fetch_image_for_layout(url.clone(), &*node, id);
|
fetch_image_for_layout(url.clone(), &*node, id, self.image_cache_thread.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut images = self.pending_layout_images.borrow_mut();
|
let mut images = self.pending_layout_images.borrow_mut();
|
||||||
|
@ -1897,38 +1897,43 @@ impl Runnable for PostMessageHandler {
|
||||||
|
|
||||||
struct LayoutImageContext {
|
struct LayoutImageContext {
|
||||||
node: Trusted<Node>,
|
node: Trusted<Node>,
|
||||||
data: Vec<u8>,
|
|
||||||
id: PendingImageId,
|
id: PendingImageId,
|
||||||
url: ServoUrl,
|
url: ServoUrl,
|
||||||
|
cache: ImageCacheThread,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FetchResponseListener for LayoutImageContext {
|
impl FetchResponseListener for LayoutImageContext {
|
||||||
fn process_request_body(&mut self) {}
|
fn process_request_body(&mut self) {}
|
||||||
fn process_request_eof(&mut self) {}
|
fn process_request_eof(&mut self) {}
|
||||||
fn process_response(&mut self, _metadata: Result<FetchMetadata, NetworkError>) {/*XXXjdm*/}
|
fn process_response(&mut self, metadata: Result<FetchMetadata, NetworkError>) {
|
||||||
|
self.cache.notify_pending_response(
|
||||||
fn process_response_chunk(&mut self, mut payload: Vec<u8>) {
|
self.id,
|
||||||
self.data.append(&mut payload);
|
FetchResponseMsg::ProcessResponse(metadata));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_response_eof(&mut self, _response: Result<(), NetworkError>) {
|
fn process_response_chunk(&mut self, payload: Vec<u8>) {
|
||||||
|
self.cache.notify_pending_response(
|
||||||
|
self.id,
|
||||||
|
FetchResponseMsg::ProcessResponseChunk(payload));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_response_eof(&mut self, response: Result<(), NetworkError>) {
|
||||||
let node = self.node.root();
|
let node = self.node.root();
|
||||||
let document = document_from_node(&*node);
|
let document = document_from_node(&*node);
|
||||||
let window = document.window();
|
self.cache.notify_pending_response(self.id,
|
||||||
let image_cache = window.image_cache_thread();
|
FetchResponseMsg::ProcessResponseEOF(response));
|
||||||
image_cache.store_complete_image_bytes(self.id, self.data.clone());
|
|
||||||
document.finish_load(LoadType::Image(self.url.clone()));
|
document.finish_load(LoadType::Image(self.url.clone()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PreInvoke for LayoutImageContext {}
|
impl PreInvoke for LayoutImageContext {}
|
||||||
|
|
||||||
fn fetch_image_for_layout(url: ServoUrl, node: &Node, id: PendingImageId) {
|
fn fetch_image_for_layout(url: ServoUrl, node: &Node, id: PendingImageId, cache: ImageCacheThread) {
|
||||||
let context = Arc::new(Mutex::new(LayoutImageContext {
|
let context = Arc::new(Mutex::new(LayoutImageContext {
|
||||||
node: Trusted::new(node),
|
node: Trusted::new(node),
|
||||||
data: vec![],
|
|
||||||
id: id,
|
id: id,
|
||||||
url: url.clone(),
|
url: url.clone(),
|
||||||
|
cache: cache,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let document = document_from_node(node);
|
let document = document_from_node(node);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue