aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/script_task.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/script_task.rs')
-rw-r--r--components/script/script_task.rs422
1 files changed, 249 insertions, 173 deletions
diff --git a/components/script/script_task.rs b/components/script/script_task.rs
index 51361bd1436..28a2e6437c0 100644
--- a/components/script/script_task.rs
+++ b/components/script/script_task.rs
@@ -49,16 +49,17 @@ use msg::constellation_msg::{LoadData, PipelineId, SubpageId};
use msg::constellation_msg::{Failure, Msg, WindowSizeData, PipelineExitType};
use msg::constellation_msg::Msg as ConstellationMsg;
use net::image_cache_task::ImageCacheTask;
-use net::resource_task::{ResourceTask, ControlMsg};
+use net::resource_task::{ResourceTask, ControlMsg, LoadResponse};
use net::resource_task::LoadData as NetLoadData;
use net::storage_task::StorageTask;
use string_cache::Atom;
use util::geometry::to_frac_px;
use util::smallvec::SmallVec;
use util::str::DOMString;
-use util::task::spawn_named_with_send_on_failure;
+use util::task::{spawn_named, spawn_named_with_send_on_failure};
use util::task_state;
+use geom::Rect;
use geom::point::Point2D;
use hyper::header::{LastModified, Headers};
use js::jsapi::{JS_SetWrapObjectCallbacks, JS_SetGCZeal, JS_DEFAULT_ZEAL_FREQ, JS_GC};
@@ -83,6 +84,32 @@ use time::Tm;
thread_local!(pub static STACK_ROOTS: Cell<Option<RootCollectionPtr>> = Cell::new(None));
+struct InProgressLoad {
+ pipeline_id: PipelineId,
+ subpage_id: Option<(PipelineId, SubpageId)>,
+ window_size: WindowSizeData,
+ layout_chan: LayoutChan,
+ clip_rect: Option<Rect<f32>>,
+ url: Url,
+}
+
+impl InProgressLoad {
+ fn new(id: PipelineId,
+ subpage_id: Option<(PipelineId, SubpageId)>,
+ layout_chan: LayoutChan,
+ window_size: WindowSizeData,
+ url: Url) -> InProgressLoad {
+ InProgressLoad {
+ pipeline_id: id,
+ subpage_id: subpage_id,
+ layout_chan: layout_chan,
+ window_size: window_size,
+ clip_rect: None,
+ url: url,
+ }
+ }
+}
+
#[derive(Copy)]
pub enum TimerSource {
FromWindow(PipelineId),
@@ -118,6 +145,8 @@ pub enum ScriptMsg {
RunnableMsg(Box<Runnable+Send>),
/// A DOM object's last pinned reference was removed (dispatched to all tasks).
RefcountCleanup(TrustedReference),
+ /// The final network response for a page has arrived.
+ PageFetchComplete(PipelineId, Option<SubpageId>, LoadResponse),
}
/// A cloneable interface for communicating with an event loop.
@@ -175,11 +204,15 @@ impl Drop for StackRootTLS {
/// FIXME: Rename to `Page`, following WebKit?
pub struct ScriptTask {
/// A handle to the information pertaining to page layout
- page: DOMRefCell<Rc<Page>>,
+ page: DOMRefCell<Option<Rc<Page>>>,
+ /// A list of data pertaining to loads that have not yet received a network response
+ incomplete_loads: DOMRefCell<Vec<InProgressLoad>>,
/// A handle to the image cache task.
image_cache_task: ImageCacheTask,
/// A handle to the resource task.
resource_task: ResourceTask,
+ /// A handle to the storage task.
+ storage_task: StorageTask,
/// The port on which the script task receives messages (load URL, exit, etc.)
port: Receiver<ScriptMsg>,
@@ -274,15 +307,14 @@ impl ScriptTaskFactory for ScriptTask {
storage_task: StorageTask,
image_cache_task: ImageCacheTask,
devtools_chan: Option<DevtoolsControlChan>,
- window_size: WindowSizeData)
+ window_size: WindowSizeData,
+ load_data: LoadData)
where C: ScriptListener + Send + 'static {
let ConstellationChan(const_chan) = constellation_chan.clone();
let (script_chan, script_port) = channel();
let layout_chan = LayoutChan(layout_chan.sender());
spawn_named_with_send_on_failure("ScriptTask", task_state::SCRIPT, move || {
- let script_task = ScriptTask::new(id,
- box compositor as Box<ScriptListener>,
- layout_chan,
+ let script_task = ScriptTask::new(box compositor as Box<ScriptListener>,
script_port,
NonWorkerScriptChan(script_chan),
control_chan,
@@ -291,9 +323,13 @@ impl ScriptTaskFactory for ScriptTask {
resource_task,
storage_task,
image_cache_task,
- devtools_chan,
- window_size);
+ devtools_chan);
let mut failsafe = ScriptMemoryFailsafe::new(&script_task);
+
+ let new_load = InProgressLoad::new(id, None, layout_chan, window_size,
+ load_data.url.clone());
+ script_task.start_page_load(new_load, load_data);
+
script_task.start();
// This must always be the very last operation performed before the task completes
@@ -312,9 +348,7 @@ unsafe extern "C" fn debug_gc_callback(_rt: *mut JSRuntime, status: JSGCStatus)
impl ScriptTask {
/// Creates a new script task.
- pub fn new(id: PipelineId,
- compositor: Box<ScriptListener+'static>,
- layout_chan: LayoutChan,
+ pub fn new(compositor: Box<ScriptListener+'static>,
port: Receiver<ScriptMsg>,
chan: NonWorkerScriptChan,
control_chan: ScriptControlChan,
@@ -323,8 +357,7 @@ impl ScriptTask {
resource_task: ResourceTask,
storage_task: StorageTask,
img_cache_task: ImageCacheTask,
- devtools_chan: Option<DevtoolsControlChan>,
- window_size: WindowSizeData)
+ devtools_chan: Option<DevtoolsControlChan>)
-> ScriptTask {
let (js_runtime, js_context) = ScriptTask::new_rt_and_cx();
let wrap_for_same_compartment = wrap_for_same_compartment as
@@ -348,19 +381,14 @@ impl ScriptTask {
Some(pre_wrap));
}
- let page = Page::new(id, None, layout_chan, window_size,
- resource_task.clone(),
- storage_task,
- constellation_chan.clone(),
- js_context.clone(),
- devtools_chan.clone());
-
let (devtools_sender, devtools_receiver) = channel();
ScriptTask {
- page: DOMRefCell::new(Rc::new(page)),
+ page: DOMRefCell::new(None),
+ incomplete_loads: DOMRefCell::new(vec!()),
image_cache_task: img_cache_task,
resource_task: resource_task,
+ storage_task: storage_task,
port: port,
chan: chan,
@@ -417,6 +445,10 @@ impl ScriptTask {
(js_runtime, js_context)
}
+ fn root_page(&self) -> Rc<Page> {
+ self.page.borrow().as_ref().unwrap().clone()
+ }
+
pub fn get_cx(&self) -> *mut JSContext {
(**self.js_context.borrow().as_ref().unwrap()).ptr
}
@@ -439,17 +471,19 @@ impl ScriptTask {
let mut resizes = vec!();
{
- let page = self.page.borrow_mut();
- for page in page.iter() {
- // Only process a resize if layout is idle.
- let layout_join_port = page.layout_join_port.borrow();
- if layout_join_port.is_none() {
- let mut resize_event = page.resize_event.get();
- match resize_event.take() {
- Some(size) => resizes.push((page.id, size)),
- None => ()
+ let page = self.page.borrow();
+ if let Some(ref page) = page.as_ref() {
+ for page in page.iter() {
+ // Only process a resize if layout is idle.
+ let layout_join_port = page.layout_join_port.borrow();
+ if layout_join_port.is_none() {
+ let mut resize_event = page.resize_event.get();
+ match resize_event.take() {
+ Some(size) => resizes.push((page.id, size)),
+ None => ()
+ }
+ page.resize_event.set(None);
}
- page.resize_event.set(None);
}
}
}
@@ -502,17 +536,10 @@ impl ScriptTask {
self.handle_new_layout(new_layout_info);
}
MixedMessage::FromConstellation(ConstellationControlMsg::Resize(id, size)) => {
- let page = self.page.borrow_mut();
- let page = page.find(id).expect("resize sent to nonexistent pipeline");
- page.resize_event.set(Some(size));
+ self.handle_resize(id, size);
}
MixedMessage::FromConstellation(ConstellationControlMsg::Viewport(id, rect)) => {
- let page = self.page.borrow_mut();
- let inner_page = page.find(id).expect("Page rect message sent to nonexistent pipeline");
- if inner_page.set_page_clip_rect_with_new_viewport(rect) {
- let page = get_page(&*page, id);
- self.force_reflow(&*page);
- }
+ self.handle_viewport(id, rect);
}
_ => {
sequential.push(event);
@@ -555,8 +582,8 @@ impl ScriptTask {
match msg {
ConstellationControlMsg::AttachLayout(_) =>
panic!("should have handled AttachLayout already"),
- ConstellationControlMsg::Load(id, parent, load_data) =>
- self.load(id, parent, load_data),
+ ConstellationControlMsg::Activate(id) =>
+ self.handle_activate(id),
ConstellationControlMsg::SendEvent(id, event) =>
self.handle_event(id, event),
ConstellationControlMsg::ReflowComplete(id, reflow_id) =>
@@ -598,57 +625,91 @@ impl ScriptTask {
runnable.handler(),
ScriptMsg::RefcountCleanup(addr) =>
LiveDOMReferences::cleanup(self.get_cx(), addr),
+ ScriptMsg::PageFetchComplete(id, subpage, response) =>
+ self.handle_page_fetch_complete(id, subpage, response),
}
}
fn handle_msg_from_devtools(&self, msg: DevtoolScriptControlMsg) {
+ let page = self.root_page();
match msg {
DevtoolScriptControlMsg::EvaluateJS(id, s, reply) =>
- devtools::handle_evaluate_js(&*self.page.borrow(), id, s, reply),
+ devtools::handle_evaluate_js(&page, id, s, reply),
DevtoolScriptControlMsg::GetRootNode(id, reply) =>
- devtools::handle_get_root_node(&*self.page.borrow(), id, reply),
+ devtools::handle_get_root_node(&page, id, reply),
DevtoolScriptControlMsg::GetDocumentElement(id, reply) =>
- devtools::handle_get_document_element(&*self.page.borrow(), id, reply),
+ devtools::handle_get_document_element(&page, id, reply),
DevtoolScriptControlMsg::GetChildren(id, node_id, reply) =>
- devtools::handle_get_children(&*self.page.borrow(), id, node_id, reply),
+ devtools::handle_get_children(&page, id, node_id, reply),
DevtoolScriptControlMsg::GetLayout(id, node_id, reply) =>
- devtools::handle_get_layout(&*self.page.borrow(), id, node_id, reply),
+ devtools::handle_get_layout(&page, id, node_id, reply),
DevtoolScriptControlMsg::ModifyAttribute(id, node_id, modifications) =>
- devtools::handle_modify_attribute(&*self.page.borrow(), id, node_id, modifications),
+ devtools::handle_modify_attribute(&page, id, node_id, modifications),
DevtoolScriptControlMsg::WantsLiveNotifications(pipeline_id, to_send) =>
- devtools::handle_wants_live_notifications(&*self.page.borrow(), pipeline_id, to_send),
+ devtools::handle_wants_live_notifications(&page, pipeline_id, to_send),
+ }
+ }
+
+ fn handle_resize(&self, id: PipelineId, size: WindowSizeData) {
+ let page = self.page.borrow();
+ if let Some(ref page) = page.as_ref() {
+ if let Some(ref page) = page.find(id) {
+ page.resize_event.set(Some(size));
+ return;
+ }
+ }
+ let mut loads = self.incomplete_loads.borrow_mut();
+ if let Some(ref mut load) = loads.iter_mut().find(|load| load.pipeline_id == id) {
+ load.window_size = size;
+ return;
}
+ panic!("resize sent to nonexistent pipeline");
}
+ fn handle_viewport(&self, id: PipelineId, rect: Rect<f32>) {
+ let page = self.page.borrow();
+ if let Some(page) = page.as_ref() {
+ if let Some(ref inner_page) = page.find(id) {
+ if inner_page.set_page_clip_rect_with_new_viewport(rect) {
+ let page = get_page(page, id);
+ self.force_reflow(&*page);
+ }
+ return;
+ }
+ }
+ let mut loads = self.incomplete_loads.borrow_mut();
+ if let Some(ref mut load) = loads.iter_mut().find(|load| load.pipeline_id == id) {
+ load.clip_rect = Some(rect);
+ return;
+ }
+ panic!("Page rect message sent to nonexistent pipeline");
+ }
+
fn handle_new_layout(&self, new_layout_info: NewLayoutInfo) {
let NewLayoutInfo {
old_pipeline_id,
new_pipeline_id,
subpage_id,
- layout_chan
+ layout_chan,
+ load_data,
} = new_layout_info;
- let page = self.page.borrow_mut();
+ let page = self.root_page();
let parent_page = page.find(old_pipeline_id).expect("ScriptTask: received a layout
whose parent has a PipelineId which does not correspond to a pipeline in the script
task's page tree. This is a bug.");
- let new_page = {
- let window_size = parent_page.window_size.get();
- Page::new(new_pipeline_id, Some(subpage_id),
- LayoutChan(layout_chan.downcast_ref::<Sender<layout_interface::Msg>>().unwrap().clone()),
- window_size,
- parent_page.resource_task.clone(),
- parent_page.storage_task.clone(),
- self.constellation_chan.clone(),
- self.js_context.borrow().as_ref().unwrap().clone(),
- self.devtools_chan.clone())
- };
- parent_page.children.borrow_mut().push(Rc::new(new_page));
+
+ let chan = layout_chan.downcast_ref::<Sender<layout_interface::Msg>>().unwrap();
+ let layout_chan = LayoutChan(chan.clone());
+ let new_load = InProgressLoad::new(new_pipeline_id, Some((old_pipeline_id, subpage_id)),
+ layout_chan, parent_page.window_size.get(),
+ load_data.url.clone());
+ self.start_page_load(new_load, load_data);
}
/// Handles a timer that fired.
fn handle_fire_timer_msg(&self, id: PipelineId, timer_id: TimerId) {
- let page = self.page.borrow_mut();
+ let page = self.root_page();
let page = page.find(id).expect("ScriptTask: received fire timer msg for a
pipeline ID not associated with this script task. This is a bug.");
let frame = page.frame();
@@ -658,7 +719,7 @@ impl ScriptTask {
/// Handles freeze message
fn handle_freeze_msg(&self, id: PipelineId) {
- let page = self.page.borrow_mut();
+ let page = self.root_page();
let page = page.find(id).expect("ScriptTask: received freeze msg for a
pipeline ID not associated with this script task. This is a bug.");
let frame = page.frame();
@@ -668,7 +729,7 @@ impl ScriptTask {
/// Handles thaw message
fn handle_thaw_msg(&self, id: PipelineId) {
- let page = self.page.borrow_mut();
+ let page = self.root_page();
let page = page.find(id).expect("ScriptTask: received thaw msg for a
pipeline ID not associated with this script task. This is a bug.");
let frame = page.frame();
@@ -676,10 +737,26 @@ impl ScriptTask {
window.r().thaw();
}
+ fn handle_activate(&self, pipeline_id: PipelineId) {
+ // We should only get this message when moving in history, so all pages requested
+ // should exist.
+ let page = self.root_page().find(pipeline_id).unwrap();
+
+ // Pull out the `needs_reflow` flag explicitly because `reflow` can ask for the
+ // page's URL, and we can't be holding a borrow on that URL (#4402).
+ let needed_reflow = {
+ let &mut (_, ref mut needs_reflow) = &mut *page.mut_url();
+ replace(needs_reflow, false)
+ };
+ if needed_reflow {
+ self.force_reflow(&*page);
+ }
+ }
+
/// Handles a notification that reflow completed.
fn handle_reflow_complete_msg(&self, pipeline_id: PipelineId, reflow_id: uint) {
debug!("Script: Reflow {:?} complete for {:?}", reflow_id, pipeline_id);
- let page = self.page.borrow_mut();
+ let page = self.root_page();
let page = page.find(pipeline_id).expect(
"ScriptTask: received a load message for a layout channel that is not associated \
with this script task. This is a bug.");
@@ -700,13 +777,12 @@ impl ScriptTask {
/// Window was resized, but this script was not active, so don't reflow yet
fn handle_resize_inactive_msg(&self, id: PipelineId, new_size: WindowSizeData) {
- let page = self.page.borrow_mut();
+ let page = self.root_page();
let page = page.find(id).expect("Received resize message for PipelineId not associated
with a page in the page tree. This is a bug.");
page.window_size.set(new_size);
match &mut *page.mut_url() {
- &mut Some((_, ref mut needs_reflow)) => *needs_reflow = true,
- &mut None => (),
+ &mut (_, ref mut needs_reflow) => *needs_reflow = true,
}
}
@@ -724,20 +800,29 @@ impl ScriptTask {
self.compositor.borrow_mut().close();
}
+ fn handle_page_fetch_complete(&self, id: PipelineId, subpage: Option<SubpageId>,
+ response: LoadResponse) {
+ let idx = self.incomplete_loads.borrow().iter().position(|&:load| {
+ load.pipeline_id == id && load.subpage_id.map(|sub| sub.1) == subpage
+ }).unwrap();
+ let load = self.incomplete_loads.borrow_mut().remove(idx);
+ self.load(response, load);
+ }
+
/// Handles a request for the window title.
fn handle_get_title_msg(&self, pipeline_id: PipelineId) {
- get_page(&*self.page.borrow(), pipeline_id).send_title_to_compositor();
+ get_page(&self.root_page(), pipeline_id).send_title_to_compositor();
}
/// Handles a request to exit the script task and shut down layout.
/// Returns true if the script task should shut down and false otherwise.
fn handle_exit_pipeline_msg(&self, id: PipelineId, exit_type: PipelineExitType) -> bool {
// If root is being exited, shut down all pages
- let page = self.page.borrow_mut();
+ let page = self.root_page();
if page.id == id {
debug!("shutting down layout for root page {:?}", id);
*self.js_context.borrow_mut() = None;
- shut_down_layout(&*page, (*self.js_runtime).ptr, exit_type);
+ shut_down_layout(&page, (*self.js_runtime).ptr, exit_type);
return true
}
@@ -758,98 +843,56 @@ impl ScriptTask {
/// The entry point to document loading. Defines bindings, sets up the window and document
/// objects, parses HTML and CSS, and kicks off initial layout.
- fn load(&self, pipeline_id: PipelineId,
- parent: Option<(PipelineId, SubpageId)>, load_data: LoadData) {
- let url = load_data.url.clone();
- debug!("ScriptTask: loading {} on page {:?}", url.serialize(), pipeline_id);
-
- let borrowed_page = self.page.borrow_mut();
-
- let frame_element = parent.and_then(|(parent_id, subpage_id)| {
- // In the case a parent id exists but the matching page
- // cannot be found, this means the page exists in a different
- // script task (due to origin) so it shouldn't be returned.
- // TODO: window.parent will continue to return self in that
- // case, which is wrong. We should be returning an object that
- // denies access to most properties (per
- // https://github.com/servo/servo/issues/3939#issuecomment-62287025).
- borrowed_page.find(parent_id).and_then(|page| {
- let doc = page.frame().as_ref().unwrap().document.root();
- let doc: JSRef<Node> = NodeCast::from_ref(doc.r());
-
- doc.traverse_preorder()
- .filter_map(HTMLIFrameElementCast::to_ref)
- .find(|node| node.subpage_id() == Some(subpage_id))
- .map(ElementCast::from_ref)
- .map(Temporary::from_rooted)
- })
+ fn load(&self, response: LoadResponse, incomplete: InProgressLoad) {
+ let final_url = response.metadata.final_url.clone();
+ debug!("ScriptTask: loading {} on page {:?}", incomplete.url.serialize(), incomplete.pipeline_id);
+
+ let root_page_exists = self.page.borrow().is_none();
+ assert!(incomplete.subpage_id.is_none() || root_page_exists);
+
+ let frame_element = incomplete.subpage_id.and_then(|(parent_id, subpage_id)| {
+ let borrowed_page = self.root_page();
+ // In the case a parent id exists but the matching page
+ // cannot be found, this means the page exists in a different
+ // script task (due to origin) so it shouldn't be returned.
+ // TODO: window.parent will continue to return self in that
+ // case, which is wrong. We should be returning an object that
+ // denies access to most properties (per
+ // https://github.com/servo/servo/issues/3939#issuecomment-62287025).
+ borrowed_page.find(parent_id).and_then(|page| {
+ let doc = page.frame().as_ref().unwrap().document.root();
+ let doc: JSRef<Node> = NodeCast::from_ref(doc.r());
+
+ doc.traverse_preorder()
+ .filter_map(HTMLIFrameElementCast::to_ref)
+ .find(|node| node.subpage_id() == Some(subpage_id))
+ .map(ElementCast::from_ref)
+ .map(Temporary::from_rooted)
+ })
}).root();
- let page = borrowed_page.find(pipeline_id).expect("ScriptTask: received a load
- message for a layout channel that is not associated with this script task. This
- is a bug.");
-
- // Are we reloading?
- let reloading = match *page.url() {
- Some((ref loaded, _)) => *loaded == url,
- _ => false,
- };
- if reloading {
- // Pull out the `needs_reflow` flag explicitly because `reflow` can ask for the page's
- // URL, and we can't be holding a borrow on that URL (#4402).
- let needed_reflow = match &mut *page.mut_url() {
- &mut Some((_, ref mut needs_reflow)) => replace(needs_reflow, false),
- _ => panic!("can't reload a page with no URL!")
- };
- if needed_reflow {
- self.force_reflow(&*page);
- }
- return
- }
- let last_url = replace(&mut *page.mut_url(), None).map(|(last_url, _)| last_url);
-
- let is_javascript = url.scheme.as_slice() == "javascript";
-
- self.compositor.borrow_mut().set_ready_state(pipeline_id, Loading);
-
- let (mut parser_input, final_url, last_modified) = if !is_javascript {
- // Wait for the LoadResponse so that the parser knows the final URL.
- let (input_chan, input_port) = channel();
- self.resource_task.send(ControlMsg::Load(NetLoadData {
- url: url,
- method: load_data.method,
- headers: Headers::new(),
- preserved_headers: load_data.headers,
- data: load_data.data,
- cors: None,
- consumer: input_chan,
- })).unwrap();
-
- let load_response = input_port.recv().unwrap();
+ self.compositor.borrow_mut().set_ready_state(incomplete.pipeline_id, Loading);
- let last_modified = load_response.metadata.headers.as_ref().and_then(|headers| {
- headers.get().map(|&LastModified(ref tm)| tm.clone())
- });
-
- let final_url = load_response.metadata.final_url.clone();
+ let last_modified = response.metadata.headers.as_ref().and_then(|headers| {
+ headers.get().map(|&LastModified(ref tm)| tm.clone())
+ });
- (Some(HTMLInput::InputUrl(load_response)), final_url, last_modified)
- } else {
- let doc_url = last_url.unwrap_or_else(|| {
- Url::parse("about:blank").unwrap()
- });
- (None, doc_url, None)
- };
+ let cx = self.js_context.borrow();
+ let cx = cx.as_ref().unwrap();
- // Store the final URL before we start parsing, so that DOM routines
- // (e.g. HTMLImageElement::update_image) can resolve relative URLs
- // correctly.
- {
- *page.mut_url() = Some((final_url.clone(), true));
+ let page = Rc::new(Page::new(incomplete.pipeline_id, incomplete.subpage_id.map(|p| p.1),
+ incomplete.layout_chan, incomplete.window_size,
+ self.resource_task.clone(), self.storage_task.clone(),
+ self.constellation_chan.clone(), cx.clone(),
+ self.devtools_chan.clone(), final_url.clone()));
+ if root_page_exists {
+ *self.page.borrow_mut() = Some(page.clone());
+ } else if let Some((parent, _)) = incomplete.subpage_id {
+ let parent_page = self.root_page();
+ parent_page.find(parent).expect("received load for subpage with missing parent");
+ parent_page.children.borrow_mut().push(page.clone());
}
- let cx = self.js_context.borrow();
- let cx = cx.as_ref().unwrap();
// Create the window and document objects.
let window = Window::new(cx.ptr,
page.clone(),
@@ -876,18 +919,21 @@ impl ScriptTask {
});
}
- if is_javascript {
- let evalstr = load_data.url.non_relative_scheme_data().unwrap();
+ let is_javascript = incomplete.url.scheme.as_slice() == "javascript";
+ let parse_input = if is_javascript {
+ let evalstr = incomplete.url.non_relative_scheme_data().unwrap();
let jsval = window.r().evaluate_js_on_global_with_result(evalstr);
let strval = FromJSValConvertible::from_jsval(self.get_cx(), jsval,
StringificationBehavior::Empty);
- parser_input = Some(HTMLInput::InputString(strval.unwrap_or("".to_owned())));
+ HTMLInput::InputString(strval.unwrap_or("".to_owned()))
+ } else {
+ HTMLInput::InputUrl(response)
};
- parse_html(document.r(), parser_input.unwrap(), &final_url);
+ parse_html(document.r(), parse_input, &final_url);
document.r().set_ready_state(DocumentReadyState::Interactive);
- self.compositor.borrow_mut().set_ready_state(pipeline_id, PerformingLayout);
+ self.compositor.borrow_mut().set_ready_state(incomplete.pipeline_id, PerformingLayout);
// Kick off the initial reflow of the page.
debug!("kicking off initial reflow of {:?}", final_url);
@@ -898,7 +944,7 @@ impl ScriptTask {
{
// No more reflow required
let mut page_url = page.mut_url();
- *page_url = Some((final_url.clone(), false));
+ (*page_url).1 = false;
}
// https://html.spec.whatwg.org/multipage/#the-end step 4
@@ -927,7 +973,7 @@ impl ScriptTask {
title: document.r().Title(),
url: final_url
};
- chan.send(DevtoolsControlMsg::NewGlobal(pipeline_id,
+ chan.send(DevtoolsControlMsg::NewGlobal(incomplete.pipeline_id,
self.devtools_sender.clone(),
page_info)).unwrap();
}
@@ -978,7 +1024,7 @@ impl ScriptTask {
for node in nodes.iter() {
let node_to_dirty = node::from_untrusted_node_address(self.js_runtime.ptr,
*node).root();
- let page = get_page(&*self.page.borrow(), pipeline_id);
+ let page = get_page(&self.root_page(), pipeline_id);
let frame = page.frame();
let document = frame.as_ref().unwrap().document.root();
document.r().content_changed(node_to_dirty.r(),
@@ -989,7 +1035,7 @@ impl ScriptTask {
}
ClickEvent(_button, point) => {
- let page = get_page(&*self.page.borrow(), pipeline_id);
+ let page = get_page(&self.root_page(), pipeline_id);
let frame = page.frame();
let document = frame.as_ref().unwrap().document.root();
document.r().handle_click_event(self.js_runtime.ptr, _button, point);
@@ -998,7 +1044,7 @@ impl ScriptTask {
MouseDownEvent(..) => {}
MouseUpEvent(..) => {}
MouseMoveEvent(point) => {
- let page = get_page(&*self.page.borrow(), pipeline_id);
+ let page = get_page(&self.root_page(), pipeline_id);
let frame = page.frame();
let document = frame.as_ref().unwrap().document.root();
let mouse_over_targets = &mut *self.mouse_over_targets.borrow_mut();
@@ -1009,7 +1055,7 @@ impl ScriptTask {
}
KeyEvent(key, state, modifiers) => {
- let page = get_page(&*self.page.borrow(), pipeline_id);
+ let page = get_page(&self.root_page(), pipeline_id);
let frame = page.frame();
let document = frame.as_ref().unwrap().document.root();
document.r().dispatch_key_event(
@@ -1028,7 +1074,7 @@ impl ScriptTask {
/// The entry point for content to notify that a fragment url has been requested
/// for the given pipeline.
fn trigger_fragment(&self, pipeline_id: PipelineId, fragment: String) {
- let page = get_page(&*self.page.borrow(), pipeline_id);
+ let page = get_page(&self.root_page(), pipeline_id);
match page.find_fragment_node(fragment).root() {
Some(node) => {
self.scroll_fragment_point(pipeline_id, node.r());
@@ -1040,7 +1086,7 @@ impl ScriptTask {
fn handle_resize_event(&self, pipeline_id: PipelineId, new_size: WindowSizeData) {
let window = {
- let page = get_page(&*self.page.borrow(), pipeline_id);
+ let page = get_page(&self.root_page(), pipeline_id);
page.window_size.set(new_size);
let frame = page.frame();
@@ -1081,12 +1127,42 @@ impl ScriptTask {
fn handle_reflow_event(&self, pipeline_id: PipelineId) {
debug!("script got reflow event");
- let page = get_page(&*self.page.borrow(), pipeline_id);
+ let page = get_page(&self.root_page(), pipeline_id);
let frame = page.frame();
if frame.is_some() {
self.force_reflow(&*page);
}
}
+
+ fn start_page_load(&self, incomplete: InProgressLoad, mut load_data: LoadData) {
+ let id = incomplete.pipeline_id.clone();
+ let subpage = incomplete.subpage_id.clone().map(|p| p.1);
+
+ let script_chan = self.chan.clone();
+ let resource_task = self.resource_task.clone();
+
+ spawn_named(format!("fetch for {:?}", load_data.url), move || {
+ if load_data.url.scheme.as_slice() == "javascript" {
+ load_data.url = Url::parse("about:blank").unwrap();
+ }
+
+ let (input_chan, input_port) = channel();
+ resource_task.send(ControlMsg::Load(NetLoadData {
+ url: load_data.url,
+ method: load_data.method,
+ headers: Headers::new(),
+ preserved_headers: load_data.headers,
+ data: load_data.data,
+ cors: None,
+ consumer: input_chan,
+ })).unwrap();
+
+ let load_response = input_port.recv().unwrap();
+ script_chan.send(ScriptMsg::PageFetchComplete(id, subpage, load_response)).unwrap();
+ });
+
+ self.incomplete_loads.borrow_mut().push(incomplete);
+ }
}
/// Shuts down layout for the given page tree.