mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
136 lines
3.5 KiB
Rust
136 lines
3.5 KiB
Rust
/* 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;
|
|
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<Option<Frame>>,
|
|
|
|
/// Indicates if reflow is required when reloading.
|
|
needs_reflow: Cell<bool>,
|
|
|
|
// Child Pages.
|
|
pub children: DOMRefCell<Vec<Rc<Page>>>,
|
|
}
|
|
|
|
pub struct PageIterator {
|
|
stack: Vec<Rc<Page>>,
|
|
}
|
|
|
|
pub trait IterablePage {
|
|
fn iter(&self) -> PageIterator;
|
|
fn find(&self, id: PipelineId) -> Option<Rc<Page>>;
|
|
}
|
|
|
|
impl IterablePage for Rc<Page> {
|
|
fn iter(&self) -> PageIterator {
|
|
PageIterator {
|
|
stack: vec!(self.clone()),
|
|
}
|
|
}
|
|
fn find(&self, id: PipelineId) -> Option<Rc<Page>> {
|
|
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<Window> {
|
|
Root::from_ref(&*self.frame.borrow().as_ref().unwrap().window)
|
|
}
|
|
|
|
pub fn document(&self) -> Root<Document> {
|
|
Root::from_ref(&*self.frame.borrow().as_ref().unwrap().document)
|
|
}
|
|
|
|
// must handle root case separately
|
|
pub fn remove(&self, id: PipelineId) -> Option<Rc<Page>> {
|
|
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<Page>;
|
|
|
|
fn next(&mut self) -> Option<Rc<Page>> {
|
|
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
|
|
}
|
|
|
|
#[allow(unrooted_must_root)]
|
|
pub fn set_frame(&self, frame: Option<Frame>) {
|
|
*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<Document>,
|
|
/// The window object for this frame.
|
|
pub window: JS<Window>,
|
|
}
|