mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
Firefox timeline integration #4957
This commit is contained in:
parent
1e45d025b3
commit
97714ec5ed
15 changed files with 761 additions and 14 deletions
|
@ -2,7 +2,7 @@
|
|||
* 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 devtools_traits::{EvaluateJSReply, NodeInfo, Modification};
|
||||
use devtools_traits::{EvaluateJSReply, NodeInfo, Modification, TimelineMarker, TimelineMarkerType};
|
||||
use dom::bindings::conversions::FromJSValConvertible;
|
||||
use dom::bindings::conversions::StringificationBehavior;
|
||||
use dom::bindings::js::{JSRef, Temporary, OptionalRootable};
|
||||
|
@ -16,7 +16,7 @@ use dom::element::Element;
|
|||
use dom::document::DocumentHelpers;
|
||||
use page::Page;
|
||||
use msg::constellation_msg::PipelineId;
|
||||
use script_task::get_page;
|
||||
use script_task::{get_page, ScriptTask};
|
||||
|
||||
use std::sync::mpsc::Sender;
|
||||
use std::rc::Rc;
|
||||
|
@ -114,3 +114,36 @@ pub fn handle_wants_live_notifications(page: &Rc<Page>, pipeline_id: PipelineId,
|
|||
let window = page.window().root();
|
||||
window.r().set_devtools_wants_updates(send_notifications);
|
||||
}
|
||||
|
||||
pub fn handle_set_timeline_markers(page: &Rc<Page>,
|
||||
script_task: &ScriptTask,
|
||||
marker_types: Vec<TimelineMarkerType>,
|
||||
reply: Sender<TimelineMarker>) {
|
||||
for marker_type in &marker_types {
|
||||
match *marker_type {
|
||||
TimelineMarkerType::Reflow => {
|
||||
let window = page.window().root();
|
||||
window.r().set_devtools_timeline_marker(TimelineMarkerType::Reflow, reply.clone());
|
||||
}
|
||||
TimelineMarkerType::DOMEvent => {
|
||||
script_task.set_devtools_timeline_marker(TimelineMarkerType::DOMEvent, reply.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_drop_timeline_markers(page: &Rc<Page>,
|
||||
script_task: &ScriptTask,
|
||||
marker_types: Vec<TimelineMarkerType>) {
|
||||
let window = page.window().root();
|
||||
for marker_type in &marker_types {
|
||||
match *marker_type {
|
||||
TimelineMarkerType::Reflow => {
|
||||
window.r().drop_devtools_timeline_markers();
|
||||
}
|
||||
TimelineMarkerType::DOMEvent => {
|
||||
script_task.drop_devtools_timeline_markers();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -241,6 +241,7 @@ no_jsmanaged_fields!(ImageCacheTask, ScriptControlChan);
|
|||
no_jsmanaged_fields!(Atom, Namespace, Timer);
|
||||
no_jsmanaged_fields!(Trusted<T>);
|
||||
no_jsmanaged_fields!(PropertyDeclarationBlock);
|
||||
no_jsmanaged_fields!(HashSet<T>);
|
||||
// These three are interdependent, if you plan to put jsmanaged data
|
||||
// in one of these make sure it is propagated properly to containing structs
|
||||
no_jsmanaged_fields!(SubpageId, WindowSizeData, PipelineId);
|
||||
|
|
|
@ -34,7 +34,7 @@ use script_task::ScriptMsg;
|
|||
use script_traits::ScriptControlChan;
|
||||
use timers::{IsInterval, TimerId, TimerManager, TimerCallback};
|
||||
|
||||
use devtools_traits::DevtoolsControlChan;
|
||||
use devtools_traits::{DevtoolsControlChan, TimelineMarker, TimelineMarkerType, TracingMetadata};
|
||||
use msg::compositor_msg::ScriptListener;
|
||||
use msg::constellation_msg::{LoadData, PipelineId, SubpageId, ConstellationChan, WindowSizeData, WorkerId};
|
||||
use net_traits::ResourceTask;
|
||||
|
@ -54,13 +54,15 @@ use url::{Url, UrlParser};
|
|||
|
||||
use libc;
|
||||
use rustc_serialize::base64::{FromBase64, ToBase64, STANDARD};
|
||||
use std::cell::{Cell, Ref, RefMut};
|
||||
use std::borrow::ToOwned;
|
||||
use std::cell::{Cell, Ref, RefMut, RefCell};
|
||||
use std::collections::HashSet;
|
||||
use std::default::Default;
|
||||
use std::ffi::CString;
|
||||
use std::mem;
|
||||
use std::num::Float;
|
||||
use std::rc::Rc;
|
||||
use std::sync::mpsc::{channel, Receiver};
|
||||
use std::sync::mpsc::{channel, Receiver, Sender};
|
||||
use std::sync::mpsc::TryRecvError::{Empty, Disconnected};
|
||||
use time;
|
||||
|
||||
|
@ -102,6 +104,10 @@ pub struct Window {
|
|||
|
||||
/// For providing instructions to an optional devtools server.
|
||||
devtools_chan: Option<DevtoolsControlChan>,
|
||||
/// For sending timeline markers. Will be ignored if
|
||||
/// no devtools server
|
||||
devtools_markers: RefCell<HashSet<TimelineMarkerType>>,
|
||||
devtools_marker_sender: RefCell<Option<Sender<TimelineMarker>>>,
|
||||
|
||||
/// A flag to indicate whether the developer tools have requested live updates of
|
||||
/// page changes.
|
||||
|
@ -477,6 +483,10 @@ pub trait WindowHelpers {
|
|||
fn IndexedGetter(self, _index: u32, _found: &mut bool) -> Option<Temporary<Window>>;
|
||||
fn thaw(self);
|
||||
fn freeze(self);
|
||||
fn need_emit_timeline_marker(self, timeline_type: TimelineMarkerType) -> bool;
|
||||
fn emit_timeline_marker(self, marker: TimelineMarker);
|
||||
fn set_devtools_timeline_marker(self, marker: TimelineMarkerType, reply: Sender<TimelineMarker>);
|
||||
fn drop_devtools_timeline_markers(self);
|
||||
}
|
||||
|
||||
pub trait ScriptHelpers {
|
||||
|
@ -547,6 +557,11 @@ impl<'a> WindowHelpers for JSRef<'a, Window> {
|
|||
None => return,
|
||||
};
|
||||
|
||||
if self.need_emit_timeline_marker(TimelineMarkerType::Reflow) {
|
||||
let marker = TimelineMarker::new("Reflow".to_owned(), TracingMetadata::IntervalStart);
|
||||
self.emit_timeline_marker(marker);
|
||||
}
|
||||
|
||||
// Layout will let us know when it's done.
|
||||
let (join_chan, join_port) = channel();
|
||||
|
||||
|
@ -583,6 +598,11 @@ impl<'a> WindowHelpers for JSRef<'a, Window> {
|
|||
debug!("script: layout forked");
|
||||
|
||||
self.join_layout();
|
||||
|
||||
if self.need_emit_timeline_marker(TimelineMarkerType::Reflow) {
|
||||
let marker = TimelineMarker::new("Reflow".to_owned(), TracingMetadata::IntervalEnd);
|
||||
self.emit_timeline_marker(marker);
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(cgaebel): join_layout is racey. What if the compositor triggers a
|
||||
|
@ -776,6 +796,27 @@ impl<'a> WindowHelpers for JSRef<'a, Window> {
|
|||
fn freeze(self) {
|
||||
self.timers.suspend();
|
||||
}
|
||||
|
||||
fn need_emit_timeline_marker(self, timeline_type: TimelineMarkerType) -> bool {
|
||||
let markers = self.devtools_markers.borrow();
|
||||
markers.contains(&timeline_type)
|
||||
}
|
||||
|
||||
fn emit_timeline_marker(self, marker: TimelineMarker) {
|
||||
let sender = self.devtools_marker_sender.borrow();
|
||||
let sender = sender.as_ref().expect("There is no marker sender");
|
||||
sender.send(marker);
|
||||
}
|
||||
|
||||
fn set_devtools_timeline_marker(self, marker: TimelineMarkerType, reply: Sender<TimelineMarker>) {
|
||||
*self.devtools_marker_sender.borrow_mut() = Some(reply);
|
||||
self.devtools_markers.borrow_mut().insert(marker);
|
||||
}
|
||||
|
||||
fn drop_devtools_timeline_markers(self) {
|
||||
self.devtools_markers.borrow_mut().clear();
|
||||
*self.devtools_marker_sender.borrow_mut() = None;
|
||||
}
|
||||
}
|
||||
|
||||
impl Window {
|
||||
|
@ -836,6 +877,9 @@ impl Window {
|
|||
layout_rpc: layout_rpc,
|
||||
layout_join_port: DOMRefCell::new(None),
|
||||
window_size: Cell::new(window_size),
|
||||
|
||||
devtools_marker_sender: RefCell::new(None),
|
||||
devtools_markers: RefCell::new(HashSet::new()),
|
||||
devtools_wants_updates: Cell::new(false),
|
||||
};
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@ use devtools;
|
|||
|
||||
use devtools_traits::{DevtoolsControlChan, DevtoolsControlPort, DevtoolsPageInfo};
|
||||
use devtools_traits::{DevtoolsControlMsg, DevtoolScriptControlMsg};
|
||||
use devtools_traits::{TimelineMarker, TimelineMarkerType, TracingMetadata};
|
||||
use script_traits::CompositorEvent;
|
||||
use script_traits::CompositorEvent::{ResizeEvent, ReflowEvent, ClickEvent};
|
||||
use script_traits::CompositorEvent::{MouseDownEvent, MouseUpEvent};
|
||||
|
@ -86,6 +87,7 @@ use std::ascii::AsciiExt;
|
|||
use std::any::Any;
|
||||
use std::borrow::ToOwned;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::collections::HashSet;
|
||||
use std::num::ToPrimitive;
|
||||
use std::option::Option;
|
||||
use std::ptr;
|
||||
|
@ -279,6 +281,10 @@ pub struct ScriptTask {
|
|||
/// no such server exists.
|
||||
devtools_port: DevtoolsControlPort,
|
||||
devtools_sender: Sender<DevtoolScriptControlMsg>,
|
||||
/// For sending timeline markers. Will be ignored if
|
||||
/// no devtools server
|
||||
devtools_markers: RefCell<HashSet<TimelineMarkerType>>,
|
||||
devtools_marker_sender: RefCell<Option<Sender<TimelineMarker>>>,
|
||||
|
||||
/// The JavaScript runtime.
|
||||
js_runtime: js::rust::rt,
|
||||
|
@ -447,6 +453,8 @@ impl ScriptTask {
|
|||
devtools_chan: devtools_chan,
|
||||
devtools_port: devtools_receiver,
|
||||
devtools_sender: devtools_sender,
|
||||
devtools_markers: RefCell::new(HashSet::new()),
|
||||
devtools_marker_sender: RefCell::new(None),
|
||||
|
||||
js_runtime: js_runtime,
|
||||
js_context: DOMRefCell::new(Some(js_context)),
|
||||
|
@ -700,6 +708,10 @@ impl ScriptTask {
|
|||
devtools::handle_modify_attribute(&page, id, node_id, modifications),
|
||||
DevtoolScriptControlMsg::WantsLiveNotifications(pipeline_id, to_send) =>
|
||||
devtools::handle_wants_live_notifications(&page, pipeline_id, to_send),
|
||||
DevtoolScriptControlMsg::SetTimelineMarkers(_pipeline_id, marker_types, reply) =>
|
||||
devtools::handle_set_timeline_markers(&page, self, marker_types, reply),
|
||||
DevtoolScriptControlMsg::DropTimelineMarkers(_pipeline_id, marker_types) =>
|
||||
devtools::handle_drop_timeline_markers(&page, self, marker_types),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1150,8 +1162,14 @@ impl ScriptTask {
|
|||
///
|
||||
/// TODO: Actually perform DOM event dispatch.
|
||||
fn handle_event(&self, pipeline_id: PipelineId, event: CompositorEvent) {
|
||||
|
||||
match event {
|
||||
ResizeEvent(new_size) => {
|
||||
let _marker;
|
||||
if self.need_emit_timeline_marker(TimelineMarkerType::DOMEvent) {
|
||||
_marker = AutoDOMEventMarker::new(self);
|
||||
}
|
||||
|
||||
self.handle_resize_event(pipeline_id, new_size);
|
||||
}
|
||||
|
||||
|
@ -1179,6 +1197,10 @@ impl ScriptTask {
|
|||
}
|
||||
|
||||
ClickEvent(button, point) => {
|
||||
let _marker;
|
||||
if self.need_emit_timeline_marker(TimelineMarkerType::DOMEvent) {
|
||||
_marker = AutoDOMEventMarker::new(self);
|
||||
}
|
||||
let page = get_page(&self.root_page(), pipeline_id);
|
||||
let document = page.document().root();
|
||||
document.r().handle_click_event(self.js_runtime.ptr, button, point);
|
||||
|
@ -1187,6 +1209,10 @@ impl ScriptTask {
|
|||
MouseDownEvent(..) => {}
|
||||
MouseUpEvent(..) => {}
|
||||
MouseMoveEvent(point) => {
|
||||
let _marker;
|
||||
if self.need_emit_timeline_marker(TimelineMarkerType::DOMEvent) {
|
||||
_marker = AutoDOMEventMarker::new(self);
|
||||
}
|
||||
let page = get_page(&self.root_page(), pipeline_id);
|
||||
let document = page.document().root();
|
||||
let mouse_over_targets = &mut *self.mouse_over_targets.borrow_mut();
|
||||
|
@ -1195,6 +1221,10 @@ impl ScriptTask {
|
|||
}
|
||||
|
||||
KeyEvent(key, state, modifiers) => {
|
||||
let _marker;
|
||||
if self.need_emit_timeline_marker(TimelineMarkerType::DOMEvent) {
|
||||
_marker = AutoDOMEventMarker::new(self);
|
||||
}
|
||||
let page = get_page(&self.root_page(), pipeline_id);
|
||||
let document = page.document().root();
|
||||
document.r().dispatch_key_event(
|
||||
|
@ -1311,6 +1341,26 @@ impl ScriptTask {
|
|||
|
||||
self.incomplete_loads.borrow_mut().push(incomplete);
|
||||
}
|
||||
|
||||
fn need_emit_timeline_marker(&self, timeline_type: TimelineMarkerType) -> bool {
|
||||
self.devtools_markers.borrow().contains(&timeline_type)
|
||||
}
|
||||
|
||||
fn emit_timeline_marker(&self, marker: TimelineMarker) {
|
||||
let sender = self.devtools_marker_sender.borrow();
|
||||
let sender = sender.as_ref().expect("There is no marker sender");
|
||||
sender.send(marker);
|
||||
}
|
||||
|
||||
pub fn set_devtools_timeline_marker(&self, marker: TimelineMarkerType, reply: Sender<TimelineMarker>) {
|
||||
*self.devtools_marker_sender.borrow_mut() = Some(reply);
|
||||
self.devtools_markers.borrow_mut().insert(marker);
|
||||
}
|
||||
|
||||
pub fn drop_devtools_timeline_markers(&self) {
|
||||
self.devtools_markers.borrow_mut().clear();
|
||||
*self.devtools_marker_sender.borrow_mut() = None;
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for ScriptTask {
|
||||
|
@ -1321,6 +1371,28 @@ impl Drop for ScriptTask {
|
|||
}
|
||||
}
|
||||
|
||||
struct AutoDOMEventMarker<'a> {
|
||||
script_task: &'a ScriptTask
|
||||
}
|
||||
|
||||
impl<'a> AutoDOMEventMarker<'a> {
|
||||
fn new(script_task: &'a ScriptTask) -> AutoDOMEventMarker<'a> {
|
||||
let marker = TimelineMarker::new("DOMEvent".to_owned(), TracingMetadata::IntervalStart);
|
||||
script_task.emit_timeline_marker(marker);
|
||||
AutoDOMEventMarker {
|
||||
script_task: script_task
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl<'a> Drop for AutoDOMEventMarker<'a> {
|
||||
fn drop(&mut self) {
|
||||
let marker = TimelineMarker::new("DOMEvent".to_owned(), TracingMetadata::IntervalEnd);
|
||||
self.script_task.emit_timeline_marker(marker);
|
||||
}
|
||||
}
|
||||
|
||||
/// Shuts down layout for the given page tree.
|
||||
fn shut_down_layout(page_tree: &Rc<Page>, exit_type: PipelineExitType) {
|
||||
let mut channels = vec!();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue