1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-11 14:04:03 +00:00

fix: TS code after napi changes

This commit is contained in:
Andreas Coroiu
2025-10-01 13:22:46 +02:00
parent c6f2289c5b
commit 6b06b4e3ad
6 changed files with 306 additions and 293 deletions

View File

@@ -1,142 +1,46 @@
/* tslint:disable */
/* eslint-disable */
/* auto-generated by NAPI-RS */
export declare namespace passwords {
/** The error message returned when a password is not found during retrieval or deletion. */
export const PASSWORD_NOT_FOUND: string
/**
* Fetch the stored password from the keychain.
* Throws {@link Error} with message {@link PASSWORD_NOT_FOUND} if the password does not exist.
*/
export function getPassword(service: string, account: string): Promise<string>
/** Save the password to the keychain. Adds an entry if none exists otherwise updates the existing entry. */
export function setPassword(service: string, account: string, password: string): Promise<void>
/**
* Delete the stored password from the keychain.
* Throws {@link Error} with message {@link PASSWORD_NOT_FOUND} if the password does not exist.
*/
export function deletePassword(service: string, account: string): Promise<void>
/** Checks if the os secure storage is available */
export function isAvailable(): Promise<boolean>
}
export declare namespace biometrics {
export function prompt(hwnd: Buffer, message: string): Promise<boolean>
export function available(): Promise<boolean>
export function setBiometricSecret(service: string, account: string, secret: string, keyMaterial: KeyMaterial | undefined | null, ivB64: string): Promise<string>
/**
* Retrieves the biometric secret for the given service and account.
* Throws Error with message [`passwords::PASSWORD_NOT_FOUND`] if the secret does not exist.
*/
export function getBiometricSecret(service: string, account: string, keyMaterial?: KeyMaterial | undefined | null): Promise<string>
/**
* Derives key material from biometric data. Returns a string encoded with a
* base64 encoded key and the base64 encoded challenge used to create it
* separated by a `|` character.
*
* If the iv is provided, it will be used as the challenge. Otherwise a random challenge will be generated.
*
* `format!("<key_base64>|<iv_base64>")`
*/
export function deriveKeyMaterial(iv?: string | undefined | null): Promise<OsDerivedKey>
export interface KeyMaterial {
osKeyPartB64: string
clientKeyPartB64?: string
}
export interface OsDerivedKey {
keyB64: string
ivB64: string
}
}
export declare namespace clipboards {
export function read(): Promise<string>
export function write(text: string, password: boolean): Promise<void>
}
export declare namespace sshagent {
export interface PrivateKey {
privateKey: string
name: string
cipherId: string
}
export interface SshKey {
privateKey: string
publicKey: string
keyFingerprint: string
}
export interface SshUiRequest {
cipherId?: string
isList: boolean
processName: string
isForwarding: boolean
namespace?: string
}
export function serve(callback: (err: Error | null, arg: SshUiRequest) => any): Promise<SshAgentState>
export function stop(agentState: SshAgentState): void
export function isRunning(agentState: SshAgentState): boolean
export function setKeys(agentState: SshAgentState, newKeys: Array<PrivateKey>): void
export function lock(agentState: SshAgentState): void
export function clearKeys(agentState: SshAgentState): void
export class SshAgentState { }
}
export declare namespace processisolations {
export function disableCoredumps(): Promise<void>
export function isCoreDumpingDisabled(): Promise<boolean>
export function isolateProcess(): Promise<void>
}
export declare namespace powermonitors {
export function onLock(callback: (err: Error | null, ) => any): Promise<void>
export function isLockMonitorAvailable(): Promise<boolean>
}
export declare namespace windows_registry {
export function createKey(key: string, subkey: string, value: string): Promise<void>
export function deleteKey(key: string, subkey: string): Promise<void>
}
export declare namespace ipc {
export interface IpcMessage {
clientId: number
kind: IpcMessageType
message?: string
}
export const enum IpcMessageType {
Connected = 0,
Disconnected = 1,
Message = 2
}
export class IpcServer {
/* eslint-disable */
export declare namespace autofill {
export class AutofillIpcServer {
/**
* Create and start the IPC server without blocking.
*
* @param name The endpoint name to listen on. This name uniquely identifies the IPC connection and must be the same for both the server and client.
* @param callback This function will be called whenever a message is received from a client.
*/
static listen(name: string, callback: (error: null | Error, message: IpcMessage) => void): Promise<IpcServer>
static listen(name: string, registrationCallback: (error: null | Error, clientId: number, sequenceNumber: number, message: PasskeyRegistrationRequest) => void, assertionCallback: (error: null | Error, clientId: number, sequenceNumber: number, message: PasskeyAssertionRequest) => void, assertionWithoutUserInterfaceCallback: (error: null | Error, clientId: number, sequenceNumber: number, message: PasskeyAssertionWithoutUserInterfaceRequest) => void): Promise<AutofillIpcServer>
/** Return the path to the IPC server. */
getPath(): string
/** Stop the IPC server. */
stop(): void
/**
* Send a message over the IPC server to all the connected clients
*
* @return The number of clients that the message was sent to. Note that the number of messages
* actually received may be less, as some clients could disconnect before receiving the message.
*/
send(message: string): number
completeRegistration(clientId: number, sequenceNumber: number, response: PasskeyRegistrationResponse): number
completeAssertion(clientId: number, sequenceNumber: number, response: PasskeyAssertionResponse): number
completeError(clientId: number, sequenceNumber: number, error: string): number
}
}
export declare namespace autostart {
export function setAutostart(autostart: boolean, params: Array<string>): Promise<void>
}
export declare namespace autofill {
export function runCommand(value: string): Promise<string>
export const enum UserVerification {
Preferred = 'preferred',
Required = 'required',
Discouraged = 'discouraged'
export interface PasskeyAssertionRequest {
rpId: string
clientDataHash: Array<number>
userVerification: UserVerification
allowedCredentials: Array<Array<number>>
windowXy: Position
}
export interface Position {
x: number
y: number
export interface PasskeyAssertionResponse {
rpId: string
userHandle: Array<number>
signature: Array<number>
clientDataHash: Array<number>
authenticatorData: Array<number>
credentialId: Array<number>
}
export interface PasskeyAssertionWithoutUserInterfaceRequest {
rpId: string
credentialId: Array<number>
userName: string
userHandle: Array<number>
recordIdentifier?: string
clientDataHash: Array<number>
userVerification: UserVerification
windowXy: Position
}
export interface PasskeyRegistrationRequest {
rpId: string
@@ -153,66 +57,60 @@ export declare namespace autofill {
credentialId: Array<number>
attestationObject: Array<number>
}
export interface PasskeyAssertionRequest {
rpId: string
clientDataHash: Array<number>
userVerification: UserVerification
allowedCredentials: Array<Array<number>>
windowXy: Position
export interface Position {
x: number
y: number
}
export interface PasskeyAssertionWithoutUserInterfaceRequest {
rpId: string
credentialId: Array<number>
userName: string
userHandle: Array<number>
recordIdentifier?: string
clientDataHash: Array<number>
userVerification: UserVerification
windowXy: Position
}
export interface PasskeyAssertionResponse {
rpId: string
userHandle: Array<number>
signature: Array<number>
clientDataHash: Array<number>
authenticatorData: Array<number>
credentialId: Array<number>
}
export class IpcServer {
/**
* Create and start the IPC server without blocking.
*
* @param name The endpoint name to listen on. This name uniquely identifies the IPC connection and must be the same for both the server and client.
* @param callback This function will be called whenever a message is received from a client.
*/
static listen(name: string, registrationCallback: (error: null | Error, clientId: number, sequenceNumber: number, message: PasskeyRegistrationRequest) => void, assertionCallback: (error: null | Error, clientId: number, sequenceNumber: number, message: PasskeyAssertionRequest) => void, assertionWithoutUserInterfaceCallback: (error: null | Error, clientId: number, sequenceNumber: number, message: PasskeyAssertionWithoutUserInterfaceRequest) => void): Promise<IpcServer>
/** Return the path to the IPC server. */
getPath(): string
/** Stop the IPC server. */
stop(): void
completeRegistration(clientId: number, sequenceNumber: number, response: PasskeyRegistrationResponse): number
completeAssertion(clientId: number, sequenceNumber: number, response: PasskeyAssertionResponse): number
completeError(clientId: number, sequenceNumber: number, error: string): number
export function runCommand(value: string): Promise<string>
export const enum UserVerification {
Preferred = 'preferred',
Required = 'required',
Discouraged = 'discouraged'
}
}
export declare namespace passkey_authenticator {
export function register(): void
export declare namespace autostart {
export function setAutostart(autostart: boolean, params: Array<string>): Promise<void>
}
export declare namespace logging {
export const enum LogLevel {
Trace = 0,
Debug = 1,
Info = 2,
Warn = 3,
Error = 4
export declare namespace autotype {
export function getForegroundWindowTitle(): string
export function typeInput(input: Array<number>): void
}
export declare namespace biometrics {
export function available(): Promise<boolean>
/**
* Derives key material from biometric data. Returns a string encoded with a
* base64 encoded key and the base64 encoded challenge used to create it
* separated by a `|` character.
*
* If the iv is provided, it will be used as the challenge. Otherwise a random challenge will be generated.
*
* `format!("<key_base64>|<iv_base64>")`
*/
export function deriveKeyMaterial(iv?: string | undefined | null): Promise<OsDerivedKey>
/**
* Retrieves the biometric secret for the given service and account.
* Throws Error with message [`passwords::PASSWORD_NOT_FOUND`] if the secret does not exist.
*/
export function getBiometricSecret(service: string, account: string, keyMaterial?: KeyMaterial | undefined | null): Promise<string>
export interface KeyMaterial {
osKeyPartB64: string
clientKeyPartB64?: string
}
export function initNapiLog(jsLogFn: (err: Error | null, arg0: LogLevel, arg1: string) => any): void
export interface OsDerivedKey {
keyB64: string
ivB64: string
}
export function prompt(hwnd: Buffer, message: string): Promise<boolean>
export function setBiometricSecret(service: string, account: string, secret: string, keyMaterial: KeyMaterial | undefined | null, ivB64: string): Promise<string>
}
export declare namespace chromium_importer {
export interface ProfileInfo {
id: string
name: string
}
export function getAvailableProfiles(browser: string): Array<ProfileInfo>
export function getInstalledBrowsers(): Array<string>
export function importLogins(browser: string, profileId: string): Promise<Array<LoginImportResult>>
export interface Login {
url: string
username: string
@@ -228,11 +126,125 @@ export declare namespace chromium_importer {
login?: Login
failure?: LoginImportFailure
}
export function getInstalledBrowsers(): Array<string>
export function getAvailableProfiles(browser: string): Array<ProfileInfo>
export function importLogins(browser: string, profileId: string): Promise<Array<LoginImportResult>>
export interface ProfileInfo {
id: string
name: string
}
}
export declare namespace autotype {
export function getForegroundWindowTitle(): string
export function typeInput(input: Array<number>): void
export declare namespace clipboards {
export function read(): Promise<string>
export function write(text: string, password: boolean): Promise<void>
}
export declare namespace ipc {
export class NativeIpcServer {
/**
* Create and start the IPC server without blocking.
*
* @param name The endpoint name to listen on. This name uniquely identifies the IPC connection and must be the same for both the server and client.
* @param callback This function will be called whenever a message is received from a client.
*/
static listen(name: string, callback: (error: null | Error, message: IpcMessage) => void): Promise<NativeIpcServer>
/** Return the path to the IPC server. */
getPath(): string
/** Stop the IPC server. */
stop(): void
/**
* Send a message over the IPC server to all the connected clients
*
* @return The number of clients that the message was sent to. Note that the number of messages
* actually received may be less, as some clients could disconnect before receiving the message.
*/
send(message: string): number
}
export interface IpcMessage {
clientId: number
kind: IpcMessageType
message?: string
}
export const enum IpcMessageType {
Connected = 0,
Disconnected = 1,
Message = 2
}
}
export declare namespace logging {
export function initNapiLog(jsLogFn: ((err: Error | null, arg0: LogLevel, arg1: string) => any)): void
export const enum LogLevel {
Trace = 0,
Debug = 1,
Info = 2,
Warn = 3,
Error = 4
}
}
export declare namespace passkey_authenticator {
export function register(): void
}
export declare namespace passwords {
/**
* Delete the stored password from the keychain.
* Throws {@link Error} with message {@link PASSWORD_NOT_FOUND} if the password does not exist.
*/
export function deletePassword(service: string, account: string): Promise<void>
/**
* Fetch the stored password from the keychain.
* Throws {@link Error} with message {@link PASSWORD_NOT_FOUND} if the password does not exist.
*/
export function getPassword(service: string, account: string): Promise<string>
/** Checks if the os secure storage is available */
export function isAvailable(): Promise<boolean>
/** The error message returned when a password is not found during retrieval or deletion. */
export const PASSWORD_NOT_FOUND: string
/** Save the password to the keychain. Adds an entry if none exists otherwise updates the existing entry. */
export function setPassword(service: string, account: string, password: string): Promise<void>
}
export declare namespace powermonitors {
export function isLockMonitorAvailable(): Promise<boolean>
export function onLock(callback: ((err: Error | null, ) => any)): Promise<void>
}
export declare namespace processisolations {
export function disableCoredumps(): Promise<void>
export function isCoreDumpingDisabled(): Promise<boolean>
export function isolateProcess(): Promise<void>
}
export declare namespace sshagent {
export class SshAgentState {
}
export function clearKeys(agentState: SshAgentState): void
export function isRunning(agentState: SshAgentState): boolean
export function lock(agentState: SshAgentState): void
export interface PrivateKey {
privateKey: string
name: string
cipherId: string
}
export function serve(callback: ((err: Error | null, arg: SshUiRequest) => Promise<boolean>)): Promise<SshAgentState>
export function setKeys(agentState: SshAgentState, newKeys: Array<PrivateKey>): void
export interface SshKey {
privateKey: string
publicKey: string
keyFingerprint: string
}
export interface SshUiRequest {
cipherId?: string
isList: boolean
processName: string
isForwarding: boolean
namespace?: string
}
export function stop(agentState: SshAgentState): void
}
export declare namespace windows_registry {
export function createKey(key: string, subkey: string, value: string): Promise<void>
export function deleteKey(key: string, subkey: string): Promise<void>
}

View File

@@ -3,7 +3,7 @@
"version": "0.1.0",
"description": "",
"scripts": {
"build": "napi build --platform --js false",
"build": "napi build --platform --no-js",
"test": "cargo test"
},
"author": "",

View File

@@ -170,10 +170,8 @@ pub mod sshagent {
use std::sync::Arc;
use desktop_core::ssh_agent::BitwardenSshKey;
use napi::{
bindgen_prelude::Promise,
threadsafe_function::{ErrorStrategy::CalleeHandled, ThreadsafeFunction},
};
use napi::bindgen_prelude::Promise;
use napi::threadsafe_function::{ThreadsafeFunction, ThreadsafeFunctionCallMode};
use tokio::{self, sync::Mutex};
use tracing::error;
@@ -208,13 +206,15 @@ pub mod sshagent {
#[allow(clippy::unused_async)] // FIXME: Remove unused async!
#[napi]
pub async fn serve(
callback: ThreadsafeFunction<SshUIRequest, CalleeHandled>,
callback: ThreadsafeFunction<SshUIRequest, Promise<bool>>,
) -> napi::Result<SshAgentState> {
let (auth_request_tx, mut auth_request_rx) =
tokio::sync::mpsc::channel::<desktop_core::ssh_agent::SshAgentUIRequest>(32);
let (auth_response_tx, auth_response_rx) =
tokio::sync::broadcast::channel::<(u32, bool)>(32);
let auth_response_tx_arc = Arc::new(Mutex::new(auth_response_tx));
// Wrap callback in Arc so it can be shared across spawned tasks
let callback = Arc::new(callback);
tokio::spawn(async move {
let _ = auth_response_rx;
@@ -224,42 +224,49 @@ pub mod sshagent {
tokio::spawn(async move {
let auth_response_tx_arc = cloned_response_tx_arc;
let callback = cloned_callback;
let promise_result: Result<Promise<bool>, napi::Error> = callback
.call_async(Ok(SshUIRequest {
// In NAPI v3, obtain the JS callback return as a Promise<boolean> and await it in Rust
let (tx, rx) = std::sync::mpsc::channel::<Promise<bool>>();
let status = callback.call_with_return_value(
Ok(SshUIRequest {
cipher_id: request.cipher_id,
is_list: request.is_list,
process_name: request.process_name,
is_forwarding: request.is_forwarding,
namespace: request.namespace,
}))
.await;
match promise_result {
Ok(promise_result) => match promise_result.await {
Ok(result) => {
let _ = auth_response_tx_arc
.lock()
.await
.send((request.request_id, result))
.expect("should be able to send auth response to agent");
}
Err(e) => {
error!(error = %e, "Calling UI callback promise was rejected");
let _ = auth_response_tx_arc
.lock()
.await
.send((request.request_id, false))
.expect("should be able to send auth response to agent");
}),
ThreadsafeFunctionCallMode::Blocking,
move |ret: Result<Promise<bool>, napi::Error>, _env| {
if let Ok(p) = ret {
let _ = tx.send(p);
}
Ok(())
},
Err(e) => {
error!(error = %e, "Calling UI callback could not create promise");
let _ = auth_response_tx_arc
.lock()
.await
.send((request.request_id, false))
.expect("should be able to send auth response to agent");
);
let result = if status == napi::Status::Ok {
match rx.recv() {
Ok(promise) => match promise.await {
Ok(v) => v,
Err(e) => {
error!(error = %e, "UI callback promise rejected");
false
}
},
Err(e) => {
error!(error = %e, "Failed to receive UI callback promise");
false
}
}
}
} else {
error!(error = ?status, "Calling UI callback failed");
false
};
let _ = auth_response_tx_arc
.lock()
.await
.send((request.request_id, result))
.expect("should be able to send auth response to agent");
});
}
});
@@ -347,14 +354,12 @@ pub mod processisolations {
#[napi]
pub mod powermonitors {
use napi::{
threadsafe_function::{
ErrorStrategy::CalleeHandled, ThreadsafeFunction, ThreadsafeFunctionCallMode,
},
threadsafe_function::{ThreadsafeFunction, ThreadsafeFunctionCallMode},
tokio,
};
#[napi]
pub async fn on_lock(callback: ThreadsafeFunction<(), CalleeHandled>) -> napi::Result<()> {
pub async fn on_lock(callback: ThreadsafeFunction<()>) -> napi::Result<()> {
let (tx, mut rx) = tokio::sync::mpsc::channel::<()>(32);
desktop_core::powermonitor::on_lock(tx)
.await
@@ -393,9 +398,7 @@ pub mod windows_registry {
#[napi]
pub mod ipc {
use desktop_core::ipc::server::{Message, MessageType};
use napi::threadsafe_function::{
ErrorStrategy, ThreadsafeFunction, ThreadsafeFunctionCallMode,
};
use napi::threadsafe_function::{ThreadsafeFunction, ThreadsafeFunctionCallMode};
#[napi(object)]
pub struct IpcMessage {
@@ -432,12 +435,12 @@ pub mod ipc {
}
#[napi]
pub struct IpcServer {
pub struct NativeIpcServer {
server: desktop_core::ipc::server::Server,
}
#[napi]
impl IpcServer {
impl NativeIpcServer {
/// Create and start the IPC server without blocking.
///
/// @param name The endpoint name to listen on. This name uniquely identifies the IPC connection and must be the same for both the server and client.
@@ -447,7 +450,7 @@ pub mod ipc {
pub async fn listen(
name: String,
#[napi(ts_arg_type = "(error: null | Error, message: IpcMessage) => void")]
callback: ThreadsafeFunction<IpcMessage, ErrorStrategy::CalleeHandled>,
callback: ThreadsafeFunction<IpcMessage>,
) -> napi::Result<Self> {
let (send, mut recv) = tokio::sync::mpsc::channel::<Message>(32);
tokio::spawn(async move {
@@ -464,7 +467,7 @@ pub mod ipc {
))
})?;
Ok(IpcServer { server })
Ok(NativeIpcServer { server })
}
/// Return the path to the IPC server.
@@ -510,9 +513,7 @@ pub mod autostart {
#[napi]
pub mod autofill {
use desktop_core::ipc::server::{Message, MessageType};
use napi::threadsafe_function::{
ErrorStrategy, ThreadsafeFunction, ThreadsafeFunctionCallMode,
};
use napi::threadsafe_function::{ThreadsafeFunction, ThreadsafeFunctionCallMode};
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use tracing::error;
@@ -617,14 +618,14 @@ pub mod autofill {
}
#[napi]
pub struct IpcServer {
pub struct AutofillIpcServer {
server: desktop_core::ipc::server::Server,
}
// FIXME: Remove unwraps! They panic and terminate the whole application.
#[allow(clippy::unwrap_used)]
#[napi]
impl IpcServer {
impl AutofillIpcServer {
/// Create and start the IPC server without blocking.
///
/// @param name The endpoint name to listen on. This name uniquely identifies the IPC connection and must be the same for both the server and client.
@@ -638,25 +639,24 @@ pub mod autofill {
#[napi(
ts_arg_type = "(error: null | Error, clientId: number, sequenceNumber: number, message: PasskeyRegistrationRequest) => void"
)]
registration_callback: ThreadsafeFunction<
(u32, u32, PasskeyRegistrationRequest),
ErrorStrategy::CalleeHandled,
>,
registration_callback: ThreadsafeFunction<(
u32,
u32,
PasskeyRegistrationRequest,
)>,
#[napi(
ts_arg_type = "(error: null | Error, clientId: number, sequenceNumber: number, message: PasskeyAssertionRequest) => void"
)]
assertion_callback: ThreadsafeFunction<
(u32, u32, PasskeyAssertionRequest),
ErrorStrategy::CalleeHandled,
>,
assertion_callback: ThreadsafeFunction<(u32, u32, PasskeyAssertionRequest)>,
#[napi(
ts_arg_type = "(error: null | Error, clientId: number, sequenceNumber: number, message: PasskeyAssertionWithoutUserInterfaceRequest) => void"
)]
assertion_without_user_interface_callback: ThreadsafeFunction<
(u32, u32, PasskeyAssertionWithoutUserInterfaceRequest),
ErrorStrategy::CalleeHandled,
>,
) -> napi::Result<Self> {
assertion_without_user_interface_callback: ThreadsafeFunction<(
u32,
u32,
PasskeyAssertionWithoutUserInterfaceRequest,
)>,
) -> napi::Result<Self> {
let (send, mut recv) = tokio::sync::mpsc::channel::<Message>(32);
tokio::spawn(async move {
while let Some(Message {
@@ -742,7 +742,7 @@ pub mod autofill {
))
})?;
Ok(IpcServer { server })
Ok(AutofillIpcServer { server })
}
/// Return the path to the IPC server.
@@ -835,9 +835,7 @@ pub mod logging {
use std::fmt::Write;
use std::sync::OnceLock;
use napi::threadsafe_function::{
ErrorStrategy::CalleeHandled, ThreadsafeFunction, ThreadsafeFunctionCallMode,
};
use napi::threadsafe_function::{ThreadsafeFunction, ThreadsafeFunctionCallMode};
use tracing::Level;
use tracing_subscriber::fmt::format::{DefaultVisitor, Writer};
use tracing_subscriber::{
@@ -847,7 +845,7 @@ pub mod logging {
Layer,
};
struct JsLogger(OnceLock<ThreadsafeFunction<(LogLevel, String), CalleeHandled>>);
struct JsLogger(OnceLock<ThreadsafeFunction<(LogLevel, String)>>);
static JS_LOGGER: JsLogger = JsLogger(OnceLock::new());
#[napi]
@@ -925,7 +923,7 @@ pub mod logging {
}
#[napi]
pub fn init_napi_log(js_log_fn: ThreadsafeFunction<(LogLevel, String), CalleeHandled>) {
pub fn init_napi_log(js_log_fn: ThreadsafeFunction<(LogLevel, String)>) {
let _ = JS_LOGGER.0.set(js_log_fn);
let filter = EnvFilter::builder()
@@ -1035,7 +1033,7 @@ pub mod chromium_importer {
#[napi]
pub mod autotype {
#[napi]
pub fn get_foreground_window_title() -> napi::Result<String, napi::Status> {
pub fn get_foreground_window_title() -> napi::Result<String> {
autotype::get_foreground_window_title().map_err(|_| {
napi::Error::from_reason(
"Autotype Error: failed to get foreground window title".to_string(),
@@ -1044,7 +1042,7 @@ pub mod autotype {
}
#[napi]
pub fn type_input(input: Vec<u16>) -> napi::Result<(), napi::Status> {
pub fn type_input(input: Vec<u16>) -> napi::Result<()> {
autotype::type_input(input).map_err(|_| {
napi::Error::from_reason("Autotype Error: failed to type input".to_string())
})

View File

@@ -37,7 +37,7 @@ export class MainSshAgentService {
init() {
// handle sign request passing to UI
sshagent
.serve(async (err: Error, sshUiRequest: sshagent.SshUiRequest) => {
.serve(async (err: Error | null, sshUiRequest: sshagent.SshUiRequest): Promise<boolean> => {
// clear all old (> SIGN_TIMEOUT) requests
this.requestResponses = this.requestResponses.filter(
(response) => response.timestamp > new Date(Date.now() - this.SIGN_TIMEOUT),

View File

@@ -14,7 +14,7 @@ import { isDev } from "../utils";
import { WindowMain } from "./window.main";
export class NativeMessagingMain {
private ipcServer: ipc.IpcServer | null;
private ipcServer: ipc.NativeIpcServer | null;
private connected: number[] = [];
constructor(
@@ -78,37 +78,40 @@ export class NativeMessagingMain {
this.ipcServer.stop();
}
this.ipcServer = await ipc.IpcServer.listen("bitwarden", (error, msg) => {
switch (msg.kind) {
case ipc.IpcMessageType.Connected: {
this.connected.push(msg.clientId);
this.logService.info("Native messaging client " + msg.clientId + " has connected");
break;
}
case ipc.IpcMessageType.Disconnected: {
const index = this.connected.indexOf(msg.clientId);
if (index > -1) {
this.connected.splice(index, 1);
this.ipcServer = await ipc.NativeIpcServer.listen(
"bitwarden",
(error: Error | null, msg: ipc.IpcMessage) => {
switch (msg.kind) {
case ipc.IpcMessageType.Connected: {
this.connected.push(msg.clientId);
this.logService.info("Native messaging client " + msg.clientId + " has connected");
break;
}
case ipc.IpcMessageType.Disconnected: {
const index = this.connected.indexOf(msg.clientId);
if (index > -1) {
this.connected.splice(index, 1);
}
this.logService.info("Native messaging client " + msg.clientId + " has disconnected");
break;
}
case ipc.IpcMessageType.Message:
try {
const msgJson = JSON.parse(msg.message);
this.logService.debug("Native messaging message:", msgJson);
this.windowMain.win?.webContents.send("nativeMessaging", msgJson);
} catch (e) {
this.logService.warning("Error processing message:", e, msg.message);
this.logService.info("Native messaging client " + msg.clientId + " has disconnected");
break;
}
break;
case ipc.IpcMessageType.Message:
try {
const msgJson = JSON.parse(msg.message);
this.logService.debug("Native messaging message:", msgJson);
this.windowMain.win?.webContents.send("nativeMessaging", msgJson);
} catch (e) {
this.logService.warning("Error processing message:", e, msg.message);
}
break;
default:
this.logService.warning("Unknown message type:", msg.kind, msg.message);
break;
}
});
default:
this.logService.warning("Unknown message type:", msg.kind, msg.message);
break;
}
},
);
this.logService.info("Native messaging server started at:", this.ipcServer.getPath());

View File

@@ -16,7 +16,7 @@ export type RunCommandParams<C extends CommandDefinition> = {
export type RunCommandResult<C extends CommandDefinition> = C["output"];
export class NativeAutofillMain {
private ipcServer: autofill.IpcServer | null;
private ipcServer?: autofill.AutofillIpcServer;
constructor(
private logService: LogService,
@@ -34,13 +34,13 @@ export class NativeAutofillMain {
},
);
this.ipcServer = await autofill.IpcServer.listen(
this.ipcServer = await autofill.AutofillIpcServer.listen(
"autofill",
// RegistrationCallback
(error, clientId, sequenceNumber, request) => {
if (error) {
this.logService.error("autofill.IpcServer.registration", error);
this.ipcServer.completeError(clientId, sequenceNumber, String(error));
this.ipcServer?.completeError(clientId, sequenceNumber, String(error));
return;
}
this.windowMain.win.webContents.send("autofill.passkeyRegistration", {
@@ -53,7 +53,7 @@ export class NativeAutofillMain {
(error, clientId, sequenceNumber, request) => {
if (error) {
this.logService.error("autofill.IpcServer.assertion", error);
this.ipcServer.completeError(clientId, sequenceNumber, String(error));
this.ipcServer?.completeError(clientId, sequenceNumber, String(error));
return;
}
this.windowMain.win.webContents.send("autofill.passkeyAssertion", {
@@ -66,7 +66,7 @@ export class NativeAutofillMain {
(error, clientId, sequenceNumber, request) => {
if (error) {
this.logService.error("autofill.IpcServer.assertion", error);
this.ipcServer.completeError(clientId, sequenceNumber, String(error));
this.ipcServer?.completeError(clientId, sequenceNumber, String(error));
return;
}
this.windowMain.win.webContents.send("autofill.passkeyAssertionWithoutUserInterface", {
@@ -80,19 +80,19 @@ export class NativeAutofillMain {
ipcMain.on("autofill.completePasskeyRegistration", (event, data) => {
this.logService.warning("autofill.completePasskeyRegistration", data);
const { clientId, sequenceNumber, response } = data;
this.ipcServer.completeRegistration(clientId, sequenceNumber, response);
this.ipcServer?.completeRegistration(clientId, sequenceNumber, response);
});
ipcMain.on("autofill.completePasskeyAssertion", (event, data) => {
this.logService.warning("autofill.completePasskeyAssertion", data);
const { clientId, sequenceNumber, response } = data;
this.ipcServer.completeAssertion(clientId, sequenceNumber, response);
this.ipcServer?.completeAssertion(clientId, sequenceNumber, response);
});
ipcMain.on("autofill.completeError", (event, data) => {
this.logService.warning("autofill.completeError", data);
const { clientId, sequenceNumber, error } = data;
this.ipcServer.completeError(clientId, sequenceNumber, String(error));
this.ipcServer?.completeError(clientId, sequenceNumber, String(error));
});
}