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:
Martin Robinson 2014-11-11 08:20:37 -08:00
parent c1d218cf02
commit 6a46eef5cd
4 changed files with 126 additions and 95 deletions

View file

@ -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.
}

View file

@ -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())
}
}

View file

@ -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),

View file

@ -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| {