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

[DO NOT MERGE] Initiate image loads in the script thread #14781

Closed
wants to merge 8 commits into from

Send response for image requests progressively to image cache.

  • Loading branch information
jdm committed Jan 11, 2017
commit 1ada828cac917678ad52c10d2c4ef51282b879a4
@@ -355,8 +355,11 @@ impl ImageCache {
let result = self.get_image_or_meta_if_available(url, use_placeholder, can_request);
let _ = consumer.send(result);
}
ImageCacheCommand::StoreDecodeImage(id, image_vector) => {
self.store_decode_image(id, image_vector);
ImageCacheCommand::StoreDecodeImage(id, data) => {
self.handle_progress(ResourceLoadInfo {
action: data,
key: id
});
}
};

@@ -368,7 +371,7 @@ impl ImageCache {
match (msg.action, msg.key) {
(FetchResponseMsg::ProcessRequestBody, _) |
(FetchResponseMsg::ProcessRequestEOF, _) => return,
(FetchResponseMsg::ProcessResponse(_), _) => {}
(FetchResponseMsg::ProcessResponse(_response), _) => {}
(FetchResponseMsg::ProcessResponseChunk(data), _) => {
let pending_load = self.pending_loads.get_by_key_mut(&msg.key).unwrap();
pending_load.bytes.extend_from_slice(&data);
@@ -538,21 +541,6 @@ impl ImageCache {
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.
@@ -2,6 +2,7 @@
* 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/. */

use FetchResponseMsg;
use image::base::{Image, ImageMetadata};
use ipc_channel::ipc::{self, IpcSender};
use servo_url::ServoUrl;
@@ -86,7 +87,7 @@ pub enum ImageCacheCommand {

/// Instruct the cache to store this data as a newly-complete network request and continue
/// decoding the result into pixel data
StoreDecodeImage(PendingImageId, Vec<u8>),
StoreDecodeImage(PendingImageId, FetchResponseMsg),

/// Clients must wait for a response before shutting down the ResourceThread
Exit(IpcSender<()>),
@@ -145,9 +146,9 @@ impl ImageCacheThread {
let _ = self.chan.send(msg);
}

/// Decode the given image bytes and cache the result for the given pending ID.
pub fn store_complete_image_bytes(&self, id: PendingImageId, image_data: Vec<u8>) {
let msg = ImageCacheCommand::StoreDecodeImage(id, image_data);
/// Inform the image cache about a response for a pending request.
pub fn notify_pending_response(&self, id: PendingImageId, data: FetchResponseMsg) {
let msg = ImageCacheCommand::StoreDecodeImage(id, data);
let _ = self.chan.send(msg);
}

@@ -170,15 +170,15 @@ pub trait FetchTaskTarget {
fn process_response_eof(&mut self, response: &Response);
}

#[derive(Serialize, Deserialize)]
#[derive(Clone, Serialize, Deserialize)]
pub enum FilteredMetadata {
Basic(Metadata),
Cors(Metadata),
Opaque,
OpaqueRedirect
}

#[derive(Serialize, Deserialize)]
#[derive(Clone, Serialize, Deserialize)]
pub enum FetchMetadata {
Unfiltered(Metadata),
Filtered {
@@ -26,10 +26,11 @@ use dom::window::Window;
use html5ever_atoms::LocalName;
use ipc_channel::ipc;
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_cache_thread::{ImageResponder, ImageResponse, PendingImageId, ImageState};
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 network_listener::{NetworkListener, PreInvoke};
use script_thread::Runnable;
@@ -101,8 +102,6 @@ impl Runnable for ImageRequestRunnable {

let context = Arc::new(Mutex::new(ImageContext {
elem: trusted_node,
data: vec!(),
metadata: None,
url: this.img_url.clone(),
status: Ok(()),
id: this.id,
@@ -189,10 +188,6 @@ impl Runnable for ImageResponseHandlerRunnable {
struct ImageContext {
/// The element that initiated the request.
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.
url: ServoUrl,
/// Indicates whether the request failed, and why
@@ -201,17 +196,28 @@ struct ImageContext {
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 {
fn process_request_body(&mut self) {}
fn process_request_eof(&mut self) {}

fn process_response(&mut self, metadata: Result<FetchMetadata, NetworkError>) {
self.metadata = metadata.ok().map(|meta| match meta {
self.image_cache().notify_pending_response(
self.id,
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 {
Some((c, _)) => Some(c),
_ => None,
@@ -225,18 +231,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() {
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 document = document_from_node(&*elem);
let window = document.window();
let image_cache = window.image_cache_thread();
image_cache.store_complete_image_bytes(self.id, self.data.clone());
let image_cache = self.image_cache();
image_cache.notify_pending_response(self.id,
FetchResponseMsg::ProcessResponseEOF(response));
document.finish_load(LoadType::Image(self.url.clone()));
}
}
@@ -56,8 +56,8 @@ use js::jsapi::{JS_GC, JS_GetRuntime, SetWindowProxy};
use js::jsval::UndefinedValue;
use js::rust::Runtime;
use msg::constellation_msg::{FrameType, PipelineId};
use net_traits::{FetchResponseMsg, NetworkError};
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::{PendingImageResponse, ImageCacheThread, PendingImageId};
use net_traits::request::{Type as RequestType, RequestInit as FetchRequestInit};
@@ -1183,7 +1183,7 @@ impl Window {
let node = from_untrusted_node_address(js_runtime.rt(), image.node);

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();
@@ -1845,38 +1845,43 @@ impl Runnable for PostMessageHandler {

struct LayoutImageContext {
node: Trusted<Node>,
data: Vec<u8>,
id: PendingImageId,
url: ServoUrl,
cache: ImageCacheThread,
}

impl FetchResponseListener for LayoutImageContext {
fn process_request_body(&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(
self.id,
FetchResponseMsg::ProcessResponse(metadata));
}

fn process_response_chunk(&mut self, mut payload: Vec<u8>) {
self.data.append(&mut payload);
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>) {
fn process_response_eof(&mut self, response: Result<(), NetworkError>) {
let node = self.node.root();
let document = document_from_node(&*node);
let window = document.window();
let image_cache = window.image_cache_thread();
image_cache.store_complete_image_bytes(self.id, self.data.clone());
self.cache.notify_pending_response(self.id,
FetchResponseMsg::ProcessResponseEOF(response));
document.finish_load(LoadType::Image(self.url.clone()));
}
}

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 {
node: Trusted::new(node),
data: vec![],
id: id,
url: url.clone(),
cache: cache,
}));

let document = document_from_node(node);
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.