/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::cell::DOMRefCell; use dom::bindings::js::{JS, Root}; use dom::document::{Document, DocumentHelpers}; use dom::node::NodeHelpers; use dom::window::Window; use msg::constellation_msg::PipelineId; use std::cell::Cell; use std::rc::Rc; /// Encapsulates a handle to a frame in a frame tree. #[derive(JSTraceable, HeapSizeOf)] #[allow(unrooted_must_root)] // FIXME(#6687) this is wrong pub struct Page { /// Pipeline id associated with this page. id: PipelineId, /// The outermost frame containing the document and window. frame: DOMRefCell>, /// Indicates if reflow is required when reloading. needs_reflow: Cell, // Child Pages. pub children: DOMRefCell>>, } pub struct PageIterator { stack: Vec>, } pub trait IterablePage { fn iter(&self) -> PageIterator; fn find(&self, id: PipelineId) -> Option>; } impl IterablePage for Rc { fn iter(&self) -> PageIterator { PageIterator { stack: vec!(self.clone()), } } fn find(&self, id: PipelineId) -> Option> { if self.id == id { return Some(self.clone()); } for page in &*self.children.borrow() { let found = page.find(id); if found.is_some() { return found; } } None } } impl Page { pub fn new(id: PipelineId) -> Page { Page { id: id, frame: DOMRefCell::new(None), needs_reflow: Cell::new(true), children: DOMRefCell::new(vec!()), } } pub fn pipeline(&self) -> PipelineId { self.id } pub fn window(&self) -> Root { self.frame.borrow().as_ref().unwrap().window.root() } pub fn document(&self) -> Root { self.frame.borrow().as_ref().unwrap().document.root() } // must handle root case separately pub fn remove(&self, id: PipelineId) -> Option> { let remove_idx = { self.children .borrow_mut() .iter_mut() .position(|page_tree| page_tree.id == id) }; match remove_idx { Some(idx) => Some(self.children.borrow_mut().remove(idx)), None => { self.children .borrow_mut() .iter_mut() .filter_map(|page_tree| page_tree.remove(id)) .next() } } } } impl Iterator for PageIterator { type Item = Rc; fn next(&mut self) -> Option> { match self.stack.pop() { Some(next) => { for child in &*next.children.borrow() { self.stack.push(child.clone()); } Some(next) }, None => None, } } } impl Page { pub fn set_reflow_status(&self, status: bool) -> bool { let old = self.needs_reflow.get(); self.needs_reflow.set(status); old } pub fn set_frame(&self, frame: Option) { *self.frame.borrow_mut() = frame; } } /// Information for one frame in the browsing context. #[derive(JSTraceable, HeapSizeOf)] #[must_root] pub struct Frame { /// The document for this frame. pub document: JS, /// The window object for this frame. pub window: JS, }