use roder_api::chrome::ChromePermissionMode;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ChromeActionClass {
Inspect,
Interact,
Protected,
Prohibited,
}
pub fn classify_action(kind: &str) -> ChromeActionClass {
match kind {
"page/captcha" | "page/solveCaptcha" => ChromeActionClass::Prohibited,
"page/eval" | "page/upload" | "page/download" | "tab/navigate" => {
ChromeActionClass::Protected
}
"page/click" | "page/type" | "page/keypress" | "page/scroll" | "page/select"
| "tab/open" | "tab/close" | "tab/activate" | "tabs/group" => ChromeActionClass::Interact,
_ => ChromeActionClass::Inspect,
}
}
pub fn guard(kind: &str, mode: ChromePermissionMode) -> Result<(), String> {
match classify_action(kind) {
ChromeActionClass::Prohibited => Err(format!(
"browser action {kind:?} is prohibited and cannot be performed"
)),
ChromeActionClass::Protected if mode != ChromePermissionMode::Control => Err(format!(
"browser action {kind:?} is protected and requires control mode plus explicit approval"
)),
ChromeActionClass::Interact if mode == ChromePermissionMode::Observe => Err(format!(
"browser action {kind:?} requires assist or control mode"
)),
_ => Ok(()),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn prohibited_actions_are_refused_in_every_mode() {
for mode in [
ChromePermissionMode::Observe,
ChromePermissionMode::Assist,
ChromePermissionMode::Control,
] {
assert!(guard("page/captcha", mode).is_err());
}
}
#[test]
fn protected_actions_require_control_mode() {
assert!(guard("page/eval", ChromePermissionMode::Assist).is_err());
assert!(guard("page/eval", ChromePermissionMode::Control).is_ok());
}
#[test]
fn inspection_allowed_in_assist() {
assert!(guard("page/snapshot", ChromePermissionMode::Assist).is_ok());
assert_eq!(classify_action("tabs/list"), ChromeActionClass::Inspect);
}
}