mirror of
https://github.com/servo/servo.git
synced 2025-08-01 19:50:30 +01:00
Update FrameTree pipelines when appropriate
Instead of simply creating a new FrameTree when an iframe starts a load, update the existing FrameTree's pipeline. This prevents the FrameTree from accumulating many extra children.
This commit is contained in:
parent
c1d218cf02
commit
6a46eef5cd
4 changed files with 126 additions and 95 deletions
|
@ -98,7 +98,7 @@ struct FrameTree {
|
||||||
/// The ID of this frame.
|
/// The ID of this frame.
|
||||||
pub id: FrameId,
|
pub id: FrameId,
|
||||||
/// The pipeline for this frame.
|
/// The pipeline for this frame.
|
||||||
pub pipeline: Rc<Pipeline>,
|
pub pipeline: RefCell<Rc<Pipeline>>,
|
||||||
/// The parent frame's pipeline.
|
/// The parent frame's pipeline.
|
||||||
pub parent: RefCell<Option<Rc<Pipeline>>>,
|
pub parent: RefCell<Option<Rc<Pipeline>>>,
|
||||||
/// A vector of child frames.
|
/// A vector of child frames.
|
||||||
|
@ -112,7 +112,7 @@ impl FrameTree {
|
||||||
-> FrameTree {
|
-> FrameTree {
|
||||||
FrameTree {
|
FrameTree {
|
||||||
id: id,
|
id: id,
|
||||||
pipeline: pipeline,
|
pipeline: RefCell::new(pipeline.clone()),
|
||||||
parent: RefCell::new(parent_pipeline),
|
parent: RefCell::new(parent_pipeline),
|
||||||
children: RefCell::new(vec!()),
|
children: RefCell::new(vec!()),
|
||||||
has_compositor_layer: Cell::new(false),
|
has_compositor_layer: Cell::new(false),
|
||||||
|
@ -165,7 +165,7 @@ pub struct FrameTreeDiff {
|
||||||
impl FrameTree {
|
impl FrameTree {
|
||||||
fn to_sendable(&self) -> SendableFrameTree {
|
fn to_sendable(&self) -> SendableFrameTree {
|
||||||
SendableFrameTree {
|
SendableFrameTree {
|
||||||
pipeline: self.pipeline.to_sendable(),
|
pipeline: self.pipeline.borrow().to_sendable(),
|
||||||
children: self.children
|
children: self.children
|
||||||
.borrow()
|
.borrow()
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -178,18 +178,24 @@ impl FrameTree {
|
||||||
trait FrameTreeTraversal {
|
trait FrameTreeTraversal {
|
||||||
fn contains(&self, id: PipelineId) -> bool;
|
fn contains(&self, id: PipelineId) -> bool;
|
||||||
fn find(&self, id: PipelineId) -> Option<Self>;
|
fn find(&self, id: PipelineId) -> Option<Self>;
|
||||||
|
fn find_with_subpage_id(&self, id: Option<SubpageId>) -> Option<Rc<FrameTree>>;
|
||||||
fn replace_child(&self, id: PipelineId, new_child: Self) -> ReplaceResult;
|
fn replace_child(&self, id: PipelineId, new_child: Self) -> ReplaceResult;
|
||||||
fn iter(&self) -> FrameTreeIterator;
|
fn iter(&self) -> FrameTreeIterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FrameTreeTraversal for Rc<FrameTree> {
|
impl FrameTreeTraversal for Rc<FrameTree> {
|
||||||
fn contains(&self, id: PipelineId) -> bool {
|
fn contains(&self, id: PipelineId) -> bool {
|
||||||
self.iter().any(|frame_tree| id == frame_tree.pipeline.id)
|
self.iter().any(|frame_tree| id == frame_tree.pipeline.borrow().id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the frame tree whose key is id
|
/// Returns the frame tree whose key is id
|
||||||
fn find(&self, id: PipelineId) -> Option<Rc<FrameTree>> {
|
fn find(&self, id: PipelineId) -> Option<Rc<FrameTree>> {
|
||||||
self.iter().find(|frame_tree| id == frame_tree.pipeline.id)
|
self.iter().find(|frame_tree| id == frame_tree.pipeline.borrow().id)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the frame tree whose subpage is id
|
||||||
|
fn find_with_subpage_id(&self, id: Option<SubpageId>) -> Option<Rc<FrameTree>> {
|
||||||
|
self.iter().find(|frame_tree| id == frame_tree.pipeline.borrow().subpage_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Replaces a node of the frame tree in place. Returns the node that was removed or the
|
/// Replaces a node of the frame tree in place. Returns the node that was removed or the
|
||||||
|
@ -198,7 +204,7 @@ impl FrameTreeTraversal for Rc<FrameTree> {
|
||||||
for frame_tree in self.iter() {
|
for frame_tree in self.iter() {
|
||||||
let mut children = frame_tree.children.borrow_mut();
|
let mut children = frame_tree.children.borrow_mut();
|
||||||
let child = children.iter_mut()
|
let child = children.iter_mut()
|
||||||
.find(|child| child.frame_tree.pipeline.id == id);
|
.find(|child| child.frame_tree.pipeline.borrow().id == id);
|
||||||
match child {
|
match child {
|
||||||
Some(child) => {
|
Some(child) => {
|
||||||
*new_child.parent.borrow_mut() = child.frame_tree.parent.borrow().clone();
|
*new_child.parent.borrow_mut() = child.frame_tree.parent.borrow().clone();
|
||||||
|
@ -293,7 +299,7 @@ impl NavigationContext {
|
||||||
/// Loads a new set of page frames, returning all evicted frame trees
|
/// Loads a new set of page frames, returning all evicted frame trees
|
||||||
fn load(&mut self, frame_tree: Rc<FrameTree>, compositor_proxy: &mut CompositorProxy)
|
fn load(&mut self, frame_tree: Rc<FrameTree>, compositor_proxy: &mut CompositorProxy)
|
||||||
-> Vec<Rc<FrameTree>> {
|
-> Vec<Rc<FrameTree>> {
|
||||||
debug!("navigating to {}", frame_tree.pipeline.id);
|
debug!("navigating to {}", frame_tree.pipeline.borrow().id);
|
||||||
let evicted = replace(&mut self.next, vec!());
|
let evicted = replace(&mut self.next, vec!());
|
||||||
match self.current.take() {
|
match self.current.take() {
|
||||||
Some(current) => self.previous.push(current),
|
Some(current) => self.previous.push(current),
|
||||||
|
@ -334,7 +340,7 @@ impl NavigationContext {
|
||||||
self.current = Some(new_frame.clone());
|
self.current = Some(new_frame.clone());
|
||||||
compositor_proxy.send(CompositorMsg::ChangePageLoadData(
|
compositor_proxy.send(CompositorMsg::ChangePageLoadData(
|
||||||
new_frame.id,
|
new_frame.id,
|
||||||
new_frame.pipeline.load_data.clone()));
|
new_frame.pipeline.borrow().load_data.clone()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -463,11 +469,12 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
|
||||||
debug!("constellation got frame rect message");
|
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, subpage_id, Rect::from_untyped(&rect));
|
||||||
}
|
}
|
||||||
ConstellationMsg::ScriptLoadedURLInIFrame(url, source_pipeline_id, subpage_id, sandbox) => {
|
ConstellationMsg::ScriptLoadedURLInIFrame(url, source_pipeline_id, new_subpage_id, old_subpage_id, sandbox) => {
|
||||||
debug!("constellation got iframe URL load message");
|
debug!("constellation got iframe URL load message");
|
||||||
self.handle_script_loaded_url_in_iframe_msg(url,
|
self.handle_script_loaded_url_in_iframe_msg(url,
|
||||||
source_pipeline_id,
|
source_pipeline_id,
|
||||||
subpage_id,
|
new_subpage_id,
|
||||||
|
old_subpage_id,
|
||||||
sandbox);
|
sandbox);
|
||||||
}
|
}
|
||||||
ConstellationMsg::SetCursor(cursor) => self.handle_set_cursor_msg(cursor),
|
ConstellationMsg::SetCursor(cursor) => self.handle_set_cursor_msg(cursor),
|
||||||
|
@ -550,12 +557,12 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let idx = self.pending_frames.iter().position(|pending| {
|
let idx = self.pending_frames.iter().position(|pending| {
|
||||||
pending.after.pipeline.id == pipeline_id
|
pending.after.pipeline.borrow().id == pipeline_id
|
||||||
});
|
});
|
||||||
match idx {
|
match idx {
|
||||||
Some(idx) => {
|
Some(idx) => {
|
||||||
debug!("removing pending frame change for failed pipeline");
|
debug!("removing pending frame change for failed pipeline");
|
||||||
self.pending_frames[idx].after.pipeline.force_exit();
|
self.pending_frames[idx].after.pipeline.borrow().force_exit();
|
||||||
self.compositor_proxy.send(CompositorMsg::PaintTaskExited(old_pipeline.id));
|
self.compositor_proxy.send(CompositorMsg::PaintTaskExited(old_pipeline.id));
|
||||||
self.pending_frames.remove(idx);
|
self.pending_frames.remove(idx);
|
||||||
},
|
},
|
||||||
|
@ -607,7 +614,7 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
|
||||||
|
|
||||||
// Returns true if a child frame tree's subpage id matches the given subpage id
|
// Returns true if a child frame tree's subpage id matches the given subpage id
|
||||||
let subpage_eq = |child_frame_tree: & &mut ChildFrameTree| {
|
let subpage_eq = |child_frame_tree: & &mut ChildFrameTree| {
|
||||||
child_frame_tree.frame_tree.pipeline.
|
child_frame_tree.frame_tree.pipeline.borrow().
|
||||||
subpage_id.expect("Constellation:
|
subpage_id.expect("Constellation:
|
||||||
child frame does not have a subpage id. This should not be possible.")
|
child frame does not have a subpage id. This should not be possible.")
|
||||||
== subpage_id
|
== subpage_id
|
||||||
|
@ -668,7 +675,7 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
|
||||||
device_pixel_ratio: ScaleFactor<ViewportPx,DevicePixel,f32>) {
|
device_pixel_ratio: ScaleFactor<ViewportPx,DevicePixel,f32>) {
|
||||||
child_frame_tree.rect = Some(rect);
|
child_frame_tree.rect = Some(rect);
|
||||||
// NOTE: work around borrowchk issues
|
// NOTE: work around borrowchk issues
|
||||||
let pipeline = &child_frame_tree.frame_tree.pipeline;
|
let pipeline = &*child_frame_tree.frame_tree.pipeline.borrow();
|
||||||
if !already_sent.contains(&pipeline.id) {
|
if !already_sent.contains(&pipeline.id) {
|
||||||
if is_active {
|
if is_active {
|
||||||
let ScriptControlChan(ref script_chan) = pipeline.script_chan;
|
let ScriptControlChan(ref script_chan) = pipeline.script_chan;
|
||||||
|
@ -688,31 +695,60 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn update_child_pipeline(frame_tree: Rc<FrameTree>,
|
||||||
|
new_pipeline: Rc<Pipeline>,
|
||||||
|
old_subpage_id: SubpageId) {
|
||||||
|
let existing_tree = match frame_tree.find_with_subpage_id(Some(old_subpage_id)) {
|
||||||
|
Some(existing_tree) => existing_tree.clone(),
|
||||||
|
None => panic!("Tried to update non-existing frame tree with pipeline={} subpage={}",
|
||||||
|
new_pipeline.id,
|
||||||
|
old_subpage_id),
|
||||||
|
};
|
||||||
|
|
||||||
|
*existing_tree.pipeline.borrow_mut() = new_pipeline;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_or_update_child_pipeline(&mut self,
|
||||||
|
frame_tree: Rc<FrameTree>,
|
||||||
|
new_pipeline: Rc<Pipeline>,
|
||||||
|
new_rect: Option<TypedRect<PagePx, f32>>,
|
||||||
|
old_subpage_id: Option<SubpageId>) {
|
||||||
|
match old_subpage_id {
|
||||||
|
Some(old_subpage_id) =>
|
||||||
|
Constellation::update_child_pipeline(frame_tree.clone(), new_pipeline, old_subpage_id),
|
||||||
|
None => {
|
||||||
|
let new_frame_tree =
|
||||||
|
Rc::new(FrameTree::new(self.get_next_frame_id(), new_pipeline,
|
||||||
|
Some(frame_tree.pipeline.borrow().clone())));
|
||||||
|
frame_tree.children.borrow_mut().push(ChildFrameTree::new(new_frame_tree,
|
||||||
|
new_rect));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// The script task associated with pipeline_id has loaded a URL in an iframe via script. This
|
// The script task associated with pipeline_id has loaded a URL in an iframe via script. This
|
||||||
// will result in a new pipeline being spawned and a frame tree being added to
|
// will result in a new pipeline being spawned and a frame tree being added to
|
||||||
// source_pipeline_id's frame tree's children. This message is never the result of a page
|
// containing_page_pipeline_id's frame tree's children. This message is never the result of a
|
||||||
// navigation.
|
// page navigation.
|
||||||
fn handle_script_loaded_url_in_iframe_msg(&mut self,
|
fn handle_script_loaded_url_in_iframe_msg(&mut self,
|
||||||
url: Url,
|
url: Url,
|
||||||
source_pipeline_id: PipelineId,
|
containing_page_pipeline_id: PipelineId,
|
||||||
subpage_id: SubpageId,
|
new_subpage_id: SubpageId,
|
||||||
|
old_subpage_id: Option<SubpageId>,
|
||||||
sandbox: IFrameSandboxState) {
|
sandbox: IFrameSandboxState) {
|
||||||
// Start by finding the frame trees matching the pipeline id,
|
// Start by finding the frame trees matching the pipeline id,
|
||||||
// and add the new pipeline to their sub frames.
|
// and add the new pipeline to their sub frames.
|
||||||
let frame_trees = self.find_all(source_pipeline_id);
|
let frame_trees = self.find_all(containing_page_pipeline_id);
|
||||||
if frame_trees.is_empty() {
|
if frame_trees.is_empty() {
|
||||||
panic!("Constellation: source pipeline id of ScriptLoadedURLInIFrame is not in
|
panic!("Constellation: source pipeline id of ScriptLoadedURLInIFrame is not in
|
||||||
navigation context, nor is it in a pending frame. This should be
|
navigation context, nor is it in a pending frame. This should be
|
||||||
impossible.");
|
impossible.");
|
||||||
}
|
}
|
||||||
|
|
||||||
let next_pipeline_id = self.get_next_pipeline_id();
|
|
||||||
|
|
||||||
// Compare the pipeline's url to the new url. If the origin is the same,
|
// 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
|
// then reuse the script task in creating the new pipeline
|
||||||
let source_pipeline = self.pipelines.get(&source_pipeline_id).expect("Constellation:
|
let source_pipeline = self.pipelines.get(&containing_page_pipeline_id).expect("Constellation:
|
||||||
source Id of ScriptLoadedURLInIFrame does have an associated pipeline in
|
source Id of ScriptLoadedURLInIFrameMsg does have an associated pipeline in
|
||||||
constellation. This should be impossible.").clone();
|
constellation. This should be impossible.").clone();
|
||||||
|
|
||||||
let source_url = source_pipeline.load_data.url.clone();
|
let source_url = source_pipeline.load_data.url.clone();
|
||||||
|
@ -730,21 +766,20 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let new_frame_pipeline_id = self.get_next_pipeline_id();
|
||||||
let pipeline = self.new_pipeline(
|
let pipeline = self.new_pipeline(
|
||||||
next_pipeline_id,
|
new_frame_pipeline_id,
|
||||||
Some(subpage_id),
|
Some(new_subpage_id),
|
||||||
script_pipeline,
|
script_pipeline,
|
||||||
LoadData::new(url)
|
LoadData::new(url)
|
||||||
);
|
);
|
||||||
|
|
||||||
let rect = self.pending_sizes.remove(&(source_pipeline_id, subpage_id));
|
let rect = self.pending_sizes.remove(&(containing_page_pipeline_id, new_subpage_id));
|
||||||
for frame_tree in frame_trees.iter() {
|
for frame_tree in frame_trees.iter() {
|
||||||
let next_frame_id = self.get_next_frame_id();
|
self.create_or_update_child_pipeline(frame_tree.clone(),
|
||||||
frame_tree.children.borrow_mut().push(ChildFrameTree::new(
|
pipeline.clone(),
|
||||||
Rc::new(FrameTree::new(next_frame_id,
|
rect,
|
||||||
pipeline.clone(),
|
old_subpage_id);
|
||||||
Some(source_pipeline.clone()))),
|
|
||||||
rect));
|
|
||||||
}
|
}
|
||||||
self.pipelines.insert(pipeline.id, pipeline);
|
self.pipelines.insert(pipeline.id, pipeline);
|
||||||
}
|
}
|
||||||
|
@ -778,7 +813,7 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
|
||||||
// changes would be overridden by changing the subframe associated with source_id.
|
// changes would be overridden by changing the subframe associated with source_id.
|
||||||
|
|
||||||
let parent = source_frame.parent.clone();
|
let parent = source_frame.parent.clone();
|
||||||
let subpage_id = source_frame.pipeline.subpage_id;
|
let subpage_id = source_frame.pipeline.borrow().subpage_id;
|
||||||
let next_pipeline_id = self.get_next_pipeline_id();
|
let next_pipeline_id = self.get_next_pipeline_id();
|
||||||
let next_frame_id = self.get_next_frame_id();
|
let next_frame_id = self.get_next_frame_id();
|
||||||
let pipeline = self.new_pipeline(next_pipeline_id, subpage_id, None, load_data);
|
let pipeline = self.new_pipeline(next_pipeline_id, subpage_id, None, load_data);
|
||||||
|
@ -805,7 +840,7 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
|
||||||
} else {
|
} else {
|
||||||
let old = self.current_frame().as_ref().unwrap();
|
let old = self.current_frame().as_ref().unwrap();
|
||||||
for frame in old.iter() {
|
for frame in old.iter() {
|
||||||
frame.pipeline.revoke_paint_permission();
|
frame.pipeline.borrow().revoke_paint_permission();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.navigation_context.forward(&mut *self.compositor_proxy)
|
self.navigation_context.forward(&mut *self.compositor_proxy)
|
||||||
|
@ -817,7 +852,7 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
|
||||||
} else {
|
} else {
|
||||||
let old = self.current_frame().as_ref().unwrap();
|
let old = self.current_frame().as_ref().unwrap();
|
||||||
for frame in old.iter() {
|
for frame in old.iter() {
|
||||||
frame.pipeline.revoke_paint_permission();
|
frame.pipeline.borrow().revoke_paint_permission();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.navigation_context.back(&mut *self.compositor_proxy)
|
self.navigation_context.back(&mut *self.compositor_proxy)
|
||||||
|
@ -825,7 +860,7 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
|
||||||
};
|
};
|
||||||
|
|
||||||
for frame in destination_frame.iter() {
|
for frame in destination_frame.iter() {
|
||||||
frame.pipeline.load();
|
frame.pipeline.borrow().load();
|
||||||
}
|
}
|
||||||
self.grant_paint_permission(destination_frame, NavigationType::Navigate);
|
self.grant_paint_permission(destination_frame, NavigationType::Navigate);
|
||||||
|
|
||||||
|
@ -838,9 +873,9 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
|
||||||
|
|
||||||
fn handle_key_msg(&self, key: Key, state: KeyState, mods: KeyModifiers) {
|
fn handle_key_msg(&self, key: Key, state: KeyState, mods: KeyModifiers) {
|
||||||
self.current_frame().as_ref().map(|frame| {
|
self.current_frame().as_ref().map(|frame| {
|
||||||
let ScriptControlChan(ref chan) = frame.pipeline.script_chan;
|
let ScriptControlChan(ref chan) = frame.pipeline.borrow().script_chan;
|
||||||
chan.send(ConstellationControlMsg::SendEvent(
|
chan.send(ConstellationControlMsg::SendEvent(
|
||||||
frame.pipeline.id, CompositorEvent::KeyEvent(key, state, mods)));
|
frame.pipeline.borrow().id, CompositorEvent::KeyEvent(key, state, mods)));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -871,7 +906,7 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
|
||||||
// If it is not found, it simply means that this pipeline will not receive
|
// If it is not found, it simply means that this pipeline will not receive
|
||||||
// permission to paint.
|
// permission to paint.
|
||||||
let pending_index = self.pending_frames.iter().rposition(|frame_change| {
|
let pending_index = self.pending_frames.iter().rposition(|frame_change| {
|
||||||
frame_change.after.pipeline.id == pipeline_id
|
frame_change.after.pipeline.borrow().id == pipeline_id
|
||||||
});
|
});
|
||||||
match pending_index {
|
match pending_index {
|
||||||
Some(pending_index) => {
|
Some(pending_index) => {
|
||||||
|
@ -897,7 +932,7 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
|
||||||
frame not contained in the current frame. This is a bug");
|
frame not contained in the current frame. This is a bug");
|
||||||
|
|
||||||
for frame in to_revoke.iter() {
|
for frame in to_revoke.iter() {
|
||||||
frame.pipeline.revoke_paint_permission();
|
frame.pipeline.borrow().revoke_paint_permission();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If to_add is not the root frame, then replace revoked_frame with it.
|
// If to_add is not the root frame, then replace revoked_frame with it.
|
||||||
|
@ -907,8 +942,8 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
|
||||||
{
|
{
|
||||||
if to_add.parent.borrow().is_some() {
|
if to_add.parent.borrow().is_some() {
|
||||||
debug!("Constellation: replacing {} with {} in {}",
|
debug!("Constellation: replacing {} with {} in {}",
|
||||||
revoke_id, to_add.pipeline.id,
|
revoke_id, to_add.pipeline.borrow().id,
|
||||||
next_frame_tree.pipeline.id);
|
next_frame_tree.pipeline.borrow().id);
|
||||||
flag = true;
|
flag = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -921,7 +956,7 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
|
||||||
// Add to_add to parent's children, if it is not the root
|
// Add to_add to parent's children, if it is not the root
|
||||||
let parent = &to_add.parent;
|
let parent = &to_add.parent;
|
||||||
for parent in parent.borrow().iter() {
|
for parent in parent.borrow().iter() {
|
||||||
let subpage_id = to_add.pipeline.subpage_id
|
let subpage_id = to_add.pipeline.borrow().subpage_id
|
||||||
.expect("Constellation:
|
.expect("Constellation:
|
||||||
Child frame's subpage id is None. This should be impossible.");
|
Child frame's subpage id is None. This should be impossible.");
|
||||||
let rect = self.pending_sizes.remove(&(parent.id, subpage_id));
|
let rect = self.pending_sizes.remove(&(parent.id, subpage_id));
|
||||||
|
@ -945,14 +980,14 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
|
||||||
let mut already_seen = HashSet::new();
|
let mut already_seen = HashSet::new();
|
||||||
for frame_tree in self.current_frame().iter() {
|
for frame_tree in self.current_frame().iter() {
|
||||||
debug!("constellation sending resize message to active frame");
|
debug!("constellation sending resize message to active frame");
|
||||||
let pipeline = &frame_tree.pipeline;
|
let pipeline = &*frame_tree.pipeline.borrow();;
|
||||||
let ScriptControlChan(ref chan) = pipeline.script_chan;
|
let ScriptControlChan(ref chan) = pipeline.script_chan;
|
||||||
let _ = chan.send_opt(ConstellationControlMsg::Resize(pipeline.id, new_size));
|
let _ = chan.send_opt(ConstellationControlMsg::Resize(pipeline.id, new_size));
|
||||||
already_seen.insert(pipeline.id);
|
already_seen.insert(pipeline.id);
|
||||||
}
|
}
|
||||||
for frame_tree in self.navigation_context.previous.iter()
|
for frame_tree in self.navigation_context.previous.iter()
|
||||||
.chain(self.navigation_context.next.iter()) {
|
.chain(self.navigation_context.next.iter()) {
|
||||||
let pipeline = &frame_tree.pipeline;
|
let pipeline = &*frame_tree.pipeline.borrow();
|
||||||
if !already_seen.contains(&pipeline.id) {
|
if !already_seen.contains(&pipeline.id) {
|
||||||
debug!("constellation sending resize message to inactive frame");
|
debug!("constellation sending resize message to inactive frame");
|
||||||
let ScriptControlChan(ref chan) = pipeline.script_chan;
|
let ScriptControlChan(ref chan) = pipeline.script_chan;
|
||||||
|
@ -967,9 +1002,10 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
|
||||||
let frame_tree = &change.after;
|
let frame_tree = &change.after;
|
||||||
if frame_tree.parent.borrow().is_none() {
|
if frame_tree.parent.borrow().is_none() {
|
||||||
debug!("constellation sending resize message to pending outer frame ({})",
|
debug!("constellation sending resize message to pending outer frame ({})",
|
||||||
frame_tree.pipeline.id);
|
frame_tree.pipeline.borrow().id);
|
||||||
let ScriptControlChan(ref chan) = frame_tree.pipeline.script_chan;
|
let ScriptControlChan(ref chan) = frame_tree.pipeline.borrow().script_chan;
|
||||||
let _ = chan.send_opt(ConstellationControlMsg::Resize(frame_tree.pipeline.id, new_size));
|
let _ = chan.send_opt(ConstellationControlMsg::Resize(
|
||||||
|
frame_tree.pipeline.borrow().id, new_size));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -981,15 +1017,15 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
|
||||||
// TODO(tkuehn): should only exit once per unique script task,
|
// TODO(tkuehn): should only exit once per unique script task,
|
||||||
// and then that script task will handle sub-exits
|
// and then that script task will handle sub-exits
|
||||||
for frame_tree in frame_tree.iter() {
|
for frame_tree in frame_tree.iter() {
|
||||||
frame_tree.pipeline.exit(PipelineExitType::PipelineOnly);
|
frame_tree.pipeline.borrow().exit(PipelineExitType::PipelineOnly);
|
||||||
self.compositor_proxy.send(CompositorMsg::PaintTaskExited(frame_tree.pipeline.id));
|
self.compositor_proxy.send(CompositorMsg::PaintTaskExited(frame_tree.pipeline.borrow().id));
|
||||||
self.pipelines.remove(&frame_tree.pipeline.id);
|
self.pipelines.remove(&frame_tree.pipeline.borrow().id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_evicted_frames(&mut self, evicted: Vec<Rc<FrameTree>>) {
|
fn handle_evicted_frames(&mut self, evicted: Vec<Rc<FrameTree>>) {
|
||||||
for frame_tree in evicted.into_iter() {
|
for frame_tree in evicted.into_iter() {
|
||||||
if !self.navigation_context.contains(frame_tree.pipeline.id) {
|
if !self.navigation_context.contains(frame_tree.pipeline.borrow().id) {
|
||||||
self.close_pipelines(frame_tree);
|
self.close_pipelines(frame_tree);
|
||||||
} else {
|
} else {
|
||||||
let frames = frame_tree.children.borrow().iter()
|
let frames = frame_tree.children.borrow().iter()
|
||||||
|
@ -1030,7 +1066,7 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
|
||||||
let mut iter = frame_tree.iter();
|
let mut iter = frame_tree.iter();
|
||||||
for frame in iter {
|
for frame in iter {
|
||||||
frame.has_compositor_layer.set(true);
|
frame.has_compositor_layer.set(true);
|
||||||
frame.pipeline.grant_paint_permission();
|
frame.pipeline.borrow().grant_paint_permission();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(()) => {} // message has been discarded, probably shutting down
|
Err(()) => {} // message has been discarded, probably shutting down
|
||||||
|
@ -1043,7 +1079,7 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
|
||||||
-> Option<(ChildFrameTree, Rc<FrameTree>)> {
|
-> Option<(ChildFrameTree, Rc<FrameTree>)> {
|
||||||
for child in frame_tree.children.borrow().iter() {
|
for child in frame_tree.children.borrow().iter() {
|
||||||
let child_frame_tree = child.frame_tree.clone();
|
let child_frame_tree = child.frame_tree.clone();
|
||||||
if child.frame_tree.pipeline.id == child_pipeline_id {
|
if child.frame_tree.pipeline.borrow().id == child_pipeline_id {
|
||||||
return Some((ChildFrameTree::new(child_frame_tree, child.rect),
|
return Some((ChildFrameTree::new(child_frame_tree, child.rect),
|
||||||
frame_tree.clone()));
|
frame_tree.clone()));
|
||||||
}
|
}
|
||||||
|
@ -1070,13 +1106,13 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
|
||||||
};
|
};
|
||||||
|
|
||||||
if child.frame_tree.has_compositor_layer.get() {
|
if child.frame_tree.has_compositor_layer.get() {
|
||||||
child.frame_tree.pipeline.grant_paint_permission();
|
child.frame_tree.pipeline.borrow().grant_paint_permission();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let sendable_frame_tree_diff = FrameTreeDiff {
|
let sendable_frame_tree_diff = FrameTreeDiff {
|
||||||
parent_pipeline: parent.pipeline.to_sendable(),
|
parent_pipeline: parent.pipeline.borrow().to_sendable(),
|
||||||
pipeline: child.frame_tree.pipeline.to_sendable(),
|
pipeline: child.frame_tree.pipeline.borrow().to_sendable(),
|
||||||
rect: child.rect,
|
rect: child.rect,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1085,7 +1121,7 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
|
||||||
match port.recv_opt() {
|
match port.recv_opt() {
|
||||||
Ok(()) => {
|
Ok(()) => {
|
||||||
child.frame_tree.has_compositor_layer.set(true);
|
child.frame_tree.has_compositor_layer.set(true);
|
||||||
child.frame_tree.pipeline.grant_paint_permission();
|
child.frame_tree.pipeline.borrow().grant_paint_permission();
|
||||||
}
|
}
|
||||||
Err(()) => {} // The message has been discarded, we are probably shutting down.
|
Err(()) => {} // The message has been discarded, we are probably shutting down.
|
||||||
}
|
}
|
||||||
|
|
|
@ -144,8 +144,8 @@ pub trait TLayoutNode {
|
||||||
Some(elem) => elem,
|
Some(elem) => elem,
|
||||||
None => panic!("not an iframe element!")
|
None => panic!("not an iframe element!")
|
||||||
};
|
};
|
||||||
let size = (*iframe_element.unsafe_get()).size().unwrap();
|
((*iframe_element.unsafe_get()).containing_page_pipeline_id().unwrap(),
|
||||||
(*size.pipeline_id(), *size.subpage_id())
|
(*iframe_element.unsafe_get()).subpage_id().unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -203,7 +203,7 @@ pub enum Msg {
|
||||||
LoadComplete,
|
LoadComplete,
|
||||||
FrameRect(PipelineId, SubpageId, Rect<f32>),
|
FrameRect(PipelineId, SubpageId, Rect<f32>),
|
||||||
LoadUrl(PipelineId, LoadData),
|
LoadUrl(PipelineId, LoadData),
|
||||||
ScriptLoadedURLInIFrame(Url, PipelineId, SubpageId, IFrameSandboxState),
|
ScriptLoadedURLInIFrame(Url, PipelineId, SubpageId, Option<SubpageId>, IFrameSandboxState),
|
||||||
Navigate(NavigationDirection),
|
Navigate(NavigationDirection),
|
||||||
PainterReady(PipelineId),
|
PainterReady(PipelineId),
|
||||||
ResizedWindow(WindowSizeData),
|
ResizedWindow(WindowSizeData),
|
||||||
|
|
|
@ -20,7 +20,7 @@ use dom::node::{Node, NodeHelpers, NodeTypeId, window_from_node};
|
||||||
use dom::urlhelper::UrlHelper;
|
use dom::urlhelper::UrlHelper;
|
||||||
use dom::virtualmethods::VirtualMethods;
|
use dom::virtualmethods::VirtualMethods;
|
||||||
use dom::window::Window;
|
use dom::window::Window;
|
||||||
use page::IterablePage;
|
use page::{IterablePage, Page};
|
||||||
|
|
||||||
use servo_msg::constellation_msg::{PipelineId, SubpageId, ConstellationChan};
|
use servo_msg::constellation_msg::{PipelineId, SubpageId, ConstellationChan};
|
||||||
use servo_msg::constellation_msg::IFrameSandboxState::{IFrameSandboxed, IFrameUnsandboxed};
|
use servo_msg::constellation_msg::IFrameSandboxState::{IFrameSandboxed, IFrameUnsandboxed};
|
||||||
|
@ -44,7 +44,8 @@ enum SandboxAllowance {
|
||||||
#[dom_struct]
|
#[dom_struct]
|
||||||
pub struct HTMLIFrameElement {
|
pub struct HTMLIFrameElement {
|
||||||
htmlelement: HTMLElement,
|
htmlelement: HTMLElement,
|
||||||
size: Cell<Option<IFrameSize>>,
|
subpage_id: Cell<Option<SubpageId>>,
|
||||||
|
containing_page_pipeline_id: Cell<Option<PipelineId>>,
|
||||||
sandbox: Cell<Option<u8>>,
|
sandbox: Cell<Option<u8>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,31 +55,12 @@ impl HTMLIFrameElementDerived for EventTarget {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[jstraceable]
|
|
||||||
#[privatize]
|
|
||||||
#[deriving(Copy)]
|
|
||||||
pub struct IFrameSize {
|
|
||||||
pipeline_id: PipelineId,
|
|
||||||
subpage_id: SubpageId,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IFrameSize {
|
|
||||||
#[inline]
|
|
||||||
pub fn pipeline_id<'a>(&'a self) -> &'a PipelineId {
|
|
||||||
&self.pipeline_id
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn subpage_id<'a>(&'a self) -> &'a SubpageId {
|
|
||||||
&self.subpage_id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait HTMLIFrameElementHelpers {
|
pub trait HTMLIFrameElementHelpers {
|
||||||
fn is_sandboxed(self) -> bool;
|
fn is_sandboxed(self) -> bool;
|
||||||
fn get_url(self) -> Option<Url>;
|
fn get_url(self) -> Option<Url>;
|
||||||
/// http://www.whatwg.org/html/#process-the-iframe-attributes
|
/// http://www.whatwg.org/html/#process-the-iframe-attributes
|
||||||
fn process_the_iframe_attributes(self);
|
fn process_the_iframe_attributes(self);
|
||||||
|
fn generate_new_subpage_id(self, page: &Page) -> (SubpageId, Option<SubpageId>);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> HTMLIFrameElementHelpers for JSRef<'a, HTMLIFrameElement> {
|
impl<'a> HTMLIFrameElementHelpers for JSRef<'a, HTMLIFrameElement> {
|
||||||
|
@ -100,6 +82,13 @@ impl<'a> HTMLIFrameElementHelpers for JSRef<'a, HTMLIFrameElement> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn generate_new_subpage_id(self, page: &Page) -> (SubpageId, Option<SubpageId>) {
|
||||||
|
let old_subpage_id = self.subpage_id.get();
|
||||||
|
let subpage_id = page.get_next_subpage_id();
|
||||||
|
self.subpage_id.set(Some(subpage_id));
|
||||||
|
(subpage_id, old_subpage_id)
|
||||||
|
}
|
||||||
|
|
||||||
fn process_the_iframe_attributes(self) {
|
fn process_the_iframe_attributes(self) {
|
||||||
let url = match self.get_url() {
|
let url = match self.get_url() {
|
||||||
Some(url) => url.clone(),
|
Some(url) => url.clone(),
|
||||||
|
@ -112,19 +101,19 @@ impl<'a> HTMLIFrameElementHelpers for JSRef<'a, HTMLIFrameElement> {
|
||||||
IFrameUnsandboxed
|
IFrameUnsandboxed
|
||||||
};
|
};
|
||||||
|
|
||||||
// Subpage Id
|
|
||||||
let window = window_from_node(self).root();
|
let window = window_from_node(self).root();
|
||||||
let window = window.r();
|
let window = window.r();
|
||||||
let page = window.page();
|
let page = window.page();
|
||||||
let subpage_id = page.get_next_subpage_id();
|
let (new_subpage_id, old_subpage_id) = self.generate_new_subpage_id(page);
|
||||||
|
|
||||||
self.size.set(Some(IFrameSize {
|
self.containing_page_pipeline_id.set(Some(page.id));
|
||||||
pipeline_id: page.id,
|
|
||||||
subpage_id: subpage_id,
|
|
||||||
}));
|
|
||||||
|
|
||||||
let ConstellationChan(ref chan) = page.constellation_chan;
|
let ConstellationChan(ref chan) = page.constellation_chan;
|
||||||
chan.send(ConstellationMsg::ScriptLoadedURLInIFrame(url, page.id, subpage_id, sandboxed));
|
chan.send(ConstellationMsg::ScriptLoadedURLInIFrame(url,
|
||||||
|
page.id,
|
||||||
|
new_subpage_id,
|
||||||
|
old_subpage_id,
|
||||||
|
sandboxed));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,7 +121,8 @@ impl HTMLIFrameElement {
|
||||||
fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: JSRef<Document>) -> HTMLIFrameElement {
|
fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: JSRef<Document>) -> HTMLIFrameElement {
|
||||||
HTMLIFrameElement {
|
HTMLIFrameElement {
|
||||||
htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLIFrameElement, localName, prefix, document),
|
htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLIFrameElement, localName, prefix, document),
|
||||||
size: Cell::new(None),
|
subpage_id: Cell::new(None),
|
||||||
|
containing_page_pipeline_id: Cell::new(None),
|
||||||
sandbox: Cell::new(None),
|
sandbox: Cell::new(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -144,8 +134,13 @@ impl HTMLIFrameElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn size(&self) -> Option<IFrameSize> {
|
pub fn containing_page_pipeline_id(&self) -> Option<PipelineId> {
|
||||||
self.size.get()
|
self.containing_page_pipeline_id.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn subpage_id(&self) -> Option<SubpageId> {
|
||||||
|
self.subpage_id.get()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,11 +166,11 @@ impl<'a> HTMLIFrameElementMethods for JSRef<'a, HTMLIFrameElement> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn GetContentWindow(self) -> Option<Temporary<Window>> {
|
fn GetContentWindow(self) -> Option<Temporary<Window>> {
|
||||||
self.size.get().and_then(|size| {
|
self.subpage_id.get().and_then(|subpage_id| {
|
||||||
let window = window_from_node(self).root();
|
let window = window_from_node(self).root();
|
||||||
let children = window.page().children.borrow();
|
let children = window.page().children.borrow();
|
||||||
let child = children.iter().find(|child| {
|
let child = children.iter().find(|child| {
|
||||||
child.subpage_id.unwrap() == size.subpage_id
|
child.subpage_id.unwrap() == subpage_id
|
||||||
});
|
});
|
||||||
child.and_then(|page| {
|
child.and_then(|page| {
|
||||||
page.frame.borrow().as_ref().map(|frame| {
|
page.frame.borrow().as_ref().map(|frame| {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue