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 new(name: String) -> Self {
109 Self {
110 name,
111 configuration: HashMap::new(),
112 supported_options: HashMap::from([
113 ("cacheDisabled", false),
114 ("colorSchemeSimulation", true),
115 ("customFormatters", false),
116 ("customUserAgent", false),
117 ("javascriptEnabled", false),
118 ("overrideDPPX", false),
119 ("printSimulationEnabled", false),
120 ("rdmPaneMaxTouchPoints", false),
121 ("rdmPaneOrientation", false),
122 ("recordAllocations", false),
123 ("reloadOnTouchSimulationToggle", false),
124 ("restoreFocus", false),
125 ("serviceWorkersTestingEnabled", false),
126 ("setTabOffline", false),
127 ("touchEventsOverride", false),
128 ("tracerOptions", false),
129 ("useSimpleHighlightersForReducedMotion", false),
130 ]),
131 }
132 }
133}
134
135impl ActorEncode<TargetConfigurationActorMsg> for TargetConfigurationActor {
136 fn encode(&self, _: &ActorRegistry) -> TargetConfigurationActorMsg {
137 TargetConfigurationActorMsg {
138 actor: self.name(),
139 configuration: self.configuration.clone(),
140 traits: TargetConfigurationTraits {
141 supported_options: self.supported_options.clone(),
142 },
143 }
144 }
145}