roder_ext_chrome/
policy.rs1use roder_api::chrome::ChromePermissionMode;
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15pub enum ChromeActionClass {
16 Inspect,
18 Interact,
20 Protected,
22 Prohibited,
24}
25
26pub fn classify_action(kind: &str) -> ChromeActionClass {
28 match kind {
29 "page/captcha" | "page/solveCaptcha" => ChromeActionClass::Prohibited,
31
32 "page/eval" | "page/upload" | "page/download" | "tab/navigate" => {
34 ChromeActionClass::Protected
35 }
36
37 "page/click" | "page/type" | "page/keypress" | "page/scroll" | "page/select"
39 | "tab/open" | "tab/close" | "tab/activate" | "tabs/group" => ChromeActionClass::Interact,
40
41 _ => ChromeActionClass::Inspect,
44 }
45}
46
47pub fn guard(kind: &str, mode: ChromePermissionMode) -> Result<(), String> {
50 match classify_action(kind) {
51 ChromeActionClass::Prohibited => Err(format!(
52 "browser action {kind:?} is prohibited and cannot be performed"
53 )),
54 ChromeActionClass::Protected if mode != ChromePermissionMode::Control => Err(format!(
55 "browser action {kind:?} is protected and requires control mode plus explicit approval"
56 )),
57 ChromeActionClass::Interact if mode == ChromePermissionMode::Observe => Err(format!(
58 "browser action {kind:?} requires assist or control mode"
59 )),
60 _ => Ok(()),
61 }
62}
63
64#[cfg(test)]
65mod tests {
66 use super::*;
67
68 #[test]
69 fn prohibited_actions_are_refused_in_every_mode() {
70 for mode in [
71 ChromePermissionMode::Observe,
72 ChromePermissionMode::Assist,
73 ChromePermissionMode::Control,
74 ] {
75 assert!(guard("page/captcha", mode).is_err());
76 }
77 }
78
79 #[test]
80 fn protected_actions_require_control_mode() {
81 assert!(guard("page/eval", ChromePermissionMode::Assist).is_err());
82 assert!(guard("page/eval", ChromePermissionMode::Control).is_ok());
83 }
84
85 #[test]
86 fn inspection_allowed_in_assist() {
87 assert!(guard("page/snapshot", ChromePermissionMode::Assist).is_ok());
88 assert_eq!(classify_action("tabs/list"), ChromeActionClass::Inspect);
89 }
90}