1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 //! This module contains shared types and messages for use by devtools/script. 6 //! The traits are here instead of in script so that the devtools crate can be 7 //! modified independently of the rest of Servo. 8 9 #![crate_name = "devtools_traits"] 10 #![crate_type = "rlib"] 11 12 #![allow(non_snake_case)] 13 #![deny(unsafe_code)] 14 15 #[macro_use] 16 extern crate bitflags; 17 extern crate hyper; 18 extern crate ipc_channel; 19 extern crate malloc_size_of; 20 #[macro_use] extern crate malloc_size_of_derive; 21 extern crate msg; 22 #[macro_use] extern crate serde; 23 extern crate servo_url; 24 extern crate time; 25 26 use hyper::header::Headers; 27 use hyper::method::Method; 28 use ipc_channel::ipc::IpcSender; 29 use msg::constellation_msg::PipelineId; 30 use servo_url::ServoUrl; 31 use std::net::TcpStream; 32 use time::Duration; 33 use time::Tm; 34 35 // Information would be attached to NewGlobal to be received and show in devtools. 36 // Extend these fields if we need more information. 37 #[derive(Debug, Deserialize, Serialize)] 38 pub struct DevtoolsPageInfo { 39 pub title: String, 40 pub url: ServoUrl, 41 } 42 43 #[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)] 44 pub struct CSSError { 45 pub filename: String, 46 pub line: u32, 47 pub column: u32, 48 pub msg: String 49 } 50 51 /// Messages to instruct the devtools server to update its known actors/state 52 /// according to changes in the browser. 53 #[derive(Debug)] 54 pub enum DevtoolsControlMsg { 55 /// Messages from threads in the chrome process (resource/constellation/devtools) 56 FromChrome(ChromeToDevtoolsControlMsg), 57 /// Messages from script threads 58 FromScript(ScriptToDevtoolsControlMsg), 59 } 60 61 /// Events that the devtools server must act upon. 62 #[derive(Debug)] 63 pub enum ChromeToDevtoolsControlMsg { 64 /// A new client has connected to the server. 65 AddClient(TcpStream), 66 /// The browser is shutting down. 67 ServerExitMsg, 68 /// A network event occurred (request, reply, etc.). The actor with the 69 /// provided name should be notified. 70 NetworkEvent(String, NetworkEvent), 71 } 72 73 #[derive(Debug, Deserialize, Serialize)] 74 /// Events that the devtools server must act upon. 75 pub enum ScriptToDevtoolsControlMsg { 76 /// A new global object was created, associated with a particular pipeline. 77 /// The means of communicating directly with it are provided. 78 NewGlobal((PipelineId, Option<WorkerId>), 79 IpcSender<DevtoolScriptControlMsg>, 80 DevtoolsPageInfo), 81 /// A particular page has invoked the console API. 82 ConsoleAPI(PipelineId, ConsoleMessage, Option<WorkerId>), 83 /// An animation frame with the given timestamp was processed in a script thread. 84 /// The actor with the provided name should be notified. 85 FramerateTick(String, f64), 86 87 /// Report a CSS parse error for the given pipeline 88 ReportCSSError(PipelineId, CSSError), 89 } 90 91 /// Serialized JS return values 92 /// TODO: generalize this beyond the EvaluateJS message? 93 #[derive(Debug, Deserialize, Serialize)] 94 pub enum EvaluateJSReply { 95 VoidValue, 96 NullValue, 97 BooleanValue(bool), 98 NumberValue(f64), 99 StringValue(String), 100 ActorValue { class: String, uuid: String }, 101 } 102 103 #[derive(Debug, Deserialize, Serialize)] 104 pub struct AttrInfo { 105 pub namespace: String, 106 pub name: String, 107 pub value: String, 108 } 109 110 #[derive(Debug, Deserialize, Serialize)] 111 pub struct NodeInfo { 112 pub uniqueId: String, 113 pub baseURI: String, 114 pub parent: String, 115 pub nodeType: u16, 116 pub namespaceURI: String, 117 pub nodeName: String, 118 pub numChildren: usize, 119 120 pub name: String, 121 pub publicId: String, 122 pub systemId: String, 123 124 pub attrs: Vec<AttrInfo>, 125 126 pub isDocumentElement: bool, 127 128 pub shortValue: String, 129 pub incompleteValue: bool, 130 } 131 132 pub struct StartedTimelineMarker { 133 name: String, 134 start_time: PreciseTime, 135 start_stack: Option<Vec<()>>, 136 } 137 138 #[derive(Debug, Deserialize, Serialize)] 139 pub struct TimelineMarker { 140 pub name: String, 141 pub start_time: PreciseTime, 142 pub start_stack: Option<Vec<()>>, 143 pub end_time: PreciseTime, 144 pub end_stack: Option<Vec<()>>, 145 } 146 147 #[derive(Clone, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)] 148 pub enum TimelineMarkerType { 149 Reflow, 150 DOMEvent, 151 } 152 153 /// The properties of a DOM node as computed by layout. 154 #[derive(Debug, Deserialize, Serialize)] 155 pub struct ComputedNodeLayout { 156 pub display: String, 157 pub position: String, 158 pub zIndex: String, 159 pub boxSizing: String, 160 161 pub autoMargins: AutoMargins, 162 pub marginTop: String, 163 pub marginRight: String, 164 pub marginBottom: String, 165 pub marginLeft: String, 166 167 pub borderTopWidth: String, 168 pub borderRightWidth: String, 169 pub borderBottomWidth: String, 170 pub borderLeftWidth: String, 171 172 pub paddingTop: String, 173 pub paddingRight: String, 174 pub paddingBottom: String, 175 pub paddingLeft: String, 176 177 pub width: f32, 178 pub height: f32, 179 } 180 181 #[derive(Debug, Deserialize, Serialize)] 182 pub struct AutoMargins { 183 pub top: bool, 184 pub right: bool, 185 pub bottom: bool, 186 pub left: bool, 187 } 188 189 /// Messages to process in a particular script thread, as instructed by a devtools client. 190 /// TODO: better error handling, e.g. if pipeline id lookup fails? 191 #[derive(Debug, Deserialize, Serialize)] 192 pub enum DevtoolScriptControlMsg { 193 /// Evaluate a JS snippet in the context of the global for the given pipeline. 194 EvaluateJS(PipelineId, String, IpcSender<EvaluateJSReply>), 195 /// Retrieve the details of the root node (ie. the document) for the given pipeline. 196 GetRootNode(PipelineId, IpcSender<Option<NodeInfo>>), 197 /// Retrieve the details of the document element for the given pipeline. 198 GetDocumentElement(PipelineId, IpcSender<Option<NodeInfo>>), 199 /// Retrieve the details of the child nodes of the given node in the given pipeline. 200 GetChildren(PipelineId, String, IpcSender<Option<Vec<NodeInfo>>>), 201 /// Retrieve the computed layout properties of the given node in the given pipeline. 202 GetLayout(PipelineId, String, IpcSender<Option<ComputedNodeLayout>>), 203 /// Retrieve all stored console messages for the given pipeline. 204 GetCachedMessages(PipelineId, CachedConsoleMessageTypes, IpcSender<Vec<CachedConsoleMessage>>), 205 /// Update a given node's attributes with a list of modifications. 206 ModifyAttribute(PipelineId, String, Vec<Modification>), 207 /// Request live console messages for a given pipeline (true if desired, false otherwise). 208 WantsLiveNotifications(PipelineId, bool), 209 /// Request live notifications for a given set of timeline events for a given pipeline. 210 SetTimelineMarkers(PipelineId, Vec<TimelineMarkerType>, IpcSender<Option<TimelineMarker>>), 211 /// Withdraw request for live timeline notifications for a given pipeline. 212 DropTimelineMarkers(PipelineId, Vec<TimelineMarkerType>), 213 /// Request a callback directed at the given actor name from the next animation frame 214 /// executed in the given pipeline. 215 RequestAnimationFrame(PipelineId, String), 216 /// Direct the given pipeline to reload the current page. 217 Reload(PipelineId), 218 } 219 220 #[derive(Debug, Deserialize, Serialize)] 221 pub struct Modification { 222 pub attributeName: String, 223 pub newValue: Option<String>, 224 } 225 226 #[derive(Clone, Debug, Deserialize, Serialize)] 227 pub enum LogLevel { 228 Log, 229 Debug, 230 Info, 231 Warn, 232 Error, 233 } 234 235 #[derive(Clone, Debug, Deserialize, Serialize)] 236 pub struct ConsoleMessage { 237 pub message: String, 238 pub logLevel: LogLevel, 239 pub filename: String, 240 pub lineNumber: usize, 241 pub columnNumber: usize, 242 } 243 244 bitflags! { 245 #[derive(Deserialize, Serialize)] 246 pub struct CachedConsoleMessageTypes: u8 { 247 const PAGE_ERROR = 1 << 0; 248 const CONSOLE_API = 1 << 1; 249 } 250 } 251 252 #[derive(Debug, Deserialize, Serialize)] 253 pub struct PageError { 254 #[serde(rename = "_type")] 255 pub type_: String, 256 pub errorMessage: String, 257 pub sourceName: String, 258 pub lineText: String, 259 pub lineNumber: u32, 260 pub columnNumber: u32, 261 pub category: String, 262 pub timeStamp: u64, 263 pub error: bool, 264 pub warning: bool, 265 pub exception: bool, 266 pub strict: bool, 267 pub private: bool, 268 } 269 270 #[derive(Debug, Deserialize, Serialize)] 271 pub struct ConsoleAPI { 272 #[serde(rename = "_type")] 273 pub type_: String, 274 pub level: String, 275 pub filename: String, 276 pub lineNumber: u32, 277 pub functionName: String, 278 pub timeStamp: u64, 279 pub private: bool, 280 pub arguments: Vec<String>, 281 } 282 283 #[derive(Debug, Deserialize, Serialize)] 284 pub enum CachedConsoleMessage { 285 PageError(PageError), 286 ConsoleAPI(ConsoleAPI), 287 } 288 289 #[derive(Debug, PartialEq)] 290 pub struct HttpRequest { 291 pub url: ServoUrl, 292 pub method: Method, 293 pub headers: Headers, 294 pub body: Option<Vec<u8>>, 295 pub pipeline_id: PipelineId, 296 pub startedDateTime: Tm, 297 pub timeStamp: i64, 298 pub connect_time: u64, 299 pub send_time: u64, 300 pub is_xhr: bool, 301 } 302 303 #[derive(Debug, PartialEq)] 304 pub struct HttpResponse { 305 pub headers: Option<Headers>, 306 pub status: Option<(u16, Vec<u8>)>, 307 pub body: Option<Vec<u8>>, 308 pub pipeline_id: PipelineId, 309 } 310 311 #[derive(Debug)] 312 pub enum NetworkEvent { 313 HttpRequest(HttpRequest), 314 HttpResponse(HttpResponse), 315 } 316 317 impl TimelineMarker { start(name: String) -> StartedTimelineMarker318 pub fn start(name: String) -> StartedTimelineMarker { 319 StartedTimelineMarker { 320 name: name, 321 start_time: PreciseTime::now(), 322 start_stack: None, 323 } 324 } 325 } 326 327 impl StartedTimelineMarker { end(self) -> TimelineMarker328 pub fn end(self) -> TimelineMarker { 329 TimelineMarker { 330 name: self.name, 331 start_time: self.start_time, 332 start_stack: self.start_stack, 333 end_time: PreciseTime::now(), 334 end_stack: None, 335 } 336 } 337 } 338 339 /// A replacement for `time::PreciseTime` that isn't opaque, so we can serialize it. 340 /// 341 /// The reason why this doesn't go upstream is that `time` is slated to be part of Rust's standard 342 /// library, which definitely can't have any dependencies on `serde`. But `serde` can't implement 343 /// `Deserialize` and `Serialize` itself, because `time::PreciseTime` is opaque! A Catch-22. So I'm 344 /// duplicating the definition here. 345 #[derive(Clone, Copy, Debug, Deserialize, Serialize)] 346 pub struct PreciseTime(u64); 347 348 impl PreciseTime { now() -> PreciseTime349 pub fn now() -> PreciseTime { 350 PreciseTime(time::precise_time_ns()) 351 } 352 to(&self, later: PreciseTime) -> Duration353 pub fn to(&self, later: PreciseTime) -> Duration { 354 Duration::nanoseconds((later.0 - self.0) as i64) 355 } 356 } 357 358 #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)] 359 pub struct WorkerId(pub u32); 360