support open browser
This commit is contained in:
119
src-tauri/src/browsers.rs
Normal file
119
src-tauri/src/browsers.rs
Normal file
@@ -0,0 +1,119 @@
|
||||
use std::{env, path::PathBuf};
|
||||
|
||||
use crate::models::BrowserDefinition;
|
||||
|
||||
pub fn browser_definitions() -> Vec<BrowserDefinition> {
|
||||
vec![
|
||||
BrowserDefinition {
|
||||
id: "chrome",
|
||||
name: "Google Chrome",
|
||||
local_app_data_segments: &["Google", "Chrome", "User Data"],
|
||||
executable_candidates: &[
|
||||
ExecutableCandidate::ProgramFiles(&[
|
||||
"Google",
|
||||
"Chrome",
|
||||
"Application",
|
||||
"chrome.exe",
|
||||
]),
|
||||
ExecutableCandidate::ProgramFilesX86(&[
|
||||
"Google",
|
||||
"Chrome",
|
||||
"Application",
|
||||
"chrome.exe",
|
||||
]),
|
||||
ExecutableCandidate::LocalAppData(&[
|
||||
"Google",
|
||||
"Chrome",
|
||||
"Application",
|
||||
"chrome.exe",
|
||||
]),
|
||||
],
|
||||
},
|
||||
BrowserDefinition {
|
||||
id: "edge",
|
||||
name: "Microsoft Edge",
|
||||
local_app_data_segments: &["Microsoft", "Edge", "User Data"],
|
||||
executable_candidates: &[
|
||||
ExecutableCandidate::ProgramFiles(&[
|
||||
"Microsoft",
|
||||
"Edge",
|
||||
"Application",
|
||||
"msedge.exe",
|
||||
]),
|
||||
ExecutableCandidate::ProgramFilesX86(&[
|
||||
"Microsoft",
|
||||
"Edge",
|
||||
"Application",
|
||||
"msedge.exe",
|
||||
]),
|
||||
],
|
||||
},
|
||||
BrowserDefinition {
|
||||
id: "brave",
|
||||
name: "Brave",
|
||||
local_app_data_segments: &["BraveSoftware", "Brave-Browser", "User Data"],
|
||||
executable_candidates: &[
|
||||
ExecutableCandidate::ProgramFiles(&[
|
||||
"BraveSoftware",
|
||||
"Brave-Browser",
|
||||
"Application",
|
||||
"brave.exe",
|
||||
]),
|
||||
ExecutableCandidate::ProgramFilesX86(&[
|
||||
"BraveSoftware",
|
||||
"Brave-Browser",
|
||||
"Application",
|
||||
"brave.exe",
|
||||
]),
|
||||
ExecutableCandidate::LocalAppData(&[
|
||||
"BraveSoftware",
|
||||
"Brave-Browser",
|
||||
"Application",
|
||||
"brave.exe",
|
||||
]),
|
||||
],
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
pub fn browser_definition_by_id(browser_id: &str) -> Option<BrowserDefinition> {
|
||||
browser_definitions()
|
||||
.into_iter()
|
||||
.find(|definition| definition.id == browser_id)
|
||||
}
|
||||
|
||||
pub fn resolve_browser_executable(browser_id: &str) -> Option<PathBuf> {
|
||||
let definition = browser_definition_by_id(browser_id)?;
|
||||
definition
|
||||
.executable_candidates
|
||||
.iter()
|
||||
.find_map(resolve_executable_candidate)
|
||||
.filter(|path| path.is_file())
|
||||
}
|
||||
|
||||
fn resolve_executable_candidate(candidate: &ExecutableCandidate) -> Option<PathBuf> {
|
||||
match candidate {
|
||||
ExecutableCandidate::ProgramFiles(segments) => env::var_os("ProgramFiles")
|
||||
.map(PathBuf::from)
|
||||
.map(|root| join_segments(root, segments)),
|
||||
ExecutableCandidate::ProgramFilesX86(segments) => env::var_os("ProgramFiles(x86)")
|
||||
.map(PathBuf::from)
|
||||
.map(|root| join_segments(root, segments)),
|
||||
ExecutableCandidate::LocalAppData(segments) => env::var_os("LOCALAPPDATA")
|
||||
.map(PathBuf::from)
|
||||
.map(|root| join_segments(root, segments)),
|
||||
}
|
||||
}
|
||||
|
||||
fn join_segments(mut root: PathBuf, segments: &[&str]) -> PathBuf {
|
||||
for segment in segments {
|
||||
root.push(segment);
|
||||
}
|
||||
root
|
||||
}
|
||||
|
||||
pub enum ExecutableCandidate {
|
||||
ProgramFiles(&'static [&'static str]),
|
||||
ProgramFilesX86(&'static [&'static str]),
|
||||
LocalAppData(&'static [&'static str]),
|
||||
}
|
||||
@@ -1,6 +1,64 @@
|
||||
use crate::{models::ScanResponse, scanner};
|
||||
use std::{path::PathBuf, process::Command};
|
||||
|
||||
use crate::{
|
||||
browsers::{browser_definition_by_id, resolve_browser_executable},
|
||||
models::ScanResponse,
|
||||
scanner,
|
||||
utils::local_app_data_dir,
|
||||
};
|
||||
|
||||
#[tauri::command]
|
||||
pub fn scan_browsers() -> Result<ScanResponse, String> {
|
||||
scanner::scan_browsers()
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn open_browser_profile(browser_id: String, profile_id: String) -> Result<(), String> {
|
||||
let definition = browser_definition_by_id(&browser_id)
|
||||
.ok_or_else(|| format!("Unsupported browser: {browser_id}"))?;
|
||||
let executable_path = resolve_browser_executable(&browser_id)
|
||||
.ok_or_else(|| format!("Unable to locate executable for browser: {browser_id}"))?;
|
||||
let local_app_data = local_app_data_dir().ok_or_else(|| {
|
||||
"Unable to resolve the LOCALAPPDATA directory for the current user.".to_string()
|
||||
})?;
|
||||
let user_data_dir = definition
|
||||
.local_app_data_segments
|
||||
.iter()
|
||||
.fold(local_app_data, |path, segment| path.join(segment));
|
||||
let profile_directory = user_data_dir.join(&profile_id);
|
||||
|
||||
if !user_data_dir.is_dir() {
|
||||
return Err(format!(
|
||||
"User data directory does not exist: {}",
|
||||
user_data_dir.display()
|
||||
));
|
||||
}
|
||||
|
||||
if !profile_directory.is_dir() {
|
||||
return Err(format!(
|
||||
"Profile directory does not exist: {}",
|
||||
profile_directory.display()
|
||||
));
|
||||
}
|
||||
|
||||
spawn_browser_process(executable_path, user_data_dir, profile_id)
|
||||
}
|
||||
|
||||
fn spawn_browser_process(
|
||||
executable_path: PathBuf,
|
||||
user_data_dir: PathBuf,
|
||||
profile_id: String,
|
||||
) -> Result<(), String> {
|
||||
Command::new(&executable_path)
|
||||
.arg(format!("--user-data-dir={}", user_data_dir.display()))
|
||||
.arg(format!("--profile-directory={profile_id}"))
|
||||
.arg("https://www.google.com")
|
||||
.spawn()
|
||||
.map(|_| ())
|
||||
.map_err(|error| {
|
||||
format!(
|
||||
"Failed to open browser profile with executable {}: {error}",
|
||||
executable_path.display()
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
mod browsers;
|
||||
mod commands;
|
||||
mod models;
|
||||
mod scanner;
|
||||
@@ -7,7 +8,10 @@ mod utils;
|
||||
pub fn run() {
|
||||
tauri::Builder::default()
|
||||
.plugin(tauri_plugin_opener::init())
|
||||
.invoke_handler(tauri::generate_handler![commands::scan_browsers])
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
commands::scan_browsers,
|
||||
commands::open_browser_profile
|
||||
])
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
}
|
||||
|
||||
@@ -61,6 +61,7 @@ pub struct BrowserDefinition {
|
||||
pub id: &'static str,
|
||||
pub name: &'static str,
|
||||
pub local_app_data_segments: &'static [&'static str],
|
||||
pub executable_candidates: &'static [crate::browsers::ExecutableCandidate],
|
||||
}
|
||||
|
||||
pub struct TempExtension {
|
||||
|
||||
@@ -7,6 +7,7 @@ use std::{
|
||||
use serde_json::Value;
|
||||
|
||||
use crate::{
|
||||
browsers::browser_definitions,
|
||||
models::{
|
||||
BookmarkSummary, BrowserDefinition, BrowserStats, BrowserView, ExtensionSummary,
|
||||
ProfileSummary, ScanResponse, TempBookmark, TempExtension,
|
||||
@@ -30,26 +31,6 @@ pub fn scan_browsers() -> Result<ScanResponse, String> {
|
||||
Ok(ScanResponse { browsers })
|
||||
}
|
||||
|
||||
fn browser_definitions() -> Vec<BrowserDefinition> {
|
||||
vec![
|
||||
BrowserDefinition {
|
||||
id: "chrome",
|
||||
name: "Google Chrome",
|
||||
local_app_data_segments: &["Google", "Chrome", "User Data"],
|
||||
},
|
||||
BrowserDefinition {
|
||||
id: "edge",
|
||||
name: "Microsoft Edge",
|
||||
local_app_data_segments: &["Microsoft", "Edge", "User Data"],
|
||||
},
|
||||
BrowserDefinition {
|
||||
id: "brave",
|
||||
name: "Brave",
|
||||
local_app_data_segments: &["BraveSoftware", "Brave-Browser", "User Data"],
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
fn scan_browser(local_app_data: &Path, definition: BrowserDefinition) -> Option<BrowserView> {
|
||||
let root = definition
|
||||
.local_app_data_segments
|
||||
|
||||
Reference in New Issue
Block a user