devtools/actors/
inspector.rs1use std::cell::RefCell;
8use std::collections::HashMap;
9
10use devtools_traits::DevtoolScriptControlMsg;
11use devtools_traits::DevtoolScriptControlMsg::GetRootNode;
12use ipc_channel::ipc::{self, IpcSender};
13use serde::Serialize;
14use serde_json::{self, Map, Value};
15
16use crate::StreamId;
17use crate::actor::{Actor, ActorError, ActorRegistry};
18use crate::actors::browsing_context::BrowsingContextActor;
19use crate::actors::inspector::highlighter::{HighlighterActor, HighlighterMsg};
20use crate::actors::inspector::node::NodeInfoToProtocol;
21use crate::actors::inspector::page_style::{PageStyleActor, PageStyleMsg};
22use crate::actors::inspector::walker::{WalkerActor, WalkerMsg};
23use crate::protocol::ClientRequest;
24
25pub mod accessibility;
26pub mod css_properties;
27pub mod highlighter;
28pub mod layout;
29pub mod node;
30pub mod page_style;
31pub mod style_rule;
32pub mod walker;
33
34#[derive(Serialize)]
35#[serde(rename_all = "camelCase")]
36struct GetPageStyleReply {
37 from: String,
38 page_style: PageStyleMsg,
39}
40
41#[derive(Serialize)]
42struct GetWalkerReply {
43 from: String,
44 walker: WalkerMsg,
45}
46
47#[derive(Serialize)]
48struct SupportsHighlightersReply {
49 from: String,
50 value: bool,
51}
52
53#[derive(Serialize)]
54struct GetHighlighterReply {
55 from: String,
56 highlighter: HighlighterMsg,
57}
58
59pub struct InspectorActor {
60 pub name: String,
61 pub walker: RefCell<Option<String>>,
62 pub page_style: RefCell<Option<String>>,
63 pub highlighter: RefCell<Option<String>>,
64 pub script_chan: IpcSender<DevtoolScriptControlMsg>,
65 pub browsing_context: String,
66}
67
68impl Actor for InspectorActor {
69 fn name(&self) -> String {
70 self.name.clone()
71 }
72
73 fn handle_message(
74 &self,
75 request: ClientRequest,
76 registry: &ActorRegistry,
77 msg_type: &str,
78 _msg: &Map<String, Value>,
79 _id: StreamId,
80 ) -> Result<(), ActorError> {
81 let browsing_context = registry.find::<BrowsingContextActor>(&self.browsing_context);
82 let pipeline = browsing_context.active_pipeline_id.get();
83 match msg_type {
84 "getWalker" => {
85 let (tx, rx) = ipc::channel().unwrap();
86 self.script_chan.send(GetRootNode(pipeline, tx)).unwrap();
87 let root_info = rx.recv().unwrap().ok_or(ActorError::Internal)?;
88
89 let name = self
90 .walker
91 .borrow()
92 .clone()
93 .unwrap_or_else(|| registry.new_name("walker"));
94
95 let root =
96 root_info.encode(registry, self.script_chan.clone(), pipeline, name.clone());
97
98 if self.walker.borrow().is_none() {
99 let walker = WalkerActor {
100 name,
101 script_chan: self.script_chan.clone(),
102 pipeline,
103 root_node: root.clone(),
104 mutations: RefCell::new(vec![]),
105 };
106 let mut walker_name = self.walker.borrow_mut();
107 *walker_name = Some(walker.name());
108 registry.register_later(Box::new(walker));
109 }
110
111 let msg = GetWalkerReply {
112 from: self.name(),
113 walker: WalkerMsg {
114 actor: self.walker.borrow().clone().unwrap(),
115 root,
116 },
117 };
118 request.reply_final(&msg)?
119 },
120
121 "getPageStyle" => {
122 if self.page_style.borrow().is_none() {
123 let style = PageStyleActor {
124 name: registry.new_name("page-style"),
125 script_chan: self.script_chan.clone(),
126 pipeline,
127 };
128 let mut page_style = self.page_style.borrow_mut();
129 *page_style = Some(style.name());
130 registry.register_later(Box::new(style));
131 }
132
133 let msg = GetPageStyleReply {
134 from: self.name(),
135 page_style: PageStyleMsg {
136 actor: self.page_style.borrow().clone().unwrap(),
137 traits: HashMap::from([
138 ("fontStretchLevel4".into(), true),
139 ("fontStyleLevel4".into(), true),
140 ("fontVariations".into(), true),
141 ("fontWeightLevel4".into(), true),
142 ]),
143 },
144 };
145 request.reply_final(&msg)?
146 },
147
148 "supportsHighlighters" => {
149 let msg = SupportsHighlightersReply {
150 from: self.name(),
151 value: true,
152 };
153 request.reply_final(&msg)?
154 },
155
156 "getHighlighterByType" => {
157 if self.highlighter.borrow().is_none() {
158 let highlighter_actor = HighlighterActor {
159 name: registry.new_name("highlighter"),
160 pipeline,
161 script_sender: self.script_chan.clone(),
162 };
163 let mut highlighter = self.highlighter.borrow_mut();
164 *highlighter = Some(highlighter_actor.name());
165 registry.register_later(Box::new(highlighter_actor));
166 }
167
168 let msg = GetHighlighterReply {
169 from: self.name(),
170 highlighter: HighlighterMsg {
171 actor: self.highlighter.borrow().clone().unwrap(),
172 },
173 };
174 request.reply_final(&msg)?
175 },
176 _ => return Err(ActorError::UnrecognizedPacketType),
177 };
178 Ok(())
179 }
180}