mirror of
https://github.com/bitwarden/browser
synced 2025-12-14 15:23:33 +00:00
PM-19424: React to IPC disconnect (#14123)
* React to IPC disconnects * Minor cleanup * Update apps/desktop/package.json Co-authored-by: Daniel García <dani-garcia@users.noreply.github.com> * Relaxed ordering --------- Co-authored-by: Daniel García <dani-garcia@users.noreply.github.com>
This commit is contained in:
@@ -49,6 +49,12 @@ trait Callback: Send + Sync {
|
||||
fn error(&self, error: BitwardenError);
|
||||
}
|
||||
|
||||
#[derive(uniffi::Enum, Debug)]
|
||||
pub enum ConnectionStatus {
|
||||
Connected,
|
||||
Disconnected,
|
||||
}
|
||||
|
||||
#[derive(uniffi::Object)]
|
||||
pub struct MacOSProviderClient {
|
||||
to_server_send: tokio::sync::mpsc::Sender<String>,
|
||||
@@ -57,6 +63,9 @@ pub struct MacOSProviderClient {
|
||||
response_callbacks_counter: AtomicU32,
|
||||
#[allow(clippy::type_complexity)]
|
||||
response_callbacks_queue: Arc<Mutex<HashMap<u32, (Box<dyn Callback>, Instant)>>>,
|
||||
|
||||
// Flag to track connection status - atomic for thread safety without locks
|
||||
connection_status: Arc<std::sync::atomic::AtomicBool>,
|
||||
}
|
||||
|
||||
#[uniffi::export]
|
||||
@@ -74,11 +83,13 @@ impl MacOSProviderClient {
|
||||
to_server_send,
|
||||
response_callbacks_counter: AtomicU32::new(0),
|
||||
response_callbacks_queue: Arc::new(Mutex::new(HashMap::new())),
|
||||
connection_status: Arc::new(std::sync::atomic::AtomicBool::new(false)),
|
||||
};
|
||||
|
||||
let path = desktop_core::ipc::path("autofill");
|
||||
|
||||
let queue = client.response_callbacks_queue.clone();
|
||||
let connection_status = client.connection_status.clone();
|
||||
|
||||
std::thread::spawn(move || {
|
||||
let rt = tokio::runtime::Builder::new_current_thread()
|
||||
@@ -96,9 +107,11 @@ impl MacOSProviderClient {
|
||||
match serde_json::from_str::<SerializedMessage>(&message) {
|
||||
Ok(SerializedMessage::Command(CommandMessage::Connected)) => {
|
||||
info!("Connected to server");
|
||||
connection_status.store(true, std::sync::atomic::Ordering::Relaxed);
|
||||
}
|
||||
Ok(SerializedMessage::Command(CommandMessage::Disconnected)) => {
|
||||
info!("Disconnected from server");
|
||||
connection_status.store(false, std::sync::atomic::Ordering::Relaxed);
|
||||
}
|
||||
Ok(SerializedMessage::Message {
|
||||
sequence_number,
|
||||
@@ -159,6 +172,17 @@ impl MacOSProviderClient {
|
||||
) {
|
||||
self.send_message(request, Box::new(callback));
|
||||
}
|
||||
|
||||
pub fn get_connection_status(&self) -> ConnectionStatus {
|
||||
let is_connected = self
|
||||
.connection_status
|
||||
.load(std::sync::atomic::Ordering::Relaxed);
|
||||
if is_connected {
|
||||
ConnectionStatus::Connected
|
||||
} else {
|
||||
ConnectionStatus::Disconnected
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
|
||||
@@ -62,12 +62,56 @@ class CredentialProviderViewController: ASCredentialProviderViewController {
|
||||
return MacOsProviderClient.connect()
|
||||
}()
|
||||
|
||||
// Timer for checking connection status
|
||||
private var connectionMonitorTimer: Timer?
|
||||
private var lastConnectionStatus: ConnectionStatus = .disconnected
|
||||
|
||||
// Setup the connection monitoring timer
|
||||
private func setupConnectionMonitoring() {
|
||||
// Check connection status every 1 second
|
||||
connectionMonitorTimer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { [weak self] _ in
|
||||
self?.checkConnectionStatus()
|
||||
}
|
||||
|
||||
// Make sure timer runs even when UI is busy
|
||||
RunLoop.current.add(connectionMonitorTimer!, forMode: .common)
|
||||
|
||||
// Initial check
|
||||
checkConnectionStatus()
|
||||
}
|
||||
|
||||
// Check the connection status by calling into Rust
|
||||
private func checkConnectionStatus() {
|
||||
// Get the current connection status from Rust
|
||||
let currentStatus = client.getConnectionStatus()
|
||||
|
||||
// Only post notification if state changed
|
||||
if currentStatus != lastConnectionStatus {
|
||||
if(currentStatus == .connected) {
|
||||
logger.log("[autofill-extension] Connection status changed: Connected")
|
||||
} else {
|
||||
logger.log("[autofill-extension] Connection status changed: Disconnected")
|
||||
}
|
||||
|
||||
// Save the new status
|
||||
lastConnectionStatus = currentStatus
|
||||
|
||||
// If we just disconnected, try to cancel the request
|
||||
if currentStatus == .disconnected {
|
||||
self.extensionContext.cancelRequest(withError: BitwardenError.Internal("Bitwarden desktop app disconnected"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
init() {
|
||||
logger = Logger(subsystem: "com.bitwarden.desktop.autofill-extension", category: "credential-provider")
|
||||
|
||||
logger.log("[autofill-extension] initializing extension")
|
||||
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
|
||||
// Setup connection monitoring now that self is available
|
||||
setupConnectionMonitoring()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
@@ -76,6 +120,10 @@ class CredentialProviderViewController: ASCredentialProviderViewController {
|
||||
|
||||
deinit {
|
||||
logger.log("[autofill-extension] deinitializing extension")
|
||||
|
||||
// Stop the connection monitor timer
|
||||
connectionMonitorTimer?.invalidate()
|
||||
connectionMonitorTimer = nil
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
"scripts": {
|
||||
"postinstall": "electron-rebuild",
|
||||
"start": "cross-env ELECTRON_IS_DEV=0 ELECTRON_NO_UPDATER=1 electron ./build",
|
||||
"build-native-macos": "cd desktop_native && ./macos_provider/build.sh && node build.js cross-platform",
|
||||
"build-native": "cd desktop_native && node build.js",
|
||||
"build": "cross-env NODE_OPTIONS=\"--max-old-space-size=8192\" concurrently -n Main,Rend,Prel -c yellow,cyan \"npm run build:main\" \"npm run build:renderer\" \"npm run build:preload\"",
|
||||
"build:dev": "concurrently -n Main,Rend -c yellow,cyan \"npm run build:main:dev\" \"npm run build:renderer:dev\"",
|
||||
|
||||
Reference in New Issue
Block a user