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