From 891d914b5ffdc25d2b3b43e8eed356f7cd722eda Mon Sep 17 00:00:00 2001 From: Glenn Watson Date: Tue, 29 Sep 2015 13:19:31 +1000 Subject: [PATCH 1/3] Remove SubpageId. This changes PipelineId to be a UUID and removes the concept of SubpageId. Iframes are now able to generate their own pipeline ID during navigation which simplifies a lot of logic in other parts of the code. Other parts of the code, such as the compositor and layout only ever deal with pipeline ids. --- components/compositing/constellation.rs | 193 +++++++++------------ components/compositing/pipeline.rs | 21 ++- components/devtools/lib.rs | 2 +- components/gfx/paint_task.rs | 2 +- components/layout/display_list_builder.rs | 6 +- components/layout/fragment.rs | 8 +- components/layout/layout_task.rs | 2 +- components/layout/wrapper.rs | 7 +- components/msg/Cargo.toml | 1 + components/msg/constellation_msg.rs | 50 ++++-- components/msg/lib.rs | 1 + components/msg/webdriver_msg.rs | 4 +- components/script/dom/bindings/trace.rs | 4 +- components/script/dom/document.rs | 10 +- components/script/dom/htmliframeelement.rs | 82 ++++----- components/script/dom/servohtmlparser.rs | 10 +- components/script/dom/window.rs | 22 +-- components/script/script_task.rs | 85 ++++----- components/script/webdriver_handlers.rs | 8 +- components/script_traits/lib.rs | 16 +- components/servo/Cargo.lock | 2 + components/util/Cargo.toml | 1 + components/util/lib.rs | 1 + components/util/mem.rs | 2 + components/webdriver_server/lib.rs | 4 +- 25 files changed, 252 insertions(+), 292 deletions(-) diff --git a/components/compositing/constellation.rs b/components/compositing/constellation.rs index 656a254d40e8..7dd70317b4d5 100644 --- a/components/compositing/constellation.rs +++ b/components/compositing/constellation.rs @@ -30,7 +30,7 @@ use msg::constellation_msg::WebDriverCommandMsg; use msg::constellation_msg::{FrameId, PipelineExitType, PipelineId}; use msg::constellation_msg::{IFrameSandboxState, MozBrowserEvent, NavigationDirection}; use msg::constellation_msg::{Key, KeyModifiers, KeyState, LoadData}; -use msg::constellation_msg::{SubpageId, WindowSizeData}; +use msg::constellation_msg::WindowSizeData; use msg::constellation_msg::{self, ConstellationChan, Failure}; use msg::webdriver_msg; use net_traits::image_cache_task::ImageCacheTask; @@ -94,18 +94,12 @@ pub struct Constellation { /// Maps from pipeline ID to the frame that contains it. pipeline_to_frame_map: HashMap, - /// Maps from a (parent pipeline, subpage) to the actual child pipeline ID. - subpage_map: HashMap<(PipelineId, SubpageId), PipelineId>, - /// A channel through which messages can be sent to the font cache. font_cache_task: FontCacheTask, /// ID of the root frame. root_frame_id: Option, - /// The next free ID to assign to a pipeline. - next_pipeline_id: PipelineId, - /// The next free ID to assign to a frame. next_frame_id: FrameId, @@ -256,9 +250,7 @@ impl Constellation { pipelines: HashMap::new(), frames: HashMap::new(), pipeline_to_frame_map: HashMap::new(), - subpage_map: HashMap::new(), pending_frames: vec!(), - next_pipeline_id: PipelineId(0), root_frame_id: None, next_frame_id: FrameId(0), focus_pipeline_id: None, @@ -297,20 +289,16 @@ impl Constellation { /// Helper function for creating a pipeline fn new_pipeline(&mut self, - parent_info: Option<(PipelineId, SubpageId)>, + new_pipeline_id: PipelineId, + parent_pipeline_id: Option, initial_window_rect: Option>, script_channel: Option>, - load_data: LoadData) - -> PipelineId { - let pipeline_id = self.next_pipeline_id; - let PipelineId(ref mut i) = self.next_pipeline_id; - *i += 1; - + load_data: LoadData) { let spawning_paint_only = script_channel.is_some(); let (pipeline, mut pipeline_content) = Pipeline::create::(InitialPipelineState { - id: pipeline_id, - parent_info: parent_info, + id: new_pipeline_id, + parent_info: parent_pipeline_id, constellation_chan: self.chan.clone(), compositor_proxy: self.compositor_proxy.clone_compositor_proxy(), devtools_chan: self.devtools_chan.clone(), @@ -334,9 +322,8 @@ impl Constellation { pipeline_content.start_all::(); } - assert!(!self.pipelines.contains_key(&pipeline_id)); - self.pipelines.insert(pipeline_id, pipeline); - pipeline_id + assert!(!self.pipelines.contains_key(&new_pipeline_id)); + self.pipelines.insert(new_pipeline_id, pipeline); } // Push a new (loading) pipeline to the list of pending frame changes @@ -398,23 +385,22 @@ impl Constellation { } // A layout assigned a size and position to a subframe. This needs to be reflected by // all frame trees in the navigation context containing the subframe. - ConstellationMsg::FrameRect(pipeline_id, subpage_id, rect) => { + ConstellationMsg::FrameRect(pipeline_id, rect) => { debug!("constellation got frame rect message"); - self.handle_frame_rect_msg(pipeline_id, subpage_id, Rect::from_untyped(&rect)); + self.handle_frame_rect_msg(pipeline_id, Rect::from_untyped(&rect)); } ConstellationMsg::ScriptLoadedURLInIFrame(url, - source_pipeline_id, - new_subpage_id, - old_subpage_id, + parent_pipeline_id, + new_pipeline_id, + old_pipeline_id, sandbox) => { - debug!("constellation got iframe URL load message {:?} {:?} {:?}", - source_pipeline_id, - old_subpage_id, - new_subpage_id); + debug!("constellation got iframe URL load message {:?} {:?}", + old_pipeline_id, + new_pipeline_id); self.handle_script_loaded_url_in_iframe_msg(url, - source_pipeline_id, - new_subpage_id, - old_subpage_id, + parent_pipeline_id, + new_pipeline_id, + old_pipeline_id, sandbox); } ConstellationMsg::SetCursor(cursor) => self.handle_set_cursor_msg(cursor), @@ -443,9 +429,9 @@ impl Constellation { self.handle_dom_load(pipeline_id) } // Handle a forward or back request - ConstellationMsg::Navigate(pipeline_info, direction) => { + ConstellationMsg::Navigate(pipeline_id, direction) => { debug!("constellation got navigation message"); - self.handle_navigate_msg(pipeline_info, direction); + self.handle_navigate_msg(pipeline_id, direction); } // Notification that painting has finished and is requesting permission to paint. ConstellationMsg::PainterReady(pipeline_id) => { @@ -464,21 +450,21 @@ impl Constellation { debug!("constellation got get-pipeline-title message"); self.handle_get_pipeline_title_msg(pipeline_id); } - ConstellationMsg::MozBrowserEvent(pipeline_id, - subpage_id, + ConstellationMsg::MozBrowserEvent(parent_pipeline_id, + pipeline_id, event) => { debug!("constellation got mozbrowser event message"); - self.handle_mozbrowser_event_msg(pipeline_id, - subpage_id, + self.handle_mozbrowser_event_msg(parent_pipeline_id, + pipeline_id, event); } ConstellationMsg::GetPipeline(frame_id, resp_chan) => { debug!("constellation got get root pipeline message"); self.handle_get_pipeline(frame_id, resp_chan); } - ConstellationMsg::GetFrame(parent_pipeline_id, subpage_id, resp_chan) => { + ConstellationMsg::GetFrame(pipeline_id, resp_chan) => { debug!("constellation got get root pipeline message"); - self.handle_get_frame(parent_pipeline_id, subpage_id, resp_chan); + self.handle_get_frame(pipeline_id, resp_chan); } ConstellationMsg::Focus(pipeline_id) => { debug!("constellation got focus message"); @@ -513,9 +499,9 @@ impl Constellation { let is_ready = self.handle_is_ready_to_save_image(pipeline_states); self.compositor_proxy.send(CompositorMsg::IsReadyToSaveImageReply(is_ready)); } - ConstellationMsg::RemoveIFrame(containing_pipeline_id, subpage_id) => { + ConstellationMsg::RemoveIFrame(pipeline_id) => { debug!("constellation got remove iframe message"); - self.handle_remove_iframe_msg(containing_pipeline_id, subpage_id); + self.handle_remove_iframe_msg(pipeline_id); } ConstellationMsg::NewFavicon(url) => { debug!("constellation got new favicon message"); @@ -558,7 +544,7 @@ impl Constellation { fn handle_failure_msg(&mut self, pipeline_id: PipelineId, - parent_info: Option<(PipelineId, SubpageId)>) { + parent_info: Option) { debug!("handling failure message from pipeline {:?}, {:?}", pipeline_id, parent_info); if opts::get().hard_fail { @@ -586,38 +572,40 @@ impl Constellation { debug!("creating replacement pipeline for about:failure"); let window_rect = self.pipeline(pipeline_id).rect; - let new_pipeline_id = - self.new_pipeline(parent_info, - window_rect, - None, - LoadData::new(Url::parse("about:failure").unwrap())); + let new_pipeline_id = PipelineId::new(); + self.new_pipeline(new_pipeline_id, + parent_info, + window_rect, + None, + LoadData::new(Url::parse("about:failure").unwrap())); self.push_pending_frame(new_pipeline_id, Some(pipeline_id)); } fn handle_init_load(&mut self, url: Url) { let window_rect = Rect::new(Point2D::zero(), self.window_size.visible_viewport); - let root_pipeline_id = - self.new_pipeline(None, Some(window_rect), None, LoadData::new(url.clone())); + let root_pipeline_id = PipelineId::nil(); + self.new_pipeline(root_pipeline_id, None, Some(window_rect), None, LoadData::new(url.clone())); self.handle_load_start_msg(&root_pipeline_id); self.push_pending_frame(root_pipeline_id, None); self.compositor_proxy.send(CompositorMsg::ChangePageUrl(root_pipeline_id, url)); } - fn handle_frame_rect_msg(&mut self, containing_pipeline_id: PipelineId, subpage_id: SubpageId, + fn handle_frame_rect_msg(&mut self, pipeline_id: PipelineId, rect: TypedRect) { // Store the new rect inside the pipeline let (pipeline_id, script_chan) = { // Find the pipeline that corresponds to this rectangle. It's possible that this // pipeline may have already exited before we process this message, so just // early exit if that occurs. - let pipeline_id = self.subpage_map.get(&(containing_pipeline_id, subpage_id)).map(|id| *id); - let pipeline = match pipeline_id { - Some(pipeline_id) => self.mut_pipeline(pipeline_id), + let pipeline = self.pipelines.get_mut(&pipeline_id); + match pipeline { + Some(pipeline) => { + pipeline.rect = Some(rect); + (pipeline.id, pipeline.script_chan.clone()) + } None => return, - }; - pipeline.rect = Some(rect); - (pipeline.id, pipeline.script_chan.clone()) + } }; script_chan.send(ConstellationControlMsg::Resize(pipeline_id, WindowSizeData { @@ -642,14 +630,14 @@ impl Constellation { // page navigation. fn handle_script_loaded_url_in_iframe_msg(&mut self, url: Url, - containing_pipeline_id: PipelineId, - new_subpage_id: SubpageId, - old_subpage_id: Option, + parent_pipeline_id: PipelineId, + new_pipeline_id: PipelineId, + old_pipeline_id: Option, sandbox: IFrameSandboxState) { // Compare the pipeline's url to the new url. If the origin is the same, // then reuse the script task in creating the new pipeline let script_chan = { - let source_pipeline = self.pipeline(containing_pipeline_id); + let source_pipeline = self.pipeline(parent_pipeline_id); let source_url = source_pipeline.url.clone(); @@ -671,17 +659,14 @@ impl Constellation { }; // Create the new pipeline, attached to the parent and push to pending frames - let old_pipeline_id = old_subpage_id.map(|old_subpage_id| { - self.find_subpage(containing_pipeline_id, old_subpage_id).id - }); let window_rect = old_pipeline_id.and_then(|old_pipeline_id| { self.pipeline(old_pipeline_id).rect }); - let new_pipeline_id = self.new_pipeline(Some((containing_pipeline_id, new_subpage_id)), - window_rect, - script_chan, - LoadData::new(url)); - self.subpage_map.insert((containing_pipeline_id, new_subpage_id), new_pipeline_id); + self.new_pipeline(new_pipeline_id, + Some(parent_pipeline_id), + window_rect, + script_chan, + LoadData::new(url)); self.push_pending_frame(new_pipeline_id, old_pipeline_id); } @@ -714,14 +699,14 @@ impl Constellation { // the new load. The framing element must be notified about the // requested change so it can update its internal state. match self.pipeline(source_id).parent_info { - Some((parent_pipeline_id, subpage_id)) => { + Some(parent_pipeline_id) => { self.handle_load_start_msg(&source_id); // Message the constellation to find the script task for this iframe // and issue an iframe load through there. let parent_pipeline = self.pipeline(parent_pipeline_id); let script_channel = &parent_pipeline.script_chan; - script_channel.send(ConstellationControlMsg::Navigate(parent_pipeline_id, - subpage_id, + script_channel.send(ConstellationControlMsg::Navigate(source_id, + parent_pipeline_id, load_data)).unwrap(); Some(source_id) } @@ -740,7 +725,8 @@ impl Constellation { // Create the new pipeline let window_rect = self.pipeline(source_id).rect; - let new_pipeline_id = self.new_pipeline(None, window_rect, None, load_data); + let new_pipeline_id = PipelineId::new(); + self.new_pipeline(new_pipeline_id, None, window_rect, None, load_data); self.push_pending_frame(new_pipeline_id, Some(source_id)); // Send message to ScriptTask that will suspend all timers @@ -789,14 +775,13 @@ impl Constellation { } fn handle_navigate_msg(&mut self, - pipeline_info: Option<(PipelineId, SubpageId)>, + pipeline_id: Option, direction: constellation_msg::NavigationDirection) { debug!("received message to navigate {:?}", direction); // Get the frame id associated with the pipeline that sent // the navigate message, or use root frame id by default. - let frame_id = pipeline_info.map_or(self.root_frame_id, |(containing_pipeline_id, subpage_id)| { - let pipeline_id = self.find_subpage(containing_pipeline_id, subpage_id).id; + let frame_id = pipeline_id.map_or(self.root_frame_id, |pipeline_id| { self.pipeline_to_frame_map.get(&pipeline_id).map(|id| *id) }).unwrap(); @@ -855,14 +840,14 @@ impl Constellation { self.revoke_paint_permission(prev_pipeline_id); self.send_frame_tree_and_grant_paint_permission(); - // Update the owning iframe to point to the new subpage id. + // Update the owning iframe to point to the new pipeline id. // This makes things like contentDocument work correctly. - if let Some((parent_pipeline_id, subpage_id)) = pipeline_info { + if let Some(pipeline_id) = pipeline_id { + let parent_pipeline_id = self.pipeline(pipeline_id).parent_info.unwrap(); let script_chan = &self.pipeline(parent_pipeline_id).script_chan; - let (_, new_subpage_id) = self.pipeline(next_pipeline_id).parent_info.unwrap(); - script_chan.send(ConstellationControlMsg::UpdateSubpageId(parent_pipeline_id, - subpage_id, - new_subpage_id)).unwrap(); + script_chan.send(ConstellationControlMsg::UpdatePipelineId(parent_pipeline_id, + prev_pipeline_id, + next_pipeline_id)).unwrap(); // If this is an iframe, send a mozbrowser location change event. // This is the result of a back/forward navigation. @@ -903,14 +888,14 @@ impl Constellation { fn handle_mozbrowser_event_msg(&mut self, containing_pipeline_id: PipelineId, - subpage_id: SubpageId, + pipeline_id: PipelineId, event: MozBrowserEvent) { assert!(prefs::get_pref("dom.mozbrowser.enabled").as_boolean().unwrap_or(false)); // Find the script channel for the given parent pipeline, // and pass the event to that script task. let pipeline = self.pipeline(containing_pipeline_id); - pipeline.trigger_mozbrowser_event(subpage_id, event); + pipeline.trigger_mozbrowser_event(pipeline_id, event); } fn handle_get_pipeline(&mut self, frame_id: Option, @@ -926,21 +911,18 @@ impl Constellation { } fn handle_get_frame(&mut self, - containing_pipeline_id: PipelineId, - subpage_id: SubpageId, + pipeline_id: PipelineId, resp_chan: IpcSender>) { - let frame_id = self.subpage_map.get(&(containing_pipeline_id, subpage_id)).and_then( - |x| self.pipeline_to_frame_map.get(&x)).map(|x| *x); + let frame_id = self.pipeline_to_frame_map.get(&pipeline_id).map(|x| *x); resp_chan.send(frame_id).unwrap(); } fn focus_parent_pipeline(&self, pipeline_id: PipelineId) { // Send a message to the parent of the provided pipeline (if it exists) // telling it to mark the iframe element as focused. - if let Some((containing_pipeline_id, subpage_id)) = self.pipeline(pipeline_id).parent_info { + if let Some(containing_pipeline_id) = self.pipeline(pipeline_id).parent_info { let pipeline = self.pipeline(containing_pipeline_id); - let event = ConstellationControlMsg::FocusIFrame(containing_pipeline_id, - subpage_id); + let event = ConstellationControlMsg::FocusIFrame(containing_pipeline_id, pipeline_id); pipeline.script_chan.send(event).unwrap(); self.focus_parent_pipeline(containing_pipeline_id); @@ -954,8 +936,7 @@ impl Constellation { self.focus_parent_pipeline(pipeline_id); } - fn handle_remove_iframe_msg(&mut self, containing_pipeline_id: PipelineId, subpage_id: SubpageId) { - let pipeline_id = self.find_subpage(containing_pipeline_id, subpage_id).id; + fn handle_remove_iframe_msg(&mut self, pipeline_id: PipelineId) { let frame_id = self.pipeline_to_frame_map.get(&pipeline_id).map(|id| *id); match frame_id { Some(frame_id) => { @@ -1073,7 +1054,7 @@ impl Constellation { // If a child frame, add it to the parent pipeline. Otherwise // it must surely be the root frame being created! match self.pipeline(frame_change.new_pipeline_id).parent_info { - Some((parent_id, _)) => { + Some(parent_id) => { self.mut_pipeline(parent_id).add_child(frame_id); } None => { @@ -1297,7 +1278,7 @@ impl Constellation { self.frames.remove(&frame_id).unwrap(); - if let Some((parent_pipeline_id, _)) = parent_info { + if let Some(parent_pipeline_id) = parent_info { let parent_pipeline = self.mut_pipeline(parent_pipeline_id); parent_pipeline.remove_child(frame_id); } @@ -1325,11 +1306,6 @@ impl Constellation { let pipeline = self.pipelines.remove(&pipeline_id).unwrap(); - // If a child pipeline, remove from subpage map - if let Some(info) = pipeline.parent_info { - self.subpage_map.remove(&info); - } - // Remove assocation between this pipeline and its holding frame self.pipeline_to_frame_map.remove(&pipeline_id); @@ -1401,15 +1377,15 @@ impl Constellation { let event_info = { let pipeline = self.pipeline(pipeline_id); - pipeline.parent_info.map(|(containing_pipeline_id, subpage_id)| { - (containing_pipeline_id, subpage_id, pipeline.url.serialize()) + pipeline.parent_info.map(|containing_pipeline_id| { + (containing_pipeline_id, pipeline.url.serialize()) }) }; // If this is an iframe, then send the event with new url - if let Some((containing_pipeline_id, subpage_id, url)) = event_info { + if let Some((containing_pipeline_id, url)) = event_info { let parent_pipeline = self.pipeline(containing_pipeline_id); - parent_pipeline.trigger_mozbrowser_event(subpage_id, MozBrowserEvent::LocationChange(url)); + parent_pipeline.trigger_mozbrowser_event(pipeline_id, MozBrowserEvent::LocationChange(url)); } } } @@ -1450,11 +1426,4 @@ impl Constellation { fn mut_pipeline(&mut self, pipeline_id: PipelineId) -> &mut Pipeline { self.pipelines.get_mut(&pipeline_id).expect("unable to find pipeline - this is a bug") } - - fn find_subpage(&mut self, containing_pipeline_id: PipelineId, subpage_id: SubpageId) -> &mut Pipeline { - let pipeline_id = *self.subpage_map - .get(&(containing_pipeline_id, subpage_id)) - .expect("no subpage pipeline_id"); - self.mut_pipeline(pipeline_id) - } } diff --git a/components/compositing/pipeline.rs b/components/compositing/pipeline.rs index 73cabc1d35e1..f0e1649881f8 100644 --- a/components/compositing/pipeline.rs +++ b/components/compositing/pipeline.rs @@ -13,7 +13,7 @@ use ipc_channel::ipc::{self, IpcReceiver, IpcSender}; use ipc_channel::router::ROUTER; use layers::geometry::DevicePixel; use layout_traits::{LayoutControlChan, LayoutTaskFactory}; -use msg::constellation_msg::{ConstellationChan, Failure, FrameId, PipelineId, SubpageId}; +use msg::constellation_msg::{ConstellationChan, Failure, FrameId, PipelineId}; use msg::constellation_msg::{LoadData, MozBrowserEvent, PipelineExitType, WindowSizeData}; use net_traits::ResourceTask; use net_traits::image_cache_task::ImageCacheTask; @@ -35,7 +35,7 @@ use util::prefs; /// A uniquely-identifiable pipeline of script task, layout task, and paint task. pub struct Pipeline { pub id: PipelineId, - pub parent_info: Option<(PipelineId, SubpageId)>, + pub parent_info: Option, pub script_chan: Sender, /// A channel to layout, for performing reflows and shutdown. pub layout_chan: LayoutControlChan, @@ -68,7 +68,7 @@ pub struct InitialPipelineState { pub id: PipelineId, /// The subpage ID of this pipeline to create in its pipeline parent. /// If `None`, this is the root. - pub parent_info: Option<(PipelineId, SubpageId)>, + pub parent_info: Option, /// A channel to the associated constellation. pub constellation_chan: ConstellationChan, /// A channel to the compositor. @@ -137,12 +137,11 @@ impl Pipeline { let (script_chan, script_port) = match state.script_chan { Some(script_chan) => { - let (containing_pipeline_id, subpage_id) = - state.parent_info.expect("script_pipeline != None but subpage_id == None"); + let containing_pipeline_id = + state.parent_info.expect("script_pipeline != None but parent id == None"); let new_layout_info = NewLayoutInfo { containing_pipeline_id: containing_pipeline_id, new_pipeline_id: state.id, - subpage_id: subpage_id, load_data: state.load_data.clone(), paint_chan: box layout_to_paint_chan.clone() as Box, failure: failure, @@ -200,7 +199,7 @@ impl Pipeline { } pub fn new(id: PipelineId, - parent_info: Option<(PipelineId, SubpageId)>, + parent_info: Option, script_chan: Sender, layout_chan: LayoutControlChan, chrome_to_paint_chan: Sender, @@ -287,12 +286,12 @@ impl Pipeline { } pub fn trigger_mozbrowser_event(&self, - subpage_id: SubpageId, - event: MozBrowserEvent) { + pipeline_id: PipelineId, + event: MozBrowserEvent) { assert!(prefs::get_pref("dom.mozbrowser.enabled").as_boolean().unwrap_or(false)); let event = ConstellationControlMsg::MozBrowserEvent(self.id, - subpage_id, + pipeline_id, event); self.script_chan.send(event).unwrap(); } @@ -300,7 +299,7 @@ impl Pipeline { pub struct PipelineContent { id: PipelineId, - parent_info: Option<(PipelineId, SubpageId)>, + parent_info: Option, constellation_chan: ConstellationChan, compositor_proxy: Box, devtools_chan: Option>, diff --git a/components/devtools/lib.rs b/components/devtools/lib.rs index c0049b31ad33..1dad9f710c28 100644 --- a/components/devtools/lib.rs +++ b/components/devtools/lib.rs @@ -433,7 +433,7 @@ fn run_server(sender: Sender, //TODO: Get pipeline_id from NetworkEventMessage after fixing the send in http_loader // For now, the id of the first pipeline is passed handle_network_event(actors.clone(), connections, &actor_pipelines, &mut actor_requests, - &actor_workers, PipelineId(0), request_id, network_event); + &actor_workers, PipelineId::nil(), request_id, network_event); }, Ok(DevtoolsControlMsg::FromChrome(ChromeToDevtoolsControlMsg::ServerExitMsg)) | Err(RecvError) => break diff --git a/components/gfx/paint_task.rs b/components/gfx/paint_task.rs index 3c139fafaaa2..30aaacdf5041 100644 --- a/components/gfx/paint_task.rs +++ b/components/gfx/paint_task.rs @@ -175,7 +175,7 @@ impl PaintTask where C: PaintListener + Send + 'static { canvas_map: HashMap::new() }; - let reporter_name = format!("paint-reporter-{}", id.0); + let reporter_name = format!("paint-reporter-{:?}", id); mem_profiler_chan.run_with_memory_reporting(|| { paint_task.start(); }, reporter_name, chrome_to_paint_chan, ChromeToPaintMsg::CollectReports); diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs index 4bc788c0ce71..a79b1d248e53 100644 --- a/components/layout/display_list_builder.rs +++ b/components/layout/display_list_builder.rs @@ -1372,12 +1372,10 @@ impl FragmentDisplayListBuilding for Fragment { Size2D::new(content_size.width.to_f32_px(), content_size.height.to_f32_px())); - debug!("finalizing position and size of iframe for {:?},{:?}", - iframe_fragment.pipeline_id, - iframe_fragment.subpage_id); + debug!("finalizing position and size of iframe for {:?}", + iframe_fragment.pipeline_id); let ConstellationChan(ref chan) = layout_context.shared.constellation_chan; chan.send(ConstellationMsg::FrameRect(iframe_fragment.pipeline_id, - iframe_fragment.subpage_id, iframe_rect)).unwrap(); } diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs index c6cea07b77b7..af235e72d3fc 100644 --- a/components/layout/fragment.rs +++ b/components/layout/fragment.rs @@ -22,7 +22,7 @@ use inline::{InlineMetrics, LAST_FRAGMENT_OF_ELEMENT}; use ipc_channel::ipc::IpcSender; use layout_debug; use model::{self, IntrinsicISizes, IntrinsicISizesContribution, MaybeAuto, specified}; -use msg::constellation_msg::{ConstellationChan, Msg, PipelineId, SubpageId}; +use msg::constellation_msg::{ConstellationChan, Msg, PipelineId}; use net_traits::image::base::Image; use net_traits::image_cache_task::UsePlaceholder; use rustc_serialize::{Encodable, Encoder}; @@ -576,17 +576,14 @@ impl ReplacedImageFragmentInfo { pub struct IframeFragmentInfo { /// The pipeline ID of this iframe. pub pipeline_id: PipelineId, - /// The subpage ID of this iframe. - pub subpage_id: SubpageId, } impl IframeFragmentInfo { /// Creates the information specific to an iframe fragment. pub fn new(node: &ThreadSafeLayoutNode) -> IframeFragmentInfo { - let (pipeline_id, subpage_id) = node.iframe_pipeline_and_subpage_ids(); + let pipeline_id = node.iframe_pipeline_id(); IframeFragmentInfo { pipeline_id: pipeline_id, - subpage_id: subpage_id, } } @@ -2219,7 +2216,6 @@ impl Fragment { SpecificFragmentInfo::Iframe(ref iframe_info) => { let ConstellationChan(ref chan) = constellation_chan; chan.send(Msg::FrameRect(iframe_info.pipeline_id, - iframe_info.subpage_id, Rect::zero())).unwrap(); } _ => {} diff --git a/components/layout/layout_task.rs b/components/layout/layout_task.rs index c5f9c3710351..3c936a0d1067 100644 --- a/components/layout/layout_task.rs +++ b/components/layout/layout_task.rs @@ -275,7 +275,7 @@ impl LayoutTaskFactory for LayoutTask { time_profiler_chan, mem_profiler_chan.clone()); - let reporter_name = format!("layout-reporter-{}", id.0); + let reporter_name = format!("layout-reporter-{:?}", id); mem_profiler_chan.run_with_memory_reporting(|| { layout.start(); }, reporter_name, layout_chan.0, Msg::CollectReports); diff --git a/components/layout/wrapper.rs b/components/layout/wrapper.rs index 17102f0095d8..3769103708e3 100644 --- a/components/layout/wrapper.rs +++ b/components/layout/wrapper.rs @@ -37,7 +37,7 @@ use gfx::display_list::OpaqueNode; use gfx::text::glyph::CharIndex; use incremental::RestyleDamage; use ipc_channel::ipc::IpcSender; -use msg::constellation_msg::{PipelineId, SubpageId}; +use msg::constellation_msg::PipelineId; use opaque_node::OpaqueNodeMethods; use script::dom::attr::AttrValue; use script::dom::bindings::codegen::InheritTypes::{CharacterDataCast, ElementCast}; @@ -1013,12 +1013,11 @@ impl<'ln> ThreadSafeLayoutNode<'ln> { /// If this node is an iframe element, returns its pipeline and subpage IDs. If this node is /// not an iframe element, fails. - pub fn iframe_pipeline_and_subpage_ids(&self) -> (PipelineId, SubpageId) { + pub fn iframe_pipeline_id(&self) -> PipelineId { unsafe { let iframe_element = HTMLIFrameElementCast::to_layout_js(self.get_jsmanaged()) .expect("not an iframe element!"); - ((*iframe_element.unsafe_get()).containing_page_pipeline_id().unwrap(), - (*iframe_element.unsafe_get()).subpage_id().unwrap()) + (*iframe_element.unsafe_get()).pipeline_id().unwrap() } } } diff --git a/components/msg/Cargo.toml b/components/msg/Cargo.toml index a1f6f80c1faa..e0e58b2360ac 100644 --- a/components/msg/Cargo.toml +++ b/components/msg/Cargo.toml @@ -50,6 +50,7 @@ rustc-serialize = "0.3.4" euclid = "0.2" serde = "0.6" serde_macros = "0.5" +uuid = "0.1.17" [target.x86_64-apple-darwin.dependencies] core-foundation = "0.1" diff --git a/components/msg/constellation_msg.rs b/components/msg/constellation_msg.rs index ab244707c283..5f0f9dd2293f 100644 --- a/components/msg/constellation_msg.rs +++ b/components/msg/constellation_msg.rs @@ -16,6 +16,8 @@ use ipc_channel::ipc::IpcSender; use layers::geometry::DevicePixel; use offscreen_gl_context::GLContextAttributes; use png::Image; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use serde::bytes::ByteBuf; use std::collections::HashMap; use std::sync::mpsc::{Receiver, Sender, channel}; use style_traits::viewport::ViewportConstraints; @@ -23,6 +25,7 @@ use url::Url; use util::cursor::Cursor; use util::geometry::{PagePx, ViewportPx}; use util::mem::HeapSizeOf; +use uuid::Uuid; use webdriver_msg::{LoadStatus, WebDriverScriptCommand}; #[derive(Clone)] @@ -45,7 +48,7 @@ pub enum IFrameSandboxState { #[derive(Clone, Copy, Deserialize, Serialize)] pub struct Failure { pub pipeline_id: PipelineId, - pub parent_info: Option<(PipelineId, SubpageId)>, + pub parent_info: Option, } #[derive(Copy, Clone, Deserialize, Serialize, HeapSizeOf)] @@ -221,10 +224,10 @@ pub enum Msg { LoadComplete(PipelineId), /// Dispatched after the DOM load event has fired on a document DOMLoad(PipelineId), - FrameRect(PipelineId, SubpageId, Rect), + FrameRect(PipelineId, Rect), LoadUrl(PipelineId, LoadData), - ScriptLoadedURLInIFrame(Url, PipelineId, SubpageId, Option, IFrameSandboxState), - Navigate(Option<(PipelineId, SubpageId)>, NavigationDirection), + ScriptLoadedURLInIFrame(Url, PipelineId, PipelineId, Option, IFrameSandboxState), + Navigate(Option, NavigationDirection), PainterReady(PipelineId), ResizedWindow(WindowSizeData), KeyEvent(Key, KeyState, KeyModifiers), @@ -234,7 +237,7 @@ pub enum Msg { /// Requests that the constellation inform the compositor of the a cursor change. SetCursor(Cursor), /// Dispatch a mozbrowser event to a given iframe. Only available in experimental mode. - MozBrowserEvent(PipelineId, SubpageId, MozBrowserEvent), + MozBrowserEvent(PipelineId, PipelineId, MozBrowserEvent), /// Indicates whether this pipeline is currently running animations. ChangeRunningAnimationsState(PipelineId, AnimationState), /// Requests that the constellation instruct layout to begin a new tick of the animation. @@ -243,8 +246,8 @@ pub enum Msg { /// id, or for the root frame if this is None, over a provided channel GetPipeline(Option, IpcSender>), /// Request that the constellation send the FrameId corresponding to the document - /// with the provided parent pipeline id and subpage id - GetFrame(PipelineId, SubpageId, IpcSender>), + /// with the provided pipeline id + GetFrame(PipelineId, IpcSender>), /// Notifies the constellation that this frame has received focus. Focus(PipelineId), /// Requests that the constellation retrieve the current contents of the clipboard @@ -258,7 +261,7 @@ pub enum Msg { /// Query the constellation to see if the current compositor output is stable IsReadyToSaveImage(HashMap), /// Notification that this iframe should be removed. - RemoveIFrame(PipelineId, SubpageId), + RemoveIFrame(PipelineId), /// Favicon detected NewFavicon(Url), /// tag finished parsing @@ -391,11 +394,8 @@ pub struct FrameId(pub u32); #[derive(Clone, PartialEq, Eq, Copy, Hash, Debug, Deserialize, Serialize, HeapSizeOf)] pub struct WorkerId(pub u32); -#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug, Deserialize, Serialize, HeapSizeOf)] -pub struct PipelineId(pub u32); - -#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug, Deserialize, Serialize, HeapSizeOf)] -pub struct SubpageId(pub u32); +#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug, HeapSizeOf)] +pub struct PipelineId(Uuid); // The type of pipeline exit. During complete shutdowns, pipelines do not have to // release resources automatically released on process termination. @@ -404,3 +404,27 @@ pub enum PipelineExitType { PipelineOnly, Complete, } + +impl PipelineId { + pub fn new() -> PipelineId { + PipelineId(Uuid::new_v4()) + } + + pub fn nil() -> PipelineId { + PipelineId(Uuid::nil()) + } +} + +impl Serialize for PipelineId { + fn serialize(&self, serializer: &mut S) -> Result<(),S::Error> where S: Serializer { + let &PipelineId(uuid) = self; + uuid.as_bytes().serialize(serializer) + } +} + +impl Deserialize for PipelineId { + fn deserialize(deserializer: &mut D) -> Result where D: Deserializer { + let bytes = try!(ByteBuf::deserialize(deserializer)); + Ok(PipelineId(Uuid::from_bytes(&bytes).unwrap())) + } +} diff --git a/components/msg/lib.rs b/components/msg/lib.rs index 995b1bc55870..4b69294712a4 100644 --- a/components/msg/lib.rs +++ b/components/msg/lib.rs @@ -24,6 +24,7 @@ extern crate serde; extern crate style_traits; extern crate url; extern crate util; +extern crate uuid; pub mod compositor_msg; pub mod constellation_msg; diff --git a/components/msg/webdriver_msg.rs b/components/msg/webdriver_msg.rs index db0fccac228c..63ac4aa7ffd4 100644 --- a/components/msg/webdriver_msg.rs +++ b/components/msg/webdriver_msg.rs @@ -2,7 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use constellation_msg::{PipelineId, SubpageId}; +use constellation_msg::PipelineId; use ipc_channel::ipc::IpcSender; use rustc_serialize::json::{Json, ToJson}; use url::Url; @@ -16,7 +16,7 @@ pub enum WebDriverScriptCommand { GetActiveElement(IpcSender>), GetElementTagName(String, IpcSender>), GetElementText(String, IpcSender>), - GetFrameId(WebDriverFrameId, IpcSender, ()>>), + GetFrameId(WebDriverFrameId, IpcSender, ()>>), GetUrl(IpcSender), GetTitle(IpcSender) } diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index 94d3ad97c934..0f8a04c27872 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -51,7 +51,7 @@ use js::rust::Runtime; use layout_interface::{LayoutChan, LayoutRPC}; use libc; use msg::constellation_msg::ConstellationChan; -use msg::constellation_msg::{PipelineId, SubpageId, WindowSizeData, WorkerId}; +use msg::constellation_msg::{PipelineId, WindowSizeData, WorkerId}; use net_traits::image::base::Image; use net_traits::image_cache_task::{ImageCacheChan, ImageCacheTask}; use net_traits::storage_task::StorageType; @@ -281,7 +281,7 @@ no_jsmanaged_fields!(PropertyDeclarationBlock); no_jsmanaged_fields!(HashSet); // These three are interdependent, if you plan to put jsmanaged data // in one of these make sure it is propagated properly to containing structs -no_jsmanaged_fields!(SubpageId, WindowSizeData, PipelineId); +no_jsmanaged_fields!(WindowSizeData, PipelineId); no_jsmanaged_fields!(WorkerId); no_jsmanaged_fields!(QuirksMode); no_jsmanaged_fields!(Runtime); diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index db4c72af8dc4..d7d9f2bce855 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -77,7 +77,7 @@ use msg::compositor_msg::ScriptToCompositorMsg; use msg::constellation_msg::AnimationState; use msg::constellation_msg::Msg as ConstellationMsg; use msg::constellation_msg::{ALT, CONTROL, SHIFT, SUPER}; -use msg::constellation_msg::{ConstellationChan, FocusType, Key, KeyModifiers, KeyState, MozBrowserEvent, SubpageId}; +use msg::constellation_msg::{ConstellationChan, FocusType, Key, KeyModifiers, KeyState, MozBrowserEvent, PipelineId}; use net_traits::ControlMsg::{GetCookiesForUrl, SetCookiesForUrl}; use net_traits::CookieSource::NonHTTP; use net_traits::{AsyncResponseTarget, Metadata, PendingAsyncLoad}; @@ -865,10 +865,10 @@ impl Document { if htmliframeelement::mozbrowser_enabled() { let window = self.window.root(); - if let Some((containing_pipeline_id, subpage_id)) = window.r().parent_info() { + if let Some(containing_pipeline_id) = window.r().parent_pipeline() { let ConstellationChan(ref chan) = window.r().constellation_chan(); let event = ConstellationMsg::MozBrowserEvent(containing_pipeline_id, - subpage_id, + window.r().pipeline(), event); chan.send(event).unwrap(); } @@ -973,10 +973,10 @@ impl Document { } /// Find an iframe element in the document. - pub fn find_iframe(&self, subpage_id: SubpageId) -> Option> { + pub fn find_iframe(&self, pipeline_id: PipelineId) -> Option> { NodeCast::from_ref(self).traverse_preorder() .filter_map(HTMLIFrameElementCast::to_root) - .find(|node| node.r().subpage_id() == Some(subpage_id)) + .find(|node| node.r().pipeline_id() == Some(pipeline_id)) } } diff --git a/components/script/dom/htmliframeelement.rs b/components/script/dom/htmliframeelement.rs index 8e0016f4bb08..56d8da3faf01 100644 --- a/components/script/dom/htmliframeelement.rs +++ b/components/script/dom/htmliframeelement.rs @@ -28,7 +28,7 @@ use js::jsapi::{JSAutoCompartment, JSAutoRequest, RootedValue}; use js::jsval::UndefinedValue; use msg::constellation_msg::IFrameSandboxState::{IFrameSandboxed, IFrameUnsandboxed}; use msg::constellation_msg::Msg as ConstellationMsg; -use msg::constellation_msg::{ConstellationChan, MozBrowserEvent, NavigationDirection, PipelineId, SubpageId}; +use msg::constellation_msg::{ConstellationChan, MozBrowserEvent, NavigationDirection, PipelineId}; use page::IterablePage; use std::ascii::AsciiExt; use std::borrow::ToOwned; @@ -57,8 +57,7 @@ enum SandboxAllowance { #[dom_struct] pub struct HTMLIFrameElement { htmlelement: HTMLElement, - subpage_id: Cell>, - containing_page_pipeline_id: Cell>, + pipeline_id: Cell>, sandbox: Cell>, } @@ -91,12 +90,11 @@ impl HTMLIFrameElement { }) } - pub fn generate_new_subpage_id(&self) -> (SubpageId, Option) { - let old_subpage_id = self.subpage_id.get(); - let win = window_from_node(self); - let subpage_id = win.r().get_next_subpage_id(); - self.subpage_id.set(Some(subpage_id)); - (subpage_id, old_subpage_id) + pub fn generate_new_pipeline_id(&self) -> (PipelineId, Option) { + let old_pipeline_id = self.pipeline_id.get(); + let new_pipeline_id = PipelineId::new(); + self.pipeline_id.set(Some(new_pipeline_id)); + (new_pipeline_id, old_pipeline_id) } pub fn navigate_child_browsing_context(&self, url: Url) { @@ -108,15 +106,13 @@ impl HTMLIFrameElement { let window = window_from_node(self); let window = window.r(); - let (new_subpage_id, old_subpage_id) = self.generate_new_subpage_id(); - - self.containing_page_pipeline_id.set(Some(window.pipeline())); + let (new_pipeline_id, old_pipeline_id) = self.generate_new_pipeline_id(); let ConstellationChan(ref chan) = window.constellation_chan(); chan.send(ConstellationMsg::ScriptLoadedURLInIFrame(url, window.pipeline(), - new_subpage_id, - old_subpage_id, + new_pipeline_id, + old_pipeline_id, sandboxed)).unwrap(); if mozbrowser_enabled() { @@ -158,8 +154,8 @@ impl HTMLIFrameElement { } } - pub fn update_subpage_id(&self, new_subpage_id: SubpageId) { - self.subpage_id.set(Some(new_subpage_id)); + pub fn update_pipeline_id(&self, new_pipeline_id: PipelineId) { + self.pipeline_id.set(Some(new_pipeline_id)); } #[allow(unsafe_code)] @@ -190,8 +186,7 @@ impl HTMLIFrameElement { HTMLIFrameElement { htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLIFrameElement, localName, prefix, document), - subpage_id: Cell::new(None), - containing_page_pipeline_id: Cell::new(None), + pipeline_id: Cell::new(None), sandbox: Cell::new(None), } } @@ -204,14 +199,8 @@ impl HTMLIFrameElement { Node::reflect_node(box element, document, HTMLIFrameElementBinding::Wrap) } - #[inline] - pub fn containing_page_pipeline_id(&self) -> Option { - self.containing_page_pipeline_id.get() - } - - #[inline] - pub fn subpage_id(&self) -> Option { - self.subpage_id.get() + pub fn pipeline_id(&self) -> Option { + self.pipeline_id.get() } } @@ -222,10 +211,9 @@ pub fn Navigate(iframe: &HTMLIFrameElement, direction: NavigationDirection) -> F let window = window_from_node(iframe); let window = window.r(); - let pipeline_info = Some((iframe.containing_page_pipeline_id().unwrap(), - iframe.subpage_id().unwrap())); + let pipeline_id = iframe.pipeline_id().unwrap(); let ConstellationChan(ref chan) = window.constellation_chan(); - let msg = ConstellationMsg::Navigate(pipeline_info, direction); + let msg = ConstellationMsg::Navigate(Some(pipeline_id), direction); chan.send(msg).unwrap(); } @@ -263,13 +251,13 @@ impl HTMLIFrameElementMethods for HTMLIFrameElement { // https://html.spec.whatwg.org/multipage/#dom-iframe-contentwindow fn GetContentWindow(&self) -> Option> { - self.subpage_id.get().and_then(|subpage_id| { + self.pipeline_id.get().and_then(|pipeline_id| { let window = window_from_node(self); let window = window.r(); let children = window.page().children.borrow(); children.iter().find(|page| { let window = page.window(); - window.r().subpage() == Some(subpage_id) + window.r().pipeline() == pipeline_id }).map(|page| page.window()) }) } @@ -408,24 +396,20 @@ impl VirtualMethods for HTMLIFrameElement { } // https://html.spec.whatwg.org/multipage/#a-browsing-context-is-discarded - match (self.containing_page_pipeline_id(), self.subpage_id()) { - (Some(containing_pipeline_id), Some(subpage_id)) => { - let window = window_from_node(self); - let window = window.r(); - - let ConstellationChan(ref chan) = window.constellation_chan(); - let msg = ConstellationMsg::RemoveIFrame(containing_pipeline_id, - subpage_id); - chan.send(msg).unwrap(); - - // Resetting the subpage id to None is required here so that - // if this iframe is subsequently re-added to the document - // the load doesn't think that it's a navigation, but instead - // a new iframe. Without this, the constellation gets very - // confused. - self.subpage_id.set(None); - } - _ => {} + if let Some(pipeline_id) = self.pipeline_id() { + let window = window_from_node(self); + let window = window.r(); + + let ConstellationChan(ref chan) = window.constellation_chan(); + let msg = ConstellationMsg::RemoveIFrame(pipeline_id); + chan.send(msg).unwrap(); + + // Resetting the pipeline id to None is required here so that + // if this iframe is subsequently re-added to the document + // the load doesn't think that it's a navigation, but instead + // a new iframe. Without this, the constellation gets very + // confused. + self.pipeline_id.set(None); } } } diff --git a/components/script/dom/servohtmlparser.rs b/components/script/dom/servohtmlparser.rs index fd8547683471..fe7364104e22 100644 --- a/components/script/dom/servohtmlparser.rs +++ b/components/script/dom/servohtmlparser.rs @@ -26,7 +26,7 @@ use html5ever::tree_builder::{NodeOrText, TreeBuilder, TreeBuilderOpts}; use hyper::header::ContentType; use hyper::mime::{Mime, SubLevel, TopLevel}; use js::jsapi::JSTracer; -use msg::constellation_msg::{PipelineId, SubpageId}; +use msg::constellation_msg::PipelineId; use net_traits::{AsyncResponseListener, Metadata}; use network_listener::PreInvoke; use parse::Parser; @@ -73,8 +73,6 @@ pub struct ParserContext { is_image_document: Cell, /// The pipeline associated with this document. id: PipelineId, - /// The subpage associated with this document. - subpage: Option, /// The target event loop for the response notifications. script_chan: Box, /// The URL for this document. @@ -82,13 +80,12 @@ pub struct ParserContext { } impl ParserContext { - pub fn new(id: PipelineId, subpage: Option, script_chan: Box, + pub fn new(id: PipelineId, script_chan: Box, url: Url) -> ParserContext { ParserContext { parser: RefCell::new(None), is_image_document: Cell::new(false), id: id, - subpage: subpage, script_chan: script_chan, url: url, } @@ -99,8 +96,7 @@ impl AsyncResponseListener for ParserContext { fn headers_available(&self, metadata: Metadata) { let content_type = metadata.content_type.clone(); - let parser = ScriptTask::page_fetch_complete(self.id.clone(), self.subpage.clone(), - metadata); + let parser = ScriptTask::page_fetch_complete(self.id.clone(), metadata); let parser = match parser { Some(parser) => parser, None => return, diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index 4cec46c7814c..10ca49ebbd48 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -43,7 +43,7 @@ use layout_interface::{ContentBoxResponse, ContentBoxesResponse, ResolvedStyleRe use layout_interface::{LayoutChan, LayoutRPC, Msg, Reflow, ReflowGoal, ReflowQueryType}; use libc; use msg::compositor_msg::{LayerId, ScriptToCompositorMsg}; -use msg::constellation_msg::{ConstellationChan, LoadData, PipelineId, SubpageId, WindowSizeData, WorkerId}; +use msg::constellation_msg::{ConstellationChan, LoadData, PipelineId, WindowSizeData, WorkerId}; use msg::webdriver_msg::{WebDriverJSError, WebDriverJSResult}; use net_traits::ResourceTask; use net_traits::image_cache_task::{ImageCacheChan, ImageCacheTask}; @@ -151,8 +151,6 @@ pub struct Window { /// page changes. devtools_wants_updates: Cell, - next_subpage_id: Cell, - /// Pending resize event, if any. resize_event: Cell>, @@ -160,7 +158,7 @@ pub struct Window { id: PipelineId, /// Subpage id associated with this page, if any. - parent_info: Option<(PipelineId, SubpageId)>, + parent_info: Option, /// Unique id for last reflow request; used for confirming completion reply. last_reflow_id: Cell, @@ -257,11 +255,7 @@ impl Window { self.id } - pub fn subpage(&self) -> Option { - self.parent_info.map(|p| p.1) - } - - pub fn parent_info(&self) -> Option<(PipelineId, SubpageId)> { + pub fn parent_pipeline(&self) -> Option { self.parent_info } @@ -1126,13 +1120,6 @@ impl Window { WindowProxyHandler(self.dom_static.windowproxy_handler.0) } - pub fn get_next_subpage_id(&self) -> SubpageId { - let subpage_id = self.next_subpage_id.get(); - let SubpageId(id_num) = subpage_id; - self.next_subpage_id.set(SubpageId(id_num + 1)); - subpage_id - } - pub fn layout_is_idle(&self) -> bool { self.layout_join_port.borrow().is_none() } @@ -1269,7 +1256,7 @@ impl Window { constellation_chan: ConstellationChan, layout_chan: LayoutChan, id: PipelineId, - parent_info: Option<(PipelineId, SubpageId)>, + parent_info: Option, window_size: Option) -> Root { let layout_rpc: Box = { @@ -1312,7 +1299,6 @@ impl Window { fragment_name: DOMRefCell::new(None), last_reflow_id: Cell::new(0), resize_event: Cell::new(None), - next_subpage_id: Cell::new(SubpageId(0)), layout_chan: layout_chan, layout_rpc: layout_rpc, layout_join_port: DOMRefCell::new(None), diff --git a/components/script/script_task.rs b/components/script/script_task.rs index a935e4b91f58..dc4bc23bb5a7 100644 --- a/components/script/script_task.rs +++ b/components/script/script_task.rs @@ -66,7 +66,7 @@ use msg::compositor_msg::{LayerId, ScriptToCompositorMsg}; use msg::constellation_msg::Msg as ConstellationMsg; use msg::constellation_msg::{ConstellationChan, FocusType, LoadData}; use msg::constellation_msg::{MozBrowserEvent, PipelineExitType, PipelineId}; -use msg::constellation_msg::{SubpageId, WindowSizeData, WorkerId}; +use msg::constellation_msg::{WindowSizeData, WorkerId}; use msg::webdriver_msg::WebDriverScriptCommand; use net_traits::LoadData as NetLoadData; use net_traits::image_cache_task::{ImageCacheChan, ImageCacheResult, ImageCacheTask}; @@ -128,7 +128,7 @@ struct InProgressLoad { /// The pipeline which requested this load. pipeline_id: PipelineId, /// The parent pipeline and child subpage associated with this load, if any. - parent_info: Option<(PipelineId, SubpageId)>, + parent_info: Option, /// The current window size associated with this pipeline. window_size: Option, /// Channel to the layout task associated with this pipeline. @@ -142,7 +142,7 @@ struct InProgressLoad { impl InProgressLoad { /// Create a new InProgressLoad object. fn new(id: PipelineId, - parent_info: Option<(PipelineId, SubpageId)>, + parent_info: Option, layout_chan: LayoutChan, window_size: Option, url: Url) -> InProgressLoad { @@ -490,7 +490,7 @@ impl ScriptTaskFactory for ScriptTask { load_data.url.clone()); script_task.start_page_load(new_load, load_data); - let reporter_name = format!("script-reporter-{}", id.0); + let reporter_name = format!("script-reporter-{:?}", id); mem_profiler_chan.run_with_memory_reporting(|| { script_task.start(); }, reporter_name, channel_for_reporter, CommonScriptMsg::CollectReports); @@ -558,11 +558,11 @@ unsafe extern "C" fn shadow_check_callback(_cx: *mut JSContext, } impl ScriptTask { - pub fn page_fetch_complete(id: PipelineId, subpage: Option, metadata: Metadata) + pub fn page_fetch_complete(id: PipelineId, metadata: Metadata) -> Option> { SCRIPT_TASK_ROOT.with(|root| { let script_task = unsafe { &*root.borrow().unwrap() }; - script_task.handle_page_fetch_complete(id, subpage, metadata) + script_task.handle_page_fetch_complete(id, metadata) }) } @@ -906,8 +906,8 @@ impl ScriptTask { match msg { ConstellationControlMsg::AttachLayout(_) => panic!("should have handled AttachLayout already"), - ConstellationControlMsg::Navigate(pipeline_id, subpage_id, load_data) => - self.handle_navigate(pipeline_id, Some(subpage_id), load_data), + ConstellationControlMsg::Navigate(pipeline_id, parent_pipeline_id, load_data) => + self.handle_navigate(pipeline_id, Some(parent_pipeline_id), load_data), ConstellationControlMsg::SendEvent(id, event) => self.handle_event(id, event), ConstellationControlMsg::ReflowComplete(id, reflow_id) => @@ -927,17 +927,19 @@ impl ScriptTask { ConstellationControlMsg::Thaw(pipeline_id) => self.handle_thaw_msg(pipeline_id), ConstellationControlMsg::MozBrowserEvent(parent_pipeline_id, - subpage_id, + pipeline_id, event) => self.handle_mozbrowser_event_msg(parent_pipeline_id, - subpage_id, + pipeline_id, event), - ConstellationControlMsg::UpdateSubpageId(containing_pipeline_id, - old_subpage_id, - new_subpage_id) => - self.handle_update_subpage_id(containing_pipeline_id, old_subpage_id, new_subpage_id), - ConstellationControlMsg::FocusIFrame(containing_pipeline_id, subpage_id) => - self.handle_focus_iframe_msg(containing_pipeline_id, subpage_id), + ConstellationControlMsg::UpdatePipelineId(parent_pipeline_id, + old_pipeline_id, + new_pipeline_id) => + self.handle_update_pipeline_id(parent_pipeline_id, + old_pipeline_id, + new_pipeline_id), + ConstellationControlMsg::FocusIFrame(containing_pipeline_id, pipeline_id) => + self.handle_focus_iframe_msg(containing_pipeline_id, pipeline_id), ConstellationControlMsg::WebDriverScriptCommand(pipeline_id, msg) => self.handle_webdriver_msg(pipeline_id, msg), ConstellationControlMsg::TickAllAnimations(pipeline_id) => @@ -1128,7 +1130,6 @@ impl ScriptTask { let NewLayoutInfo { containing_pipeline_id, new_pipeline_id, - subpage_id, load_data, paint_chan, failure, @@ -1168,7 +1169,7 @@ impl ScriptTask { .unwrap(); // Kick off the fetch for the new resource. - let new_load = InProgressLoad::new(new_pipeline_id, Some((containing_pipeline_id, subpage_id)), + let new_load = InProgressLoad::new(new_pipeline_id, Some(containing_pipeline_id), layout_chan, parent_window.r().window_size(), load_data.url.clone()); self.start_page_load(new_load, load_data); @@ -1313,12 +1314,12 @@ impl ScriptTask { fn handle_focus_iframe_msg(&self, parent_pipeline_id: PipelineId, - subpage_id: SubpageId) { + pipeline_id: PipelineId) { let borrowed_page = self.root_page(); let page = borrowed_page.find(parent_pipeline_id).unwrap(); let doc = page.document(); - let frame_element = doc.find_iframe(subpage_id); + let frame_element = doc.find_iframe(pipeline_id); if let Some(ref frame_element) = frame_element { let element = ElementCast::from_ref(frame_element.r()); @@ -1332,13 +1333,13 @@ impl ScriptTask { /// https://developer.mozilla.org/en-US/docs/Web/Events/mozbrowserloadstart fn handle_mozbrowser_event_msg(&self, parent_pipeline_id: PipelineId, - subpage_id: SubpageId, + pipeline_id: PipelineId, event: MozBrowserEvent) { let borrowed_page = self.root_page(); let frame_element = borrowed_page.find(parent_pipeline_id).and_then(|page| { let doc = page.document(); - doc.find_iframe(subpage_id) + doc.find_iframe(pipeline_id) }); if let Some(ref frame_element) = frame_element { @@ -1346,18 +1347,18 @@ impl ScriptTask { } } - fn handle_update_subpage_id(&self, - containing_pipeline_id: PipelineId, - old_subpage_id: SubpageId, - new_subpage_id: SubpageId) { + fn handle_update_pipeline_id(&self, + parent_pipeline_id: PipelineId, + old_pipeline_id: PipelineId, + new_pipeline_id: PipelineId) { let borrowed_page = self.root_page(); - let frame_element = borrowed_page.find(containing_pipeline_id).and_then(|page| { + let frame_element = borrowed_page.find(parent_pipeline_id).and_then(|page| { let doc = page.document(); - doc.find_iframe(old_subpage_id) + doc.find_iframe(old_pipeline_id) }); - frame_element.r().unwrap().update_subpage_id(new_subpage_id); + frame_element.r().unwrap().update_pipeline_id(new_pipeline_id); } /// Handles a notification that reflow completed. @@ -1401,10 +1402,10 @@ impl ScriptTask { /// We have received notification that the response associated with a load has completed. /// Kick off the document and frame tree creation process using the result. - fn handle_page_fetch_complete(&self, id: PipelineId, subpage: Option, + fn handle_page_fetch_complete(&self, id: PipelineId, metadata: Metadata) -> Option> { let idx = self.incomplete_loads.borrow().iter().position(|load| { - load.pipeline_id == id && load.parent_info.map(|info| info.1) == subpage + load.pipeline_id == id }); // The matching in progress load structure may not exist if // the pipeline exited before the page load completed. @@ -1499,7 +1500,7 @@ impl ScriptTask { // existing one. let root_page_exists = self.page.borrow().is_some(); - let frame_element = incomplete.parent_info.and_then(|(parent_id, subpage_id)| { + let frame_element = incomplete.parent_info.and_then(|parent_id| { // The root page may not exist yet, if the parent of this frame // exists in a different script task. let borrowed_page = self.page.borrow(); @@ -1514,7 +1515,7 @@ impl ScriptTask { borrowed_page.as_ref().and_then(|borrowed_page| { borrowed_page.find(parent_id).and_then(|page| { let doc = page.document(); - doc.find_iframe(subpage_id) + doc.find_iframe(incomplete.pipeline_id) }) }) }); @@ -1524,7 +1525,7 @@ impl ScriptTask { if !root_page_exists { // We have a new root frame tree. *self.page.borrow_mut() = Some(page.clone()); - } else if let Some((parent, _)) = incomplete.parent_info { + } else if let Some(parent) = incomplete.parent_info { // We have a new child frame. let parent_page = self.root_page(); // TODO(gw): This find will fail when we are sharing script tasks @@ -1781,7 +1782,10 @@ impl ScriptTask { /// https://html.spec.whatwg.org/multipage/#navigating-across-documents /// The entry point for content to notify that a new load has been requested /// for the given pipeline (specifically the "navigate" algorithm). - fn handle_navigate(&self, pipeline_id: PipelineId, subpage_id: Option, load_data: LoadData) { + fn handle_navigate(&self, + pipeline_id: PipelineId, + parent_pipeline_id: Option, + load_data: LoadData) { // Step 8. { let nurl = &load_data.url; @@ -1803,12 +1807,12 @@ impl ScriptTask { } } - match subpage_id { - Some(subpage_id) => { + match parent_pipeline_id { + Some(parent_pipeline_id) => { let borrowed_page = self.root_page(); - let iframe = borrowed_page.find(pipeline_id).and_then(|page| { + let iframe = borrowed_page.find(parent_pipeline_id).and_then(|page| { let doc = page.document(); - doc.find_iframe(subpage_id) + doc.find_iframe(pipeline_id) }); if let Some(iframe) = iframe.r() { iframe.navigate_child_browsing_context(load_data.url); @@ -1853,12 +1857,11 @@ impl ScriptTask { /// argument until a notification is received that the fetch is complete. fn start_page_load(&self, incomplete: InProgressLoad, mut load_data: LoadData) { let id = incomplete.pipeline_id.clone(); - let subpage = incomplete.parent_info.clone().map(|p| p.1); let script_chan = self.chan.clone(); let resource_task = self.resource_task.clone(); - let context = Arc::new(Mutex::new(ParserContext::new(id, subpage, script_chan.clone(), + let context = Arc::new(Mutex::new(ParserContext::new(id, script_chan.clone(), load_data.url.clone()))); let (action_sender, action_receiver) = ipc::channel().unwrap(); let listener = box NetworkListener { diff --git a/components/script/webdriver_handlers.rs b/components/script/webdriver_handlers.rs index 15b31ff63e74..49de9a145a91 100644 --- a/components/script/webdriver_handlers.rs +++ b/components/script/webdriver_handlers.rs @@ -17,7 +17,7 @@ use ipc_channel::ipc::IpcSender; use js::jsapi::JSContext; use js::jsapi::{HandleValue, RootedValue}; use js::jsval::UndefinedValue; -use msg::constellation_msg::{PipelineId, SubpageId}; +use msg::constellation_msg::PipelineId; use msg::webdriver_msg::{WebDriverFrameId, WebDriverJSError, WebDriverJSResult, WebDriverJSValue}; use page::Page; use script_task::get_page; @@ -85,7 +85,7 @@ pub fn handle_execute_async_script(page: &Rc, pub fn handle_get_frame_id(page: &Rc, pipeline: PipelineId, webdriver_frame_id: WebDriverFrameId, - reply: IpcSender, ()>>) { + reply: IpcSender, ()>>) { let window = match webdriver_frame_id { WebDriverFrameId::Short(_) => { // This isn't supported yet @@ -108,8 +108,8 @@ pub fn handle_get_frame_id(page: &Rc, } }; - let frame_id = window.map(|x| x.and_then(|x| x.r().parent_info())); - reply.send(frame_id).unwrap() + let pipeline_id = window.map(|x| x.map(|x| x.r().pipeline())); + reply.send(pipeline_id).unwrap() } pub fn handle_find_element_css(page: &Rc, _pipeline: PipelineId, selector: String, diff --git a/components/script_traits/lib.rs b/components/script_traits/lib.rs index ba0f25d42e0f..dd9fffa613e5 100644 --- a/components/script_traits/lib.rs +++ b/components/script_traits/lib.rs @@ -28,7 +28,7 @@ use ipc_channel::ipc::{IpcReceiver, IpcSender}; use libc::c_void; use msg::compositor_msg::{Epoch, LayerId, ScriptToCompositorMsg}; use msg::constellation_msg::{ConstellationChan, Failure, PipelineId, WindowSizeData}; -use msg::constellation_msg::{Key, KeyModifiers, KeyState, LoadData, SubpageId}; +use msg::constellation_msg::{Key, KeyModifiers, KeyState, LoadData}; use msg::constellation_msg::{MozBrowserEvent, PipelineExitType}; use msg::webdriver_msg::WebDriverScriptCommand; use net_traits::ResourceTask; @@ -69,8 +69,6 @@ pub struct NewLayoutInfo { pub containing_pipeline_id: PipelineId, /// Id of the newly-created pipeline. pub new_pipeline_id: PipelineId, - /// Id of the new frame associated with this pipeline. - pub subpage_id: SubpageId, /// Network request data which will be initiated by the script task. pub load_data: LoadData, /// The paint channel, cast to `Box`. @@ -125,13 +123,13 @@ pub enum ConstellationControlMsg { /// Notifies script task to resume all its timers Thaw(PipelineId), /// Notifies script task that a url should be loaded in this iframe. - Navigate(PipelineId, SubpageId, LoadData), + Navigate(PipelineId, PipelineId, LoadData), /// Requests the script task forward a mozbrowser event to an iframe it owns - MozBrowserEvent(PipelineId, SubpageId, MozBrowserEvent), - /// Updates the current subpage id of a given iframe - UpdateSubpageId(PipelineId, SubpageId, SubpageId), + MozBrowserEvent(PipelineId, PipelineId, MozBrowserEvent), + /// Updates the current pipeline id of a given iframe + UpdatePipelineId(PipelineId, PipelineId, PipelineId), /// Set an iframe to be focused. Used when an element in an iframe gains focus. - FocusIFrame(PipelineId, SubpageId), + FocusIFrame(PipelineId, PipelineId), /// Passes a webdriver command to the script task for execution WebDriverScriptCommand(PipelineId, WebDriverScriptCommand), /// Notifies script task that all animations are done @@ -182,7 +180,7 @@ pub struct InitialScriptState { pub id: PipelineId, /// The subpage ID of this pipeline to create in its pipeline parent. /// If `None`, this is the root. - pub parent_info: Option<(PipelineId, SubpageId)>, + pub parent_info: Option, /// The compositor. pub compositor: IpcSender, /// A channel with which messages can be sent to us (the script task). diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock index d8e1833c5daf..2e34056252ef 100644 --- a/components/servo/Cargo.lock +++ b/components/servo/Cargo.lock @@ -1099,6 +1099,7 @@ dependencies = [ "style_traits 0.0.1", "url 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)", "util 0.0.1", + "uuid 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1833,6 +1834,7 @@ dependencies = [ "smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "url 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)", + "uuid 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/components/util/Cargo.toml b/components/util/Cargo.toml index c1f215b06480..90f397fdafea 100644 --- a/components/util/Cargo.toml +++ b/components/util/Cargo.toml @@ -58,3 +58,4 @@ string_cache = "0.1" lazy_static = "0.1" getopts = "0.2.11" hyper = "0.6" +uuid = "0.1.17" diff --git a/components/util/lib.rs b/components/util/lib.rs index 0fd7cc034dee..ab766c9dc19a 100644 --- a/components/util/lib.rs +++ b/components/util/lib.rs @@ -47,6 +47,7 @@ extern crate serde; extern crate smallvec; extern crate string_cache; extern crate url; +extern crate uuid; use std::sync::Arc; diff --git a/components/util/mem.rs b/components/util/mem.rs index aac020b33343..bd27b1498ff7 100644 --- a/components/util/mem.rs +++ b/components/util/mem.rs @@ -37,6 +37,7 @@ use str::LengthOrPercentageOrAuto; use string_cache::atom::Atom; use string_cache::namespace::Namespace; use url; +use uuid::Uuid; extern { // Get the size of a heap block. @@ -417,3 +418,4 @@ known_heap_size!(0, JSVal, PagePx, ViewportPx, DevicePixel, QuirksMode, OsRng, R known_heap_size!(0, TokenSerializationType, LengthOrPercentageOrAuto); known_heap_size!(0, PseudoElement, Combinator, str); +known_heap_size!(0, Uuid); diff --git a/components/webdriver_server/lib.rs b/components/webdriver_server/lib.rs index 22776126a942..57580b56295a 100644 --- a/components/webdriver_server/lib.rs +++ b/components/webdriver_server/lib.rs @@ -450,10 +450,10 @@ impl Handler { } let frame = match receiver.recv().unwrap() { - Ok(Some((pipeline_id, subpage_id))) => { + Ok(Some(pipeline_id)) => { let (sender, receiver) = ipc::channel().unwrap(); let ConstellationChan(ref const_chan) = self.constellation_chan; - const_chan.send(ConstellationMsg::GetFrame(pipeline_id, subpage_id, sender)).unwrap(); + const_chan.send(ConstellationMsg::GetFrame(pipeline_id, sender)).unwrap(); receiver.recv().unwrap() }, Ok(None) => None, From 64c703ae5e471c3eddca61a934ebf8c0af146643 Mon Sep 17 00:00:00 2001 From: Glenn Watson Date: Wed, 30 Sep 2015 09:08:32 +1000 Subject: [PATCH 2/3] Appease test-tidy --- components/compositing/constellation.rs | 3 +-- components/msg/constellation_msg.rs | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/components/compositing/constellation.rs b/components/compositing/constellation.rs index 7dd70317b4d5..00dee8188064 100644 --- a/components/compositing/constellation.rs +++ b/components/compositing/constellation.rs @@ -29,8 +29,7 @@ use msg::constellation_msg::Msg as ConstellationMsg; use msg::constellation_msg::WebDriverCommandMsg; use msg::constellation_msg::{FrameId, PipelineExitType, PipelineId}; use msg::constellation_msg::{IFrameSandboxState, MozBrowserEvent, NavigationDirection}; -use msg::constellation_msg::{Key, KeyModifiers, KeyState, LoadData}; -use msg::constellation_msg::WindowSizeData; +use msg::constellation_msg::{Key, KeyModifiers, KeyState, LoadData, WindowSizeData}; use msg::constellation_msg::{self, ConstellationChan, Failure}; use msg::webdriver_msg; use net_traits::image_cache_task::ImageCacheTask; diff --git a/components/msg/constellation_msg.rs b/components/msg/constellation_msg.rs index 5f0f9dd2293f..b5fe48ec7b39 100644 --- a/components/msg/constellation_msg.rs +++ b/components/msg/constellation_msg.rs @@ -16,8 +16,8 @@ use ipc_channel::ipc::IpcSender; use layers::geometry::DevicePixel; use offscreen_gl_context::GLContextAttributes; use png::Image; -use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde::bytes::ByteBuf; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; use std::collections::HashMap; use std::sync::mpsc::{Receiver, Sender, channel}; use style_traits::viewport::ViewportConstraints; @@ -416,7 +416,7 @@ impl PipelineId { } impl Serialize for PipelineId { - fn serialize(&self, serializer: &mut S) -> Result<(),S::Error> where S: Serializer { + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer { let &PipelineId(uuid) = self; uuid.as_bytes().serialize(serializer) } From c319d3e6855ecb8efd8d9b47bdd18ee9635eadb5 Mon Sep 17 00:00:00 2001 From: Glenn Watson Date: Wed, 30 Sep 2015 14:33:14 +1000 Subject: [PATCH 3/3] Introduce a namespace structure stored in TLS for any threads that create pipeline IDs. This is currently the constellation, and each script thread that is created. This guarantees that pipeline IDs are unique, without relying on UUIDs. Each time a new script thread is created, the constellation passes through a new namespace identifier. --- components/compositing/constellation.rs | 10 ++++ components/compositing/pipeline.rs | 7 ++- components/msg/Cargo.toml | 1 - components/msg/constellation_msg.rs | 76 ++++++++++++++++++------- components/msg/lib.rs | 2 +- components/script/script_task.rs | 4 +- components/script_traits/lib.rs | 4 +- components/servo/Cargo.lock | 2 - components/util/Cargo.toml | 1 - components/util/lib.rs | 1 - components/util/mem.rs | 2 - 11 files changed, 78 insertions(+), 32 deletions(-) diff --git a/components/compositing/constellation.rs b/components/compositing/constellation.rs index 00dee8188064..29af08a2c8ad 100644 --- a/components/compositing/constellation.rs +++ b/components/compositing/constellation.rs @@ -30,6 +30,7 @@ use msg::constellation_msg::WebDriverCommandMsg; use msg::constellation_msg::{FrameId, PipelineExitType, PipelineId}; use msg::constellation_msg::{IFrameSandboxState, MozBrowserEvent, NavigationDirection}; use msg::constellation_msg::{Key, KeyModifiers, KeyState, LoadData, WindowSizeData}; +use msg::constellation_msg::{PipelineNamespaceId, PipelineIdNamespace}; use msg::constellation_msg::{self, ConstellationChan, Failure}; use msg::webdriver_msg; use net_traits::image_cache_task::ImageCacheTask; @@ -129,6 +130,9 @@ pub struct Constellation { /// A list of in-process senders to `WebGLPaintTask`s. webgl_paint_tasks: Vec>, + + /// Next namespace id for pipeline id generation, + next_namespace_id: PipelineNamespaceId, } /// State needed to construct a constellation. @@ -271,7 +275,9 @@ impl Constellation { webdriver: WebDriverData::new(), canvas_paint_tasks: Vec::new(), webgl_paint_tasks: Vec::new(), + next_namespace_id: PipelineNamespaceId(1), }; + PipelineIdNamespace::install(PipelineNamespaceId(0)); constellation.run(); }); constellation_chan @@ -311,8 +317,12 @@ impl Constellation { script_chan: script_channel, load_data: load_data, device_pixel_ratio: self.window_size.device_pixel_ratio, + pipeline_namespace_id: self.next_namespace_id, }); + let PipelineNamespaceId(namespace_id) = self.next_namespace_id; + self.next_namespace_id = PipelineNamespaceId(namespace_id + 1); + // TODO(pcwalton): In multiprocess mode, send that `PipelineContent` instance over to // the content process and call this over there. if spawning_paint_only { diff --git a/components/compositing/pipeline.rs b/components/compositing/pipeline.rs index f0e1649881f8..a2138ee85e96 100644 --- a/components/compositing/pipeline.rs +++ b/components/compositing/pipeline.rs @@ -14,7 +14,7 @@ use ipc_channel::router::ROUTER; use layers::geometry::DevicePixel; use layout_traits::{LayoutControlChan, LayoutTaskFactory}; use msg::constellation_msg::{ConstellationChan, Failure, FrameId, PipelineId}; -use msg::constellation_msg::{LoadData, MozBrowserEvent, PipelineExitType, WindowSizeData}; +use msg::constellation_msg::{LoadData, MozBrowserEvent, PipelineExitType, PipelineNamespaceId, WindowSizeData}; use net_traits::ResourceTask; use net_traits::image_cache_task::ImageCacheTask; use net_traits::storage_task::StorageTask; @@ -96,6 +96,8 @@ pub struct InitialPipelineState { pub script_chan: Option>, /// Information about the page to load. pub load_data: LoadData, + /// The namespace ID to use for creating new pipeline IDs. + pub pipeline_namespace_id: PipelineNamespaceId, } impl Pipeline { @@ -193,6 +195,7 @@ impl Pipeline { pipeline_port: pipeline_port, paint_shutdown_chan: paint_shutdown_chan, layout_shutdown_chan: layout_shutdown_chan, + pipeline_namespace_id: state.pipeline_namespace_id, }; (pipeline, pipeline_content) @@ -321,6 +324,7 @@ pub struct PipelineContent { paint_shutdown_chan: Sender<()>, pipeline_port: Option>, layout_shutdown_chan: Sender<()>, + pipeline_namespace_id: PipelineNamespaceId, } impl PipelineContent { @@ -353,6 +357,7 @@ impl PipelineContent { mem_profiler_chan: self.mem_profiler_chan.clone(), devtools_chan: self.devtools_chan, window_size: self.window_size, + pipeline_namespace_id: self.pipeline_namespace_id, }, &layout_pair, self.load_data.clone()); LayoutTaskFactory::create(None::<&mut LTF>, diff --git a/components/msg/Cargo.toml b/components/msg/Cargo.toml index e0e58b2360ac..a1f6f80c1faa 100644 --- a/components/msg/Cargo.toml +++ b/components/msg/Cargo.toml @@ -50,7 +50,6 @@ rustc-serialize = "0.3.4" euclid = "0.2" serde = "0.6" serde_macros = "0.5" -uuid = "0.1.17" [target.x86_64-apple-darwin.dependencies] core-foundation = "0.1" diff --git a/components/msg/constellation_msg.rs b/components/msg/constellation_msg.rs index b5fe48ec7b39..edccb3170f27 100644 --- a/components/msg/constellation_msg.rs +++ b/components/msg/constellation_msg.rs @@ -16,8 +16,8 @@ use ipc_channel::ipc::IpcSender; use layers::geometry::DevicePixel; use offscreen_gl_context::GLContextAttributes; use png::Image; -use serde::bytes::ByteBuf; -use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use serde::{Deserializer, Serializer}; +use std::cell::RefCell; use std::collections::HashMap; use std::sync::mpsc::{Receiver, Sender, channel}; use style_traits::viewport::ViewportConstraints; @@ -25,7 +25,6 @@ use url::Url; use util::cursor::Cursor; use util::geometry::{PagePx, ViewportPx}; use util::mem::HeapSizeOf; -use uuid::Uuid; use webdriver_msg::{LoadStatus, WebDriverScriptCommand}; #[derive(Clone)] @@ -388,14 +387,56 @@ pub enum NavigationDirection { Back, } +#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug, Deserialize, Serialize, HeapSizeOf)] +pub struct PipelineNamespaceId(pub u32); + +#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug, Deserialize, Serialize, HeapSizeOf)] +pub struct PipelineIndex(u32); + +pub struct PipelineIdNamespace { + id: PipelineNamespaceId, + next_index: PipelineIndex, +} + +impl PipelineIdNamespace { + pub fn install(namespace_id: PipelineNamespaceId) { + PIPELINE_NAMESPACE.with(|tls| { + let mut namespace = tls.borrow_mut(); + assert!(namespace.is_none()); + + *namespace = Some(PipelineIdNamespace { + id: namespace_id, + next_index: PipelineIndex(1), + }); + }); + } + + fn next(&mut self) -> PipelineId { + let pipeline_id = PipelineId { + namespace_id: self.id, + index: self.next_index, + }; + + let PipelineIndex(current_index) = self.next_index; + self.next_index = PipelineIndex(current_index + 1); + + pipeline_id + } +} + +thread_local!(pub static PIPELINE_NAMESPACE: RefCell> = RefCell::new(None)); + #[derive(Clone, PartialEq, Eq, Copy, Hash, Debug, Deserialize, Serialize)] pub struct FrameId(pub u32); #[derive(Clone, PartialEq, Eq, Copy, Hash, Debug, Deserialize, Serialize, HeapSizeOf)] pub struct WorkerId(pub u32); -#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug, HeapSizeOf)] -pub struct PipelineId(Uuid); +#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug, Deserialize, Serialize, HeapSizeOf)] +pub struct PipelineId { + namespace_id: PipelineNamespaceId, + index: PipelineIndex +} // The type of pipeline exit. During complete shutdowns, pipelines do not have to // release resources automatically released on process termination. @@ -407,24 +448,17 @@ pub enum PipelineExitType { impl PipelineId { pub fn new() -> PipelineId { - PipelineId(Uuid::new_v4()) + PIPELINE_NAMESPACE.with(|tls| { + let mut namespace = tls.borrow_mut(); + let mut namespace = namespace.as_mut().expect("No namespace set for this thread!"); + namespace.next() + }) } pub fn nil() -> PipelineId { - PipelineId(Uuid::nil()) - } -} - -impl Serialize for PipelineId { - fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer { - let &PipelineId(uuid) = self; - uuid.as_bytes().serialize(serializer) - } -} - -impl Deserialize for PipelineId { - fn deserialize(deserializer: &mut D) -> Result where D: Deserializer { - let bytes = try!(ByteBuf::deserialize(deserializer)); - Ok(PipelineId(Uuid::from_bytes(&bytes).unwrap())) + PipelineId { + namespace_id: PipelineNamespaceId(0), + index: PipelineIndex(0), + } } } diff --git a/components/msg/lib.rs b/components/msg/lib.rs index 4b69294712a4..f839a603d99f 100644 --- a/components/msg/lib.rs +++ b/components/msg/lib.rs @@ -3,6 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #![feature(custom_derive, plugin)] +#![feature(const_fn)] #![plugin(serde_macros, plugins)] #[macro_use] @@ -24,7 +25,6 @@ extern crate serde; extern crate style_traits; extern crate url; extern crate util; -extern crate uuid; pub mod compositor_msg; pub mod constellation_msg; diff --git a/components/script/script_task.rs b/components/script/script_task.rs index dc4bc23bb5a7..4353d5ff3f99 100644 --- a/components/script/script_task.rs +++ b/components/script/script_task.rs @@ -66,7 +66,7 @@ use msg::compositor_msg::{LayerId, ScriptToCompositorMsg}; use msg::constellation_msg::Msg as ConstellationMsg; use msg::constellation_msg::{ConstellationChan, FocusType, LoadData}; use msg::constellation_msg::{MozBrowserEvent, PipelineExitType, PipelineId}; -use msg::constellation_msg::{WindowSizeData, WorkerId}; +use msg::constellation_msg::{PipelineIdNamespace, WindowSizeData, WorkerId}; use msg::webdriver_msg::WebDriverScriptCommand; use net_traits::LoadData as NetLoadData; use net_traits::image_cache_task::{ImageCacheChan, ImageCacheResult, ImageCacheTask}; @@ -467,6 +467,7 @@ impl ScriptTaskFactory for ScriptTask { let (script_chan, script_port) = channel(); let layout_chan = LayoutChan(layout_chan.sender()); let failure_info = state.failure_info; + let pipeline_namespace_id = state.pipeline_namespace_id; spawn_named_with_send_on_failure(format!("ScriptTask {:?}", state.id), task_state::SCRIPT, move || { let roots = RootCollection::new(); let _stack_roots_tls = StackRootTLS::new(&roots); @@ -479,6 +480,7 @@ impl ScriptTaskFactory for ScriptTask { let script_task = ScriptTask::new(state, script_port, chan); + PipelineIdNamespace::install(pipeline_namespace_id); SCRIPT_TASK_ROOT.with(|root| { *root.borrow_mut() = Some(&script_task as *const _); diff --git a/components/script_traits/lib.rs b/components/script_traits/lib.rs index dd9fffa613e5..0c1a2692d8a6 100644 --- a/components/script_traits/lib.rs +++ b/components/script_traits/lib.rs @@ -29,7 +29,7 @@ use libc::c_void; use msg::compositor_msg::{Epoch, LayerId, ScriptToCompositorMsg}; use msg::constellation_msg::{ConstellationChan, Failure, PipelineId, WindowSizeData}; use msg::constellation_msg::{Key, KeyModifiers, KeyState, LoadData}; -use msg::constellation_msg::{MozBrowserEvent, PipelineExitType}; +use msg::constellation_msg::{MozBrowserEvent, PipelineExitType, PipelineNamespaceId}; use msg::webdriver_msg::WebDriverScriptCommand; use net_traits::ResourceTask; use net_traits::image_cache_task::ImageCacheTask; @@ -205,6 +205,8 @@ pub struct InitialScriptState { pub devtools_chan: Option>, /// Information about the initial window size. pub window_size: Option, + /// The ID of the namespace to use when creating pipeline IDs. + pub pipeline_namespace_id: PipelineNamespaceId, } /// This trait allows creating a `ScriptTask` without depending on the `script` diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock index 2e34056252ef..d8e1833c5daf 100644 --- a/components/servo/Cargo.lock +++ b/components/servo/Cargo.lock @@ -1099,7 +1099,6 @@ dependencies = [ "style_traits 0.0.1", "url 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)", "util 0.0.1", - "uuid 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1834,7 +1833,6 @@ dependencies = [ "smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "url 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/components/util/Cargo.toml b/components/util/Cargo.toml index 90f397fdafea..c1f215b06480 100644 --- a/components/util/Cargo.toml +++ b/components/util/Cargo.toml @@ -58,4 +58,3 @@ string_cache = "0.1" lazy_static = "0.1" getopts = "0.2.11" hyper = "0.6" -uuid = "0.1.17" diff --git a/components/util/lib.rs b/components/util/lib.rs index ab766c9dc19a..0fd7cc034dee 100644 --- a/components/util/lib.rs +++ b/components/util/lib.rs @@ -47,7 +47,6 @@ extern crate serde; extern crate smallvec; extern crate string_cache; extern crate url; -extern crate uuid; use std::sync::Arc; diff --git a/components/util/mem.rs b/components/util/mem.rs index bd27b1498ff7..aac020b33343 100644 --- a/components/util/mem.rs +++ b/components/util/mem.rs @@ -37,7 +37,6 @@ use str::LengthOrPercentageOrAuto; use string_cache::atom::Atom; use string_cache::namespace::Namespace; use url; -use uuid::Uuid; extern { // Get the size of a heap block. @@ -418,4 +417,3 @@ known_heap_size!(0, JSVal, PagePx, ViewportPx, DevicePixel, QuirksMode, OsRng, R known_heap_size!(0, TokenSerializationType, LengthOrPercentageOrAuto); known_heap_size!(0, PseudoElement, Combinator, str); -known_heap_size!(0, Uuid);