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 = PauseActor::register(registry);
153 let msg = ThreadAttached {
154 from: self.name(),
155 type_: "paused".to_owned(),
156 actor: pause_name,
157 frame: 0,
158 error: 0,
159 recording_endpoint: 0,
160 execution_point: 0,
161 popped_frames: vec![],
162 why: PauseReason {
163 type_: "attached".to_owned(),
164 on_next: None,
165 },
166 };
167 request.write_json_packet(&msg)?;
168 request.reply_final(&EmptyReplyMsg { from: self.name() })?
169 },
170
171 "resume" => {
172 let resume: ResumeRequest =
173 serde_json::from_value(msg.clone().into()).map_err(|_| ActorError::Internal)?;
174
175 let _ = self.script_sender.send(DevtoolScriptControlMsg::Resume(
176 resume.get_type(),
177 resume.frame_actor_id,
178 ));
179
180 let msg = ThreadResumedReply {
181 from: self.name(),
182 type_: "resumed".to_owned(),
183 };
184 request.write_json_packet(&msg)?;
185 request.reply_final(&EmptyReplyMsg { from: self.name() })?
186 },
187
188 "interrupt" => {
189 self.script_sender
190 .send(DevtoolScriptControlMsg::Interrupt)
191 .map_err(|_| ActorError::Internal)?;
192
193 request.reply_final(&EmptyReplyMsg { from: self.name() })?
194 },
195
196 "reconfigure" => request.reply_final(&EmptyReplyMsg { from: self.name() })?,
197
198 "getAvailableEventBreakpoints" => {
199 let msg = GetAvailableEventBreakpointsReply {
201 from: self.name(),
202 value: vec![],
203 };
204 request.reply_final(&msg)?
205 },
206
207 "sources" => {
210 let msg = SourcesReply {
211 from: self.name(),
212 sources: self.source_manager.source_forms(registry),
213 };
214 request.reply_final(&msg)?
215 },
216
217 "frames" => {
218 let Some(ref browsing_context_name) = self.browsing_context_name else {
219 return Err(ActorError::Internal);
220 };
221 let browsing_context_actor =
222 registry.find::<BrowsingContextActor>(browsing_context_name);
223
224 let frames: FramesRequest =
225 serde_json::from_value(msg.clone().into()).map_err(|_| ActorError::Internal)?;
226
227 let Some((tx, rx)) = channel() else {
228 return Err(ActorError::Internal);
229 };
230 self.script_sender
231 .send(DevtoolScriptControlMsg::ListFrames(
232 browsing_context_actor.pipeline_id(),
233 frames.start,
234 frames.count,
235 tx,
236 ))
237 .map_err(|_| ActorError::Internal)?;
238
239 let result = rx.recv().map_err(|_| ActorError::Internal)?;
240 let msg = FramesReply {
243 from: self.name(),
244 frames: result
245 .iter()
246 .map(|frame_name| registry.encode::<FrameActor, _>(frame_name))
247 .collect(),
248 };
249 request.reply_final(&msg)?
250 },
251
252 _ => return Err(ActorError::UnrecognizedPacketType),
253 };
254 Ok(())
255 }
256}