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

Implement document load tracking. #3714

Closed
wants to merge 4 commits into from
Closed
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

@@ -121,7 +121,6 @@ impl Pipeline {
failure,
script_chan.clone(),
paint_chan.clone(),
resource_task,
image_cache_task,
font_cache_task,
time_profiler_chan,
@@ -48,7 +48,7 @@ use servo_msg::constellation_msg::Msg as ConstellationMsg;
use servo_msg::constellation_msg::{ConstellationChan, Failure, PipelineExitType, PipelineId};
use servo_net::image_cache_task::{ImageCacheTask, ImageResponseMsg};
use servo_net::local_image_cache::{ImageResponder, LocalImageCache};
use servo_net::resource_task::{ResourceTask, load_bytes_iter};
use servo_net::resource_task::{PendingAsyncLoad, load_bytes_iter};
use servo_util::cursor::Cursor;
use servo_util::geometry::Au;
use servo_util::logical_geometry::LogicalPoint;
@@ -127,9 +127,6 @@ pub struct LayoutTask {
/// The channel on which messages can be sent to the time profiler.
pub time_profiler_chan: TimeProfilerChan,

/// The channel on which messages can be sent to the resource task.
pub resource_task: ResourceTask,

/// The channel on which messages can be sent to the image cache.
pub image_cache_task: ImageCacheTask,

@@ -178,7 +175,6 @@ impl LayoutTaskFactory for LayoutTask {
failure_msg: Failure,
script_chan: ScriptControlChan,
paint_chan: PaintChan,
resource_task: ResourceTask,
img_cache_task: ImageCacheTask,
font_cache_task: FontCacheTask,
time_profiler_chan: TimeProfilerChan,
@@ -196,7 +192,6 @@ impl LayoutTaskFactory for LayoutTask {
constellation_chan,
script_chan,
paint_chan,
resource_task,
img_cache_task,
font_cache_task,
time_profiler_chan);
@@ -245,7 +240,6 @@ impl LayoutTask {
constellation_chan: ConstellationChan,
script_chan: ScriptControlChan,
paint_chan: PaintChan,
resource_task: ResourceTask,
image_cache_task: ImageCacheTask,
font_cache_task: FontCacheTask,
time_profiler_chan: TimeProfilerChan)
@@ -269,7 +263,6 @@ impl LayoutTask {
script_chan: script_chan,
paint_chan: paint_chan,
time_profiler_chan: time_profiler_chan,
resource_task: resource_task,
image_cache_task: image_cache_task.clone(),
font_cache_task: font_cache_task,
first_reflow: Cell::new(true),
@@ -393,7 +386,7 @@ impl LayoutTask {
-> bool {
match request {
Msg::AddStylesheet(sheet) => self.handle_add_stylesheet(sheet, possibly_locked_rw_data),
Msg::LoadStylesheet(url) => self.handle_load_stylesheet(url, possibly_locked_rw_data),
Msg::LoadStylesheet(url, pending) => self.handle_load_stylesheet(url, pending, possibly_locked_rw_data),
Msg::SetQuirksMode => self.handle_set_quirks_mode(possibly_locked_rw_data),
Msg::GetRPC(response_chan) => {
response_chan.send(box LayoutRPCImpl(self.rw_data.clone()) as
@@ -474,12 +467,13 @@ impl LayoutTask {

fn handle_load_stylesheet<'a>(&'a self,
url: Url,
pending: PendingAsyncLoad,
possibly_locked_rw_data:
&mut Option<MutexGuard<'a, LayoutTaskData>>) {
// TODO: Get the actual value. http://dev.w3.org/csswg/css-syntax/#environment-encoding
let environment_encoding = UTF_8 as EncodingRef;

let (metadata, iter) = load_bytes_iter(&self.resource_task, url);
let (metadata, iter) = load_bytes_iter(pending);
let protocol_encoding_label = metadata.charset.as_ref().map(|s| s.as_slice());
let final_url = metadata.final_url;

@@ -488,6 +482,11 @@ impl LayoutTask {
protocol_encoding_label,
Some(environment_encoding),
StylesheetOrigin::Author);

//TODO: mark critical subresources as blocking load as well
let ScriptControlChan(ref chan) = self.script_chan;
chan.send(ConstellationControlMsg::StylesheetLoadComplete(self.id, url));

self.handle_add_stylesheet(sheet, possibly_locked_rw_data);
}

@@ -38,6 +38,17 @@ extern crate encoding;
extern crate libc;
extern crate url;

#[allow(non_snake_case)]
mod ICE_workaround {
use super::script::layout_interface::Msg;

#[allow(dead_code)]
fn ice_workaround() {
let (tx, _rx) = channel();
tx.send(Msg::SetQuirksMode);
}
}

// Listed first because of macro definitions
pub mod layout_debug;

@@ -21,7 +21,6 @@ use gfx::font_cache_task::FontCacheTask;
use gfx::paint_task::PaintChan;
use servo_msg::constellation_msg::{ConstellationChan, Failure, PipelineId, PipelineExitType};
use servo_net::image_cache_task::ImageCacheTask;
use servo_net::resource_task::ResourceTask;
use servo_util::time::TimeProfilerChan;
use script_traits::{ScriptControlChan, OpaqueScriptLayoutChannel};
use std::comm::Sender;
@@ -46,7 +45,6 @@ pub trait LayoutTaskFactory {
failure_msg: Failure,
script_chan: ScriptControlChan,
paint_chan: PaintChan,
resource_task: ResourceTask,
img_cache_task: ImageCacheTask,
font_cache_task: FontCacheTask,
time_profiler_chan: TimeProfilerChan,
@@ -4,8 +4,9 @@

use image::base::{Image, load_from_memory};
use resource_task;
use resource_task::{LoadData, ResourceTask};
use resource_task::{LoadData, ResourceTask, PendingAsyncLoad};
use resource_task::ProgressMsg::{Payload, Done};
use servo_msg::constellation_msg::PipelineId;

use servo_util::task::spawn_named;
use servo_util::taskpool::TaskPool;
@@ -17,10 +18,31 @@ use std::sync::{Arc, Mutex};
use serialize::{Encoder, Encodable};
use url::Url;

pub struct ImageCacheChannel {
task: ImageCacheTask,
pipeline: PipelineId,
notifier: Sender<ImageNotification>,
}

impl ImageCacheChannel {
pub fn new(task: ImageCacheTask, pipeline: PipelineId, notifier: Sender<ImageNotification>)
-> ImageCacheChannel {
ImageCacheChannel {
task: task,
pipeline: pipeline,
notifier: notifier,
}
}
pub fn load(&self, load: PendingAsyncLoad) {
self.task.send(Msg::Prefetch(load.url().clone(),
Some((self.notifier.clone(), self.pipeline))));
}
}

pub enum Msg {
/// Tell the cache that we may need a particular image soon. Must be posted
/// before Decode
Prefetch(Url),
Prefetch(Url, Option<(Sender<ImageNotification>, PipelineId)>),

/// Tell the cache to decode an image. Must be posted before GetImage/WaitForImage
Decode(Url),
@@ -162,22 +184,53 @@ enum AfterPrefetch {
DoNotDecode
}

pub enum ImageNotification {
ImageLoadComplete(PipelineId, Url)
}

impl ImageCache {
pub fn run(&mut self) {
let mut store_chan: Option<Sender<()>> = None;
let mut store_prefetched_chan: Option<Sender<()>> = None;
let mut pending_clients: HashMap<Url, Vec<(Sender<ImageNotification>, PipelineId)>> = HashMap::new();

loop {
let msg = self.port.recv();

match msg {
Msg::Prefetch(url) => self.prefetch(url),
Msg::Prefetch(url, notifier) => {
let pending_request = self.prefetch(url.clone());
notifier.map(|(notifier, pipeline)| {
if pending_request {
let new_client = (notifier, pipeline);
match pending_clients.entry(url.clone()) {
Occupied(mut clients) => {
clients.get_mut().push(new_client);
}
Vacant(entry) => {
entry.set(vec!(new_client));
}
}
} else {
notifier.send(ImageNotification::ImageLoadComplete(pipeline,
url.clone()));
}
});
}
Msg::StorePrefetchedImageData(url, data) => {
store_prefetched_chan.map(|chan| {
chan.send(());
});
store_prefetched_chan = None;

pending_clients.get(&url).map(|clients| {
for &(ref chan, ref pipeline) in clients.iter() {
chan.send(ImageNotification::ImageLoadComplete(pipeline.clone(),
url.clone()));
}
});
pending_clients.remove(&url);

self.store_prefetched_image_data(url, data);
}
Msg::Decode(url) => self.decode(url),
@@ -241,7 +294,8 @@ impl ImageCache {
self.state_map.insert(url, state);
}

fn prefetch(&mut self, url: Url) {
// returns true if a network request is in progress, false otherwise
fn prefetch(&mut self, url: Url) -> bool {
match self.get_state(&url) {
ImageState::Init => {
let to_cache = self.chan.clone();
@@ -258,11 +312,15 @@ impl ImageCache {
});

self.set_state(url, ImageState::Prefetching(AfterPrefetch::DoNotDecode));
true
}

ImageState::Prefetching(..) | ImageState::Prefetched(..) |
ImageState::Decoding | ImageState::Decoded(..) | ImageState::Failed => {
ImageState::Prefetching(..) => true,

ImageState::Prefetched(..) | ImageState::Decoding | ImageState::Decoded(..) |
ImageState::Failed => {
// We've already begun working on this image
false
}
}
}
@@ -15,6 +15,7 @@ extern crate png;
#[phase(plugin, link)]
extern crate log;
extern crate serialize;
extern crate "msg" as servo_msg;
extern crate "util" as servo_util;
extern crate stb_image;
extern crate time;
@@ -64,7 +64,7 @@ impl<NodeAddress: Send> LocalImageCache<NodeAddress> {
state.prefetched = true;
}

self.image_cache_task.send(Msg::Prefetch((*url).clone()));
self.image_cache_task.send(Msg::Prefetch((*url).clone(), None));
}

pub fn decode(&mut self, url: &Url) {
@@ -106,6 +106,39 @@ impl Metadata {
}
}

/// Initialized but unsent request. Encapsulates everything necessary to instruct
/// the resource task to make a new request.
pub struct PendingAsyncLoad {
resource_task: ResourceTask,
pub load_data: LoadData,
input_port: Receiver<LoadResponse>,
}

impl PendingAsyncLoad {
pub fn new(resource_task: ResourceTask, url: Url) -> PendingAsyncLoad {
let (tx, rx) = channel();
PendingAsyncLoad {
resource_task: resource_task,
load_data: LoadData::new(url, tx),
input_port: rx,
}
}

pub fn load(self) -> Receiver<LoadResponse> {
self.load_with(|_| {})
}

pub fn load_with(mut self, cb: |load_data: &mut LoadData|) -> Receiver<LoadResponse> {
cb(&mut self.load_data);
self.resource_task.send(ControlMsg::Load(self.load_data));
self.input_port
}

pub fn url(&self) -> &Url {
&self.load_data.url
}
}

/// Message sent in response to `Load`. Contains metadata, and a port
/// for receiving the data.
///
@@ -247,10 +280,8 @@ impl ResourceManager {
}

/// Load a URL asynchronously and iterate over chunks of bytes from the response.
pub fn load_bytes_iter(resource_task: &ResourceTask, url: Url) -> (Metadata, ProgressMsgPortIterator) {
let (input_chan, input_port) = channel();
resource_task.send(ControlMsg::Load(LoadData::new(url, input_chan)));

pub fn load_bytes_iter(pending: PendingAsyncLoad) -> (Metadata, ProgressMsgPortIterator) {
let input_port = pending.load();
let response = input_port.recv();
let iter = ProgressMsgPortIterator { progress_port: response.progress_port };
(response.metadata, iter)
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.