Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion components/constellation/constellation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1623,12 +1623,12 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
pipeline_id: PipelineId,
event: MozBrowserEvent) {
assert!(PREFS.is_mozbrowser_enabled());
let frame_id = self.pipelines.get(&pipeline_id).map(|pipeline| pipeline.frame_id);

// Find the script channel for the given parent pipeline,
// and pass the event to that script thread.
// If the pipeline lookup fails, it is because we have torn down the pipeline,
// so it is reasonable to silently ignore the event.
let frame_id = self.pipelines.get(&pipeline_id).map(|pipeline| pipeline.frame_id);
match self.pipelines.get(&parent_pipeline_id) {
Some(pipeline) => pipeline.trigger_mozbrowser_event(frame_id, event),
None => warn!("Pipeline {:?} handling mozbrowser event after closure.", parent_pipeline_id),
Expand Down Expand Up @@ -2206,6 +2206,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>

// Close a frame (and all children)
fn close_frame(&mut self, frame_id: FrameId, exit_mode: ExitPipelineMode) {
debug!("Closing frame {:?}.", frame_id);
// Store information about the pipelines to be closed. Then close the
// pipelines, before removing ourself from the frames hash map. This
// ordering is vital - so that if close_pipeline() ends up closing
Expand Down Expand Up @@ -2241,10 +2242,12 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
};
parent_pipeline.remove_child(frame_id);
}
debug!("Closed frame {:?}.", frame_id);
}

// Close all pipelines at and beneath a given frame
fn close_pipeline(&mut self, pipeline_id: PipelineId, exit_mode: ExitPipelineMode) {
debug!("Closing pipeline {:?}.", pipeline_id);
// Store information about the frames to be closed. Then close the
// frames, before removing ourself from the pipelines hash map. This
// ordering is vital - so that if close_frames() ends up closing
Expand Down Expand Up @@ -2284,6 +2287,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
ExitPipelineMode::Normal => pipeline.exit(),
ExitPipelineMode::Force => pipeline.force_exit(),
}
debug!("Closed pipeline {:?}.", pipeline_id);
}

// Randomly close a pipeline -if --random-pipeline-closure-probability is set
Expand Down
108 changes: 40 additions & 68 deletions components/script/devtools.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@ use dom::bindings::inheritance::Castable;
use dom::bindings::js::Root;
use dom::bindings::reflector::Reflectable;
use dom::bindings::str::DOMString;
use dom::browsingcontext::BrowsingContext;
use dom::element::Element;
use dom::globalscope::GlobalScope;
use dom::node::Node;
use dom::node::{Node, window_from_node};
use dom::window::Window;
use ipc_channel::ipc::IpcSender;
use js::jsapi::{JSAutoCompartment, ObjectClassName};
use js::jsval::UndefinedValue;
use msg::constellation_msg::PipelineId;
use script_thread::Documents;
use std::ffi::CStr;
use std::str;
use style::properties::longhands::{margin_bottom, margin_left, margin_right, margin_top};
Expand Down Expand Up @@ -72,53 +72,35 @@ pub fn handle_evaluate_js(global: &GlobalScope, eval: String, reply: IpcSender<E
reply.send(result).unwrap();
}

