mirror of
https://github.com/servo/servo.git
synced 2025-08-02 04:00:32 +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.
|
||||
pub id: FrameId,
|
||||
/// The pipeline for this frame.
|
||||
pub pipeline: Rc<Pipeline>,
|
||||
pub pipeline: RefCell<Rc<Pipeline>>,
|
||||
/// The parent frame's pipeline.
|
||||
pub parent: RefCell<Option<Rc<Pipeline>>>,
|
||||
/// A vector of child frames.
|
||||
|
@ -112,7 +112,7 @@ impl FrameTree {
|
|||
-> FrameTree {
|
||||
FrameTree {
|
||||
id: id,
|
||||
pipeline: pipeline,
|
||||
pipeline: RefCell::new(pipeline.clone()),
|
||||
parent: RefCell::new(parent_pipeline),
|
||||
children: RefCell::new(vec!()),
|
||||
has_compositor_layer: Cell::new(false),
|
||||
|
@ -165,7 +165,7 @@ pub struct FrameTreeDiff {
|
|||
impl FrameTree {
|
||||
fn to_sendable(&self) -> SendableFrameTree {
|
||||
SendableFrameTree {
|
||||
pipeline: self.pipeline.to_sendable(),
|
||||
pipeline: self.pipeline.borrow().to_sendable(),
|
||||
children: self.children
|
||||
.borrow()
|
||||
.iter()
|
||||
|
@ -178,18 +178,24 @@ impl FrameTree {
|
|||
trait FrameTreeTraversal {
|
||||
fn contains(&self, id: PipelineId) -> bool;
|
||||
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 iter(&self) -> FrameTreeIterator;
|
||||
}
|
||||
|
||||
impl FrameTreeTraversal for Rc<FrameTree> {
|
||||
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
|
||||
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
|
||||
|
@ -198,7 +204,7 @@ impl FrameTreeTraversal for Rc<FrameTree> {
|
|||
for frame_tree in self.iter() {
|
||||
let mut children = frame_tree.children.borrow_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 {
|
||||
Some(child) => {
|
||||
*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
|
||||
fn load(&mut self, frame_tree: Rc<FrameTree>, compositor_proxy: &mut CompositorProxy)
|
||||
-> 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!());
|
||||
match self.current.take() {
|
||||
Some(current) => self.previous.push(current),
|
||||
|
@ -334,7 +340,7 @@ impl NavigationContext {
|
|||
self.current = Some(new_frame.clone());
|
||||
compositor_proxy.send(CompositorMsg::ChangePageLoadData(
|
||||
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");
|
||||
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");
|
||||
self.handle_script_loaded_url_in_iframe_msg(url,
|
||||
source_pipeline_id,
|
||||
subpage_id,
|
||||
new_subpage_id,
|
||||
old_subpage_id,
|
||||
sandbox);
|
||||
}
|
||||
ConstellationMsg::SetCursor(cursor) => self.handle_set_cursor_msg(cursor),
|
||||
|
@ -550,12 +557,12 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
|
|||
|
||||
loop {
|
||||
let idx = self.pending_frames.iter().position(|pending| {
|
||||
pending.after.pipeline.id == pipeline_id
|
||||
pending.after.pipeline.borrow().id == pipeline_id
|
||||
});
|
||||
match idx {
|
||||
Some(idx) => {
|
||||
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.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
|
||||
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:
|
||||
child frame does not have a subpage id. This should not be possible.")
|
||||
== subpage_id
|
||||
|
@ -668,7 +675,7 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
|
|||
device_pixel_ratio: ScaleFactor<ViewportPx,DevicePixel,f32>) {
|
||||
child_frame_tree.rect = Some(rect);
|
||||
// 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 is_active {
|
||||
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
|
||||
// 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
|
||||
// navigation.
|
||||
// containing_page_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,
|
||||
url: Url,
|
||||
source_pipeline_id: PipelineId,
|
||||
subpage_id: SubpageId,
|
||||
containing_page_pipeline_id: PipelineId,
|
||||
new_subpage_id: SubpageId,
|
||||
old_subpage_id: Option<SubpageId>,
|
||||
sandbox: IFrameSandboxState) {
|
||||
// Start by finding the frame trees matching the pipeline id,
|
||||
// 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() {
|
||||
panic!("Constellation: source pipeline id of ScriptLoadedURLInIFrame is not in
|
||||
navigation context, nor is it in a pending frame. This should be
|
||||
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,
|
||||
// then reuse the script task in creating the new pipeline
|
||||
let source_pipeline = self.pipelines.get(&source_pipeline_id).expect("Constellation:
|
||||
source Id of ScriptLoadedURLInIFrame does have an associated pipeline in
|
||||
let source_pipeline = self.pipelines.get(&containing_page_pipeline_id).expect("Constellation:
|
||||
source Id of ScriptLoadedURLInIFrameMsg does have an associated pipeline in
|
||||
constellation. This should be impossible.").clone();
|
||||
|
||||
let source_url = source_pipeline.load_data.url.clone();
|
||||
|
@ -730,21 +766,20 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
|
|||
None
|
||||
};
|
||||
|
||||
let new_frame_pipeline_id = self.get_next_pipeline_id();
|
||||
let pipeline = self.new_pipeline(
|
||||
next_pipeline_id,
|
||||
Some(subpage_id),
|
||||
new_frame_pipeline_id,
|
||||
Some(new_subpage_id),
|
||||
script_pipeline,
|
||||
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() {
|
||||
let next_frame_id = self.get_next_frame_id();
|
||||
frame_tree.children.borrow_mut().push(ChildFrameTree::new(
|
||||
Rc::new(FrameTree::new(next_frame_id,
|
||||
self.create_or_update_child_pipeline(frame_tree.clone(),
|
||||
pipeline.clone(),
|
||||
Some(source_pipeline.clone()))),
|
||||
rect));
|
||||
rect,
|
||||
old_subpage_id);
|
||||
}
|
||||
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.
|
||||
|
||||
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_frame_id = self.get_next_frame_id();
|
||||
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 {
|
||||
let old = self.current_frame().as_ref().unwrap();
|
||||
for frame in old.iter() {
|
||||
frame.pipeline.revoke_paint_permission();
|
||||
frame.pipeline.borrow().revoke_paint_permission();
|
||||
}
|
||||
}
|
||||
self.navigation_context.forward(&mut *self.compositor_proxy)
|
||||
|
@ -817,7 +852,7 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
|
|||
} else {
|
||||
let old = self.current_frame().as_ref().unwrap();
|
||||
for frame in old.iter() {
|
||||
frame.pipeline.revoke_paint_permission();
|
||||
frame.pipeline.borrow().revoke_paint_permission();
|
||||
}
|
||||
}
|
||||
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() {
|
||||
frame.pipeline.load();
|
||||
frame.pipeline.borrow().load();
|
||||
}
|
||||
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) {
|
||||
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(
|
||||
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
|
||||
// permission to paint.
|
||||
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 {
|
||||
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");
|
||||
|
||||
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.
|
||||
|
@ -907,8 +942,8 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
|
|||
{
|
||||
if to_add.parent.borrow().is_some() {
|
||||
debug!("Constellation: replacing {} with {} in {}",
|
||||
revoke_id, to_add.pipeline.id,
|
||||
next_frame_tree.pipeline.id);
|
||||
revoke_id, to_add.pipeline.borrow().id,
|
||||
next_frame_tree.pipeline.borrow().id);
|
||||
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
|
||||
let parent = &to_add.parent;
|
||||
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:
|
||||
Child frame's subpage id is None. This should be impossible.");
|
||||
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();
|
||||
for frame_tree in self.current_frame().iter() {
|
||||
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 _ = chan.send_opt(ConstellationControlMsg::Resize(pipeline.id, new_size));
|
||||
already_seen.insert(pipeline.id);
|
||||
}
|
||||
for frame_tree in self.navigation_context.previous.iter()
|
||||
.chain(self.navigation_context.next.iter()) {
|
||||
let pipeline = &frame_tree.pipeline;
|
||||
let pipeline = &*frame_tree.pipeline.borrow();
|
||||
if !already_seen.contains(&pipeline.id) {
|
||||
debug!("constellation sending resize message to inactive frame");
|
||||
let ScriptControlChan(ref chan) = pipeline.script_chan;
|
||||
|
@ -967,9 +1002,10 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
|
|||
let frame_tree = &change.after;
|
||||
if frame_tree.parent.borrow().is_none() {
|
||||
debug!("constellation sending resize message to pending outer frame ({})",
|
||||
frame_tree.pipeline.id);
|
||||
let ScriptControlChan(ref chan) = frame_tree.pipeline.script_chan;
|
||||
let _ = chan.send_opt(ConstellationControlMsg::Resize(frame_tree.pipeline.id, new_size));
|
||||
frame_tree.pipeline.borrow().id);
|
||||
let ScriptControlChan(ref chan) = frame_tree.pipeline.borrow().script_chan;
|
||||
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,
|
||||
// and then that script task will handle sub-exits
|
||||
for frame_tree in frame_tree.iter() {
|
||||
frame_tree.pipeline.exit(PipelineExitType::PipelineOnly);
|
||||
self.compositor_proxy.send(CompositorMsg::PaintTaskExited(frame_tree.pipeline.id));
|
||||
self.pipelines.remove(&frame_tree.pipeline.id);
|
||||
frame_tree.pipeline.borrow().exit(PipelineExitType::PipelineOnly);
|
||||
self.compositor_proxy.send(CompositorMsg::PaintTaskExited(frame_tree.pipeline.borrow().id));
|
||||
self.pipelines.remove(&frame_tree.pipeline.borrow().id);
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_evicted_frames(&mut self, evicted: Vec<Rc<FrameTree>>) {
|
||||
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);
|
||||
} else {
|
||||
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();
|
||||
for frame in iter {
|
||||
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
|
||||
|
@ -1043,7 +1079,7 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
|
|||
-> Option<(ChildFrameTree, Rc<FrameTree>)> {
|
||||
for child in frame_tree.children.borrow().iter() {
|
||||
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),
|
||||
frame_tree.clone()));
|
||||
}
|
||||
|
@ -1070,13 +1106,13 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
|
|||
};
|
||||
|
||||
if child.frame_tree.has_compositor_layer.get() {
|
||||
child.frame_tree.pipeline.grant_paint_permission();
|
||||
child.frame_tree.pipeline.borrow().grant_paint_permission();
|
||||
return;
|
||||
}
|
||||
|
||||
let sendable_frame_tree_diff = FrameTreeDiff {
|
||||
parent_pipeline: parent.pipeline.to_sendable(),
|
||||
pipeline: child.frame_tree.pipeline.to_sendable(),
|
||||
parent_pipeline: parent.pipeline.borrow().to_sendable(),
|
||||
pipeline: child.frame_tree.pipeline.borrow().to_sendable(),
|
||||
rect: child.rect,
|
||||
};
|
||||
|
||||
|
@ -1085,7 +1121,7 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
|
|||
match port.recv_opt() {
|
||||
Ok(()) => {
|
||||
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.
|
||||
}
|
||||
|
|
|
@ -144,8 +144,8 @@ pub trait TLayoutNode {
|
|||
Some(elem) => elem,
|
||||
None => panic!("not an iframe element!")
|
||||
};
|
||||
let size = (*iframe_element.unsafe_get()).size().unwrap();
|
||||
(*size.pipeline_id(), *size.subpage_id())
|
||||
((*iframe_element.unsafe_get()).containing_page_pipeline_id().unwrap(),
|
||||
(*iframe_element.unsafe_get()).subpage_id().unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -203,7 +203,7 @@ pub enum Msg {
|
|||
LoadComplete,
|
||||
FrameRect(PipelineId, SubpageId, Rect<f32>),
|
||||
LoadUrl(PipelineId, LoadData),
|
||||
ScriptLoadedURLInIFrame(Url, PipelineId, SubpageId, IFrameSandboxState),
|
||||
ScriptLoadedURLInIFrame(Url, PipelineId, SubpageId, Option<SubpageId>, IFrameSandboxState),
|
||||
Navigate(NavigationDirection),
|
||||
PainterReady(PipelineId),
|
||||
ResizedWindow(WindowSizeData),
|
||||
|
|
|
@ -20,7 +20,7 @@ use dom::node::{Node, NodeHelpers, NodeTypeId, window_from_node};
|
|||
use dom::urlhelper::UrlHelper;
|
||||
use dom::virtualmethods::VirtualMethods;
|
||||
use dom::window::Window;
|
||||
use page::IterablePage;
|
||||
use page::{IterablePage, Page};
|
||||
|
||||
use servo_msg::constellation_msg::{PipelineId, SubpageId, ConstellationChan};
|
||||
use servo_msg::constellation_msg::IFrameSandboxState::{IFrameSandboxed, IFrameUnsandboxed};
|
||||
|
@ -44,7 +44,8 @@ enum SandboxAllowance {
|
|||
#[dom_struct]
|
||||
pub struct HTMLIFrameElement {
|
||||
htmlelement: HTMLElement,
|
||||
size: Cell<Option<IFrameSize>>,
|
||||
subpage_id: Cell<Option<SubpageId>>,
|
||||
containing_page_pipeline_id: Cell<Option<PipelineId>>,
|
||||
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 {
|
||||
fn is_sandboxed(self) -> bool;
|
||||
fn get_url(self) -> Option<Url>;
|
||||
/// http://www.whatwg.org/html/#process-the-iframe-attributes
|
||||
fn process_the_iframe_attributes(self);
|
||||
fn generate_new_subpage_id(self, page: &Page) -> (SubpageId, Option<SubpageId>);
|
||||
}
|
||||
|
||||
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) {
|
||||
let url = match self.get_url() {
|
||||
Some(url) => url.clone(),
|
||||
|
@ -112,19 +101,19 @@ impl<'a> HTMLIFrameElementHelpers for JSRef<'a, HTMLIFrameElement> {
|
|||
IFrameUnsandboxed
|
||||
};
|
||||
|
||||
// Subpage Id
|
||||
let window = window_from_node(self).root();
|
||||
let window = window.r();
|
||||
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 {
|
||||
pipeline_id: page.id,
|
||||
subpage_id: subpage_id,
|
||||
}));
|
||||
self.containing_page_pipeline_id.set(Some(page.id));
|
||||
|
||||
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 {
|
||||
HTMLIFrameElement {
|
||||
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),
|
||||
}
|
||||
}
|
||||
|
@ -144,8 +134,13 @@ impl HTMLIFrameElement {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn size(&self) -> Option<IFrameSize> {
|
||||
self.size.get()
|
||||
pub fn containing_page_pipeline_id(&self) -> Option<PipelineId> {
|
||||
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>> {
|
||||
self.size.get().and_then(|size| {
|
||||
self.subpage_id.get().and_then(|subpage_id| {
|
||||
let window = window_from_node(self).root();
|
||||
let children = window.page().children.borrow();
|
||||
let child = children.iter().find(|child| {
|
||||
child.subpage_id.unwrap() == size.subpage_id
|
||||
child.subpage_id.unwrap() == subpage_id
|
||||
});
|
||||
child.and_then(|page| {
|
||||
page.frame.borrow().as_ref().map(|frame| {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue