From 2348fbf46dbd8a90e3edc0d7a6c6ba704273b3c7 Mon Sep 17 00:00:00 2001 From: Tim Kuehn Date: Tue, 30 Jul 2013 16:13:04 -0700 Subject: [PATCH] added subpage ids to map from iframe to all associated pipelines --- src/components/main/constellation.rs | 61 +++++++++---------- src/components/main/pipeline.rs | 23 ++++--- src/components/msg/constellation_msg.rs | 4 +- src/components/script/dom/element.rs | 3 + .../script/html/hubbub_html_parser.rs | 17 +++++- src/components/script/script_task.rs | 10 +-- 6 files changed, 71 insertions(+), 47 deletions(-) diff --git a/src/components/main/constellation.rs b/src/components/main/constellation.rs index b5783533da9..dac5d743198 100644 --- a/src/components/main/constellation.rs +++ b/src/components/main/constellation.rs @@ -269,7 +269,7 @@ impl Constellation { /// Helper function for getting a unique pipeline Id fn get_next_pipeline_id(&mut self) -> PipelineId { let id = self.next_pipeline_id; - self.next_pipeline_id = PipelineId(*id + 1); + *self.next_pipeline_id += 1; id } @@ -297,16 +297,17 @@ impl Constellation { // This should only be called once per constellation, and only by the browser InitLoadUrlMsg(url) => { let pipeline = @mut Pipeline::create(self.get_next_pipeline_id(), - self.chan.clone(), - self.compositor_chan.clone(), - self.image_cache_task.clone(), - self.resource_task.clone(), - self.profiler_chan.clone(), - copy self.opts, - { - let size = self.compositor_chan.get_size(); - from_value(Size2D(size.width as uint, size.height as uint)) - }); + None, + self.chan.clone(), + self.compositor_chan.clone(), + self.image_cache_task.clone(), + self.resource_task.clone(), + self.profiler_chan.clone(), + copy self.opts, + { + let size = self.compositor_chan.get_size(); + from_value(Size2D(size.width as uint, size.height as uint)) + }); if url.path.ends_with(".js") { pipeline.script_chan.send(ExecuteMsg(pipeline.id, url)); } else { @@ -324,7 +325,7 @@ impl Constellation { self.pipelines.insert(pipeline.id, pipeline); } - LoadIframeUrlMsg(url, source_pipeline_id, size_future) => { + LoadIframeUrlMsg(url, source_pipeline_id, subpage_id, size_future) => { // A message from the script associated with pipeline_id that it has // parsed an iframe during html parsing. This iframe will result in a // new pipeline being spawned and a frame tree being added to pipeline_id's @@ -368,6 +369,7 @@ impl Constellation { source_url.port == url.port) { // Reuse the script task if same-origin url's Pipeline::with_script(next_pipeline_id, + Some(subpage_id), self.chan.clone(), self.compositor_chan.clone(), self.image_cache_task.clone(), @@ -378,6 +380,7 @@ impl Constellation { } else { // Create a new script task if not same-origin url's Pipeline::create(next_pipeline_id, + Some(subpage_id), self.chan.clone(), self.compositor_chan.clone(), self.image_cache_task.clone(), @@ -421,33 +424,29 @@ impl Constellation { // Being here means either there are no pending frames, or none of the pending // changes would be overriden by changing the subframe associated with source_id. + let source_frame = self.current_frame().get_ref().find_mut(source_id).expect( + "Constellation: received a LoadUrlMsg from a pipeline_id associated + with a pipeline not in the active frame tree. This should be + impossible."); + let parent = source_frame.parent.clone(); + let subpage_id = source_frame.pipeline.subpage_id.clone(); let next_pipeline_id = self.get_next_pipeline_id(); + let pipeline = @mut Pipeline::create(next_pipeline_id, - self.chan.clone(), - self.compositor_chan.clone(), - self.image_cache_task.clone(), - self.resource_task.clone(), - self.profiler_chan.clone(), - copy self.opts, - size_future); + subpage_id, + self.chan.clone(), + self.compositor_chan.clone(), + self.image_cache_task.clone(), + self.resource_task.clone(), + self.profiler_chan.clone(), + copy self.opts, + size_future); if url.path.ends_with(".js") { pipeline.script_chan.send(ExecuteMsg(pipeline.id, url)); } else { pipeline.load(url, Some(constellation_msg::Load)); - let parent = if self.current_frame().get_ref().pipeline.id == source_id { - // source_id is the root of the current frame tree; replace whole tree - None - } else { - // id is not the root of the current frame tree, but is in the frame tree; - // replace only the subtree - let source_frame = self.current_frame().get_ref().find_mut(source_id).expect( - "Constellation: received a LoadUrlMsg from a pipeline_id associated - with a pipeline not in the active frame tree. This should be - impossible."); - source_frame.parent - }; self.pending_frames.push(FrameChange{ before: Some(source_id), after: @mut FrameTree { diff --git a/src/components/main/pipeline.rs b/src/components/main/pipeline.rs index ec17e01ef21..1ea7965b02a 100644 --- a/src/components/main/pipeline.rs +++ b/src/components/main/pipeline.rs @@ -11,7 +11,7 @@ use gfx::opts::Opts; use layout::layout_task::LayoutTask; use script::layout_interface::LayoutChan; use script::script_task::{ExecuteMsg, LoadMsg}; -use servo_msg::constellation_msg::{ConstellationChan, NavigationType, PipelineId}; +use servo_msg::constellation_msg::{ConstellationChan, NavigationType, PipelineId, SubpageId}; use script::script_task::{AttachLayoutMsg, NewLayoutInfo, ScriptTask, ScriptChan}; use script::script_task; use servo_net::image_cache_task::ImageCacheTask; @@ -25,6 +25,7 @@ use std::comm; #[deriving(Clone)] pub struct Pipeline { id: PipelineId, + subpage_id: Option, script_chan: ScriptChan, layout_chan: LayoutChan, render_chan: RenderChan, @@ -36,13 +37,14 @@ pub struct Pipeline { impl Pipeline { /// Starts a render task, layout task, and script task. Returns the channels wrapped in a struct. pub fn with_script(id: PipelineId, - constellation_chan: ConstellationChan, - compositor_chan: CompositorChan, - image_cache_task: ImageCacheTask, - profiler_chan: ProfilerChan, - opts: Opts, - script_pipeline: &Pipeline, - size_future: Future>) -> Pipeline { + subpage_id: Option, + constellation_chan: ConstellationChan, + compositor_chan: CompositorChan, + image_cache_task: ImageCacheTask, + profiler_chan: ProfilerChan, + opts: Opts, + script_pipeline: &Pipeline, + size_future: Future>) -> Pipeline { let (layout_port, layout_chan) = special_stream!(LayoutChan); let (render_port, render_chan) = special_stream!(RenderChan); @@ -72,6 +74,7 @@ impl Pipeline { script_pipeline.script_chan.send(AttachLayoutMsg(new_layout_info)); Pipeline::new(id, + subpage_id, script_pipeline.script_chan.clone(), layout_chan, render_chan) @@ -79,6 +82,7 @@ impl Pipeline { } pub fn create(id: PipelineId, + subpage_id: Option, constellation_chan: ConstellationChan, compositor_chan: CompositorChan, image_cache_task: ImageCacheTask, @@ -117,18 +121,21 @@ impl Pipeline { copy opts, profiler_chan); Pipeline::new(id, + subpage_id, script_chan, layout_chan, render_chan) } pub fn new(id: PipelineId, + subpage_id: Option, script_chan: ScriptChan, layout_chan: LayoutChan, render_chan: RenderChan) -> Pipeline { Pipeline { id: id, + subpage_id: subpage_id, script_chan: script_chan, layout_chan: layout_chan, render_chan: render_chan, diff --git a/src/components/msg/constellation_msg.rs b/src/components/msg/constellation_msg.rs index 6f71f8a0454..419aadf1ae3 100644 --- a/src/components/msg/constellation_msg.rs +++ b/src/components/msg/constellation_msg.rs @@ -30,7 +30,7 @@ pub enum Msg { ExitMsg(Chan<()>), InitLoadUrlMsg(Url), LoadUrlMsg(PipelineId, Url, Future>), - LoadIframeUrlMsg(Url, PipelineId, Future>), + LoadIframeUrlMsg(Url, PipelineId, SubpageId, Future>), NavigateMsg(NavigationDirection), RendererReadyMsg(PipelineId), ResizedWindowBroadcast(Size2D), @@ -51,3 +51,5 @@ pub enum NavigationDirection { #[deriving(Clone, Eq, IterBytes)] pub struct PipelineId(uint); +#[deriving(Clone, Eq, IterBytes)] +pub struct SubpageId(uint); diff --git a/src/components/script/dom/element.rs b/src/components/script/dom/element.rs index 7f42230b61b..ac60914db1c 100644 --- a/src/components/script/dom/element.rs +++ b/src/components/script/dom/element.rs @@ -18,6 +18,8 @@ use std::str::eq_slice; use extra::net::url::Url; use geom::size::Size2D; +use servo_msg::constellation_msg::SubpageId; + pub struct Element { parent: Node, tag_name: ~str, // TODO: This should be an atom, not a ~str. @@ -112,6 +114,7 @@ pub struct HTMLHeadingElement { pub struct HTMLIframeElement { parent: Element, frame: Option, + subpage_id: Option, size_future_chan: Option>>, } diff --git a/src/components/script/html/hubbub_html_parser.rs b/src/components/script/html/hubbub_html_parser.rs index d3b94d2fe3f..2ecf58dcb45 100644 --- a/src/components/script/html/hubbub_html_parser.rs +++ b/src/components/script/html/hubbub_html_parser.rs @@ -42,6 +42,7 @@ use std::str::eq_slice; use std::result; use std::task; use hubbub::hubbub; +use servo_msg::constellation_msg::SubpageId; use servo_net::image_cache_task::ImageCacheTask; use servo_net::image_cache_task; use servo_net::resource_task::{Done, Load, Payload, ResourceTask}; @@ -83,7 +84,7 @@ enum JSMessage { pub struct HtmlParserResult { root: AbstractNode, style_port: Port, - iframe_port: Port<(Url, Future>)>, + iframe_port: Port<(Url, SubpageId, Future>)>, js_port: Port, } @@ -222,7 +223,7 @@ fn build_element_from_tag(cx: *JSContext, tag: &str) -> AbstractNode handle_element!(cx, tag, "ul", HTMLUListElementTypeId, HTMLUListElement, []); handle_element!(cx, tag, "img", HTMLImageElementTypeId, HTMLImageElement, [(image: None)]); - handle_element!(cx, tag, "iframe", HTMLIframeElementTypeId, HTMLIframeElement, [(frame: None), (size_future_chan: None)]); + handle_element!(cx, tag, "iframe", HTMLIframeElementTypeId, HTMLIframeElement, [(frame: None), (size_future_chan: None), (subpage_id: None)]); handle_element!(cx, tag, "h1", HTMLHeadingElementTypeId, HTMLHeadingElement, [(level: Heading1)]); handle_element!(cx, tag, "h2", HTMLHeadingElementTypeId, HTMLHeadingElement, [(level: Heading2)]); @@ -281,6 +282,8 @@ pub fn parse_html(cx: *JSContext, let (css_chan2, css_chan3, js_chan2) = (css_chan.clone(), css_chan.clone(), js_chan.clone()); let (iframe_port, iframe_chan) = comm::stream(); + let next_subpage_id = Cell::new(SubpageId(0)); + parser.set_tree_handler(~hubbub::TreeHandler { create_comment: |data: ~str| { debug!("create comment"); @@ -337,10 +340,18 @@ pub fn parse_html(cx: *JSContext, for src_opt.iter().advance |src| { let iframe_url = make_url(src.clone(), Some(url2.clone())); iframe_element.frame = Some(iframe_url.clone()); + + // Size future let (port, chan) = comm::oneshot(); iframe_element.size_future_chan = Some(chan); let size_future = from_port(port); - iframe_chan.send((iframe_url, size_future)); + + // Subpage Id + let subpage_id = next_subpage_id.take(); + iframe_element.subpage_id = Some(subpage_id); + next_subpage_id.put_back(SubpageId(*subpage_id + 1)); + + iframe_chan.send((iframe_url, subpage_id, size_future)); } } } diff --git a/src/components/script/script_task.rs b/src/components/script/script_task.rs index d5ba18b4402..203cbf0c55b 100644 --- a/src/components/script/script_task.rs +++ b/src/components/script/script_task.rs @@ -21,7 +21,7 @@ use layout_interface::{ReflowDocumentDamage, ReflowForDisplay, ReflowGoal}; use layout_interface::ReflowMsg; use layout_interface; use servo_msg::constellation_msg::{ConstellationChan, LoadUrlMsg, NavigationDirection}; -use servo_msg::constellation_msg::{PipelineId, RendererReadyMsg, ResizedWindowBroadcast}; +use servo_msg::constellation_msg::{PipelineId, SubpageId, RendererReadyMsg, ResizedWindowBroadcast}; use servo_msg::constellation_msg::{LoadIframeUrlMsg}; use servo_msg::constellation_msg; @@ -624,12 +624,13 @@ impl ScriptTask { // FIXME: These should be streamed to layout as they're parsed. We don't need to stop here // in the script task. - let get_iframes = |iframe_port: &Port<(Url, Future>)>| loop { + let get_iframes = |iframe_port: &Port<(Url, SubpageId, Future>)>| loop { match iframe_port.try_recv() { None => break, - Some((iframe_url, size_future)) => { + Some((iframe_url, subpage_id, size_future)) => { self.constellation_chan.send(LoadIframeUrlMsg(iframe_url, pipeline_id, + subpage_id, size_future)); } } @@ -652,9 +653,10 @@ impl ScriptTask { Left(Some(sheet)) => { page.layout_chan.send(AddStylesheetMsg(sheet)); } - Right(Some((iframe_url, size_future))) => { + Right(Some((iframe_url, subpage_id, size_future))) => { self.constellation_chan.send(LoadIframeUrlMsg(iframe_url, pipeline_id, + subpage_id, size_future)); } Right(None) => {