diff options
Diffstat (limited to 'components/script/script_task.rs')
-rw-r--r-- | components/script/script_task.rs | 422 |
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. |