Add a check on macOS to warn the user about possible SecureInput-related issues.

This commit is contained in:
Federico Terzi 2020-03-31 19:33:38 +02:00
parent 80f12194db
commit 2c8c28087d
4 changed files with 88 additions and 8 deletions

View File

@ -17,11 +17,11 @@
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
*/
// This functions are used to check if the required dependencies are satisfied
// This functions are used to check if the required dependencies and conditions are satisfied
// before starting espanso
#[cfg(target_os = "linux")]
pub fn check_dependencies() -> bool {
pub fn check_preconditions() -> bool {
use std::process::Command;
let mut result = true;
@ -48,13 +48,26 @@ pub fn check_dependencies() -> bool {
}
#[cfg(target_os = "macos")]
pub fn check_dependencies() -> bool {
// Nothing to do here
pub fn check_preconditions() -> bool {
// Make sure no app is currently using secure input.
let secure_input_app = crate::system::macos::MacSystemManager::get_secure_input_application();
if let Some((app_name, process)) = secure_input_app {
eprintln!("WARNING: An application is currently using SecureInput and might prevent espanso from working correctly.");
eprintln!();
eprintln!("APP: {}", app_name);
eprintln!("PROC: {}", process);
eprintln!();
eprintln!("Please close it or disable SecureInput for that application (most apps that use it have a");
eprintln!("setting to disable it).");
eprintln!("Until then, espanso might not work as expected.");
}
true
}
#[cfg(target_os = "windows")]
pub fn check_dependencies() -> bool {
pub fn check_preconditions() -> bool {
// Nothing needed on windows
true
}

View File

@ -1037,9 +1037,9 @@ fn release_lock(lock_file: File) {
lock_file.unlock().unwrap()
}
/// Used to make sure all the required dependencies are present before starting espanso.
/// Used to make sure all the required dependencies and conditions are satisfied before starting espanso.
fn precheck_guard() {
let satisfied = check::check_dependencies();
let satisfied = check::check_preconditions();
if !satisfied {
println!();
println!("Pre-check was not successful, espanso could not be started.");

View File

@ -74,4 +74,71 @@ impl MacSystemManager {
}
}
/// Check whether an application is currently holding the Secure Input.
/// Return None if no application has claimed SecureInput, Some((AppName, AppPath)) otherwise.
pub fn get_secure_input_application() -> Option<(String, String)> {
use std::process::Command;
use regex::Regex;
let output = Command::new("ioreg")
.arg("-d")
.arg("1")
.arg("-k")
.arg("IOConsoleUsers")
.arg("-w")
.arg("0")
.output();
lazy_static! {
static ref PID_REGEX: Regex = Regex::new("\"kCGSSessionSecureInputPID\"=(\\d+)").unwrap();
};
lazy_static! {
static ref APP_REGEX: Regex = Regex::new("/([^/]+).app/").unwrap();
};
if let Ok(output) = output {
let output_str = String::from_utf8_lossy(output.stdout.as_slice());
let caps = PID_REGEX.captures(&output_str);
if let Some(caps) = caps {
// Get the PID of the process that is handling SecureInput
let pid_str = caps.get(1).map_or("", |m| m.as_str());
let pid = pid_str.parse::<i32>().expect("Invalid pid value");
// Find the process that is handling the SecureInput
let output = Command::new("ps")
.arg("-p")
.arg(pid.to_string())
.arg("-o")
.arg("command=")
.output();
if let Ok(output) = output {
let output_str = String::from_utf8_lossy(output.stdout.as_slice());
if !output_str.trim().is_empty() {
let process = output_str.trim().to_string();
let caps = APP_REGEX.captures(&process);
let app_name = if let Some(caps) = caps {
caps.get(1).map_or("", |m| m.as_str()).to_owned()
}else{
process.to_owned()
};
Some((app_name, process))
}else{
None
}
}else{ // Can't obtain process name
None
}
}else{ // No process is holding SecureInput
None
}
}else{ // Can't execute the query to the IOKit registry
None
}
}
}

View File

@ -24,7 +24,7 @@ mod windows;
mod linux;
#[cfg(target_os = "macos")]
mod macos;
pub mod macos;
pub trait SystemManager {
fn get_current_window_title(&self) -> Option<String>;