devtools/actors/watcher/
target_configuration.rs1use std::collections::HashMap;
9use std::sync::Arc;
10
11use embedder_traits::Theme;
12use log::warn;
13use malloc_size_of_derive::MallocSizeOf;
14use serde::Serialize;
15use serde_json::{Map, Value};
16
17use crate::actor::{Actor, ActorEncode, ActorError, ActorRegistry, new_actor_name};
18use crate::actors::browsing_context::BrowsingContextActor;
19use crate::actors::tab::TabDescriptorActor;
20use crate::protocol::ClientRequest;
21use crate::{EmptyReplyMsg, RootActor, StreamId};
22
23#[derive(Serialize)]
24#[serde(rename_all = "camelCase")]
25pub(crate) struct TargetConfigurationTraits {
26 supported_options: HashMap<&'static str, bool>,
27}
28
29#[derive(Serialize)]
30pub(crate) struct TargetConfigurationActorMsg {
31 actor: String,
32 configuration: HashMap<&'static str, bool>,
33 traits: TargetConfigurationTraits,
34}
35
36#[derive(MallocSizeOf)]
37pub(crate) struct TargetConfigurationActor {
38 name: String,
39 configuration: HashMap<&'static str, bool>,
40 supported_options: HashMap<&'static str, bool>,
41}
42
43#[derive(Serialize)]
44#[serde(rename_all = "camelCase")]
45struct JavascriptEnabledReply {
46 from: String,
47 javascript_enabled: bool,
48}
49
50impl Actor for TargetConfigurationActor {
51 fn name(&self) -> &str {
52 &self.name
53 }
54
55 fn handle_message(
59 &self,
60 request: ClientRequest,
61 registry: &ActorRegistry,
62 msg_type: &str,
63 msg: &Map<String, Value>,
64 _id: StreamId,
65 ) -> Result<(), ActorError> {
66 match msg_type {
67 "updateConfiguration" => {
68 let config = msg
69 .get("configuration")
70 .ok_or(ActorError::MissingParameter)?
71 .as_object()
72 .ok_or(ActorError::BadParameterType)?;
73 if let Some(scheme_value) = config.get("colorSchemeSimulation") {
74 let theme = match scheme_value.as_str() {
75 Some("dark") => Some(Theme::Dark),
76 Some("light") => Some(Theme::Light),
77 _ => None,
78 };
79 let root_actor = registry.find::<RootActor>("root");
80 if let Some(tab_name) = root_actor.active_tab() {
81 let tab_descriptor_actor = registry.find::<TabDescriptorActor>(&tab_name);
82 let browsing_context_actor = registry.find::<BrowsingContextActor>(
83 &tab_descriptor_actor.browsing_context_name,
84 );
85 browsing_context_actor
86 .simulate_color_scheme(theme)
87 .map_err(|_| ActorError::Internal)?;
88 } else {
89 warn!("No active tab for updateConfiguration");
90 }
91 }
92 let msg = EmptyReplyMsg {
93 from: self.name().into(),
94 };
95 request.reply_final(&msg)?
96 },
97 "isJavascriptEnabled" => {
98 let msg = JavascriptEnabledReply {
99 from: self.name().into(),
100 javascript_enabled: true,
101 };
102 request.reply_final(&msg)?
103 },
104 _ => return Err(ActorError::UnrecognizedPacketType),
105 };
106 Ok(())
107 }
108}
109
110impl TargetConfigurationActor {
111 pub fn register(registry: &ActorRegistry) -> Arc<Self> {
112 let name = new_actor_name::<Self>();
113 let actor = Self {
114 name,
115 configuration: HashMap::new(),
116 supported_options: HashMap::from([
117 ("cacheDisabled", false),
118 ("colorSchemeSimulation", true),
119 ("customFormatters", false),
120 ("customUserAgent", false),
121 ("javascriptEnabled", false),
122 ("overrideDPPX", false),
123 ("printSimulationEnabled", false),
124 ("rdmPaneMaxTouchPoints", false),
125 ("rdmPaneOrientation", false),
126 ("recordAllocations", false),
127 ("reloadOnTouchSimulationToggle", false),
128 ("restoreFocus", false),
129 ("serviceWorkersTestingEnabled", false),
130 ("setTabOffline", false),
131 ("touchEventsOverride", false),
132 ("tracerOptions", false),
133 ("useSimpleHighlightersForReducedMotion", false),
134 ]),
135 };
136 registry.register::<Self>(actor)
137 }
138}
139
140impl ActorEncode<TargetConfigurationActorMsg> for TargetConfigurationActor {
141 fn encode(&self, _: &ActorRegistry) -> TargetConfigurationActorMsg {
142 TargetConfigurationActorMsg {
143 actor: self.name().into(),
144 configuration: self.configuration.clone(),
145 traits: TargetConfigurationTraits {
146 supported_options: self.supported_options.clone(),
147 },
148 }
149 }
150}