pub fn handle_get_root_node(context: &BrowsingContext, pipeline: PipelineId, reply: IpcSender<Option<NodeInfo>>) {
let context = match context.find(pipeline) {
Some(found_context) => found_context,
None => return reply.send(None).unwrap()
};

let document = context.active_document();

let node = document.upcast::<Node>();
reply.send(Some(node.summarize())).unwrap();
pub fn handle_get_root_node(documents: &Documents, pipeline: PipelineId, reply: IpcSender<Option<NodeInfo>>) {
let info = documents.find_document(pipeline)
.map(|document| document.upcast::<Node>().summarize());
reply.send(info).unwrap();
}

pub fn handle_get_document_element(context: &BrowsingContext,
pub fn handle_get_document_element(documents: &Documents,
pipeline: PipelineId,
reply: IpcSender<Option<NodeInfo>>) {
let context = match context.find(pipeline) {
Some(found_context) => found_context,
None => return reply.send(None).unwrap()
};

let document = context.active_document();
let document_element = document.GetDocumentElement().unwrap();

let node = document_element.upcast::<Node>();
reply.send(Some(node.summarize())).unwrap();
let info = documents.find_document(pipeline)
.and_then(|document| document.GetDocumentElement())
.map(|element| element.upcast::<Node>().summarize());
reply.send(info).unwrap();
}

fn find_node_by_unique_id(context: &BrowsingContext,
fn find_node_by_unique_id(documents: &Documents,
pipeline: PipelineId,
node_id: &str)
-> Option<Root<Node>> {
let context = match context.find(pipeline) {
Some(found_context) => found_context,
None => return None
};

let document = context.active_document();
let node = document.upcast::<Node>();

node.traverse_preorder().find(|candidate| candidate.unique_id() == node_id)
documents.find_document(pipeline).and_then(|document|
document.upcast::<Node>().traverse_preorder().find(|candidate| candidate.unique_id() == node_id)
)
}

pub fn handle_get_children(context: &BrowsingContext,
pub fn handle_get_children(documents: &Documents,
pipeline: PipelineId,
node_id: String,
reply: IpcSender<Option<Vec<NodeInfo>>>) {
match find_node_by_unique_id(context, pipeline, &*node_id) {
match find_node_by_unique_id(documents, pipeline, &*node_id) {
None => return reply.send(None).unwrap(),
Some(parent) => {
let children = parent.children()
Expand All @@ -130,11 +112,11 @@ pub fn handle_get_children(context: &BrowsingContext,
};
}

pub fn handle_get_layout(context: &BrowsingContext,
pub fn handle_get_layout(documents: &Documents,
pipeline: PipelineId,
node_id: String,
reply: IpcSender<Option<ComputedNodeLayout>>) {
let node = match find_node_by_unique_id(context, pipeline, &*node_id) {
let node = match find_node_by_unique_id(documents, pipeline, &*node_id) {
None => return reply.send(None).unwrap(),
Some(found_node) => found_node
};
Expand All @@ -144,7 +126,7 @@ pub fn handle_get_layout(context: &BrowsingContext,
let width = rect.Width() as f32;
let height = rect.Height() as f32;

let window = context.active_window();
let window = window_from_node(&*node);
let elem = node.downcast::<Element>().expect("should be getting layout of element");
let computed_style = window.GetComputedStyle(elem, None);

Expand Down Expand Up @@ -223,11 +205,11 @@ pub fn handle_get_cached_messages(_pipeline_id: PipelineId,
reply.send(messages).unwrap();
}

pub fn handle_modify_attribute(context: &BrowsingContext,
pub fn handle_modify_attribute(documents: &Documents,
pipeline: PipelineId,
node_id: String,
modifications: Vec<Modification>) {
let node = match find_node_by_unique_id(context, pipeline, &*node_id) {
let node = match find_node_by_unique_id(documents, pipeline, &*node_id) {
None => return warn!("node id {} for pipeline id {} is not found", &node_id, &pipeline),
Some(found_node) => found_node
};
Expand All @@ -249,49 +231,39 @@ pub fn handle_wants_live_notifications(global: &GlobalScope, send_notifications:
global.set_devtools_wants_updates(send_notifications);
}

pub fn handle_set_timeline_markers(context: &BrowsingContext,
pub fn handle_set_timeline_markers(documents: &Documents,
pipeline: PipelineId,
marker_types: Vec<TimelineMarkerType>,
reply: IpcSender<Option<TimelineMarker>>) {
match context.find(pipeline) {
match documents.find_window(pipeline) {
None => reply.send(None).unwrap(),
Some(context) => context.active_window().set_devtools_timeline_markers(marker_types, reply),
Some(window) => window.set_devtools_timeline_markers(marker_types, reply),
}
}

pub fn handle_drop_timeline_markers(context: &BrowsingContext,
pub fn handle_drop_timeline_markers(documents: &Documents,
pipeline: PipelineId,
marker_types: Vec<TimelineMarkerType>) {
if let Some(context) = context.find(pipeline) {
context.active_window().drop_devtools_timeline_markers(marker_types);
if let Some(window) = documents.find_window(pipeline) {
window.drop_devtools_timeline_markers(marker_types);
}
}

pub fn handle_request_animation_frame(context: &BrowsingContext,
pub fn handle_request_animation_frame(documents: &Documents,
id: PipelineId,
actor_name: String) {
let context = match context.find(id) {
None => return warn!("context for pipeline id {} is not found", id),
Some(found_node) => found_node
};

let doc = context.active_document();
let devtools_sender =
context.active_window().upcast::<GlobalScope>().devtools_chan().unwrap().clone();
doc.request_animation_frame(box move |time| {
let msg = ScriptToDevtoolsControlMsg::FramerateTick(actor_name, time);
devtools_sender.send(msg).unwrap();
});
if let Some(doc) = documents.find_document(id) {
let devtools_sender = doc.window().upcast::<GlobalScope>().devtools_chan().unwrap().clone();
doc.request_animation_frame(box move |time| {
let msg = ScriptToDevtoolsControlMsg::FramerateTick(actor_name, time);
devtools_sender.send(msg).unwrap();
});
}
}

pub fn handle_reload(context: &BrowsingContext,
pub fn handle_reload(documents: &Documents,
id: PipelineId) {
let context = match context.find(id) {
None => return warn!("context for pipeline id {} is not found", id),
Some(found_node) => found_node
};

let win = context.active_window();
let location = win.Location();
location.Reload();
if let Some(win) = documents.find_window(id) {
win.Location().Reload();
}
}
83 changes: 6 additions & 77 deletions components/script/dom/browsingcontext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
* 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::conversions::{ToJSValConvertible, root_from_handleobject};
use dom::bindings::inheritance::Castable;
use dom::bindings::js::{JS, MutNullableHeap, Root, RootedReference};
Expand Down Expand Up @@ -37,15 +36,9 @@ use std::cell::Cell;
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 the child browsing contexts (ex. iframe browsing context)
children: DOMRefCell<Vec<JS<BrowsingContext>>>,

/// The current active document.
/// Note that the session history is stored in the constellation,
/// in the script thread we just track the current active document.
Expand All @@ -56,19 +49,17 @@ pub struct BrowsingContext {
}

impl BrowsingContext {
pub fn new_inherited(frame_element: Option<&Element>, id: PipelineId) -> BrowsingContext {
pub fn new_inherited(frame_element: Option<&Element>) -> BrowsingContext {
BrowsingContext {
reflector: Reflector::new(),
id: id,
needs_reflow: Cell::new(true),
children: DOMRefCell::new(vec![]),
active_document: Default::default(),
frame_element: frame_element.map(JS::from_ref),
}
}

#[allow(unsafe_code)]
pub fn new(window: &Window, frame_element: Option<&Element>, id: PipelineId) -> Root<BrowsingContext> {
pub fn new(window: &Window, frame_element: Option<&Element>) -> Root<BrowsingContext> {
unsafe {
let WindowProxyHandler(handler) = window.windowproxy_handler();
assert!(!handler.is_null());
Expand All @@ -81,7 +72,7 @@ impl BrowsingContext {
rooted!(in(cx) let window_proxy = NewWindowProxy(cx, parent, handler));
assert!(!window_proxy.is_null());

let object = box BrowsingContext::new_inherited(frame_element, id);
let object = box BrowsingContext::new_inherited(frame_element);

let raw = Box::into_raw(object);
SetProxyExtra(window_proxy.get(), 0, &PrivateValue(raw as *const _));
Expand Down Expand Up @@ -118,82 +109,20 @@ impl BrowsingContext {
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_id(&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_id(&self, pipeline_id: PipelineId) -> Option<Root<Window>> {
self.children.borrow().iter().find(|context| {
let window = context.active_window();
window.upcast::<GlobalScope>().pipeline_id() == pipeline_id
}).map(|context| context.active_window())
pub fn active_pipeline_id(&self) -> Option<PipelineId> {
self.active_document.get()
.map(|doc| doc.window().upcast::<GlobalScope>().pipeline_id())
}

pub fn unset_active_document(&self) {
self.active_document.set(None)
}

pub fn iter(&self) -> ContextIterator {
ContextIterator {
stack: vec!(Root::from_ref(self)),
}
}

pub 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()
}
}

pub struct ContextIterator {
stack: Vec<Root<BrowsingContext>>,
}

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()
.map(|c| Root::from_ref(&**c)));
}
popped
}
}

#[allow(unsafe_code)]
Expand Down
Loading