forked from mirrors/gecko-dev
		
	 204eaa3597
			
		
	
	
		204eaa3597
		
	
	
	
	
		
			
			This implements a simple load-tracking system and tracks stylesheet loads as an example of how it fits together. This is a simplified and rebased version of #3714; I do not believe that the main thrust of hsivonen's comments (related to tracking navigation in browsing contexts) affect this part of the work. r? @Ms2ger Source-Repo: https://github.com/servo/servo Source-Revision: 2baa69595e2d57213c34b7e168b60885948fa85b
		
			
				
	
	
		
			147 lines
		
	
	
	
		
			3.9 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			147 lines
		
	
	
	
		
			3.9 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, Temporary, Unrooted};
 | |
| 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;
 | |
| use url::Url;
 | |
| 
 | |
| /// Encapsulates a handle to a frame in a frame tree.
 | |
| #[jstraceable]
 | |
| pub struct Page {
 | |
|     /// Pipeline id associated with this page.
 | |
|     id: PipelineId,
 | |
| 
 | |
|     /// The outermost frame containing the document and window.
 | |
|     frame: DOMRefCell<Option<Frame>>,
 | |
| 
 | |
|     /// Cached copy of the most recent url loaded by the script, after all redirections.
 | |
|     /// TODO(tkuehn): this currently does not follow any particular caching policy
 | |
|     /// and simply caches pages forever (!).
 | |
|     url: Url,
 | |
| 
 | |
|     /// 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().iter() {
 | |
|             let found = page.find(id);
 | |
|             if found.is_some() { return found; }
 | |
|         }
 | |
|         None
 | |
|     }
 | |
| 
 | |
| }
 | |
| 
 | |
| impl Page {
 | |
|     pub fn new(id: PipelineId, url: Url) -> Page {
 | |
|         Page {
 | |
|             id: id,
 | |
|             frame: DOMRefCell::new(None),
 | |
|             url: url,
 | |
|             needs_reflow: Cell::new(true),
 | |
|             children: DOMRefCell::new(vec!()),
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     pub fn pipeline(&self) -> PipelineId {
 | |
|         self.id
 | |
|     }
 | |
| 
 | |
|     pub fn window(&self) -> Temporary<Window> {
 | |
|         Temporary::from_rooted(self.frame.borrow().as_ref().unwrap().window.clone())
 | |
|     }
 | |
| 
 | |
|     pub fn window_for_script_deallocation(&self) -> Unrooted<Window> {
 | |
|         Unrooted::from_js(self.frame.borrow().as_ref().unwrap().window)
 | |
|     }
 | |
| 
 | |
|     pub fn document(&self) -> Temporary<Document> {
 | |
|         Temporary::from_rooted(self.frame.borrow().as_ref().unwrap().document.clone())
 | |
|     }
 | |
| 
 | |
|     // 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().iter() {
 | |
|                     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<Frame>) {
 | |
|         *self.frame.borrow_mut() = frame;
 | |
|     }
 | |
| }
 | |
| 
 | |
| /// Information for one frame in the browsing context.
 | |
| #[jstraceable]
 | |
| #[must_root]
 | |
| pub struct Frame {
 | |
|     /// The document for this frame.
 | |
|     pub document: JS<Document>,
 | |
|     /// The window object for this frame.
 | |
|     pub window: JS<Window>,
 | |
| }
 |