Skip to main content

browsing/browser/
permissions.rs

1//! Browser permissions management via CDP Browser domain
2
3use crate::browser::views::PermissionType;
4use crate::error::Result;
5use std::sync::Arc;
6
7/// Manages browser permissions (camera, microphone, notifications, etc.)
8#[derive(Debug, Clone)]
9pub struct PermissionsManager {
10    client: Arc<crate::browser::cdp::CdpClient>,
11}
12
13impl PermissionsManager {
14    /// Create a new permissions manager
15    pub fn new(client: Arc<crate::browser::cdp::CdpClient>) -> Self {
16        Self { client }
17    }
18
19    /// Grant permissions for a specific origin.
20    /// Common permissions: videoCapture, audioCapture, geolocation, notifications, clipboardReadWrite, displayCapture, sensors, etc.
21    pub async fn grant(&self, origin: &str, permissions: Vec<PermissionType>) -> Result<()> {
22        let perms: Vec<String> = permissions
23            .into_iter()
24            .map(|p| serde_json::to_string(&p).unwrap().trim_matches('"').to_string())
25            .collect();
26
27        self.client
28            .send_command(
29                "Browser.grantPermissions",
30                serde_json::json!({
31                    "origin": origin,
32                    "permissions": perms,
33                }),
34            )
35            .await?;
36        Ok(())
37    }
38
39    /// Reset all permissions for a specific origin
40    pub async fn reset(&self, origin: &str) -> Result<()> {
41        self.client
42            .send_command(
43                "Browser.resetPermissions",
44                serde_json::json!({ "origin": origin }),
45            )
46            .await?;
47        Ok(())
48    }
49
50    /// Convenience: grant camera permission
51    pub async fn grant_camera(&self, origin: &str) -> Result<()> {
52        self.grant(origin, vec![PermissionType::VideoCapture]).await
53    }
54
55    /// Convenience: grant microphone permission
56    pub async fn grant_microphone(&self, origin: &str) -> Result<()> {
57        self.grant(origin, vec![PermissionType::AudioCapture]).await
58    }
59
60    /// Convenience: grant camera + microphone permissions
61    pub async fn grant_camera_and_microphone(&self, origin: &str) -> Result<()> {
62        self.grant(origin, vec![PermissionType::VideoCapture, PermissionType::AudioCapture])
63            .await
64    }
65
66    /// Convenience: grant notifications permission
67    pub async fn grant_notifications(&self, origin: &str) -> Result<()> {
68        self.grant(origin, vec![PermissionType::Notifications]).await
69    }
70
71    /// Convenience: grant geolocation permission
72    pub async fn grant_geolocation(&self, origin: &str) -> Result<()> {
73        self.grant(origin, vec![PermissionType::Geolocation]).await
74    }
75
76    /// Convenience: grant clipboard access
77    pub async fn grant_clipboard(&self, origin: &str) -> Result<()> {
78        self.grant(origin, vec![PermissionType::ClipboardReadWrite]).await
79    }
80
81    /// Convenience: grant all common permissions for an origin
82    pub async fn grant_all_common(&self, origin: &str) -> Result<()> {
83        self.grant(
84            origin,
85            vec![
86                PermissionType::VideoCapture,
87                PermissionType::AudioCapture,
88                PermissionType::Geolocation,
89                PermissionType::Notifications,
90                PermissionType::ClipboardReadWrite,
91                PermissionType::DisplayCapture,
92                PermissionType::Sensors,
93            ],
94        )
95        .await
96    }
97}
98
99#[cfg(test)]
100mod tests {
101    use super::*;
102
103    #[test]
104    fn test_permission_type_serialization() {
105        let perm = PermissionType::VideoCapture;
106        let json = serde_json::to_string(&perm).unwrap();
107        assert_eq!(json, "\"videoCapture\"");
108
109        let perm = PermissionType::AudioCapture;
110        let json = serde_json::to_string(&perm).unwrap();
111        assert_eq!(json, "\"audioCapture\"");
112    }
113
114    #[test]
115    fn test_permission_types_roundtrip() {
116        let types = vec![
117            PermissionType::VideoCapture,
118            PermissionType::AudioCapture,
119            PermissionType::Geolocation,
120            PermissionType::Notifications,
121            PermissionType::ClipboardReadWrite,
122            PermissionType::DisplayCapture,
123            PermissionType::Sensors,
124            PermissionType::Nfc,
125            PermissionType::Midi,
126            PermissionType::MidiSysex,
127            PermissionType::WakeLockScreen,
128            PermissionType::WakeLockSystem,
129            PermissionType::StorageAccess,
130            PermissionType::WindowManagement,
131            PermissionType::BackgroundSync,
132            PermissionType::PaymentHandler,
133        ];
134        for t in types {
135            let json = serde_json::to_string(&t).unwrap();
136            assert!(!json.is_empty());
137        }
138    }
139}