Excise SubpageId and use only PipelineIds

SubpageId was originally introduced in 2013 to help iframes keep track of
their associated (children) pipelines. However, since each pipeline
already has a PipelineId, and those are unique, those are sufficient
to keep track of children.
This commit is contained in:
Aneesh Agrawal 2016-06-09 08:17:30 -04:00
parent b9b25b6f82
commit 56fbfd46a4
12 changed files with 145 additions and 217 deletions

View file

@ -28,7 +28,7 @@ use log::{Log, LogLevel, LogLevelFilter, LogMetadata, LogRecord};
use msg::constellation_msg::{FrameId, FrameType, PipelineId};
use msg::constellation_msg::{Key, KeyModifiers, KeyState, LoadData};
use msg::constellation_msg::{PipelineNamespace, PipelineNamespaceId, TraversalDirection};
use msg::constellation_msg::{SubpageId, WindowSizeType};
use msg::constellation_msg::WindowSizeType;
use net_traits::{self, IpcSend, ResourceThreads};
use net_traits::bluetooth_thread::BluetoothMethodMsg;
use net_traits::image_cache_thread::ImageCacheThread;
@ -135,9 +135,6 @@ pub struct Constellation<Message, LTF, STF> {
/// A list of all the frames
frames: HashMap<FrameId, Frame>,
/// 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_thread: FontCacheThread,
@ -492,7 +489,6 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
swmanager_sender: sw_mgr_clone,
pipelines: HashMap::new(),
frames: HashMap::new(),
subpage_map: HashMap::new(),
pending_frames: vec!(),
next_pipeline_namespace_id: PipelineNamespaceId(0),
root_frame_id: None,
@ -551,7 +547,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
/// Helper function for creating a pipeline
fn new_pipeline(&mut self,
pipeline_id: PipelineId,
parent_info: Option<(PipelineId, SubpageId, FrameType)>,
parent_info: Option<(PipelineId, FrameType)>,
initial_window_size: Option<TypedSize2D<f32, PagePx>>,
script_channel: Option<IpcSender<ConstellationControlMsg>>,
load_data: LoadData,
@ -564,7 +560,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
self.public_resource_threads.clone()
};
let parent_visibility = if let Some((parent_pipeline_id, _, _)) = parent_info {
let parent_visibility = if let Some((parent_pipeline_id, _)) = parent_info {
self.pipelines.get(&parent_pipeline_id).map(|pipeline| pipeline.visible)
} else {
None
@ -826,8 +822,8 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
FromScriptMsg::ScriptLoadedURLInIFrame(load_info) => {
debug!("constellation got iframe URL load message {:?} {:?} {:?}",
load_info.parent_pipeline_id,
load_info.old_subpage_id,
load_info.new_subpage_id);
load_info.old_pipeline_id,
load_info.new_pipeline_id);
self.handle_script_loaded_url_in_iframe_msg(load_info);
}
FromScriptMsg::ChangeRunningAnimationsState(pipeline_id, animation_state) => {
@ -870,10 +866,10 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
warn!("constellation got set final url message for dead pipeline");
}
}
FromScriptMsg::MozBrowserEvent(pipeline_id, subpage_id, event) => {
FromScriptMsg::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);
}
FromScriptMsg::Focus(pipeline_id) => {
@ -1230,12 +1226,8 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
// parent_pipeline_id's frame tree's children. This message is never the result of a
// page navigation.
fn handle_script_loaded_url_in_iframe_msg(&mut self, load_info: IFrameLoadInfo) {
let old_pipeline_id = load_info.old_subpage_id
.and_then(|old_subpage_id| self.subpage_map.get(&(load_info.parent_pipeline_id, old_subpage_id)))
.cloned();
let (load_data, script_chan, window_size, is_private) = {
let old_pipeline = old_pipeline_id
let old_pipeline = load_info.old_pipeline_id
.and_then(|old_pipeline_id| self.pipelines.get(&old_pipeline_id));
let source_pipeline = match self.pipelines.get(&load_info.parent_pipeline_id) {
@ -1290,16 +1282,13 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
// Create the new pipeline, attached to the parent and push to pending frames
self.new_pipeline(load_info.new_pipeline_id,
Some((load_info.parent_pipeline_id, load_info.new_subpage_id, load_info.frame_type)),
Some((load_info.parent_pipeline_id, load_info.frame_type)),
window_size,
script_chan,
load_data,
is_private);
self.subpage_map.insert((load_info.parent_pipeline_id, load_info.new_subpage_id),
load_info.new_pipeline_id);
self.push_pending_frame(load_info.new_pipeline_id, old_pipeline_id);
self.push_pending_frame(load_info.new_pipeline_id, load_info.old_pipeline_id);
}
fn handle_set_cursor_msg(&mut self, cursor: Cursor) {
@ -1347,14 +1336,14 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
.map(|root_frame| root_frame.current.pipeline_id);
let ancestor_info = self.get_mozbrowser_ancestor_info(pipeline_id);
if let Some((ancestor_id, subpage_id)) = ancestor_info {
if let Some((ancestor_id, mozbrowser_iframe_id)) = ancestor_info {
if root_pipeline_id == Some(ancestor_id) {
match root_pipeline_id.and_then(|pipeline_id| self.pipelines.get(&pipeline_id)) {
Some(root_pipeline) => {
// https://developer.mozilla.org/en-US/docs/Web/Events/mozbrowsershowmodalprompt
let event = MozBrowserEvent::ShowModalPrompt("alert".to_owned(), "Alert".to_owned(),
String::from(message), "".to_owned());
root_pipeline.trigger_mozbrowser_event(Some(subpage_id), event);
root_pipeline.trigger_mozbrowser_event(Some(mozbrowser_iframe_id), event);
}
None => return warn!("Alert sent to Pipeline {:?} after closure.", root_pipeline_id),
}
@ -1387,11 +1376,11 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
// requested change so it can update its internal state.
let parent_info = self.pipelines.get(&source_id).and_then(|source| source.parent_info);
match 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 thread for this iframe
// and issue an iframe load through there.
let msg = ConstellationControlMsg::Navigate(parent_pipeline_id, subpage_id, load_data);
let msg = ConstellationControlMsg::Navigate(parent_pipeline_id, source_id, load_data);
let result = match self.pipelines.get(&parent_pipeline_id) {
Some(parent_pipeline) => parent_pipeline.script_chan.send(msg),
None => {
@ -1586,7 +1575,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
fn handle_mozbrowser_event_msg(&mut self,
parent_pipeline_id: PipelineId,
subpage_id: Option<SubpageId>,
pipeline_id: Option<PipelineId>,
event: MozBrowserEvent) {
assert!(PREFS.is_mozbrowser_enabled());
@ -1595,7 +1584,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
// If the pipeline lookup fails, it is because we have torn down the pipeline,
// so it is reasonable to silently ignore the event.
match self.pipelines.get(&parent_pipeline_id) {
Some(pipeline) => pipeline.trigger_mozbrowser_event(subpage_id, event),
Some(pipeline) => pipeline.trigger_mozbrowser_event(pipeline_id, event),
None => warn!("Pipeline {:?} handling mozbrowser event after closure.", parent_pipeline_id),
}
}
@ -1630,14 +1619,14 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
Some(pipeline) => pipeline.parent_info,
None => return warn!("Pipeline {:?} focus parent after closure.", pipeline_id),
};
let (parent_pipeline_id, subpage_id, _) = match parent_info {
let (parent_pipeline_id, _) = match parent_info {
Some(info) => info,
None => return debug!("Pipeline {:?} focus has no parent.", pipeline_id),
};
// Send a message to the parent of the provided pipeline (if it exists)
// telling it to mark the iframe element as focused.
let msg = ConstellationControlMsg::FocusIFrame(parent_pipeline_id, subpage_id);
let msg = ConstellationControlMsg::FocusIFrame(parent_pipeline_id, pipeline_id);
let result = match self.pipelines.get(&parent_pipeline_id) {
Some(pipeline) => pipeline.script_chan.send(msg),
None => return warn!("Pipeline {:?} focus after closure.", parent_pipeline_id),
@ -1685,7 +1674,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
fn handle_visibility_change_complete(&mut self, pipeline_id: PipelineId, visibility: bool) {
let parent_pipeline_info = self.pipelines.get(&pipeline_id).and_then(|source| source.parent_info);
if let Some((parent_pipeline_id, _, _)) = parent_pipeline_info {
if let Some((parent_pipeline_id, _)) = parent_pipeline_info {
let visibility_msg = ConstellationControlMsg::NotifyVisibilityChange(parent_pipeline_id,
pipeline_id,
visibility);
@ -1855,20 +1844,12 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
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 {
let new_subpage_id = match self.pipelines.get(&next_pipeline_id) {
None => return warn!("Pipeline {:?} traversed to after closure.", next_pipeline_id),
Some(pipeline) => match pipeline.parent_info {
None => return warn!("Pipeline {:?} has no parent info.", next_pipeline_id),
Some((_, new_subpage_id, _)) => new_subpage_id,
},
};
let msg = ConstellationControlMsg::UpdateSubpageId(parent_pipeline_id,
subpage_id,
new_subpage_id,
next_pipeline_id);
if let Some((parent_pipeline_id, _)) = pipeline_info {
let msg = ConstellationControlMsg::UpdatePipelineId(parent_pipeline_id,
prev_pipeline_id,
next_pipeline_id);
let result = match self.pipelines.get(&parent_pipeline_id) {
None => return warn!("Pipeline {:?} child traversed after closure.", parent_pipeline_id),
Some(pipeline) => pipeline.script_chan.send(msg),
@ -1886,8 +1867,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
fn get_top_level_frame_for_pipeline(&self, pipeline_id: Option<PipelineId>) -> Option<FrameId> {
if PREFS.is_mozbrowser_enabled() {
pipeline_id.and_then(|id| self.get_mozbrowser_ancestor_info(id))
.and_then(|info| self.subpage_map.get(&info))
.and_then(|pipeline_id| self.pipelines.get(&pipeline_id))
.and_then(|pipeline_info| self.pipelines.get(&pipeline_info.1))
.and_then(|pipeline| pipeline.frame)
.or(self.root_frame_id)
} else {
@ -1940,7 +1920,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
// If a child frame, add it to the parent pipeline. Otherwise
// it must surely be the root frame being created!
match self.pipelines.get(&frame_change.new_pipeline_id).and_then(|pipeline| pipeline.parent_info) {
Some((parent_id, _, _)) => {
Some((parent_id, _)) => {
if let Some(parent) = self.pipelines.get_mut(&parent_id) {
parent.add_child(frame_id);
}
@ -1976,7 +1956,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
let _ = parent_pipeline.script_chan
.send(ConstellationControlMsg::FramedContentChanged(
parent_info.0,
parent_info.1));
pipeline_id));
}
}
}
@ -2250,7 +2230,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
warn!("Closing frame {:?} twice.", frame_id);
}
if let Some((parent_pipeline_id, _, _)) = parent_info {
if let Some((parent_pipeline_id, _)) = parent_info {
let parent_pipeline = match self.pipelines.get_mut(&parent_pipeline_id) {
None => return warn!("Pipeline {:?} child closed after parent.", parent_pipeline_id),
Some(parent_pipeline) => parent_pipeline,
@ -2285,10 +2265,6 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
None => return warn!("Closing pipeline {:?} twice.", pipeline_id),
};
// If a child pipeline, remove from subpage map
if let Some((parent_id, subpage_id, _)) = pipeline.parent_info {
self.subpage_map.remove(&(parent_id, subpage_id));
}
// Remove assocation between this pipeline and its holding frame
pipeline.frame = None;
@ -2388,12 +2364,13 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
/// For a given pipeline, determine the mozbrowser iframe that transitively contains
/// it. There could be arbitrary levels of nested iframes in between them.
fn get_mozbrowser_ancestor_info(&self, mut pipeline_id: PipelineId) -> Option<(PipelineId, SubpageId)> {
fn get_mozbrowser_ancestor_info(&self, original_pipeline_id: PipelineId) -> Option<(PipelineId, PipelineId)> {
let mut pipeline_id = original_pipeline_id;
loop {
match self.pipelines.get(&pipeline_id) {
Some(pipeline) => match pipeline.parent_info {
Some((parent_id, subpage_id, FrameType::MozBrowserIFrame)) => return Some((parent_id, subpage_id)),
Some((parent_id, _, _)) => pipeline_id = parent_id,
Some((parent_id, FrameType::MozBrowserIFrame)) => return Some((parent_id, pipeline_id)),
Some((parent_id, _)) => pipeline_id = parent_id,
None => return None,
},
None => {
@ -2415,15 +2392,14 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
};
// If this is a mozbrowser iframe, then send the event with new url
if let Some((parent_pipeline_id, subpage_id)) = self.get_mozbrowser_ancestor_info(pipeline_id) {
if let Some(parent_pipeline) = self.pipelines.get(&parent_pipeline_id) {
let pipeline_id = self.subpage_map.get(&(parent_pipeline_id, subpage_id));
if let Some(pipeline) = pipeline_id.and_then(|pipeline_id| self.pipelines.get(pipeline_id)) {
if let Some((ancestor_id, mozbrowser_iframe_id)) = self.get_mozbrowser_ancestor_info(pipeline_id) {
if let Some(ancestor) = self.pipelines.get(&ancestor_id) {
if let Some(pipeline) = self.pipelines.get(&mozbrowser_iframe_id) {
if let Some(frame_id) = pipeline.frame {
let can_go_forward = !self.joint_session_future(frame_id).is_empty();
let can_go_back = !self.joint_session_past(frame_id).is_empty();
let event = MozBrowserEvent::LocationChange(url, can_go_back, can_go_forward);
parent_pipeline.trigger_mozbrowser_event(Some(subpage_id), event);
ancestor.trigger_mozbrowser_event(Some(mozbrowser_iframe_id), event);
}
}
}
@ -2455,9 +2431,9 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
let event = MozBrowserEvent::Error(MozBrowserErrorType::Fatal, reason, report);
if let Some(pipeline_id) = pipeline_id {
if let Some((ancestor_id, subpage_id)) = self.get_mozbrowser_ancestor_info(pipeline_id) {
if let Some((ancestor_id, mozbrowser_iframe_id)) = self.get_mozbrowser_ancestor_info(pipeline_id) {
if let Some(ancestor) = self.pipelines.get(&ancestor_id) {
return ancestor.trigger_mozbrowser_event(Some(subpage_id), event);
return ancestor.trigger_mozbrowser_event(Some(mozbrowser_iframe_id), event);
}
}
}

View file

@ -17,8 +17,7 @@ use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
use ipc_channel::router::ROUTER;
use layers::geometry::DevicePixel;
use layout_traits::LayoutThreadFactory;
use msg::constellation_msg::{FrameId, FrameType, LoadData, PipelineId};
use msg::constellation_msg::{PipelineNamespaceId, SubpageId};
use msg::constellation_msg::{FrameId, FrameType, LoadData, PipelineId, PipelineNamespaceId};
use net_traits::{IpcSend, ResourceThreads};
use net_traits::bluetooth_thread::BluetoothMethodMsg;
use net_traits::image_cache_thread::ImageCacheThread;
@ -51,7 +50,7 @@ pub enum ChildProcess {
/// A uniquely-identifiable pipeline of script thread, layout thread, and paint thread.
pub struct Pipeline {
pub id: PipelineId,
pub parent_info: Option<(PipelineId, SubpageId, FrameType)>,
pub parent_info: Option<(PipelineId, FrameType)>,
pub script_chan: IpcSender<ConstellationControlMsg>,
/// A channel to layout, for performing reflows and shutdown.
pub layout_chan: IpcSender<LayoutControlMsg>,
@ -84,9 +83,9 @@ pub struct Pipeline {
pub struct InitialPipelineState {
/// The ID of the pipeline to create.
pub id: PipelineId,
/// The subpage ID of this pipeline to create in its pipeline parent.
/// The ID of the parent pipeline and frame type, if any.
/// If `None`, this is the root.
pub parent_info: Option<(PipelineId, SubpageId, FrameType)>,
pub parent_info: Option<(PipelineId, FrameType)>,
/// A channel to the associated constellation.
pub constellation_chan: IpcSender<ScriptMsg>,
/// A channel for the layout thread to send messages to the constellation.
@ -150,12 +149,11 @@ impl Pipeline {
let (script_chan, content_ports) = match state.script_chan {
Some(script_chan) => {
let (parent_pipeline_id, subpage_id, frame_type) =
state.parent_info.expect("script_pipeline != None but subpage_id == None");
let (parent_pipeline_id, frame_type) =
state.parent_info.expect("script_pipeline != None but parent_info == None");
let new_layout_info = NewLayoutInfo {
parent_pipeline_id: parent_pipeline_id,
new_pipeline_id: state.id,
subpage_id: subpage_id,
frame_type: frame_type,
load_data: state.load_data.clone(),
paint_chan: layout_to_paint_chan.clone().to_opaque(),
@ -273,7 +271,7 @@ impl Pipeline {
}
fn new(id: PipelineId,
parent_info: Option<(PipelineId, SubpageId, FrameType)>,
parent_info: Option<(PipelineId, FrameType)>,
script_chan: IpcSender<ConstellationControlMsg>,
layout_chan: IpcSender<LayoutControlMsg>,
compositor_proxy: Box<CompositorProxy + 'static + Send>,
@ -377,12 +375,12 @@ impl Pipeline {
}
pub fn trigger_mozbrowser_event(&self,
subpage_id: Option<SubpageId>,
child_id: Option<PipelineId>,
event: MozBrowserEvent) {
assert!(PREFS.is_mozbrowser_enabled());
let event = ConstellationControlMsg::MozBrowserEvent(self.id,
subpage_id,
child_id,
event);
if let Err(e) = self.script_chan.send(event) {
warn!("Sending mozbrowser event to script failed ({}).", e);
@ -409,7 +407,7 @@ impl Pipeline {
#[derive(Deserialize, Serialize)]
pub struct UnprivilegedPipelineContent {
id: PipelineId,
parent_info: Option<(PipelineId, SubpageId, FrameType)>,
parent_info: Option<(PipelineId, FrameType)>,
constellation_chan: IpcSender<ScriptMsg>,
layout_to_constellation_chan: IpcSender<LayoutMsg>,
scheduler_chan: IpcSender<TimerEventRequest>,