devtools/actors/inspector/
highlighter.rs

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 https://mozilla.org/MPL/2.0/. */
4
5//! Handles highlighting selected DOM nodes in the inspector. At the moment it only replies and
6//! changes nothing on Servo's side.
7
8use base::id::PipelineId;
9use devtools_traits::DevtoolScriptControlMsg;
10use ipc_channel::ipc::IpcSender;
11use serde::Serialize;
12use serde_json::{self, Map, Value};
13
14use crate::actor::{Actor, ActorError, ActorRegistry};
15use crate::protocol::ClientRequest;
16use crate::{EmptyReplyMsg, StreamId};
17
18#[derive(Serialize)]
19pub struct HighlighterMsg {
20    pub actor: String,
21}
22
23pub struct HighlighterActor {
24    pub name: String,
25    pub script_sender: IpcSender<DevtoolScriptControlMsg>,
26    pub pipeline: PipelineId,
27}
28
29#[derive(Serialize)]
30struct ShowReply {
31    from: String,
32    value: bool,
33}
34
35impl Actor for HighlighterActor {
36    fn name(&self) -> String {
37        self.name.clone()
38    }
39
40    /// The highligher actor can handle the following messages:
41    ///
42    /// - `show`: Enables highlighting for the selected node
43    ///
44    /// - `hide`: Disables highlighting for the selected node
45    fn handle_message(
46        &self,
47        request: ClientRequest,
48        registry: &ActorRegistry,
49        msg_type: &str,
50        msg: &Map<String, Value>,
51        _id: StreamId,
52    ) -> Result<(), ActorError> {
53        match msg_type {
54            "show" => {
55                let Some(node_actor) = msg.get("node") else {
56                    return Err(ActorError::MissingParameter);
57                };
58
59                let Some(node_actor_name) = node_actor.as_str() else {
60                    return Err(ActorError::BadParameterType);
61                };
62
63                if node_actor_name.starts_with("inspector") {
64                    // TODO: For some reason, the client initially asks us to highlight
65                    // the inspector? Investigate what this is supposed to mean.
66                    let msg = ShowReply {
67                        from: self.name(),
68                        value: false,
69                    };
70                    return request.reply_final(&msg);
71                }
72
73                self.instruct_script_thread_to_highlight_node(
74                    Some(node_actor_name.to_owned()),
75                    registry,
76                );
77                let msg = ShowReply {
78                    from: self.name(),
79                    value: true,
80                };
81                request.reply_final(&msg)?
82            },
83
84            "hide" => {
85                self.instruct_script_thread_to_highlight_node(None, registry);
86
87                let msg = EmptyReplyMsg { from: self.name() };
88                request.reply_final(&msg)?
89            },
90
91            _ => return Err(ActorError::UnrecognizedPacketType),
92        };
93        Ok(())
94    }
95}
96
97impl HighlighterActor {
98    fn instruct_script_thread_to_highlight_node(
99        &self,
100        node_actor: Option<String>,
101        registry: &ActorRegistry,
102    ) {
103        let node_id = node_actor.map(|node_actor| registry.actor_to_script(node_actor));
104        self.script_sender
105            .send(DevtoolScriptControlMsg::HighlightDomNode(
106                self.pipeline,
107                node_id,
108            ))
109            .unwrap();
110    }
111}