Auto merge of #5804 - jdm:docloader, r=Ms2ger

This implements a simple load-tracking system and tracks stylesheet loads as an example of how it fits together. This is a simplified and rebased version of #3714; I do not believe that the main thrust of hsivonen's comments (related to tracking navigation in browsing contexts) affect this part of the work. 

r? @Ms2ger

<!-- Reviewable:start -->
[<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/5804)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2015-05-11 14:35:33 -05:00
commit 2baa69595e
22 changed files with 459 additions and 144 deletions

View file

@ -19,6 +19,7 @@
#![allow(unsafe_code)]
use document_loader::{LoadType, DocumentLoader, NotifierData};
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::DocumentBinding::{DocumentMethods, DocumentReadyState};
use dom::bindings::codegen::InheritTypes::{ElementCast, EventTargetCast, HTMLIFrameElementCast, NodeCast, EventCast};
@ -65,7 +66,7 @@ use msg::constellation_msg::{ConstellationChan, FocusType};
use msg::constellation_msg::{LoadData, PipelineId, SubpageId, MozBrowserEvent, WorkerId};
use msg::constellation_msg::{Failure, WindowSizeData, PipelineExitType};
use msg::constellation_msg::Msg as ConstellationMsg;
use net_traits::{ResourceTask, ControlMsg, LoadResponse, LoadConsumer};
use net_traits::{ResourceTask, LoadResponse, LoadConsumer, ControlMsg};
use net_traits::LoadData as NetLoadData;
use net_traits::image_cache_task::{ImageCacheChan, ImageCacheTask, ImageCacheResult};
use net_traits::storage_task::StorageTask;
@ -190,6 +191,8 @@ pub enum ScriptMsg {
RefcountCleanup(TrustedReference),
/// The final network response for a page has arrived.
PageFetchComplete(PipelineId, Option<SubpageId>, LoadResponse),
/// Notify a document that all pending loads are complete.
DocumentLoadsComplete(PipelineId),
}
/// A cloneable interface for communicating with an event loop.
@ -728,6 +731,10 @@ impl ScriptTask {
self.handle_webdriver_msg(pipeline_id, msg),
ConstellationControlMsg::TickAllAnimations(pipeline_id) =>
self.handle_tick_all_animations(pipeline_id),
ConstellationControlMsg::StylesheetLoadComplete(id, url, responder) => {
responder.respond();
self.handle_resource_loaded(id, LoadType::Stylesheet(url));
}
}
}
@ -753,6 +760,8 @@ impl ScriptTask {
LiveDOMReferences::cleanup(self.get_cx(), addr),
ScriptMsg::PageFetchComplete(id, subpage, response) =>
self.handle_page_fetch_complete(id, subpage, response),
ScriptMsg::DocumentLoadsComplete(id) =>
self.handle_loads_complete(id),
}
}
@ -844,6 +853,12 @@ impl ScriptTask {
}
/// Handle a request to load a page in a new child frame of an existing page.
fn handle_resource_loaded(&self, pipeline: PipelineId, load: LoadType) {
let page = get_page(&self.root_page(), pipeline);
let doc = page.document().root();
doc.r().finish_load(load);
}
fn handle_new_layout(&self, new_layout_info: NewLayoutInfo) {
let NewLayoutInfo {
containing_pipeline_id,
@ -868,6 +883,25 @@ impl ScriptTask {
self.start_page_load(new_load, load_data);
}
fn handle_loads_complete(&self, pipeline: PipelineId) {
let page = get_page(&self.root_page(), pipeline);
let doc = page.document().root();
let doc = doc.r();
if doc.loader().is_blocked() {
return;
}
doc.mut_loader().inhibit_events();
// https://html.spec.whatwg.org/multipage/#the-end step 7
let addr: Trusted<Document> = Trusted::new(self.get_cx(), doc, self.chan.clone());
let handler = box DocumentProgressHandler::new(addr.clone(), DocumentProgressTask::Load);
self.chan.send(ScriptMsg::RunnableMsg(handler)).unwrap();
let ConstellationChan(ref chan) = self.constellation_chan;
chan.send(ConstellationMsg::LoadComplete).unwrap();
}
/// Handles a timer that fired.
fn handle_fire_timer_msg(&self, id: PipelineId, timer_id: TimerId) {
let page = self.root_page();
@ -1152,12 +1186,20 @@ impl ScriptTask {
_ => None
};
let notifier_data = NotifierData {
script_chan: self.chan.clone(),
pipeline: page.pipeline(),
};
let loader = DocumentLoader::new_with_task(self.resource_task.clone(),
Some(notifier_data),
Some(final_url.clone()));
let document = Document::new(window.r(),
Some(final_url.clone()),
IsHTMLDocument::HTMLDocument,
content_type,
last_modified,
DocumentSource::FromParser).root();
DocumentSource::FromParser,
loader).root();
let frame_element = frame_element.r().map(|elem| ElementCast::from_ref(elem));
window.r().init_browser_context(document.r(), frame_element);
@ -1434,22 +1476,11 @@ impl ScriptTask {
// https://html.spec.whatwg.org/multipage/#the-end step 4
let addr: Trusted<Document> = Trusted::new(self.get_cx(), document.r(), self.chan.clone());
let handler = box DocumentProgressHandler::new(addr.clone(), DocumentProgressTask::DOMContentLoaded);
self.chan.send(ScriptMsg::RunnableMsg(handler)).unwrap();
// We have no concept of a document loader right now, so just dispatch the
// "load" event as soon as we've finished executing all scripts parsed during
// the initial load.
// https://html.spec.whatwg.org/multipage/#the-end step 7
let handler = box DocumentProgressHandler::new(addr, DocumentProgressTask::Load);
let handler = box DocumentProgressHandler::new(addr, DocumentProgressTask::DOMContentLoaded);
self.chan.send(ScriptMsg::RunnableMsg(handler)).unwrap();
window.r().set_fragment_name(final_url.fragment.clone());
let ConstellationChan(ref chan) = self.constellation_chan;
chan.send(ConstellationMsg::LoadComplete).unwrap();
// Notify devtools that a new script global exists.
self.notify_devtools(document.r().Title(), final_url, (id, None));
}