1use std::collections::HashSet;
6
7use atomic_refcell::AtomicRefCell;
8use devtools_traits::{DevtoolScriptControlMsg, PauseReason};
9use malloc_size_of_derive::MallocSizeOf;
10use serde::{Deserialize, Serialize};
11use serde_json::{Map, Value};
12use servo_base::generic_channel::GenericSender;
13
14use super::source::{SourceManager, SourcesReply};
15use crate::actor::{Actor, ActorError, ActorRegistry};
16use crate::actors::frame::{FrameActor, FrameActorMsg};
17use crate::actors::pause::PauseActor;
18use crate::generic_channel::channel;
19use crate::protocol::{ClientRequest, JsonPacketStream};
20use crate::{BrowsingContextActor, EmptyReplyMsg, StreamId};
21
22#[derive(Serialize)]
23#[serde(rename_all = "camelCase")]
24struct ThreadAttached {
25 from: String,
26 #[serde(rename = "type")]
27 type_: String,
28 actor: String,
29 frame: u32,
30 error: u32,
31 recording_endpoint: u32,
32 execution_point: u32,
33 popped_frames: Vec<PoppedFrameMsg>,
34 why: PauseReason,
35}
36
37#[derive(Serialize)]
38enum PoppedFrameMsg {}
39
40#[derive(Serialize)]
41struct ThreadResumedReply {
42 from: String,
43 #[serde(rename = "type")]
44 type_: String,
45}
46
47#[derive(Serialize)]
48pub(crate) struct ThreadInterruptedReply {
49 pub from: String,
50 #[serde(rename = "type")]
51 pub type_: String,
52 pub actor: String,
53 pub frame: FrameActorMsg,
54 pub why: PauseReason,
55}
56
57#[derive(Serialize)]
58struct GetAvailableEventBreakpointsReply {
59 from: String,
60 value: Vec<()>,
61}
62
63#[derive(Serialize)]
64struct FramesReply {
65 from: String,
66 frames: Vec<FrameActorMsg>,
67}
68
69#[derive(Debug, Deserialize, Serialize)]
70#[serde(rename_all = "lowercase")]
71enum ResumeLimitType {
72 Break,
73 Finish,
74 Next,
75 Restart,
76 Step,
77}
78
79#[derive(Debug, Deserialize, Serialize)]
80struct ResumeLimit {
81 #[serde(rename = "type")]
82 type_: ResumeLimitType,
83}
84
85#[derive(Deserialize, Debug)]
86#[serde(rename_all = "camelCase")]
87struct ResumeRequest {
88 resume_limit: Option<ResumeLimit>,
89 #[serde(rename = "frameActorID")]
90 #[serde(skip_serializing_if = "Option::is_none")]
91 frame_actor_id: Option<String>,
92}
93
94#[derive(Deserialize, Debug)]
95struct FramesRequest {
96 start: u32,
97 count: u32,
98}
99
100impl ResumeRequest {
101 fn get_type(&self) -> Option<String> {
102 let resume_limit = self.resume_limit.as_ref()?;
103 serde_json::to_string(&resume_limit.type_)
104 .ok()
105 .map(|s| s.trim_matches('"').into())
106 }
107}
108
109#[derive(MallocSizeOf)]
110pub(crate) struct ThreadActor {
111 name: String,
112 pub source_manager: SourceManager,
113 script_sender: GenericSender<DevtoolScriptControlMsg>,
114 pub frames: AtomicRefCell<HashSet<String>>,
115 browsing_context_name: Option<String>,
116}
117
118impl ThreadActor {
119 pub fn register(
120 registry: &ActorRegistry,
121 script_sender: GenericSender<DevtoolScriptControlMsg>,
122 browsing_context_name: Option<String>,
123 ) -> String {
124 let name = registry.new_name::<Self>();
125 let actor = ThreadActor {
126 name: name.clone(),
127 source_manager: SourceManager::new(),
128 script_sender,
129 frames: Default::default(),
130 browsing_context_name,
131 };
132 registry.register::<Self>(actor);
133 name
134 }
135}
136
137impl Actor for ThreadActor {
138 fn name(&self) -> String {
139 self.name.clone()
140 }
141
142 fn handle_message(
143 &self,
144 mut request: ClientRequest,
145 registry: &ActorRegistry,
146 msg_type: &str,
147 msg: &Map<String, Value>,
148 _id: StreamId,
149 ) -> Result<(), ActorError> {
150 match msg_type {
151 "attach" => {
152 let pause_name = registry.new_name::<PauseActor>();
153 registry.register(PauseActor {
154 name: pause_name.clone(),
155 });
156 let msg = ThreadAttached {
157 from: self.name(),
158 type_: "paused".to_owned(),
159 actor: pause_name,
160 frame: 0,
161 error: 0,
162 recording_endpoint: 0,
163 execution_point: 0,
164 popped_frames: vec![],
165 why: PauseReason {
166 type_: "attached".to_owned(),
167 on_next: None,
168 },
169 };
170 request.write_json_packet(&msg)?;
171 request.reply_final(&EmptyReplyMsg { from: self.name() })?
172 },
173
174 "resume" => {
175 let resume: ResumeRequest =
176 serde_json::from_value(msg.clone().into()).map_err(|_| ActorError::Internal)?;
177
178 let _ = self.script_sender.send(DevtoolScriptControlMsg::Resume(
179 resume.get_type(),
180 resume.frame_actor_id,
181 ));
182
183 let msg = ThreadResumedReply {
184 from: self.name(),
185 type_: "resumed".to_owned(),
186 };
187 request.write_json_packet(&msg)?;
188 request.reply_final(&EmptyReplyMsg { from: self.name() })?
189 },
190
191 "interrupt" => {
192 self.script_sender
193 .send(DevtoolScriptControlMsg::Interrupt)
194 .map_err(|_| ActorError::Internal)?;
195
196 request.reply_final(&EmptyReplyMsg { from: self.name() })?
197 },
198
199 "reconfigure" => request.reply_final(&EmptyReplyMsg { from: self.name() })?,
200
201 "getAvailableEventBreakpoints" => {
202 let msg = GetAvailableEventBreakpointsReply {
204 from: self.name(),
205 value: vec![],
206 };
207 request.reply_final(&msg)?
208 },
209
210 "sources" => {
213 let msg = SourcesReply {
214 from: self.name(),
215 sources: self.source_manager.source_forms(registry),
216 };
217 request.reply_final(&msg)?
218 },
219
220 "frames" => {
221 let Some(ref browsing_context_name) = self.browsing_context_name else {
222 return Err(ActorError::Internal);
223 };
224 let browsing_context_actor =
225 registry.find::<BrowsingContextActor>(browsing_context_name);
226
227 let frames: FramesRequest =
228 serde_json::from_value(msg.clone().into()).map_err(|_| ActorError::Internal)?;
229
230 let Some((tx, rx)) = channel() else {
231 return Err(ActorError::Internal);
232 };
233 self.script_sender
234 .send(DevtoolScriptControlMsg::ListFrames(
235 browsing_context_actor.pipeline_id(),
236 frames.start,
237 frames.count,
238 tx,
239 ))
240 .map_err(|_| ActorError::Internal)?;
241
242 let result = rx.recv().map_err(|_| ActorError::Internal)?;
243 let msg = FramesReply {
246 from: self.name(),
247 frames: result
248 .iter()
249 .map(|frame_name| registry.encode::<FrameActor, _>(frame_name))
250 .collect(),
251 };
252 request.reply_final(&msg)?
253 },
254
255 _ => return Err(ActorError::UnrecognizedPacketType),
256 };
257 Ok(())
258 }
259}