1#![crate_name = "devtools_traits"]
16#![crate_type = "rlib"]
17#![deny(unsafe_code)]
18
19use core::fmt;
20use std::collections::HashMap;
21use std::fmt::Display;
22use std::net::TcpStream;
23use std::str::FromStr;
24use std::time::{Duration, SystemTime, UNIX_EPOCH};
25
26pub use embedder_traits::ConsoleLogLevel;
27use embedder_traits::Theme;
28use http::{HeaderMap, Method};
29use malloc_size_of_derive::MallocSizeOf;
30use net_traits::http_status::HttpStatus;
31use net_traits::request::Destination;
32use net_traits::{DebugVec, TlsSecurityInfo};
33use profile_traits::mem::ReportsChan;
34use serde::{Deserialize, Serialize};
35use servo_base::cross_process_instant::CrossProcessInstant;
36use servo_base::generic_channel::GenericSender;
37use servo_base::id::{BrowsingContextId, PipelineId, WebViewId};
38use servo_url::ServoUrl;
39use uuid::Uuid;
40
41#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
44pub struct DevtoolsPageInfo {
45 pub title: String,
46 pub url: ServoUrl,
47 pub is_top_level_global: bool,
48 pub is_service_worker: bool,
49}
50
51#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
52pub struct CSSError {
53 pub filename: String,
54 pub line: u32,
55 pub column: u32,
56 pub msg: String,
57}
58
59#[derive(Debug)]
62pub enum DevtoolsControlMsg {
63 FromChrome(ChromeToDevtoolsControlMsg),
65 FromScript(ScriptToDevtoolsControlMsg),
67 ClientExited,
69}
70
71#[expect(clippy::large_enum_variant)]
74#[derive(Debug)]
75pub enum ChromeToDevtoolsControlMsg {
76 AddClient(TcpStream),
78 ServerExitMsg,
80 NetworkEvent(String, NetworkEvent),
83 CollectMemoryReport(ReportsChan),
85}
86
87#[derive(Debug, Deserialize, Serialize)]
89pub enum NavigationState {
90 Start(ServoUrl),
92 Stop(PipelineId, DevtoolsPageInfo),
94}
95
96#[derive(Debug, Deserialize, Serialize)]
97pub enum ScriptToDevtoolsControlMsg {
99 NewGlobal(
102 (BrowsingContextId, PipelineId, Option<WorkerId>, WebViewId),
103 GenericSender<DevtoolScriptControlMsg>,
104 DevtoolsPageInfo,
105 ),
106 Navigate(BrowsingContextId, NavigationState),
108 ConsoleAPI(PipelineId, ConsoleMessage, Option<WorkerId>),
110 ClearConsole(PipelineId, Option<WorkerId>),
112 FramerateTick(String, f64),
115
116 ReportCSSError(PipelineId, CSSError),
118
119 ReportPageError(PipelineId, PageError),
121
122 TitleChanged(PipelineId, String),
124
125 CreateSourceActor(
127 GenericSender<DevtoolScriptControlMsg>,
128 PipelineId,
129 SourceInfo,
130 ),
131
132 UpdateSourceContent(PipelineId, String),
133
134 DomMutation(PipelineId, DomMutation),
135
136 DebuggerPause(PipelineId, FrameOffset, PauseReason),
138
139 CreateFrameActor(GenericSender<String>, PipelineId, FrameInfo),
141
142 CreateEnvironmentActor(
144 GenericSender<String>,
145 EnvironmentInfo,
146 Option<String>,
147 Option<String>,
148 ),
149}
150
151#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
152pub enum DomMutation {
153 AttributeModified {
154 node: String,
155 attribute_name: String,
156 new_value: Option<String>,
157 },
158}
159
160#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
161pub struct ObjectPreview {
162 pub kind: String,
163 pub own_properties: Option<Vec<PropertyDescriptor>>,
164 pub own_properties_length: Option<u32>,
165 pub function: Option<FunctionPreview>,
166 pub array_length: Option<u32>,
167 pub items: Option<Vec<DebuggerValue>>,
168}
169
170#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
171pub struct FunctionPreview {
172 pub name: Option<String>,
173 pub display_name: Option<String>,
174 pub parameter_names: Vec<String>,
175 pub is_async: Option<bool>,
176 pub is_generator: Option<bool>,
177}
178
179#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
180pub enum DebuggerValue {
181 VoidValue,
182 NullValue,
183 BooleanValue(bool),
184 NumberValue(f64),
185 StringValue(String),
186 ObjectValue {
187 uuid: String,
188 class: String,
189 own_property_length: Option<u32>,
190 preview: Option<ObjectPreview>,
191 },
192}
193
194#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
196pub struct PropertyDescriptor {
197 pub name: String,
198 pub value: DebuggerValue,
199 pub configurable: bool,
200 pub enumerable: bool,
201 pub writable: bool,
202 pub is_accessor: bool,
203}
204
205#[derive(Debug, Deserialize, Serialize)]
206pub struct EvaluateJSReply {
207 pub value: DebuggerValue,
208 pub has_exception: bool,
209}
210
211#[derive(Debug, Deserialize, Serialize)]
212pub struct AttrInfo {
213 pub namespace: String,
214 pub name: String,
215 pub value: String,
216}
217
218#[derive(Debug, Deserialize, Serialize)]
219#[serde(rename_all = "camelCase")]
220pub struct NodeInfo {
221 pub unique_id: String,
222 pub host: Option<String>,
223 #[serde(rename = "baseURI")]
224 pub base_uri: String,
225 pub parent: String,
226 pub node_type: u16,
227 pub node_name: String,
228 pub node_value: Option<String>,
229 pub num_children: usize,
230 pub attrs: Vec<AttrInfo>,
231 pub is_top_level_document: bool,
232 pub shadow_root_mode: Option<ShadowRootMode>,
233 pub is_shadow_host: bool,
234 pub display: Option<String>,
235 pub is_displayed: bool,
239
240 pub doctype_name: Option<String>,
242
243 pub doctype_public_identifier: Option<String>,
245
246 pub doctype_system_identifier: Option<String>,
248
249 pub has_event_listeners: bool,
250}
251
252pub struct StartedTimelineMarker {
253 name: String,
254 start_time: CrossProcessInstant,
255 start_stack: Option<Vec<()>>,
256}
257
258#[derive(Debug, Deserialize, Serialize)]
259pub struct TimelineMarker {
260 pub name: String,
261 pub start_time: CrossProcessInstant,
262 pub start_stack: Option<Vec<()>>,
263 pub end_time: CrossProcessInstant,
264 pub end_stack: Option<Vec<()>>,
265}
266
267#[derive(Clone, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
268pub enum TimelineMarkerType {
269 Reflow,
270 DOMEvent,
271}
272
273#[derive(Debug, Deserialize, Serialize)]
274#[serde(rename_all = "camelCase")]
275pub struct NodeStyle {
276 pub name: String,
277 pub value: String,
278 pub priority: String,
279}
280
281#[derive(Clone, Debug, Deserialize, Serialize, MallocSizeOf, PartialEq, Eq, Hash)]
282#[serde(tag = "type", rename_all = "camelCase")]
283pub enum AncestorData {
284 Layer {
285 actor_id: Option<String>,
286 value: Option<String>,
287 },
288}
289
290#[derive(Clone, Debug, Deserialize, Serialize, MallocSizeOf, PartialEq, Eq, Hash)]
291#[serde(rename_all = "camelCase")]
292pub struct MatchedRule {
293 pub selector: String,
294 pub stylesheet_index: usize,
295 pub block_id: usize,
296 pub ancestor_data: Vec<AncestorData>,
297}
298
299#[derive(Debug, Deserialize, Serialize)]
301#[serde(rename_all = "kebab-case")]
302pub struct ComputedNodeLayout {
303 pub display: String,
304 pub position: String,
305 pub z_index: String,
306 pub box_sizing: String,
307
308 pub margin_top: String,
309 pub margin_right: String,
310 pub margin_bottom: String,
311 pub margin_left: String,
312
313 pub border_top_width: String,
314 pub border_right_width: String,
315 pub border_bottom_width: String,
316 pub border_left_width: String,
317
318 pub padding_top: String,
319 pub padding_right: String,
320 pub padding_bottom: String,
321 pub padding_left: String,
322
323 pub width: f32,
324 pub height: f32,
325}
326
327#[derive(Debug, Default, Deserialize, Serialize)]
328pub struct AutoMargins {
329 pub top: bool,
330 pub right: bool,
331 pub bottom: bool,
332 pub left: bool,
333}
334
335#[derive(Debug, Deserialize, Serialize)]
338pub enum DevtoolScriptControlMsg {
339 GetRootNode(PipelineId, GenericSender<Option<NodeInfo>>),
341 GetDocumentElement(PipelineId, GenericSender<Option<NodeInfo>>),
343 GetChildren(PipelineId, String, GenericSender<Option<Vec<NodeInfo>>>),
345 GetAttributeStyle(PipelineId, String, GenericSender<Option<Vec<NodeStyle>>>),
347 GetStylesheetStyle(
349 PipelineId,
350 String,
351 MatchedRule,
352 GenericSender<Option<Vec<NodeStyle>>>,
353 ),
354 GetStyleSheets(PipelineId, GenericSender<Vec<StyleSheetInfo>>),
356 GetStyleSheetText(PipelineId, i32, GenericSender<Option<String>>),
358 GetSelectors(PipelineId, String, GenericSender<Option<Vec<MatchedRule>>>),
361 GetComputedStyle(PipelineId, String, GenericSender<Option<Vec<NodeStyle>>>),
363 GetEventListenerInfo(PipelineId, String, GenericSender<Vec<EventListenerInfo>>),
365 GetLayout(
367 PipelineId,
368 String,
369 GenericSender<Option<(ComputedNodeLayout, AutoMargins)>>,
370 ),
371 GetXPath(PipelineId, String, GenericSender<String>),
373 ModifyAttribute(PipelineId, String, Vec<AttrModification>),
375 ModifyRule(PipelineId, String, Vec<RuleModification>),
377 WantsLiveNotifications(PipelineId, bool),
379 SetTimelineMarkers(
381 PipelineId,
382 Vec<TimelineMarkerType>,
383 GenericSender<Option<TimelineMarker>>,
384 ),
385 DropTimelineMarkers(PipelineId, Vec<TimelineMarkerType>),
387 RequestAnimationFrame(PipelineId, String),
390 NavigateTo(PipelineId, ServoUrl),
393 GoBack(PipelineId),
396 GoForward(PipelineId),
399 Reload(PipelineId),
401 GetCssDatabase(GenericSender<HashMap<String, CssDatabaseProperty>>),
403 SimulateColorScheme(PipelineId, Theme),
405 HighlightDomNode(PipelineId, Option<String>),
407
408 Eval(
409 String,
410 PipelineId,
411 Option<String>,
412 GenericSender<EvaluateJSReply>,
413 ),
414 GetPossibleBreakpoints(u32, GenericSender<Vec<RecommendedBreakpointLocation>>),
415 SetBreakpoint(u32, u32, u32),
416 ClearBreakpoint(u32, u32, u32),
417 Interrupt,
418 Resume(Option<String>, Option<String>),
419 ListFrames(PipelineId, u32, u32, GenericSender<Vec<String>>),
420 GetEnvironment(String, GenericSender<String>),
421 Blackbox(u32, BlackboxCoverage),
422 Unblackbox(u32, BlackboxCoverage),
423}
424
425#[derive(Debug, Deserialize, Serialize)]
426pub enum BlackboxCoverage {
427 Full,
428 Partial((u32, u32), (u32, u32)),
429}
430
431#[derive(Clone, Debug, Deserialize, Serialize, MallocSizeOf)]
432#[serde(rename_all = "camelCase")]
433pub struct AttrModification {
434 pub attribute_name: String,
435 pub new_value: Option<String>,
436}
437
438#[derive(Clone, Debug, Deserialize, Serialize)]
439#[serde(rename_all = "camelCase")]
440pub struct RuleModification {
441 #[serde(rename = "type")]
442 pub type_: String,
443 pub index: u32,
444 pub name: String,
445 pub value: String,
446 pub priority: String,
447}
448
449#[derive(Clone, Debug, Deserialize, Serialize, MallocSizeOf)]
450#[serde(rename_all = "camelCase")]
451pub struct StackFrame {
452 pub filename: String,
453 pub function_name: String,
454 pub column_number: u32,
455 pub line_number: u32,
456 }
459
460pub fn get_time_stamp() -> u64 {
461 SystemTime::now()
462 .duration_since(UNIX_EPOCH)
463 .unwrap_or_default()
464 .as_millis() as u64
465}
466
467#[derive(Clone, Debug, Deserialize, Serialize, MallocSizeOf)]
468#[serde(rename_all = "camelCase")]
469pub struct ConsoleMessageFields {
470 pub level: ConsoleLogLevel,
471 pub filename: String,
472 pub line_number: u32,
473 pub column_number: u32,
474 pub time_stamp: u64,
475}
476
477#[derive(Clone, Debug, Deserialize, Serialize)]
478pub struct ConsoleMessage {
479 pub fields: ConsoleMessageFields,
480 pub arguments: Vec<DebuggerValue>,
481 pub stacktrace: Option<Vec<StackFrame>>,
482}
483
484#[derive(Clone, Debug, Deserialize, Serialize, MallocSizeOf)]
485#[serde(rename_all = "camelCase")]
486pub struct PageError {
487 pub error_message: String,
488 pub source_name: String,
489 pub line_number: u32,
490 pub column_number: u32,
491 pub time_stamp: u64,
492}
493
494#[derive(Debug, PartialEq, MallocSizeOf)]
495pub struct HttpRequest {
496 pub url: ServoUrl,
497 pub method: Method,
498 pub headers: HeaderMap,
499 pub body: Option<DebugVec>,
500 pub pipeline_id: PipelineId,
501 pub started_date_time: SystemTime,
502 pub time_stamp: i64,
503 pub connect_time: Duration,
504 pub send_time: Duration,
505 pub destination: Destination,
506 pub is_xhr: bool,
507 pub browsing_context_id: BrowsingContextId,
508}
509
510#[derive(Debug, PartialEq, MallocSizeOf)]
511pub struct HttpResponse {
512 #[ignore_malloc_size_of = "Http type"]
513 pub headers: Option<HeaderMap>,
514 pub status: HttpStatus,
515 pub body: Option<DebugVec>,
516 pub from_cache: bool,
517 pub pipeline_id: PipelineId,
518 pub browsing_context_id: BrowsingContextId,
519}
520
521#[derive(Debug, PartialEq)]
522pub struct SecurityInfoUpdate {
523 pub browsing_context_id: BrowsingContextId,
524 pub security_info: Option<TlsSecurityInfo>,
525}
526
527#[derive(Debug)]
528pub enum NetworkEvent {
529 HttpRequest(HttpRequest),
530 HttpRequestUpdate(HttpRequest),
531 HttpResponse(HttpResponse),
532 SecurityInfo(SecurityInfoUpdate),
533}
534
535impl NetworkEvent {
536 pub fn forward_to_devtools(&self) -> bool {
537 match self {
538 NetworkEvent::HttpRequest(http_request) => http_request.url.scheme() != "data",
539 NetworkEvent::HttpRequestUpdate(_) => true,
540 NetworkEvent::HttpResponse(_) => true,
541 NetworkEvent::SecurityInfo(_) => true,
542 }
543 }
544}
545
546impl TimelineMarker {
547 pub fn start(name: String) -> StartedTimelineMarker {
548 StartedTimelineMarker {
549 name,
550 start_time: CrossProcessInstant::now(),
551 start_stack: None,
552 }
553 }
554}
555
556impl StartedTimelineMarker {
557 pub fn end(self) -> TimelineMarker {
558 TimelineMarker {
559 name: self.name,
560 start_time: self.start_time,
561 start_stack: self.start_stack,
562 end_time: CrossProcessInstant::now(),
563 end_stack: None,
564 }
565 }
566}
567#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
568pub struct WorkerId(pub Uuid);
569impl Display for WorkerId {
570 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
571 write!(f, "{}", self.0)
572 }
573}
574impl FromStr for WorkerId {
575 type Err = uuid::Error;
576
577 fn from_str(s: &str) -> Result<Self, Self::Err> {
578 Ok(Self(s.parse()?))
579 }
580}
581
582#[derive(Debug, Deserialize, Serialize, MallocSizeOf)]
583#[serde(rename_all = "camelCase")]
584pub struct CssDatabaseProperty {
585 pub is_inherited: bool,
586 pub values: Vec<String>,
587 pub supports: Vec<String>,
588 pub subproperties: Vec<String>,
589}
590
591#[derive(Debug, Deserialize, Serialize)]
592pub enum ShadowRootMode {
593 Open,
594 Closed,
595}
596
597impl fmt::Display for ShadowRootMode {
598 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
599 match self {
600 Self::Open => write!(f, "open"),
601 Self::Closed => write!(f, "close"),
602 }
603 }
604}
605
606#[derive(Debug, Deserialize, Serialize)]
607pub struct SourceInfo {
608 pub url: ServoUrl,
609 pub introduction_type: String,
610 pub inline: bool,
611 pub worker_id: Option<WorkerId>,
612 pub content: Option<String>,
613 pub content_type: Option<String>,
614 pub spidermonkey_id: u32,
615}
616
617#[derive(Clone, Debug, Deserialize, Serialize)]
618#[serde(rename_all = "camelCase")]
619pub struct RecommendedBreakpointLocation {
620 pub script_id: u32,
621 pub offset: u32,
622 pub line_number: u32,
623 pub column_number: u32,
624 pub is_step_start: bool,
625}
626
627#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
628pub struct FrameInfo {
629 pub display_name: String,
630 pub on_stack: bool,
631 pub oldest: bool,
632 pub terminated: bool,
633 pub type_: String,
634 pub url: String,
635}
636
637#[derive(Clone, Debug, Default, Deserialize, MallocSizeOf, Serialize)]
638pub struct EnvironmentInfo {
639 pub type_: Option<String>,
640 pub scope_kind: Option<String>,
641 pub function_display_name: Option<String>,
642 pub binding_variables: Vec<PropertyDescriptor>,
643}
644
645#[derive(Clone, Debug, Deserialize, Serialize)]
646pub struct StyleSheetInfo {
647 pub href: Option<String>,
648 pub disabled: bool,
649 pub title: String,
650 pub style_sheet_index: i32,
651 pub system: bool,
652 pub rule_count: u32,
653}
654
655#[derive(Clone, Debug, Deserialize, Serialize)]
656pub struct EventListenerInfo {
657 pub event_type: String,
658 pub capturing: bool,
659}
660
661#[derive(Debug, Deserialize, Serialize)]
662#[serde(rename_all = "camelCase")]
663pub struct PauseReason {
664 #[serde(rename = "type")]
665 pub type_: String,
666 pub on_next: Option<bool>,
667}
668
669#[derive(Debug, Deserialize, Serialize)]
670pub struct FrameOffset {
671 pub actor: String,
672 pub column: u32,
673 pub line: u32,
674}