forked from mirrors/gecko-dev
		
	r? @jdm Source-Repo: https://github.com/servo/servo Source-Revision: 9d5f09e09c64d878e6c2bb273195c3c6ca9fe82c
		
			
				
	
	
		
			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> {
 | 
						|
        self.frame.borrow().as_ref().unwrap().window.root()
 | 
						|
    }
 | 
						|
 | 
						|
    pub fn document(&self) -> Root<Document> {
 | 
						|
        self.frame.borrow().as_ref().unwrap().document.root()
 | 
						|
    }
 | 
						|
 | 
						|
    // 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>,
 | 
						|
}
 |