diff options
| author | Jae-Heon Ji <32578710+jaeheonji@users.noreply.github.com> | 2023-08-12 22:35:42 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-08-12 15:35:42 +0200 |
| commit | c8ddb23297e2f4fc900b8286d57e2808ae6a4fdb (patch) | |
| tree | c96d26c8bfc24172374aefe88624b78c6890663f /zellij-server/src/plugins/unit/plugin_tests.rs | |
| parent | docs(changelog): protobuffers (diff) | |
| download | sl0ppij-c8ddb23297e2f4fc900b8286d57e2808ae6a4fdb.tar.gz sl0ppij-c8ddb23297e2f4fc900b8286d57e2808ae6a4fdb.tar.xz sl0ppij-c8ddb23297e2f4fc900b8286d57e2808ae6a4fdb.zip | |
feat: add plugin permission system (#2624)
* WIP: add exaple of permission ui
* feat: add request permission ui
* feat: add caching permission in memory
* feat: add permission check
* feat: add file caching
* fix: changes request
* feat(ui): new status bar mode (#2619)
* supermode prototype
* fix integration tests
* fix tests
* style(fmt): rustfmt
* docs(changelog): status-bar supermode
* fix(rendering): occasional glitches while resizing (#2621)
* docs(changelog): resize glitches fix
* chore(version): bump development version
* Fix colored pane frames in mirrored sessions (#2625)
* server/panes/tiled: Fix colored frames
in mirrored sessions. Colored frames were previously ignored because
they were treated like floating panes when rendering tiled panes.
* CHANGELOG: Add PR #2625
* server/tab/unit: Fix unit tests for server.
* fix(sessions): use custom lists of adjectives and nouns for generating session names (#2122)
* Create custom lists of adjectives and nouns for generating session names
* move word lists to const slices
* add logic to retry name generation
* refactor
- reuse the name generator
- iterator instead of for loop
---------
Co-authored-by: Thomas Linford <linford.t@gmail.com>
* docs(changelog): generate session names with custom words list
* feat(plugins): make plugins configurable (#2646)
* work
* make every plugin entry point configurable
* make integration tests pass
* make e2e tests pass
* add test for plugin configuration
* add test snapshot
* add plugin config parsing test
* cleanups
* style(fmt): rustfmt
* style(comment): remove commented code
* docs(changelog): configurable plugins
* style(fmt): rustfmt
* touch up ui
* fix: don't save permission data in memory
* feat: load cached permission
* test: add example test (WIP)
* fix: issue event are always denied
* test: update snapshot
* apply formatting
* refactor: update default cache function
* test: add more new test
* apply formatting
* Revert "apply formatting"
This reverts commit a4e93703fbfdb6865131daa1c8b90fc5c36ab25e.
* apply format
* fix: update cache path
* apply format
* fix: cache path
* fix: update log level
* test for github workflow
* Revert "test for github workflow"
This reverts commit 01eff3bc5d1627a4e60bc6dac8ebe5500bc5b56e.
* refactor: permission cache
* fix(test): permission grant/deny race condition
* style(fmt): rustfmt
* style(fmt): rustfmt
* configure permissions
* permission denied test
* snapshot
* add ui for small plugins
* style(fmt): rustfmt
* some cleanups
---------
Co-authored-by: Aram Drevekenin <aram@poor.dev>
Co-authored-by: har7an <99636919+har7an@users.noreply.github.com>
Co-authored-by: Kyle Sutherland-Cash <kyle.sutherlandcash@gmail.com>
Co-authored-by: Thomas Linford <linford.t@gmail.com>
Co-authored-by: Thomas Linford <tlinford@users.noreply.github.com>
Diffstat (limited to 'zellij-server/src/plugins/unit/plugin_tests.rs')
| -rw-r--r-- | zellij-server/src/plugins/unit/plugin_tests.rs | 1151 |
1 files changed, 990 insertions, 161 deletions
diff --git a/zellij-server/src/plugins/unit/plugin_tests.rs b/zellij-server/src/plugins/unit/plugin_tests.rs index 663ca94e..e995a07b 100644 --- a/zellij-server/src/plugins/unit/plugin_tests.rs +++ b/zellij-server/src/plugins/unit/plugin_tests.rs @@ -6,9 +6,10 @@ use std::collections::BTreeMap; use std::path::PathBuf; use tempfile::tempdir; use wasmer::Store; -use zellij_utils::data::{Event, Key, PluginCapabilities}; +use zellij_utils::data::{Event, Key, PermissionStatus, PermissionType, PluginCapabilities}; use zellij_utils::errors::ErrorContext; use zellij_utils::input::layout::{Layout, PluginUserConfiguration, RunPlugin, RunPluginLocation}; +use zellij_utils::input::permission::PermissionCache; use zellij_utils::input::plugins::PluginsConfig; use zellij_utils::ipc::ClientAttributes; use zellij_utils::lazy_static::lazy_static; @@ -52,6 +53,157 @@ macro_rules! log_actions_in_thread { }; } +macro_rules! grant_permissions_and_log_actions_in_thread { + ( $arc_mutex_log:expr, $exit_event:path, $receiver:expr, $exit_after_count:expr, $permission_type:expr, $cache_path:expr, $plugin_thread_sender:expr, $client_id:expr ) => { + std::thread::Builder::new() + .name("fake_screen_thread".to_string()) + .spawn({ + let log = $arc_mutex_log.clone(); + let mut exit_event_count = 0; + let cache_path = $cache_path.clone(); + let plugin_thread_sender = $plugin_thread_sender.clone(); + move || loop { + let (event, _err_ctx) = $receiver + .recv() + .expect("failed to receive event on channel"); + match event { + $exit_event(..) => { + exit_event_count += 1; + log.lock().unwrap().push(event); + if exit_event_count == $exit_after_count { + break; + } + }, + ScreenInstruction::RequestPluginPermissions(_, plugin_permission) => { + if plugin_permission.permissions.contains($permission_type) { + let _ = plugin_thread_sender.send( + PluginInstruction::PermissionRequestResult( + 0, + Some($client_id), + plugin_permission.permissions, + PermissionStatus::Granted, + Some(cache_path.clone()), + ), + ); + } else { + let _ = plugin_thread_sender.send( + PluginInstruction::PermissionRequestResult( + 0, + Some($client_id), + plugin_permission.permissions, + PermissionStatus::Denied, + Some(cache_path.clone()), + ), + ); + } + }, + _ => { + log.lock().unwrap().push(event); + }, + } + } + }) + .unwrap() + }; +} + +macro_rules! deny_permissions_and_log_actions_in_thread { + ( $arc_mutex_log:expr, $exit_event:path, $receiver:expr, $exit_after_count:expr, $permission_type:expr, $cache_path:expr, $plugin_thread_sender:expr, $client_id:expr ) => { + std::thread::Builder::new() + .name("fake_screen_thread".to_string()) + .spawn({ + let log = $arc_mutex_log.clone(); + let mut exit_event_count = 0; + let cache_path = $cache_path.clone(); + let plugin_thread_sender = $plugin_thread_sender.clone(); + move || loop { + let (event, _err_ctx) = $receiver + .recv() + .expect("failed to receive event on channel"); + match event { + $exit_event(..) => { + exit_event_count += 1; + log.lock().unwrap().push(event); + if exit_event_count == $exit_after_count { + break; + } + }, + ScreenInstruction::RequestPluginPermissions(_, plugin_permission) => { + let _ = plugin_thread_sender.send( + PluginInstruction::PermissionRequestResult( + 0, + Some($client_id), + plugin_permission.permissions, + PermissionStatus::Denied, + Some(cache_path.clone()), + ), + ); + break; + }, + _ => { + log.lock().unwrap().push(event); + }, + } + } + }) + .unwrap() + }; +} + +macro_rules! grant_permissions_and_log_actions_in_thread_naked_variant { + ( $arc_mutex_log:expr, $exit_event:path, $receiver:expr, $exit_after_count:expr, $permission_type:expr, $cache_path:expr, $plugin_thread_sender:expr, $client_id:expr ) => { + std::thread::Builder::new() + .name("fake_screen_thread".to_string()) + .spawn({ + let log = $arc_mutex_log.clone(); + let mut exit_event_count = 0; + let cache_path = $cache_path.clone(); + let plugin_thread_sender = $plugin_thread_sender.clone(); + move || loop { + let (event, _err_ctx) = $receiver + .recv() + .expect("failed to receive event on channel"); + match event { + $exit_event => { + exit_event_count += 1; + log.lock().unwrap().push(event); + if exit_event_count == $exit_after_count { + break; + } + }, + ScreenInstruction::RequestPluginPermissions(_, plugin_permission) => { + if plugin_permission.permissions.contains($permission_type) { + let _ = plugin_thread_sender.send( + PluginInstruction::PermissionRequestResult( + 0, + Some($client_id), + plugin_permission.permissions, + PermissionStatus::Granted, + Some(cache_path.clone()), + ), + ); + } else { + let _ = plugin_thread_sender.send( + PluginInstruction::PermissionRequestResult( + 0, + Some($client_id), + plugin_permission.permissions, + PermissionStatus::Denied, + Some(cache_path.clone()), + ), + ); + } + }, + _ => { + log.lock().unwrap().push(event); + }, + } + } + }) + .unwrap() + }; +} + macro_rules! log_actions_in_thread_naked_variant { ( $arc_mutex_log:expr, $exit_event:path, $receiver:expr, $exit_after_count:expr ) => { std::thread::Builder::new() @@ -167,14 +319,14 @@ fn create_plugin_thread_with_server_receiver( ) -> ( SenderWithContext<PluginInstruction>, Receiver<(ServerInstruction, ErrorContext)>, + Receiver<(ScreenInstruction, ErrorContext)>, Box<dyn FnMut()>, ) { let zellij_cwd = zellij_cwd.unwrap_or_else(|| PathBuf::from(".")); let (to_server, server_receiver): ChannelWithContext<ServerInstruction> = channels::bounded(50); let to_server = SenderWithContext::new(to_server); - let (to_screen, _screen_receiver): ChannelWithContext<ScreenInstruction> = - channels::unbounded(); + let (to_screen, screen_receiver): ChannelWithContext<ScreenInstruction> = channels::unbounded(); let to_screen = SenderWithContext::new(to_screen); let (to_plugin, plugin_receiver): ChannelWithContext<PluginInstruction> = channels::unbounded(); @@ -240,7 +392,12 @@ fn create_plugin_thread_with_server_receiver( // the plugin cache } }; - (to_plugin, server_receiver, Box::new(teardown)) + ( + to_plugin, + server_receiver, + screen_receiver, + Box::new(teardown), + ) } fn create_plugin_thread_with_pty_receiver( @@ -248,6 +405,7 @@ fn create_plugin_thread_with_pty_receiver( ) -> ( SenderWithContext<PluginInstruction>, Receiver<(PtyInstruction, ErrorContext)>, + Receiver<(ScreenInstruction, ErrorContext)>, Box<dyn FnMut()>, ) { let zellij_cwd = zellij_cwd.unwrap_or_else(|| PathBuf::from(".")); @@ -255,8 +413,7 @@ fn create_plugin_thread_with_pty_receiver( channels::bounded(50); let to_server = SenderWithContext::new(to_server); - let (to_screen, _screen_receiver): ChannelWithContext<ScreenInstruction> = - channels::unbounded(); + let (to_screen, screen_receiver): ChannelWithContext<ScreenInstruction> = channels::unbounded(); let to_screen = SenderWithContext::new(to_screen); let (to_plugin, plugin_receiver): ChannelWithContext<PluginInstruction> = channels::unbounded(); @@ -322,7 +479,7 @@ fn create_plugin_thread_with_pty_receiver( // the plugin cache } }; - (to_plugin, pty_receiver, Box::new(teardown)) + (to_plugin, pty_receiver, screen_receiver, Box::new(teardown)) } lazy_static! { @@ -344,6 +501,9 @@ pub fn load_new_plugin_from_hd() { // message (this is what the fixture plugin does) // we then listen on our mock screen receiver to make sure we got a PluginBytes instruction // that contains said render, and assert against it + let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its + let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(None); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -359,11 +519,15 @@ pub fn load_new_plugin_from_hd() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + let screen_thread = grant_permissions_and_log_actions_in_thread!( received_screen_instructions, ScreenInstruction::PluginBytes, screen_receiver, - 2 + 2, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -403,8 +567,12 @@ pub fn load_new_plugin_from_hd() { #[test] #[ignore] pub fn plugin_workers() { + let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its + // destructor removes the directory let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(None); let plugin_should_float = Some(false); + let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let plugin_title = Some("test_plugin".to_owned()); let run_plugin = RunPlugin { _allow_exec_host_cmd: false, @@ -418,11 +586,15 @@ pub fn plugin_workers() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + let screen_thread = grant_permissions_and_log_actions_in_thread!( received_screen_instructions, ScreenInstruction::PluginBytes, screen_receiver, - 3 + 3, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -465,8 +637,12 @@ pub fn plugin_workers() { #[test] #[ignore] pub fn plugin_workers_persist_state() { + let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its + // destructor removes the directory let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(None); let plugin_should_float = Some(false); + let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let plugin_title = Some("test_plugin".to_owned()); let run_plugin = RunPlugin { _allow_exec_host_cmd: false, @@ -480,11 +656,15 @@ pub fn plugin_workers_persist_state() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + let screen_thread = grant_permissions_and_log_actions_in_thread!( received_screen_instructions, ScreenInstruction::PluginBytes, screen_receiver, - 5 + 5, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -603,6 +783,7 @@ pub fn switch_to_mode_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); @@ -619,11 +800,82 @@ pub fn switch_to_mode_plugin_command() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + let screen_thread = grant_permissions_and_log_actions_in_thread!( received_screen_instructions, ScreenInstruction::ChangeMode, screen_receiver, - 1 + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id + ); + + let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); + let _ = plugin_thread_sender.send(PluginInstruction::Load( + plugin_should_float, + plugin_title, + run_plugin, + tab_index, + client_id, + size, + )); + let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![( + None, + Some(client_id), + Event::Key(Key::Char('a')), // this triggers a SwitchToMode(Tab) command in the fixture + // plugin + )])); + std::thread::sleep(std::time::Duration::from_millis(100)); + screen_thread.join().unwrap(); // this might take a while if the cache is cold + teardown(); + let switch_to_mode_event = received_screen_instructions + .lock() + .unwrap() + .iter() + .find_map(|i| { + if let ScreenInstruction::ChangeMode(..) = i { + Some(i.clone()) + } else { + None + } + }) + .clone(); + assert_snapshot!(format!("{:#?}", switch_to_mode_event)); +} + +#[test] +#[ignore] +pub fn switch_to_mode_plugin_command_permission_denied() { + let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its + // destructor removes the directory + let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); + let (plugin_thread_sender, screen_receiver, mut teardown) = + create_plugin_thread(Some(plugin_host_folder)); + let plugin_should_float = Some(false); + let plugin_title = Some("test_plugin".to_owned()); + let run_plugin = RunPlugin { + _allow_exec_host_cmd: false, + location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), + }; + let tab_index = 1; + let client_id = 1; + let size = Size { + cols: 121, + rows: 20, + }; + let received_screen_instructions = Arc::new(Mutex::new(vec![])); + let screen_thread = deny_permissions_and_log_actions_in_thread!( + received_screen_instructions, + ScreenInstruction::ChangeMode, + screen_receiver, + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -665,6 +917,7 @@ pub fn new_tabs_with_layout_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); @@ -681,11 +934,15 @@ pub fn new_tabs_with_layout_plugin_command() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + let screen_thread = grant_permissions_and_log_actions_in_thread!( received_screen_instructions, ScreenInstruction::NewTab, screen_receiver, - 2 + 2, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -741,6 +998,7 @@ pub fn new_tab_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); @@ -757,11 +1015,15 @@ pub fn new_tab_plugin_command() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + let screen_thread = grant_permissions_and_log_actions_in_thread!( received_screen_instructions, ScreenInstruction::NewTab, screen_receiver, - 1 + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -803,6 +1065,7 @@ pub fn go_to_next_tab_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); @@ -819,11 +1082,15 @@ pub fn go_to_next_tab_plugin_command() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + let screen_thread = grant_permissions_and_log_actions_in_thread!( received_screen_instructions, ScreenInstruction::SwitchTabNext, screen_receiver, - 1 + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -864,6 +1131,7 @@ pub fn go_to_previous_tab_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); @@ -880,11 +1148,15 @@ pub fn go_to_previous_tab_plugin_command() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + let screen_thread = grant_permissions_and_log_actions_in_thread!( received_screen_instructions, ScreenInstruction::SwitchTabPrev, screen_receiver, - 1 + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -925,6 +1197,7 @@ pub fn resize_focused_pane_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); @@ -941,11 +1214,15 @@ pub fn resize_focused_pane_plugin_command() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + let screen_thread = grant_permissions_and_log_actions_in_thread!( received_screen_instructions, ScreenInstruction::Resize, screen_receiver, - 1 + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -986,6 +1263,7 @@ pub fn resize_focused_pane_with_direction_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); @@ -1002,11 +1280,15 @@ pub fn resize_focused_pane_with_direction_plugin_command() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + let screen_thread = grant_permissions_and_log_actions_in_thread!( received_screen_instructions, ScreenInstruction::Resize, screen_receiver, - 1 + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -1047,6 +1329,7 @@ pub fn focus_next_pane_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); @@ -1063,11 +1346,15 @@ pub fn focus_next_pane_plugin_command() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + let screen_thread = grant_permissions_and_log_actions_in_thread!( received_screen_instructions, ScreenInstruction::FocusNextPane, screen_receiver, - 1 + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -1108,6 +1395,7 @@ pub fn focus_previous_pane_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); @@ -1124,11 +1412,15 @@ pub fn focus_previous_pane_plugin_command() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + let screen_thread = grant_permissions_and_log_actions_in_thread!( received_screen_instructions, ScreenInstruction::FocusPreviousPane, screen_receiver, - 1 + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -1169,6 +1461,7 @@ pub fn move_focus_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); @@ -1185,11 +1478,15 @@ pub fn move_focus_plugin_command() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + let screen_thread = grant_permissions_and_log_actions_in_thread!( received_screen_instructions, ScreenInstruction::MoveFocusLeft, screen_receiver, - 1 + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -1230,6 +1527,7 @@ pub fn move_focus_or_tab_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); @@ -1246,11 +1544,15 @@ pub fn move_focus_or_tab_plugin_command() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + let screen_thread = grant_permissions_and_log_actions_in_thread!( received_screen_instructions, ScreenInstruction::MoveFocusLeftOrPreviousTab, screen_receiver, - 1 + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -1291,6 +1593,7 @@ pub fn edit_scrollback_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); @@ -1307,11 +1610,15 @@ pub fn edit_scrollback_plugin_command() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + let screen_thread = grant_permissions_and_log_actions_in_thread!( received_screen_instructions, ScreenInstruction::EditScrollback, screen_receiver, - 1 + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -1352,6 +1659,7 @@ pub fn write_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); @@ -1368,11 +1676,15 @@ pub fn write_plugin_command() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + let screen_thread = grant_permissions_and_log_actions_in_thread!( received_screen_instructions, ScreenInstruction::WriteCharacter, screen_receiver, - 1 + 1, + &PermissionType::WriteToStdin, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -1413,6 +1725,7 @@ pub fn write_chars_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); @@ -1429,11 +1742,15 @@ pub fn write_chars_plugin_command() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + let screen_thread = grant_permissions_and_log_actions_in_thread!( received_screen_instructions, ScreenInstruction::WriteCharacter, screen_receiver, - 1 + 1, + &PermissionType::WriteToStdin, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -1474,6 +1791,7 @@ pub fn toggle_tab_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); @@ -1490,11 +1808,15 @@ pub fn toggle_tab_plugin_command() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + let screen_thread = grant_permissions_and_log_actions_in_thread!( received_screen_instructions, ScreenInstruction::ToggleTab, screen_receiver, - 1 + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -1535,6 +1857,7 @@ pub fn move_pane_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); @@ -1551,11 +1874,15 @@ pub fn move_pane_plugin_command() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + let screen_thread = grant_permissions_and_log_actions_in_thread!( received_screen_instructions, ScreenInstruction::MovePane, screen_receiver, - 1 + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -1596,6 +1923,7 @@ pub fn move_pane_with_direction_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); @@ -1612,11 +1940,15 @@ pub fn move_pane_with_direction_plugin_command() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + let screen_thread = grant_permissions_and_log_actions_in_thread!( received_screen_instructions, ScreenInstruction::MovePaneLeft, screen_receiver, - 1 + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -1657,6 +1989,7 @@ pub fn clear_screen_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); @@ -1673,11 +2006,16 @@ pub fn clear_screen_plugin_command() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + + let screen_thread = grant_permissions_and_log_actions_in_thread!( received_screen_instructions, ScreenInstruction::ClearScreen, screen_receiver, - 1 + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -1689,6 +2027,7 @@ pub fn clear_screen_plugin_command() { client_id, size, )); + std::thread::sleep(std::time::Duration::from_millis(100)); let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![( None, Some(client_id), @@ -1718,6 +2057,7 @@ pub fn scroll_up_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); @@ -1734,11 +2074,16 @@ pub fn scroll_up_plugin_command() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + + let screen_thread = grant_permissions_and_log_actions_in_thread!( received_screen_instructions, ScreenInstruction::ScrollUp, screen_receiver, - 1 + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -1779,6 +2124,7 @@ pub fn scroll_down_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); @@ -1795,11 +2141,15 @@ pub fn scroll_down_plugin_command() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + let screen_thread = grant_permissions_and_log_actions_in_thread!( received_screen_instructions, ScreenInstruction::ScrollDown, screen_receiver, - 1 + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -1840,6 +2190,7 @@ pub fn scroll_to_top_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); @@ -1856,11 +2207,15 @@ pub fn scroll_to_top_plugin_command() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + let screen_thread = grant_permissions_and_log_actions_in_thread!( received_screen_instructions, ScreenInstruction::ScrollToTop, screen_receiver, - 1 + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -1901,6 +2256,7 @@ pub fn scroll_to_bottom_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); @@ -1917,11 +2273,15 @@ pub fn scroll_to_bottom_plugin_command() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + let screen_thread = grant_permissions_and_log_actions_in_thread!( received_screen_instructions, ScreenInstruction::ScrollToBottom, screen_receiver, - 1 + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -1962,6 +2322,7 @@ pub fn page_scroll_up_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); @@ -1978,11 +2339,15 @@ pub fn page_scroll_up_plugin_command() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + let screen_thread = grant_permissions_and_log_actions_in_thread!( received_screen_instructions, ScreenInstruction::PageScrollUp, screen_receiver, - 1 + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -2023,6 +2388,7 @@ pub fn page_scroll_down_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); @@ -2039,11 +2405,15 @@ pub fn page_scroll_down_plugin_command() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + let screen_thread = grant_permissions_and_log_actions_in_thread!( received_screen_instructions, ScreenInstruction::PageScrollDown, screen_receiver, - 1 + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -2084,6 +2454,7 @@ pub fn toggle_focus_fullscreen_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); @@ -2100,11 +2471,15 @@ pub fn toggle_focus_fullscreen_plugin_command() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + let screen_thread = grant_permissions_and_log_actions_in_thread!( received_screen_instructions, ScreenInstruction::ToggleActiveTerminalFullscreen, screen_receiver, - 1 + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -2145,6 +2520,7 @@ pub fn toggle_pane_frames_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); @@ -2161,11 +2537,15 @@ pub fn toggle_pane_frames_plugin_command() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread_naked_variant!( + let screen_thread = grant_permissions_and_log_actions_in_thread_naked_variant!( received_screen_instructions, ScreenInstruction::TogglePaneFrames, screen_receiver, - 1 + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -2206,6 +2586,7 @@ pub fn toggle_pane_embed_or_eject_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); @@ -2222,11 +2603,15 @@ pub fn toggle_pane_embed_or_eject_plugin_command() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + let screen_thread = grant_permissions_and_log_actions_in_thread!( received_screen_instructions, ScreenInstruction::TogglePaneEmbedOrFloating, screen_receiver, - 1 + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -2267,6 +2652,7 @@ pub fn undo_rename_pane_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); @@ -2283,11 +2669,15 @@ pub fn undo_rename_pane_plugin_command() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + let screen_thread = grant_permissions_and_log_actions_in_thread!( received_screen_instructions, ScreenInstruction::UndoRenamePane, screen_receiver, - 1 + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -2328,6 +2718,7 @@ pub fn close_focus_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); @@ -2344,11 +2735,15 @@ pub fn close_focus_plugin_command() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + let screen_thread = grant_permissions_and_log_actions_in_thread!( received_screen_instructions, ScreenInstruction::CloseFocusedPane, screen_receiver, - 1 + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -2389,6 +2784,7 @@ pub fn toggle_active_tab_sync_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); @@ -2405,11 +2801,15 @@ pub fn toggle_active_tab_sync_plugin_command() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + let screen_thread = grant_permissions_and_log_actions_in_thread!( received_screen_instructions, ScreenInstruction::ToggleActiveSyncTab, screen_receiver, - 1 + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -2450,6 +2850,7 @@ pub fn close_focused_tab_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); @@ -2466,11 +2867,15 @@ pub fn close_focused_tab_plugin_command() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + let screen_thread = grant_permissions_and_log_actions_in_thread!( received_screen_instructions, ScreenInstruction::CloseTab, screen_receiver, - 1 + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -2511,6 +2916,7 @@ pub fn undo_rename_tab_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); @@ -2527,11 +2933,15 @@ pub fn undo_rename_tab_plugin_command() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + let screen_thread = grant_permissions_and_log_actions_in_thread!( received_screen_instructions, ScreenInstruction::UndoRenameTab, screen_receiver, - 1 + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -2572,6 +2982,7 @@ pub fn previous_swap_layout_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); @@ -2588,11 +2999,15 @@ pub fn previous_swap_layout_plugin_command() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + let screen_thread = grant_permissions_and_log_actions_in_thread!( received_screen_instructions, ScreenInstruction::PreviousSwapLayout, screen_receiver, - 1 + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -2633,6 +3048,7 @@ pub fn next_swap_layout_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); @@ -2649,11 +3065,15 @@ pub fn next_swap_layout_plugin_command() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + let screen_thread = grant_permissions_and_log_actions_in_thread!( received_screen_instructions, ScreenInstruction::NextSwapLayout, screen_receiver, - 1 + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -2694,6 +3114,7 @@ pub fn go_to_tab_name_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); @@ -2710,11 +3131,15 @@ pub fn go_to_tab_name_plugin_command() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + let screen_thread = grant_permissions_and_log_actions_in_thread!( received_screen_instructions, ScreenInstruction::GoToTabName, screen_receiver, - 1 + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -2755,6 +3180,7 @@ pub fn focus_or_create_tab_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); @@ -2771,11 +3197,15 @@ pub fn focus_or_create_tab_plugin_command() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + let screen_thread = grant_permissions_and_log_actions_in_thread!( received_screen_instructions, ScreenInstruction::GoToTabName, screen_receiver, - 1 + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -2816,6 +3246,7 @@ pub fn go_to_tab() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); @@ -2832,11 +3263,15 @@ pub fn go_to_tab() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + let screen_thread = grant_permissions_and_log_actions_in_thread!( received_screen_instructions, ScreenInstruction::GoToTab, screen_receiver, - 1 + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -2877,6 +3312,7 @@ pub fn start_or_reload_plugin() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); @@ -2893,11 +3329,15 @@ pub fn start_or_reload_plugin() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + let screen_thread = grant_permissions_and_log_actions_in_thread!( received_screen_instructions, ScreenInstruction::StartOrReloadPluginPane, screen_receiver, - 1 + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -2938,7 +3378,8 @@ pub fn quit_zellij_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); - let (plugin_thread_sender, server_receiver, mut teardown) = + let cache_path = plugin_host_folder.join("permissions_test.kdl"); + let (plugin_thread_sender, server_receiver, screen_receiver, mut teardown) = create_plugin_thread_with_server_receiver(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -2954,12 +3395,23 @@ pub fn quit_zellij_plugin_command() { rows: 20, }; let received_server_instruction = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + let server_thread = log_actions_in_thread!( received_server_instruction, ServerInstruction::ClientExit, server_receiver, 1 ); + let received_screen_instructions = Arc::new(Mutex::new(vec![])); + let _screen_thread = grant_permissions_and_log_actions_in_thread_naked_variant!( + received_screen_instructions, + ScreenInstruction::Exit, + screen_receiver, + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id + ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); let _ = plugin_thread_sender.send(PluginInstruction::Load( @@ -2976,7 +3428,7 @@ pub fn quit_zellij_plugin_command() { Event::Key(Key::Char('8')), // this triggers the enent in the fixture plugin )])); std::thread::sleep(std::time::Duration::from_millis(100)); - screen_thread.join().unwrap(); // this might take a while if the cache is cold + server_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_server_instruction .lock() @@ -2999,7 +3451,8 @@ pub fn detach_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); - let (plugin_thread_sender, server_receiver, mut teardown) = + let cache_path = plugin_host_folder.join("permissions_test.kdl"); + let (plugin_thread_sender, server_receiver, screen_receiver, mut teardown) = create_plugin_thread_with_server_receiver(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -3015,12 +3468,23 @@ pub fn detach_plugin_command() { rows: 20, }; let received_server_instruction = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + let server_thread = log_actions_in_thread!( received_server_instruction, ServerInstruction::DetachSession, server_receiver, 1 ); + let received_screen_instructions = Arc::new(Mutex::new(vec![])); + let _screen_thread = grant_permissions_and_log_actions_in_thread_naked_variant!( + received_screen_instructions, + ScreenInstruction::Exit, + screen_receiver, + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id + ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); let _ = plugin_thread_sender.send(PluginInstruction::Load( @@ -3037,7 +3501,7 @@ pub fn detach_plugin_command() { Event::Key(Key::Char('l')), // this triggers the enent in the fixture plugin )])); std::thread::sleep(std::time::Duration::from_millis(100)); - screen_thread.join().unwrap(); // this might take a while if the cache is cold + server_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_server_instruction .lock() @@ -3060,7 +3524,8 @@ pub fn open_file_floating_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); - let (plugin_thread_sender, pty_receiver, mut teardown) = + let cache_path = plugin_host_folder.join("permissions_test.kdl"); + let (plugin_thread_sender, pty_receiver, screen_receiver, mut teardown) = create_plugin_thread_with_pty_receiver(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -3075,13 +3540,24 @@ pub fn open_file_floating_plugin_command() { cols: 121, rows: 20, }; - let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( - received_screen_instructions, + let received_pty_instructions = Arc::new(Mutex::new(vec![])); + let pty_thread = log_actions_in_thread!( + received_pty_instructions, PtyInstruction::SpawnTerminal, pty_receiver, 1 ); + let received_screen_instructions = Arc::new(Mutex::new(vec![])); + let _screen_thread = grant_permissions_and_log_actions_in_thread_naked_variant!( + received_screen_instructions, + ScreenInstruction::Exit, + screen_receiver, + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id + ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); let _ = plugin_thread_sender.send(PluginInstruction::Load( @@ -3098,9 +3574,9 @@ pub fn open_file_floating_plugin_command() { Event::Key(Key::Ctrl('h')), // this triggers the enent in the fixture plugin )])); std::thread::sleep(std::time::Duration::from_millis(100)); - screen_thread.join().unwrap(); // this might take a while if the cache is cold + pty_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); - let new_tab_event = received_screen_instructions + let new_tab_event = received_pty_instructions .lock() .unwrap() .iter() @@ -3121,7 +3597,8 @@ pub fn open_file_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); - let (plugin_thread_sender, pty_receiver, mut teardown) = + let cache_path = plugin_host_folder.join("permissions_test.kdl"); + let (plugin_thread_sender, pty_receiver, screen_receiver, mut teardown) = create_plugin_thread_with_pty_receiver(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -3136,13 +3613,24 @@ pub fn open_file_plugin_command() { cols: 121, rows: 20, }; - let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( - received_screen_instructions, + let received_pty_instructions = Arc::new(Mutex::new(vec![])); + let pty_thread = log_actions_in_thread!( + received_pty_instructions, PtyInstruction::SpawnTerminal, pty_receiver, 1 ); + let received_screen_instructions = Arc::new(Mutex::new(vec![])); + let _screen_thread = grant_permissions_and_log_actions_in_thread_naked_variant!( + received_screen_instructions, + ScreenInstruction::Exit, + screen_receiver, + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id + ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); let _ = plugin_thread_sender.send(PluginInstruction::Load( @@ -3159,9 +3647,9 @@ pub fn open_file_plugin_command() { Event::Key(Key::Ctrl('g')), // this triggers the enent in the fixture plugin )])); std::thread::sleep(std::time::Duration::from_millis(100)); - screen_thread.join().unwrap(); // this might take a while if the cache is cold + pty_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); - let new_tab_event = received_screen_instructions + let new_tab_event = received_pty_instructions .lock() .unwrap() .iter() @@ -3182,7 +3670,8 @@ pub fn open_file_with_line_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); - let (plugin_thread_sender, pty_receiver, mut teardown) = + let cache_path = plugin_host_folder.join("permissions_test.kdl"); + let (plugin_thread_sender, pty_receiver, screen_receiver, mut teardown) = create_plugin_thread_with_pty_receiver(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -3197,14 +3686,26 @@ pub fn open_file_with_line_plugin_command() { cols: 121, rows: 20, }; - let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( - received_screen_instructions, + let received_pty_instructions = Arc::new(Mutex::new(vec![])); + let pty_thread = log_actions_in_thread!( + received_pty_instructions, PtyInstruction::SpawnTerminal, pty_receiver, 1 ); + let received_screen_instructions = Arc::new(Mutex::new(vec![])); + let _screen_thread = grant_permissions_and_log_actions_in_thread_naked_variant!( + received_screen_instructions, + ScreenInstruction::Exit, + screen_receiver, + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id + ); + let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); let _ = plugin_thread_sender.send(PluginInstruction::Load( plugin_should_float, @@ -3220,9 +3721,9 @@ pub fn open_file_with_line_plugin_command() { Event::Key(Key::Ctrl('i')), // this triggers the enent in the fixture plugin )])); std::thread::sleep(std::time::Duration::from_millis(100)); - screen_thread.join().unwrap(); // this might take a while if the cache is cold + pty_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); - let new_tab_event = received_screen_instructions + let new_tab_event = received_pty_instructions .lock() .unwrap() .iter() @@ -3243,7 +3744,8 @@ pub fn open_file_with_line_floating_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); - let (plugin_thread_sender, pty_receiver, mut teardown) = + let cache_path = plugin_host_folder.join("permissions_test.kdl"); + let (plugin_thread_sender, pty_receiver, screen_receiver, mut teardown) = create_plugin_thread_with_pty_receiver(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -3258,13 +3760,24 @@ pub fn open_file_with_line_floating_plugin_command() { cols: 121, rows: 20, }; - let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( - received_screen_instructions, + let received_pty_instructions = Arc::new(Mutex::new(vec![])); + let pty_thread = log_actions_in_thread!( + received_pty_instructions, PtyInstruction::SpawnTerminal, pty_receiver, 1 ); + let received_screen_instructions = Arc::new(Mutex::new(vec![])); + let _screen_thread = grant_permissions_and_log_actions_in_thread_naked_variant!( + received_screen_instructions, + ScreenInstruction::Exit, + screen_receiver, + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id + ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); let _ = plugin_thread_sender.send(PluginInstruction::Load( @@ -3281,9 +3794,9 @@ pub fn open_file_with_line_floating_plugin_command() { Event::Key(Key::Ctrl('j')), // this triggers the enent in the fixture plugin )])); std::thread::sleep(std::time::Duration::from_millis(100)); - screen_thread.join().unwrap(); // this might take a while if the cache is cold + pty_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); - let new_tab_event = received_screen_instructions + let new_tab_event = received_pty_instructions .lock() .unwrap() .iter() @@ -3304,7 +3817,8 @@ pub fn open_terminal_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); - let (plugin_thread_sender, pty_receiver, mut teardown) = + let cache_path = plugin_host_folder.join("permissions_test.kdl"); + let (plugin_thread_sender, pty_receiver, screen_receiver, mut teardown) = create_plugin_thread_with_pty_receiver(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -3319,13 +3833,24 @@ pub fn open_terminal_plugin_command() { cols: 121, rows: 20, }; - let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( - received_screen_instructions, + let received_pty_instructions = Arc::new(Mutex::new(vec![])); + let pty_thread = log_actions_in_thread!( + received_pty_instructions, PtyInstruction::SpawnTerminal, pty_receiver, 1 ); + let received_screen_instructions = Arc::new(Mutex::new(vec![])); + let _screen_thread = grant_permissions_and_log_actions_in_thread_naked_variant!( + received_screen_instructions, + ScreenInstruction::Exit, + screen_receiver, + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id + ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); let _ = plugin_thread_sender.send(PluginInstruction::Load( @@ -3342,9 +3867,9 @@ pub fn open_terminal_plugin_command() { Event::Key(Key::Ctrl('k')), // this triggers the enent in the fixture plugin )])); std::thread::sleep(std::time::Duration::from_millis(100)); - screen_thread.join().unwrap(); // this might take a while if the cache is cold + pty_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); - let new_tab_event = received_screen_instructions + let new_tab_event = received_pty_instructions .lock() .unwrap() .iter() @@ -3365,7 +3890,8 @@ pub fn open_terminal_floating_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); - let (plugin_thread_sender, pty_receiver, mut teardown) = + let cache_path = plugin_host_folder.join("permissions_test.kdl"); + let (plugin_thread_sender, pty_receiver, screen_receiver, mut teardown) = create_plugin_thread_with_pty_receiver(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -3380,13 +3906,24 @@ pub fn open_terminal_floating_plugin_command() { cols: 121, rows: 20, }; - let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( - received_screen_instructions, + let received_pty_instructions = Arc::new(Mutex::new(vec![])); + let pty_thread = log_actions_in_thread!( + received_pty_instructions, PtyInstruction::SpawnTerminal, pty_receiver, 1 ); + let received_screen_instructions = Arc::new(Mutex::new(vec![])); + let _screen_thread = grant_permissions_and_log_actions_in_thread_naked_variant!( + received_screen_instructions, + ScreenInstruction::Exit, + screen_receiver, + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id + ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); let _ = plugin_thread_sender.send(PluginInstruction::Load( @@ -3403,9 +3940,9 @@ pub fn open_terminal_floating_plugin_command() { Event::Key(Key::Ctrl('l')), // this triggers the enent in the fixture plugin )])); std::thread::sleep(std::time::Duration::from_millis(100)); - screen_thread.join().unwrap(); // this might take a while if the cache is cold + pty_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); - let new_tab_event = received_screen_instructions + let new_tab_event = received_pty_instructions .lock() .unwrap() .iter() @@ -3426,7 +3963,8 @@ pub fn open_command_pane_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); - let (plugin_thread_sender, pty_receiver, mut teardown) = + let cache_path = plugin_host_folder.join("permissions_test.kdl"); + let (plugin_thread_sender, pty_receiver, screen_receiver, mut teardown) = create_plugin_thread_with_pty_receiver(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -3441,13 +3979,24 @@ pub fn open_command_pane_plugin_command() { cols: 121, rows: 20, }; - let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( - received_screen_instructions, + let received_pty_instructions = Arc::new(Mutex::new(vec![])); + let pty_thread = log_actions_in_thread!( + received_pty_instructions, PtyInstruction::SpawnTerminal, pty_receiver, 1 ); + let received_screen_instructions = Arc::new(Mutex::new(vec![])); + let _screen_thread = grant_permissions_and_log_actions_in_thread_naked_variant!( + received_screen_instructions, + ScreenInstruction::Exit, + screen_receiver, + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id + ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); let _ = plugin_thread_sender.send(PluginInstruction::Load( @@ -3464,9 +4013,9 @@ pub fn open_command_pane_plugin_command() { Event::Key(Key::Ctrl('m')), // this triggers the enent in the fixture plugin )])); std::thread::sleep(std::time::Duration::from_millis(100)); - screen_thread.join().unwrap(); // this might take a while if the cache is cold + pty_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); - let new_tab_event = received_screen_instructions + let new_tab_event = received_pty_instructions .lock() .unwrap() .iter() @@ -3487,7 +4036,8 @@ pub fn open_command_pane_floating_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); - let (plugin_thread_sender, pty_receiver, mut teardown) = + let cache_path = plugin_host_folder.join("permissions_test.kdl"); + let (plugin_thread_sender, pty_receiver, screen_receiver, mut teardown) = create_plugin_thread_with_pty_receiver(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -3502,13 +4052,24 @@ pub fn open_command_pane_floating_plugin_command() { cols: 121, rows: 20, }; - let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( - received_screen_instructions, + let received_pty_instructions = Arc::new(Mutex::new(vec![])); + let pty_thread = log_actions_in_thread!( + received_pty_instructions, PtyInstruction::SpawnTerminal, pty_receiver, 1 ); + let received_screen_instructions = Arc::new(Mutex::new(vec![])); + let _screen_thread = grant_permissions_and_log_actions_in_thread_naked_variant!( + received_screen_instructions, + ScreenInstruction::Exit, + screen_receiver, + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id + ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); let _ = plugin_thread_sender.send(PluginInstruction::Load( @@ -3525,9 +4086,9 @@ pub fn open_command_pane_floating_plugin_command() { Event::Key(Key::Ctrl('n')), // this triggers the enent in the fixture plugin )])); std::thread::sleep(std::time::Duration::from_millis(100)); - screen_thread.join().unwrap(); // this might take a while if the cache is cold + pty_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); - let new_tab_event = received_screen_instructions + let new_tab_event = received_pty_instructions .lock() .unwrap() .iter() @@ -3548,6 +4109,7 @@ pub fn switch_to_tab_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); @@ -3564,11 +4126,15 @@ pub fn switch_to_tab_plugin_command() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + let screen_thread = grant_permissions_and_log_actions_in_thread!( received_screen_instructions, ScreenInstruction::GoToTab, screen_receiver, - 1 + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -3731,6 +4297,7 @@ pub fn close_terminal_pane_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); @@ -3747,11 +4314,15 @@ pub fn close_terminal_pane_plugin_command() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + let screen_thread = grant_permissions_and_log_actions_in_thread!( received_screen_instructions, ScreenInstruction::ClosePane, screen_receiver, - 1 + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -3792,6 +4363,7 @@ pub fn close_plugin_pane_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); @@ -3808,11 +4380,15 @@ pub fn close_plugin_pane_plugin_command() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + let screen_thread = grant_permissions_and_log_actions_in_thread!( received_screen_instructions, ScreenInstruction::ClosePane, screen_receiver, - 1 + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -3853,6 +4429,7 @@ pub fn focus_terminal_pane_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); @@ -3869,11 +4446,15 @@ pub fn focus_terminal_pane_plugin_command() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + let screen_thread = grant_permissions_and_log_actions_in_thread!( received_screen_instructions, ScreenInstruction::FocusPaneWithId, screen_receiver, - 1 + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -3914,6 +4495,7 @@ pub fn focus_plugin_pane_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); @@ -3930,11 +4512,15 @@ pub fn focus_plugin_pane_plugin_command() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + let screen_thread = grant_permissions_and_log_actions_in_thread!( received_screen_instructions, ScreenInstruction::FocusPaneWithId, screen_receiver, - 1 + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -3975,6 +4561,7 @@ pub fn rename_terminal_pane_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); @@ -3991,11 +4578,15 @@ pub fn rename_terminal_pane_plugin_command() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + let screen_thread = grant_permissions_and_log_actions_in_thread!( received_screen_instructions, ScreenInstruction::RenamePane, screen_receiver, - 1 + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -4036,6 +4627,7 @@ pub fn rename_plugin_pane_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); @@ -4052,11 +4644,15 @@ pub fn rename_plugin_pane_plugin_command() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + let screen_thread = grant_permissions_and_log_actions_in_thread!( received_screen_instructions, ScreenInstruction::RenamePane, screen_receiver, - 1 + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -4097,6 +4693,7 @@ pub fn rename_tab_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); @@ -4113,11 +4710,15 @@ pub fn rename_tab_plugin_command() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + let screen_thread = grant_permissions_and_log_actions_in_thread!( received_screen_instructions, ScreenInstruction::RenameTab, screen_receiver, - 1 + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -4158,6 +4759,7 @@ pub fn send_configuration_to_plugins() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); @@ -4183,11 +4785,15 @@ pub fn send_configuration_to_plugins() { rows: 20, }; let received_screen_instructions = Arc::new(Mutex::new(vec![])); - let screen_thread = log_actions_in_thread!( + let screen_thread = grant_permissions_and_log_actions_in_thread!( received_screen_instructions, ScreenInstruction::GoToTabName, screen_receiver, - 1 + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id ); let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); @@ -4224,3 +4830,226 @@ pub fn send_configuration_to_plugins() { .clone(); assert_snapshot!(format!("{:#?}", go_to_tab_event)); } + +#[test] +#[ignore] +pub fn request_plugin_permissions() { + let temp_folder = tempdir().unwrap(); + let plugin_host_folder = PathBuf::from(temp_folder.path()); + let (plugin_thread_sender, screen_receiver, mut teardown) = + create_plugin_thread(Some(plugin_host_folder)); + let plugin_should_float = Some(false); + let plugin_title = Some("test_plugin".to_owned()); + let run_plugin = RunPlugin { + _allow_exec_host_cmd: false, + location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), + }; + let tab_index = 1; + let client_id = 1; + let size = Size { + cols: 121, + rows: 20, + }; + let received_screen_instructions = Arc::new(Mutex::new(vec![])); + let screen_thread = log_actions_in_thread!( + received_screen_instructions, + ScreenInstruction::RequestPluginPermissions, + screen_receiver, + 1 + ); + + let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); + let _ = plugin_thread_sender.send(PluginInstruction::Load( + plugin_should_float, + plugin_title, + run_plugin, + tab_index, + client_id, + size, + )); + let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![( + None, + Some(client_id), + Event::Key(Key::Ctrl('1')), // this triggers the enent in the fixture plugin + )])); + std::thread::sleep(std::time::Duration::from_millis(100)); + screen_thread.join().unwrap(); // this might take a while if the cache is cold + teardown(); + let new_tab_event = received_screen_instructions + .lock() + .unwrap() + .iter() + .find_map(|i| { + if let ScreenInstruction::RequestPluginPermissions(_, plugin_permission) = i { + Some(plugin_permission.permissions.clone()) + } else { + None + } + }) + .clone(); + assert_snapshot!(format!("{:#?}", new_tab_event)); +} + +#[test] +#[ignore] +pub fn granted_permission_request_result() { + let temp_folder = tempdir().unwrap(); + let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); + + let (plugin_thread_sender, screen_receiver, mut teardown) = + create_plugin_thread(Some(plugin_host_folder)); + let plugin_should_float = Some(false); + let plugin_title = Some("test_plugin".to_owned()); + let run_plugin = RunPlugin { + _allow_exec_host_cmd: false, + location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), + }; + let tab_index = 1; + let client_id = 1; + let size = Size { + cols: 121, + rows: 20, + }; + + // here we create a fake screen thread that will send a PermissionStatus::Granted + // message for every permission request it gets + let screen_thread = std::thread::Builder::new() + .name("fake_screen_thread".to_string()) + .spawn({ + let cache_path = cache_path.clone(); + let plugin_thread_sender = plugin_thread_sender.clone(); + move || loop { + let (event, _err_ctx) = screen_receiver + .recv() + .expect("failed to receive event on channel"); + match event { + ScreenInstruction::RequestPluginPermissions(_, plugin_permission) => { + let _ = + plugin_thread_sender.send(PluginInstruction::PermissionRequestResult( + 0, + Some(client_id), + plugin_permission.permissions, + PermissionStatus::Granted, + Some(cache_path.clone()), + )); + break; + }, + ScreenInstruction::Exit => { + break; + }, + _ => {}, + } + } + }) + .unwrap(); + + let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); + let _ = plugin_thread_sender.send(PluginInstruction::Load( + plugin_should_float, + plugin_title, + run_plugin.clone(), + tab_index, + client_id, + size, + )); + let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![( + None, + Some(client_id), + Event::Key(Key::Ctrl('1')), // this triggers the enent in the fixture plugin + )])); + screen_thread.join().unwrap(); + teardown(); + + let permission_cache = PermissionCache::from_path_or_default(Some(cache_path)); + let mut permissions = permission_cache + .get_permissions(run_plugin.location.to_string()) + .clone(); + let permissions = permissions.as_mut().map(|p| { + let mut permissions = p.clone(); + permissions.sort_unstable(); + permissions + }); + + assert_snapshot!(format!("{:#?}", permissions)); +} + +#[test] +#[ignore] +pub fn denied_permission_request_result() { + let temp_folder = tempdir().unwrap(); + let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); + + let (plugin_thread_sender, screen_receiver, mut teardown) = + create_plugin_thread(Some(plugin_host_folder)); + let plugin_should_float = Some(false); + let plugin_title = Some("test_plugin".to_owned()); + let run_plugin = RunPlugin { + _allow_exec_host_cmd: false, + location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), + }; + let tab_index = 1; + let client_id = 1; + let size = Size { + cols: 121, + rows: 20, + }; + + // here we create a fake screen thread that will send a PermissionStatus::Granted + // message for every permission request it gets + let screen_thread = std::thread::Builder::new() + .name("fake_screen_thread".to_string()) + .spawn({ + let cache_path = cache_path.clone(); + let plugin_thread_sender = plugin_thread_sender.clone(); + move || loop { + let (event, _err_ctx) = screen_receiver + .recv() + .expect("failed to receive event on channel"); + match event { + ScreenInstruction::RequestPluginPermissions(_, plugin_permission) => { + let _ = + plugin_thread_sender.send(PluginInstruction::PermissionRequestResult( + 0, + Some(client_id), + plugin_permission.permissions, + PermissionStatus::Denied, + Some(cache_path.clone()), + )); + break; + }, + ScreenInstruction::Exit => { + break; + }, + _ => {}, + } + } + }) + .unwrap(); + + let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); + let _ = plugin_thread_sender.send(PluginInstruction::Load( + plugin_should_float, + plugin_title, + run_plugin.clone(), + tab_index, + client_id, + size, + )); + let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![( + None, + Some(client_id), + Event::Key(Key::Ctrl('1')), // this triggers the enent in the fixture plugin + )])); + screen_thread.join().unwrap(); + teardown(); + + let permission_cache = PermissionCache::from_path_or_default(Some(cache_path)); + let permissions = permission_cache.get_permissions(run_plugin.location.to_string()); + + assert_snapshot!(format!("{:#?}", permissions)); +} |
