diff options
Diffstat (limited to 'components/shared/devtools/lib.rs')
-rw-r--r-- | components/shared/devtools/lib.rs | 372 |
1 files changed, 372 insertions, 0 deletions
diff --git a/components/shared/devtools/lib.rs b/components/shared/devtools/lib.rs new file mode 100644 index 00000000000..57e11ad8784 --- /dev/null +++ b/components/shared/devtools/lib.rs @@ -0,0 +1,372 @@ +/* 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 https://mozilla.org/MPL/2.0/. */ + +//! This module contains shared types and messages for use by devtools/script. +//! The traits are here instead of in script so that the devtools crate can be +//! modified independently of the rest of Servo. + +#![crate_name = "devtools_traits"] +#![crate_type = "rlib"] +#![allow(non_snake_case)] +#![deny(unsafe_code)] + +use std::net::TcpStream; + +use bitflags::bitflags; +use http::{HeaderMap, Method}; +use ipc_channel::ipc::IpcSender; +use malloc_size_of_derive::MallocSizeOf; +use msg::constellation_msg::{BrowsingContextId, PipelineId}; +use serde::{Deserialize, Serialize}; +use servo_url::ServoUrl; +use time::{self, Duration, Tm}; +use uuid::Uuid; + +// Information would be attached to NewGlobal to be received and show in devtools. +// Extend these fields if we need more information. +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct DevtoolsPageInfo { + pub title: String, + pub url: ServoUrl, +} + +#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)] +pub struct CSSError { + pub filename: String, + pub line: u32, + pub column: u32, + pub msg: String, +} + +/// Messages to instruct the devtools server to update its known actors/state +/// according to changes in the browser. +#[derive(Debug)] +pub enum DevtoolsControlMsg { + /// Messages from threads in the chrome process (resource/constellation/devtools) + FromChrome(ChromeToDevtoolsControlMsg), + /// Messages from script threads + FromScript(ScriptToDevtoolsControlMsg), +} + +/// Events that the devtools server must act upon. +#[derive(Debug)] +pub enum ChromeToDevtoolsControlMsg { + /// A new client has connected to the server. + AddClient(TcpStream), + /// The browser is shutting down. + ServerExitMsg, + /// A network event occurred (request, reply, etc.). The actor with the + /// provided name should be notified. + NetworkEvent(String, NetworkEvent), +} + +/// The state of a page navigation. +#[derive(Debug, Deserialize, Serialize)] +pub enum NavigationState { + /// A browsing context is about to navigate to a given URL. + Start(ServoUrl), + /// A browsing context has completed navigating to the provided pipeline. + Stop(PipelineId, DevtoolsPageInfo), +} + +#[derive(Debug, Deserialize, Serialize)] +/// Events that the devtools server must act upon. +pub enum ScriptToDevtoolsControlMsg { + /// A new global object was created, associated with a particular pipeline. + /// The means of communicating directly with it are provided. + NewGlobal( + (BrowsingContextId, PipelineId, Option<WorkerId>), + IpcSender<DevtoolScriptControlMsg>, + DevtoolsPageInfo, + ), + /// The given browsing context is performing a navigation. + Navigate(BrowsingContextId, NavigationState), + /// A particular page has invoked the console API. + ConsoleAPI(PipelineId, ConsoleMessage, Option<WorkerId>), + /// An animation frame with the given timestamp was processed in a script thread. + /// The actor with the provided name should be notified. + FramerateTick(String, f64), + + /// Report a CSS parse error for the given pipeline + ReportCSSError(PipelineId, CSSError), + + /// Report a page error for the given pipeline + ReportPageError(PipelineId, PageError), + + /// Report a page title change + TitleChanged(PipelineId, String), +} + +/// Serialized JS return values +/// TODO: generalize this beyond the EvaluateJS message? +#[derive(Debug, Deserialize, Serialize)] +pub enum EvaluateJSReply { + VoidValue, + NullValue, + BooleanValue(bool), + NumberValue(f64), + StringValue(String), + ActorValue { class: String, uuid: String }, +} + +#[derive(Debug, Deserialize, Serialize)] +pub struct AttrInfo { + pub namespace: String, + pub name: String, + pub value: String, +} + +#[derive(Debug, Deserialize, Serialize)] +pub struct NodeInfo { + pub uniqueId: String, + pub baseURI: String, + pub parent: String, + pub nodeType: u16, + pub namespaceURI: String, + pub nodeName: String, + pub numChildren: usize, + + pub name: String, + pub publicId: String, + pub systemId: String, + + pub attrs: Vec<AttrInfo>, + + pub isDocumentElement: bool, + + pub shortValue: String, + pub incompleteValue: bool, +} + +pub struct StartedTimelineMarker { + name: String, + start_time: PreciseTime, + start_stack: Option<Vec<()>>, +} + +#[derive(Debug, Deserialize, Serialize)] +pub struct TimelineMarker { + pub name: String, + pub start_time: PreciseTime, + pub start_stack: Option<Vec<()>>, + pub end_time: PreciseTime, + pub end_stack: Option<Vec<()>>, +} + +#[derive(Clone, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)] +pub enum TimelineMarkerType { + Reflow, + DOMEvent, +} + +/// The properties of a DOM node as computed by layout. +#[derive(Debug, Deserialize, Serialize)] +pub struct ComputedNodeLayout { + pub display: String, + pub position: String, + pub zIndex: String, + pub boxSizing: String, + + pub autoMargins: AutoMargins, + pub marginTop: String, + pub marginRight: String, + pub marginBottom: String, + pub marginLeft: String, + + pub borderTopWidth: String, + pub borderRightWidth: String, + pub borderBottomWidth: String, + pub borderLeftWidth: String, + + pub paddingTop: String, + pub paddingRight: String, + pub paddingBottom: String, + pub paddingLeft: String, + + pub width: f32, + pub height: f32, +} + +#[derive(Debug, Deserialize, Serialize)] +pub struct AutoMargins { + pub top: bool, + pub right: bool, + pub bottom: bool, + pub left: bool, +} + +/// Messages to process in a particular script thread, as instructed by a devtools client. +/// TODO: better error handling, e.g. if pipeline id lookup fails? +#[derive(Debug, Deserialize, Serialize)] +pub enum DevtoolScriptControlMsg { + /// Evaluate a JS snippet in the context of the global for the given pipeline. + EvaluateJS(PipelineId, String, IpcSender<EvaluateJSReply>), + /// Retrieve the details of the root node (ie. the document) for the given pipeline. + GetRootNode(PipelineId, IpcSender<Option<NodeInfo>>), + /// Retrieve the details of the document element for the given pipeline. + GetDocumentElement(PipelineId, IpcSender<Option<NodeInfo>>), + /// Retrieve the details of the child nodes of the given node in the given pipeline. + GetChildren(PipelineId, String, IpcSender<Option<Vec<NodeInfo>>>), + /// Retrieve the computed layout properties of the given node in the given pipeline. + GetLayout(PipelineId, String, IpcSender<Option<ComputedNodeLayout>>), + /// Update a given node's attributes with a list of modifications. + ModifyAttribute(PipelineId, String, Vec<Modification>), + /// Request live console messages for a given pipeline (true if desired, false otherwise). + WantsLiveNotifications(PipelineId, bool), + /// Request live notifications for a given set of timeline events for a given pipeline. + SetTimelineMarkers( + PipelineId, + Vec<TimelineMarkerType>, + IpcSender<Option<TimelineMarker>>, + ), + /// Withdraw request for live timeline notifications for a given pipeline. + DropTimelineMarkers(PipelineId, Vec<TimelineMarkerType>), + /// Request a callback directed at the given actor name from the next animation frame + /// executed in the given pipeline. + RequestAnimationFrame(PipelineId, String), + /// Direct the given pipeline to reload the current page. + Reload(PipelineId), +} + +#[derive(Debug, Deserialize, Serialize)] +pub struct Modification { + pub attributeName: String, + pub newValue: Option<String>, +} + +#[derive(Clone, Debug, Deserialize, Serialize)] +pub enum LogLevel { + Log, + Debug, + Info, + Warn, + Error, + Clear, +} + +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct ConsoleMessage { + pub message: String, + pub logLevel: LogLevel, + pub filename: String, + pub lineNumber: usize, + pub columnNumber: usize, +} + +bitflags! { + #[derive(Deserialize, Serialize)] + pub struct CachedConsoleMessageTypes: u8 { + const PAGE_ERROR = 1 << 0; + const CONSOLE_API = 1 << 1; + } +} + +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct PageError { + #[serde(rename = "_type")] + pub type_: String, + pub errorMessage: String, + pub sourceName: String, + pub lineText: String, + pub lineNumber: u32, + pub columnNumber: u32, + pub category: String, + pub timeStamp: u64, + pub error: bool, + pub warning: bool, + pub exception: bool, + pub strict: bool, + pub private: bool, +} + +#[derive(Debug, Deserialize, Serialize)] +pub struct ConsoleAPI { + #[serde(rename = "_type")] + pub type_: String, + pub level: String, + pub filename: String, + pub lineNumber: u32, + pub functionName: String, + pub timeStamp: u64, + pub private: bool, + pub arguments: Vec<String>, +} + +#[derive(Debug, Deserialize, Serialize)] +pub enum CachedConsoleMessage { + PageError(PageError), + ConsoleAPI(ConsoleAPI), +} + +#[derive(Debug, PartialEq)] +pub struct HttpRequest { + pub url: ServoUrl, + pub method: Method, + pub headers: HeaderMap, + pub body: Option<Vec<u8>>, + pub pipeline_id: PipelineId, + pub startedDateTime: Tm, + pub timeStamp: i64, + pub connect_time: u64, + pub send_time: u64, + pub is_xhr: bool, +} + +#[derive(Debug, PartialEq)] +pub struct HttpResponse { + pub headers: Option<HeaderMap>, + pub status: Option<(u16, Vec<u8>)>, + pub body: Option<Vec<u8>>, + pub pipeline_id: PipelineId, +} + +#[derive(Debug)] +pub enum NetworkEvent { + HttpRequest(HttpRequest), + HttpResponse(HttpResponse), +} + +impl TimelineMarker { + pub fn start(name: String) -> StartedTimelineMarker { + StartedTimelineMarker { + name, + start_time: PreciseTime::now(), + start_stack: None, + } + } +} + +impl StartedTimelineMarker { + pub fn end(self) -> TimelineMarker { + TimelineMarker { + name: self.name, + start_time: self.start_time, + start_stack: self.start_stack, + end_time: PreciseTime::now(), + end_stack: None, + } + } +} + +/// A replacement for `time::PreciseTime` that isn't opaque, so we can serialize it. +/// +/// The reason why this doesn't go upstream is that `time` is slated to be part of Rust's standard +/// library, which definitely can't have any dependencies on `serde`. But `serde` can't implement +/// `Deserialize` and `Serialize` itself, because `time::PreciseTime` is opaque! A Catch-22. So I'm +/// duplicating the definition here. +#[derive(Clone, Copy, Debug, Deserialize, Serialize)] +pub struct PreciseTime(u64); + +impl PreciseTime { + pub fn now() -> PreciseTime { + PreciseTime(time::precise_time_ns()) + } + + pub fn to(&self, later: PreciseTime) -> Duration { + Duration::nanoseconds((later.0 - self.0) as i64) + } +} + +#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)] +pub struct WorkerId(pub Uuid); |