mirror of
https://github.com/servo/servo.git
synced 2025-08-06 06:00:15 +01:00
remove page and move functionality to browing context
Allow for adding history items Fixed nested iframe test failure Cleanup and small refactors fixup
This commit is contained in:
parent
392135bd0c
commit
cbc5ca65a8
9 changed files with 461 additions and 479 deletions
|
@ -3,6 +3,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use dom::bindings::cell::DOMRefCell;
|
||||
use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
|
||||
use dom::bindings::conversions::{ToJSValConvertible, root_from_handleobject};
|
||||
use dom::bindings::js::{JS, Root, RootedReference};
|
||||
use dom::bindings::proxyhandler::{fill_property_descriptor, get_property_descriptor};
|
||||
|
@ -22,27 +23,48 @@ use js::jsapi::{JS_ForwardGetPropertyTo, JS_ForwardSetPropertyTo, JS_GetClass, J
|
|||
use js::jsapi::{JS_GetOwnPropertyDescriptorById, JS_HasPropertyById, MutableHandle};
|
||||
use js::jsapi::{MutableHandleValue, ObjectOpResult, RootedObject, RootedValue};
|
||||
use js::jsval::{UndefinedValue, PrivateValue};
|
||||
use msg::constellation_msg::{PipelineId, SubpageId};
|
||||
use std::cell::Cell;
|
||||
use url::Url;
|
||||
use util::str::DOMString;
|
||||
|
||||
#[dom_struct]
|
||||
pub struct BrowsingContext {
|
||||
reflector: Reflector,
|
||||
|
||||
/// Pipeline id associated with this context.
|
||||
id: PipelineId,
|
||||
|
||||
/// Indicates if reflow is required when reloading.
|
||||
needs_reflow: Cell<bool>,
|
||||
|
||||
/// Stores this context's session history
|
||||
history: DOMRefCell<Vec<SessionHistoryEntry>>,
|
||||
active_index: usize,
|
||||
|
||||
/// The index of the active session history entry
|
||||
active_index: Cell<usize>,
|
||||
|
||||
/// Stores the child browsing contexts (ex. iframe browsing context)
|
||||
children: DOMRefCell<Vec<JS<BrowsingContext>>>,
|
||||
|
||||
frame_element: Option<JS<Element>>,
|
||||
}
|
||||
|
||||
impl BrowsingContext {
|
||||
pub fn new_inherited(frame_element: Option<&Element>) -> BrowsingContext {
|
||||
pub fn new_inherited(frame_element: Option<&Element>, id: PipelineId) -> BrowsingContext {
|
||||
BrowsingContext {
|
||||
reflector: Reflector::new(),
|
||||
id: id,
|
||||
needs_reflow: Cell::new(true),
|
||||
history: DOMRefCell::new(vec![]),
|
||||
active_index: 0,
|
||||
active_index: Cell::new(0),
|
||||
children: DOMRefCell::new(vec![]),
|
||||
frame_element: frame_element.map(JS::from_ref),
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
pub fn new(window: &Window, frame_element: Option<&Element>) -> Root<BrowsingContext> {
|
||||
pub fn new(window: &Window, frame_element: Option<&Element>, id: PipelineId) -> Root<BrowsingContext> {
|
||||
unsafe {
|
||||
let WindowProxyHandler(handler) = window.windowproxy_handler();
|
||||
assert!(!handler.is_null());
|
||||
|
@ -57,7 +79,7 @@ impl BrowsingContext {
|
|||
NewWindowProxy(cx, parent, handler));
|
||||
assert!(!window_proxy.ptr.is_null());
|
||||
|
||||
let object = box BrowsingContext::new_inherited(frame_element);
|
||||
let object = box BrowsingContext::new_inherited(frame_element, id);
|
||||
|
||||
let raw = Box::into_raw(object);
|
||||
SetProxyExtra(window_proxy.ptr, 0, &PrivateValue(raw as *const _));
|
||||
|
@ -70,12 +92,20 @@ impl BrowsingContext {
|
|||
|
||||
pub fn init(&self, document: &Document) {
|
||||
assert!(self.history.borrow().is_empty());
|
||||
assert_eq!(self.active_index, 0);
|
||||
self.history.borrow_mut().push(SessionHistoryEntry::new(document));
|
||||
assert_eq!(self.active_index.get(), 0);
|
||||
self.history.borrow_mut().push(SessionHistoryEntry::new(document, document.url().clone(), document.Title()));
|
||||
}
|
||||
|
||||
pub fn push_history(&self, document: &Document) {
|
||||
let mut history = self.history.borrow_mut();
|
||||
// Clear all session history entries after the active index
|
||||
history.drain((self.active_index.get() + 1)..);
|
||||
history.push(SessionHistoryEntry::new(document, document.url().clone(), document.Title()));
|
||||
self.active_index.set(self.active_index.get() + 1);
|
||||
}
|
||||
|
||||
pub fn active_document(&self) -> Root<Document> {
|
||||
Root::from_ref(&*self.history.borrow()[self.active_index].document)
|
||||
Root::from_ref(&self.history.borrow()[self.active_index.get()].document)
|
||||
}
|
||||
|
||||
pub fn active_window(&self) -> Root<Window> {
|
||||
|
@ -91,6 +121,92 @@ impl BrowsingContext {
|
|||
assert!(!window_proxy.get().is_null());
|
||||
window_proxy.get()
|
||||
}
|
||||
|
||||
pub fn remove(&self, id: PipelineId) -> Option<Root<BrowsingContext>> {
|
||||
let remove_idx = self.children
|
||||
.borrow()
|
||||
.iter()
|
||||
.position(|context| context.id == id);
|
||||
match remove_idx {
|
||||
Some(idx) => Some(Root::from_ref(&*self.children.borrow_mut().remove(idx))),
|
||||
None => {
|
||||
self.children
|
||||
.borrow_mut()
|
||||
.iter_mut()
|
||||
.filter_map(|context| context.remove(id))
|
||||
.next()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_reflow_status(&self, status: bool) -> bool {
|
||||
let old = self.needs_reflow.get();
|
||||
self.needs_reflow.set(status);
|
||||
old
|
||||
}
|
||||
|
||||
pub fn pipeline(&self) -> PipelineId {
|
||||
self.id
|
||||
}
|
||||
|
||||
pub fn push_child_context(&self, context: &BrowsingContext) {
|
||||
self.children.borrow_mut().push(JS::from_ref(&context));
|
||||
}
|
||||
|
||||
pub fn find_child_by_subpage(&self, subpage_id: SubpageId) -> Option<Root<Window>> {
|
||||
self.children.borrow().iter().find(|context| {
|
||||
let window = context.active_window();
|
||||
window.subpage() == Some(subpage_id)
|
||||
}).map(|context| context.active_window())
|
||||
}
|
||||
|
||||
pub fn clear_session_history(&self) {
|
||||
self.active_index.set(0);
|
||||
self.history.borrow_mut().clear();
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ContextIterator {
|
||||
stack: Vec<Root<BrowsingContext>>,
|
||||
}
|
||||
|
||||
pub trait IterableContext {
|
||||
fn iter(&self) -> ContextIterator;
|
||||
fn find(&self, id: PipelineId) -> Option<Root<BrowsingContext>>;
|
||||
}
|
||||
|
||||
impl IterableContext for BrowsingContext {
|
||||
fn iter(&self) -> ContextIterator {
|
||||
ContextIterator {
|
||||
stack: vec!(Root::from_ref(self)),
|
||||
}
|
||||
}
|
||||
|
||||
fn find(&self, id: PipelineId) -> Option<Root<BrowsingContext>> {
|
||||
if self.id == id {
|
||||
return Some(Root::from_ref(self));
|
||||
}
|
||||
|
||||
self.children.borrow()
|
||||
.iter()
|
||||
.filter_map(|c| c.find(id))
|
||||
.next()
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for ContextIterator {
|
||||
type Item = Root<BrowsingContext>;
|
||||
|
||||
fn next(&mut self) -> Option<Root<BrowsingContext>> {
|
||||
let popped = self.stack.pop();
|
||||
if let Some(ref context) = popped {
|
||||
self.stack.extend(context.children.borrow()
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(|ref c| Root::from_ref(&**c)));
|
||||
}
|
||||
popped
|
||||
}
|
||||
}
|
||||
|
||||
// This isn't a DOM struct, just a convenience struct
|
||||
|
@ -100,14 +216,16 @@ impl BrowsingContext {
|
|||
#[derive(JSTraceable, HeapSizeOf)]
|
||||
pub struct SessionHistoryEntry {
|
||||
document: JS<Document>,
|
||||
children: Vec<JS<BrowsingContext>>,
|
||||
url: Url,
|
||||
title: DOMString,
|
||||
}
|
||||
|
||||
impl SessionHistoryEntry {
|
||||
fn new(document: &Document) -> SessionHistoryEntry {
|
||||
fn new(document: &Document, url: Url, title: DOMString) -> SessionHistoryEntry {
|
||||
SessionHistoryEntry {
|
||||
document: JS::from_ref(document),
|
||||
children: vec![],
|
||||
url: url,
|
||||
title: title,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,7 +36,6 @@ use layout_interface::ReflowQueryType;
|
|||
use msg::constellation_msg::{ConstellationChan, LoadData};
|
||||
use msg::constellation_msg::{NavigationDirection, PipelineId, SubpageId};
|
||||
use net_traits::response::HttpsState;
|
||||
use page::IterablePage;
|
||||
use script_traits::IFrameSandboxState::{IFrameSandboxed, IFrameUnsandboxed};
|
||||
use script_traits::{IFrameLoadInfo, MozBrowserEvent, ScriptMsg as ConstellationMsg};
|
||||
use std::ascii::AsciiExt;
|
||||
|
@ -418,11 +417,8 @@ impl HTMLIFrameElementMethods for HTMLIFrameElement {
|
|||
self.subpage_id.get().and_then(|subpage_id| {
|
||||
let window = window_from_node(self);
|
||||
let window = window.r();
|
||||
let children = window.page().children.borrow();
|
||||
children.iter().find(|page| {
|
||||
let window = page.window();
|
||||
window.subpage() == Some(subpage_id)
|
||||
}).map(|page| page.window())
|
||||
let browsing_context = window.browsing_context();
|
||||
browsing_context.find_child_by_subpage(subpage_id)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -10,12 +10,12 @@ use dom::bindings::inheritance::Castable;
|
|||
use dom::bindings::js::{Root, RootedReference};
|
||||
use dom::bindings::refcounted::Trusted;
|
||||
use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object};
|
||||
use dom::browsingcontext::IterableContext;
|
||||
use dom::event::{Event, EventBubbles, EventCancelable};
|
||||
use dom::storageevent::StorageEvent;
|
||||
use dom::urlhelper::UrlHelper;
|
||||
use ipc_channel::ipc;
|
||||
use net_traits::storage_thread::{StorageThread, StorageThreadMsg, StorageType};
|
||||
use page::IterablePage;
|
||||
use script_runtime::ScriptChan;
|
||||
use script_thread::{MainThreadRunnable, ScriptThread};
|
||||
use task_source::dom_manipulation::DOMManipulationTask;
|
||||
|
@ -199,9 +199,9 @@ impl MainThreadRunnable for StorageEventRunnable {
|
|||
Some(storage)
|
||||
);
|
||||
|
||||
let root_page = script_thread.root_page();
|
||||
for it_page in root_page.iter() {
|
||||
let it_window_root = it_page.window();
|
||||
let root_context = script_thread.root_browsing_context();
|
||||
for it_context in root_context.iter() {
|
||||
let it_window_root = it_context.active_window();
|
||||
let it_window = it_window_root.r();
|
||||
assert!(UrlHelper::SameOrigin(&ev_url, &it_window.get_url()));
|
||||
// TODO: Such a Document object is not necessarily fully active, but events fired on such
|
||||
|
|
|
@ -51,7 +51,6 @@ use net_traits::bluetooth_thread::BluetoothMethodMsg;
|
|||
use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheThread};
|
||||
use net_traits::storage_thread::{StorageThread, StorageType};
|
||||
use num_traits::ToPrimitive;
|
||||
use page::Page;
|
||||
use profile_traits::mem;
|
||||
use reporter::CSSErrorReporter;
|
||||
use rustc_serialize::base64::{FromBase64, STANDARD, ToBase64};
|
||||
|
@ -151,7 +150,6 @@ pub struct Window {
|
|||
#[ignore_heap_size_of = "TODO(#6911) newtypes containing unmeasurable types are hard"]
|
||||
compositor: IpcSender<ScriptToCompositorMsg>,
|
||||
browsing_context: MutNullableHeap<JS<BrowsingContext>>,
|
||||
page: Rc<Page>,
|
||||
performance: MutNullableHeap<JS<Performance>>,
|
||||
navigation_start: u64,
|
||||
navigation_start_precise: f64,
|
||||
|
@ -337,10 +335,6 @@ impl Window {
|
|||
self.browsing_context.get().unwrap()
|
||||
}
|
||||
|
||||
pub fn page(&self) -> &Page {
|
||||
&*self.page
|
||||
}
|
||||
|
||||
pub fn bluetooth_thread(&self) -> IpcSender<BluetoothMethodMsg> {
|
||||
self.bluetooth_thread.clone()
|
||||
}
|
||||
|
@ -1420,7 +1414,6 @@ impl Window {
|
|||
|
||||
impl Window {
|
||||
pub fn new(runtime: Rc<Runtime>,
|
||||
page: Rc<Page>,
|
||||
script_chan: MainThreadScriptChan,
|
||||
dom_task_source: DOMManipulationTaskSource,
|
||||
user_task_source: UserInteractionTaskSource,
|
||||
|
@ -1467,7 +1460,6 @@ impl Window {
|
|||
console: Default::default(),
|
||||
crypto: Default::default(),
|
||||
compositor: compositor,
|
||||
page: page,
|
||||
navigator: Default::default(),
|
||||
image_cache_thread: image_cache_thread,
|
||||
mem_profiler_chan: mem_profiler_chan,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue