mirror of
https://github.com/zhom/donutbrowser.git
synced 2026-06-13 10:17:54 +02:00
feat: partially add wayfern
This commit is contained in:
@@ -4,6 +4,7 @@ use crate::downloaded_browsers_registry::DownloadedBrowsersRegistry;
|
||||
use crate::platform_browser;
|
||||
use crate::profile::{BrowserProfile, ProfileManager};
|
||||
use crate::proxy_manager::PROXY_MANAGER;
|
||||
use crate::wayfern_manager::{WayfernConfig, WayfernManager};
|
||||
use directories::BaseDirs;
|
||||
use serde::Serialize;
|
||||
use std::path::PathBuf;
|
||||
@@ -16,6 +17,7 @@ pub struct BrowserRunner {
|
||||
pub downloaded_browsers_registry: &'static DownloadedBrowsersRegistry,
|
||||
auto_updater: &'static crate::auto_updater::AutoUpdater,
|
||||
camoufox_manager: &'static CamoufoxManager,
|
||||
wayfern_manager: &'static WayfernManager,
|
||||
}
|
||||
|
||||
impl BrowserRunner {
|
||||
@@ -26,6 +28,7 @@ impl BrowserRunner {
|
||||
downloaded_browsers_registry: DownloadedBrowsersRegistry::instance(),
|
||||
auto_updater: crate::auto_updater::AutoUpdater::instance(),
|
||||
camoufox_manager: CamoufoxManager::instance(),
|
||||
wayfern_manager: WayfernManager::instance(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -297,6 +300,204 @@ impl BrowserRunner {
|
||||
return Ok(updated_profile);
|
||||
}
|
||||
|
||||
// Handle Wayfern profiles using WayfernManager
|
||||
if profile.browser == "wayfern" {
|
||||
// Get or create wayfern config
|
||||
let mut wayfern_config = profile.wayfern_config.clone().unwrap_or_else(|| {
|
||||
log::info!(
|
||||
"No wayfern config found for profile {}, using default",
|
||||
profile.name
|
||||
);
|
||||
WayfernConfig::default()
|
||||
});
|
||||
|
||||
// Always start a local proxy for Wayfern (for traffic monitoring and geoip support)
|
||||
let upstream_proxy = profile
|
||||
.proxy_id
|
||||
.as_ref()
|
||||
.and_then(|id| PROXY_MANAGER.get_proxy_settings_by_id(id));
|
||||
|
||||
log::info!(
|
||||
"Starting local proxy for Wayfern profile: {} (upstream: {})",
|
||||
profile.name,
|
||||
upstream_proxy
|
||||
.as_ref()
|
||||
.map(|p| format!("{}:{}", p.host, p.port))
|
||||
.unwrap_or_else(|| "DIRECT".to_string())
|
||||
);
|
||||
|
||||
// Start the proxy and get local proxy settings
|
||||
// If proxy startup fails, DO NOT launch Wayfern - it requires local proxy
|
||||
let profile_id_str = profile.id.to_string();
|
||||
let local_proxy = PROXY_MANAGER
|
||||
.start_proxy(
|
||||
app_handle.clone(),
|
||||
upstream_proxy.as_ref(),
|
||||
0, // Use 0 as temporary PID, will be updated later
|
||||
Some(&profile_id_str),
|
||||
)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
let error_msg = format!("Failed to start local proxy for Wayfern: {e}");
|
||||
log::error!("{}", error_msg);
|
||||
error_msg
|
||||
})?;
|
||||
|
||||
// Format proxy URL for wayfern - always use HTTP for the local proxy
|
||||
let proxy_url = format!("http://{}:{}", local_proxy.host, local_proxy.port);
|
||||
|
||||
// Set proxy in wayfern config
|
||||
wayfern_config.proxy = Some(proxy_url);
|
||||
|
||||
log::info!(
|
||||
"Configured local proxy for Wayfern: {:?}",
|
||||
wayfern_config.proxy
|
||||
);
|
||||
|
||||
// Check if we need to generate a new fingerprint on every launch
|
||||
let mut updated_profile = profile.clone();
|
||||
if wayfern_config.randomize_fingerprint_on_launch == Some(true) {
|
||||
log::info!(
|
||||
"Generating random fingerprint for Wayfern profile: {}",
|
||||
profile.name
|
||||
);
|
||||
|
||||
// Create a config copy without the existing fingerprint to force generation of a new one
|
||||
let mut config_for_generation = wayfern_config.clone();
|
||||
config_for_generation.fingerprint = None;
|
||||
|
||||
// Generate a new fingerprint
|
||||
let new_fingerprint = self
|
||||
.wayfern_manager
|
||||
.generate_fingerprint_config(&app_handle, profile, &config_for_generation)
|
||||
.await
|
||||
.map_err(|e| format!("Failed to generate random fingerprint: {e}"))?;
|
||||
|
||||
log::info!(
|
||||
"New fingerprint generated, length: {} chars",
|
||||
new_fingerprint.len()
|
||||
);
|
||||
|
||||
// Update the config with the new fingerprint for launching
|
||||
wayfern_config.fingerprint = Some(new_fingerprint.clone());
|
||||
|
||||
// Save the updated fingerprint to the profile so it persists
|
||||
let mut updated_wayfern_config = updated_profile.wayfern_config.clone().unwrap_or_default();
|
||||
updated_wayfern_config.fingerprint = Some(new_fingerprint);
|
||||
updated_wayfern_config.randomize_fingerprint_on_launch = Some(true);
|
||||
if wayfern_config.os.is_some() {
|
||||
updated_wayfern_config.os = wayfern_config.os.clone();
|
||||
}
|
||||
updated_profile.wayfern_config = Some(updated_wayfern_config.clone());
|
||||
|
||||
log::info!(
|
||||
"Updated profile wayfern_config with new fingerprint for profile: {}, fingerprint length: {}",
|
||||
profile.name,
|
||||
updated_wayfern_config.fingerprint.as_ref().map(|f| f.len()).unwrap_or(0)
|
||||
);
|
||||
}
|
||||
|
||||
// Launch Wayfern browser
|
||||
log::info!("Launching Wayfern for profile: {}", profile.name);
|
||||
|
||||
// Get profile path for Wayfern
|
||||
let profiles_dir = self.profile_manager.get_profiles_dir();
|
||||
let profile_data_path = updated_profile.get_profile_data_path(&profiles_dir);
|
||||
let profile_path_str = profile_data_path.to_string_lossy().to_string();
|
||||
|
||||
// Get proxy URL from config
|
||||
let proxy_url = wayfern_config.proxy.as_deref();
|
||||
|
||||
let wayfern_result = self
|
||||
.wayfern_manager
|
||||
.launch_wayfern(
|
||||
&app_handle,
|
||||
&updated_profile,
|
||||
&profile_path_str,
|
||||
&wayfern_config,
|
||||
url.as_deref(),
|
||||
proxy_url,
|
||||
)
|
||||
.await
|
||||
.map_err(|e| -> Box<dyn std::error::Error + Send + Sync> {
|
||||
format!("Failed to launch Wayfern: {e}").into()
|
||||
})?;
|
||||
|
||||
// Get the process ID from launch result
|
||||
let process_id = wayfern_result.processId.unwrap_or(0);
|
||||
log::info!("Wayfern launched successfully with PID: {process_id}");
|
||||
|
||||
// Update profile with the process info
|
||||
updated_profile.process_id = Some(process_id);
|
||||
updated_profile.last_launch = Some(SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs());
|
||||
|
||||
// Update the proxy manager with the correct PID
|
||||
if let Err(e) = PROXY_MANAGER.update_proxy_pid(0, process_id) {
|
||||
log::warn!("Warning: Failed to update proxy PID mapping: {e}");
|
||||
} else {
|
||||
log::info!("Updated proxy PID mapping from temp (0) to actual PID: {process_id}");
|
||||
}
|
||||
|
||||
// Save the updated profile
|
||||
log::info!(
|
||||
"Saving profile {} with wayfern_config fingerprint length: {}",
|
||||
updated_profile.name,
|
||||
updated_profile
|
||||
.wayfern_config
|
||||
.as_ref()
|
||||
.and_then(|c| c.fingerprint.as_ref())
|
||||
.map(|f| f.len())
|
||||
.unwrap_or(0)
|
||||
);
|
||||
self.save_process_info(&updated_profile)?;
|
||||
let _ = crate::tag_manager::TAG_MANAGER.lock().map(|tm| {
|
||||
let _ = tm.rebuild_from_profiles(&self.profile_manager.list_profiles().unwrap_or_default());
|
||||
});
|
||||
log::info!(
|
||||
"Successfully saved profile with process info: {}",
|
||||
updated_profile.name
|
||||
);
|
||||
|
||||
// Emit profiles-changed to trigger frontend to reload profiles from disk
|
||||
if let Err(e) = app_handle.emit("profiles-changed", ()) {
|
||||
log::warn!("Warning: Failed to emit profiles-changed event: {e}");
|
||||
}
|
||||
|
||||
log::info!(
|
||||
"Emitting profile events for successful Wayfern launch: {}",
|
||||
updated_profile.name
|
||||
);
|
||||
|
||||
// Emit profile update event to frontend
|
||||
if let Err(e) = app_handle.emit("profile-updated", &updated_profile) {
|
||||
log::warn!("Warning: Failed to emit profile update event: {e}");
|
||||
}
|
||||
|
||||
// Emit minimal running changed event to frontend
|
||||
#[derive(Serialize)]
|
||||
struct RunningChangedPayload {
|
||||
id: String,
|
||||
is_running: bool,
|
||||
}
|
||||
|
||||
let payload = RunningChangedPayload {
|
||||
id: updated_profile.id.to_string(),
|
||||
is_running: updated_profile.process_id.is_some(),
|
||||
};
|
||||
|
||||
if let Err(e) = app_handle.emit("profile-running-changed", &payload) {
|
||||
log::warn!("Warning: Failed to emit profile running changed event: {e}");
|
||||
} else {
|
||||
log::info!(
|
||||
"Successfully emitted profile-running-changed event for Wayfern {}: running={}",
|
||||
updated_profile.name,
|
||||
payload.is_running
|
||||
);
|
||||
}
|
||||
|
||||
return Ok(updated_profile);
|
||||
}
|
||||
|
||||
// Create browser instance
|
||||
let browser_type = BrowserType::from_str(&profile.browser)
|
||||
.map_err(|_| format!("Invalid browser type: {}", profile.browser))?;
|
||||
@@ -577,7 +778,35 @@ impl BrowserRunner {
|
||||
}
|
||||
}
|
||||
|
||||
// Use the comprehensive browser status check for non-camoufox browsers
|
||||
// Handle Wayfern profiles using WayfernManager
|
||||
if profile.browser == "wayfern" {
|
||||
let profiles_dir = self.profile_manager.get_profiles_dir();
|
||||
let profile_data_path = profile.get_profile_data_path(&profiles_dir);
|
||||
let profile_path_str = profile_data_path.to_string_lossy();
|
||||
|
||||
// Check if the process is running
|
||||
match self
|
||||
.wayfern_manager
|
||||
.find_wayfern_by_profile(&profile_path_str)
|
||||
.await
|
||||
{
|
||||
Some(_wayfern_process) => {
|
||||
log::info!(
|
||||
"Opening URL in existing Wayfern process for profile: {} (ID: {})",
|
||||
profile.name,
|
||||
profile.id
|
||||
);
|
||||
|
||||
// For Wayfern, we can use CDP to navigate to the URL
|
||||
return Err("Wayfern doesn't currently support opening URLs in existing instances. Please close the browser and launch again with the URL.".into());
|
||||
}
|
||||
None => {
|
||||
return Err("Wayfern browser is not running".into());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Use the comprehensive browser status check for non-camoufox/wayfern browsers
|
||||
let is_running = self
|
||||
.check_browser_status(app_handle.clone(), profile)
|
||||
.await?;
|
||||
@@ -657,6 +886,10 @@ impl BrowserRunner {
|
||||
// Camoufox URL opening is handled differently
|
||||
Err("URL opening in existing Camoufox instance is not supported".into())
|
||||
}
|
||||
BrowserType::Wayfern => {
|
||||
// Wayfern URL opening is handled differently
|
||||
Err("URL opening in existing Wayfern instance is not supported".into())
|
||||
}
|
||||
BrowserType::Chromium | BrowserType::Brave => {
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
@@ -1382,7 +1615,325 @@ impl BrowserRunner {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// For non-camoufox browsers, use the existing logic
|
||||
// Handle Wayfern profiles using WayfernManager
|
||||
if profile.browser == "wayfern" {
|
||||
let profiles_dir = self.profile_manager.get_profiles_dir();
|
||||
let profile_data_path = profile.get_profile_data_path(&profiles_dir);
|
||||
let profile_path_str = profile_data_path.to_string_lossy();
|
||||
|
||||
log::info!(
|
||||
"Attempting to kill Wayfern process for profile: {} (ID: {})",
|
||||
profile.name,
|
||||
profile.id
|
||||
);
|
||||
|
||||
// Stop the proxy associated with this profile first
|
||||
let profile_id_str = profile.id.to_string();
|
||||
if let Err(e) = PROXY_MANAGER
|
||||
.stop_proxy_by_profile_id(app_handle.clone(), &profile_id_str)
|
||||
.await
|
||||
{
|
||||
log::warn!(
|
||||
"Warning: Failed to stop proxy for profile {}: {e}",
|
||||
profile_id_str
|
||||
);
|
||||
}
|
||||
|
||||
let mut process_actually_stopped = false;
|
||||
match self
|
||||
.wayfern_manager
|
||||
.find_wayfern_by_profile(&profile_path_str)
|
||||
.await
|
||||
{
|
||||
Some(wayfern_process) => {
|
||||
log::info!(
|
||||
"Found Wayfern process: {} (PID: {:?})",
|
||||
wayfern_process.id,
|
||||
wayfern_process.processId
|
||||
);
|
||||
|
||||
match self.wayfern_manager.stop_wayfern(&wayfern_process.id).await {
|
||||
Ok(_) => {
|
||||
if let Some(pid) = wayfern_process.processId {
|
||||
// Verify the process actually died by checking after a short delay
|
||||
use tokio::time::{sleep, Duration};
|
||||
sleep(Duration::from_millis(500)).await;
|
||||
|
||||
use sysinfo::{Pid, System};
|
||||
let system = System::new_all();
|
||||
process_actually_stopped = system.process(Pid::from(pid as usize)).is_none();
|
||||
|
||||
if process_actually_stopped {
|
||||
log::info!(
|
||||
"Successfully stopped Wayfern process: {} (PID: {:?}) - verified process is dead",
|
||||
wayfern_process.id,
|
||||
pid
|
||||
);
|
||||
} else {
|
||||
log::warn!(
|
||||
"Wayfern stop command returned success but process {} (PID: {:?}) is still running - forcing kill",
|
||||
wayfern_process.id,
|
||||
pid
|
||||
);
|
||||
// Force kill the process
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
use crate::platform_browser;
|
||||
if let Err(e) = platform_browser::macos::kill_browser_process_impl(
|
||||
pid,
|
||||
Some(&profile_path_str),
|
||||
)
|
||||
.await
|
||||
{
|
||||
log::error!("Failed to force kill Wayfern process {}: {}", pid, e);
|
||||
} else {
|
||||
sleep(Duration::from_millis(500)).await;
|
||||
let system = System::new_all();
|
||||
process_actually_stopped = system.process(Pid::from(pid as usize)).is_none();
|
||||
if process_actually_stopped {
|
||||
log::info!(
|
||||
"Successfully force killed Wayfern process {} (PID: {:?})",
|
||||
wayfern_process.id,
|
||||
pid
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
use crate::platform_browser;
|
||||
if let Err(e) = platform_browser::linux::kill_browser_process_impl(pid).await {
|
||||
log::error!("Failed to force kill Wayfern process {}: {}", pid, e);
|
||||
} else {
|
||||
sleep(Duration::from_millis(500)).await;
|
||||
let system = System::new_all();
|
||||
process_actually_stopped = system.process(Pid::from(pid as usize)).is_none();
|
||||
if process_actually_stopped {
|
||||
log::info!(
|
||||
"Successfully force killed Wayfern process {} (PID: {:?})",
|
||||
wayfern_process.id,
|
||||
pid
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
use crate::platform_browser;
|
||||
if let Err(e) = platform_browser::windows::kill_browser_process_impl(pid).await
|
||||
{
|
||||
log::error!("Failed to force kill Wayfern process {}: {}", pid, e);
|
||||
} else {
|
||||
sleep(Duration::from_millis(500)).await;
|
||||
let system = System::new_all();
|
||||
process_actually_stopped = system.process(Pid::from(pid as usize)).is_none();
|
||||
if process_actually_stopped {
|
||||
log::info!(
|
||||
"Successfully force killed Wayfern process {} (PID: {:?})",
|
||||
wayfern_process.id,
|
||||
pid
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
process_actually_stopped = true;
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!(
|
||||
"Error stopping Wayfern process {}: {}",
|
||||
wayfern_process.id,
|
||||
e
|
||||
);
|
||||
// Try to force kill if we have a PID
|
||||
if let Some(pid) = wayfern_process.processId {
|
||||
log::info!(
|
||||
"Attempting force kill after stop_wayfern error for PID: {}",
|
||||
pid
|
||||
);
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
use crate::platform_browser;
|
||||
if let Err(kill_err) =
|
||||
platform_browser::macos::kill_browser_process_impl(pid, Some(&profile_path_str))
|
||||
.await
|
||||
{
|
||||
log::error!("Failed to force kill Wayfern process {}: {}", pid, kill_err);
|
||||
} else {
|
||||
use tokio::time::{sleep, Duration};
|
||||
sleep(Duration::from_millis(500)).await;
|
||||
use sysinfo::{Pid, System};
|
||||
let system = System::new_all();
|
||||
process_actually_stopped = system.process(Pid::from(pid as usize)).is_none();
|
||||
}
|
||||
}
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
use crate::platform_browser;
|
||||
if let Err(kill_err) =
|
||||
platform_browser::linux::kill_browser_process_impl(pid).await
|
||||
{
|
||||
log::error!("Failed to force kill Wayfern process {}: {}", pid, kill_err);
|
||||
} else {
|
||||
use tokio::time::{sleep, Duration};
|
||||
sleep(Duration::from_millis(500)).await;
|
||||
use sysinfo::{Pid, System};
|
||||
let system = System::new_all();
|
||||
process_actually_stopped = system.process(Pid::from(pid as usize)).is_none();
|
||||
}
|
||||
}
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
use crate::platform_browser;
|
||||
if let Err(kill_err) =
|
||||
platform_browser::windows::kill_browser_process_impl(pid).await
|
||||
{
|
||||
log::error!("Failed to force kill Wayfern process {}: {}", pid, kill_err);
|
||||
} else {
|
||||
use tokio::time::{sleep, Duration};
|
||||
sleep(Duration::from_millis(500)).await;
|
||||
use sysinfo::{Pid, System};
|
||||
let system = System::new_all();
|
||||
process_actually_stopped = system.process(Pid::from(pid as usize)).is_none();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {
|
||||
log::info!(
|
||||
"No running Wayfern process found for profile: {} (ID: {})",
|
||||
profile.name,
|
||||
profile.id
|
||||
);
|
||||
process_actually_stopped = true;
|
||||
}
|
||||
}
|
||||
|
||||
// If process wasn't confirmed stopped, return an error
|
||||
if !process_actually_stopped {
|
||||
log::error!(
|
||||
"Failed to stop Wayfern process for profile: {} (ID: {}) - process may still be running",
|
||||
profile.name,
|
||||
profile.id
|
||||
);
|
||||
return Err(
|
||||
format!(
|
||||
"Failed to stop Wayfern process for profile {} - process may still be running",
|
||||
profile.name
|
||||
)
|
||||
.into(),
|
||||
);
|
||||
}
|
||||
|
||||
// Clear the process ID from the profile
|
||||
let mut updated_profile = profile.clone();
|
||||
updated_profile.process_id = None;
|
||||
|
||||
// Check for pending updates and apply them
|
||||
if let Ok(Some(pending_update)) = self
|
||||
.auto_updater
|
||||
.get_pending_update(&profile.browser, &profile.version)
|
||||
{
|
||||
log::info!(
|
||||
"Found pending update for Wayfern profile {}: {} -> {}",
|
||||
profile.name,
|
||||
profile.version,
|
||||
pending_update.new_version
|
||||
);
|
||||
|
||||
match self.profile_manager.update_profile_version(
|
||||
&app_handle,
|
||||
&profile.id.to_string(),
|
||||
&pending_update.new_version,
|
||||
) {
|
||||
Ok(updated_profile_after_update) => {
|
||||
log::info!(
|
||||
"Successfully updated Wayfern profile {} from version {} to {}",
|
||||
profile.name,
|
||||
profile.version,
|
||||
pending_update.new_version
|
||||
);
|
||||
updated_profile = updated_profile_after_update;
|
||||
|
||||
if let Err(e) = self
|
||||
.auto_updater
|
||||
.dismiss_update_notification(&pending_update.id)
|
||||
{
|
||||
log::warn!("Warning: Failed to dismiss pending update notification: {e}");
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!(
|
||||
"Failed to apply pending update for Wayfern profile {}: {}",
|
||||
profile.name,
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self
|
||||
.save_process_info(&updated_profile)
|
||||
.map_err(|e| format!("Failed to update profile: {e}"))?;
|
||||
|
||||
log::info!(
|
||||
"Emitting profile events for successful Wayfern kill: {}",
|
||||
updated_profile.name
|
||||
);
|
||||
|
||||
// Emit profile update event to frontend
|
||||
if let Err(e) = app_handle.emit("profile-updated", &updated_profile) {
|
||||
log::warn!("Warning: Failed to emit profile update event: {e}");
|
||||
}
|
||||
|
||||
// Emit minimal running changed event
|
||||
#[derive(Serialize)]
|
||||
struct RunningChangedPayload {
|
||||
id: String,
|
||||
is_running: bool,
|
||||
}
|
||||
let payload = RunningChangedPayload {
|
||||
id: updated_profile.id.to_string(),
|
||||
is_running: false,
|
||||
};
|
||||
|
||||
if let Err(e) = app_handle.emit("profile-running-changed", &payload) {
|
||||
log::warn!("Warning: Failed to emit profile running changed event: {e}");
|
||||
} else {
|
||||
log::info!(
|
||||
"Successfully emitted profile-running-changed event for Wayfern {}: running={}",
|
||||
updated_profile.name,
|
||||
payload.is_running
|
||||
);
|
||||
}
|
||||
|
||||
log::info!(
|
||||
"Wayfern process cleanup completed for profile: {} (ID: {})",
|
||||
profile.name,
|
||||
profile.id
|
||||
);
|
||||
|
||||
// Consolidate browser versions after stopping a browser
|
||||
if let Ok(consolidated) = self
|
||||
.downloaded_browsers_registry
|
||||
.consolidate_browser_versions(&app_handle)
|
||||
{
|
||||
if !consolidated.is_empty() {
|
||||
log::info!("Post-stop version consolidation results:");
|
||||
for action in &consolidated {
|
||||
log::info!(" {action}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// For non-camoufox/wayfern browsers, use the existing logic
|
||||
let pid = if let Some(pid) = profile.process_id {
|
||||
// First verify the stored PID is still valid and belongs to our profile
|
||||
let system = System::new_all();
|
||||
@@ -1832,9 +2383,9 @@ pub async fn launch_browser_profile(
|
||||
profile_for_launch.id
|
||||
);
|
||||
|
||||
// Always start a local proxy before launching (non-Camoufox handled here; Camoufox has its own flow)
|
||||
// Always start a local proxy before launching (non-Camoufox/Wayfern handled here; they have their own flow)
|
||||
// This ensures all traffic goes through the local proxy for monitoring and future features
|
||||
if profile.browser != "camoufox" {
|
||||
if profile.browser != "camoufox" && profile.browser != "wayfern" {
|
||||
// Determine upstream proxy if configured; otherwise use DIRECT (no upstream)
|
||||
let upstream_proxy = profile_for_launch
|
||||
.proxy_id
|
||||
|
||||
Reference in New Issue
Block a user