zendriver_stealth/persona/
surface.rs1use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
7pub enum Surface {
8 Canvas,
9 Webgl,
10 Audio,
11 Fonts,
12 ClientRects,
13 Webrtc,
14 Hardware,
15}
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
19pub enum Strategy {
20 Native,
21 Seeded,
22 Random,
23 Block,
24 Value,
25}
26
27#[derive(Debug, Clone, Copy, PartialEq, Eq)]
29pub enum SurfaceKind {
30 Noise,
31 Value,
32 Policy,
33}
34
35impl Surface {
36 pub fn kind(self) -> SurfaceKind {
37 match self {
38 Surface::Canvas | Surface::Audio | Surface::ClientRects => SurfaceKind::Noise,
39 Surface::Webgl | Surface::Fonts | Surface::Hardware => SurfaceKind::Value,
40 Surface::Webrtc => SurfaceKind::Policy,
41 }
42 }
43
44 pub fn default_strategy(self) -> Strategy {
46 match self.kind() {
47 SurfaceKind::Noise => Strategy::Seeded,
48 SurfaceKind::Value => Strategy::Value,
49 SurfaceKind::Policy => Strategy::Block,
50 }
51 }
52
53 pub fn resolve_strategy(self, requested: Option<Strategy>) -> Strategy {
57 let req = match requested {
58 None => return self.default_strategy(),
59 Some(s) => s,
60 };
61 let ok = matches!(
62 (self.kind(), req),
63 (_, Strategy::Native)
64 | (_, Strategy::Block)
65 | (SurfaceKind::Noise, Strategy::Seeded | Strategy::Random)
66 | (SurfaceKind::Value, Strategy::Value)
67 | (SurfaceKind::Policy, Strategy::Value)
68 );
69 if ok {
70 req
71 } else {
72 tracing::warn!(
73 surface = ?self,
74 requested = ?req,
75 "strategy not meaningful for surface kind; using default"
76 );
77 self.default_strategy()
78 }
79 }
80}
81
82#[cfg(test)]
83mod tests {
84 use super::*;
85
86 #[test]
87 fn noise_default_is_seeded() {
88 assert_eq!(Surface::Canvas.resolve_strategy(None), Strategy::Seeded);
89 }
90
91 #[test]
92 fn value_strategy_on_noise_warns_and_falls_back() {
93 assert_eq!(
95 Surface::Canvas.resolve_strategy(Some(Strategy::Value)),
96 Strategy::Seeded
97 );
98 }
99
100 #[test]
101 fn native_and_block_always_pass() {
102 assert_eq!(
103 Surface::Webgl.resolve_strategy(Some(Strategy::Native)),
104 Strategy::Native
105 );
106 assert_eq!(
107 Surface::Audio.resolve_strategy(Some(Strategy::Block)),
108 Strategy::Block
109 );
110 }
111
112 #[test]
113 fn webrtc_default_is_block() {
114 assert_eq!(Surface::Webrtc.resolve_strategy(None), Strategy::Block);
115 }
116}