1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-06 00:13:28 +00:00

[PM-22788] Add Autotype Crate and Windowing Functions (#15317)

* [PM-22783] Add initial feature flag and settings toggle for autotype MVP

* [PM-22783] Undo Cargo.lock changes

* [PM-22783] Disable console.log block

* [PM-22783] Lint fix

* [PM-22783] Small updates

* [PM-22783] Build fix

* [PM-22783] Use combineLatest in updating the desktop autotype service

* [PM-22783] Check if the user is on Windows

* [PM-22783] Undo access selector html change, linting keeps removing this

* [PM-22783] Fix failing test

* [PM-22788] Add initial desktop native autotype crate based on spike ticket investigation

* [PM-22788] cargo fmt

* [PM-22783] Update autotypeEnabled to be stored in service

* [PM-22783] Add todo comments

* [PM-22783] Add SlimConfigService and MainDesktopAutotypeService

* [PM-22783] Small fixes

* [PM-22788] Add get_foreground_window_title() and cleanup

* [PM-22788] Add comment

* [PM-22788] Lint and cross platform build fixes

* [PM-22788] Update windows.rs in autotype_internal

* [PM-22788] Update windows.rs and dummy.rs in autotype_internal

* [PM-22788] cargo fmt

* [PM-22788] Edit napi result types

* [PM-22788] Edit napi result types again

* [PM-22788] Add autofill as a codeowner of the desktop_native/autotype directory

* [PM-22788] Refactor autotype code

* [PM-22788] Move autotype dependency out of windows only due to abstraction change

* [PM-22788] Fix lint errors

* [PM-22788] Updates based on PR comments

* [PM-22788] cargo fmt
This commit is contained in:
Colton Hurst
2025-07-18 10:30:19 -04:00
committed by GitHub
parent 8e185e023a
commit 8811ec41ab
12 changed files with 147 additions and 12 deletions

1
.github/CODEOWNERS vendored
View File

@@ -134,6 +134,7 @@ libs/common/src/autofill @bitwarden/team-autofill-dev
apps/desktop/macos/autofill-extension @bitwarden/team-autofill-dev
apps/desktop/src/app/components/fido2placeholder.component.ts @bitwarden/team-autofill-dev
apps/desktop/desktop_native/windows_plugin_authenticator @bitwarden/team-autofill-dev
apps/desktop/desktop_native/autotype @bitwarden/team-autofill-dev
# DuckDuckGo integration
apps/desktop/native-messaging-test-runner @bitwarden/team-autofill-dev
apps/desktop/src/services/duckduckgo-message-handler.service.ts @bitwarden/team-autofill-dev

View File

@@ -349,6 +349,14 @@ version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
[[package]]
name = "autotype"
version = "0.0.0"
dependencies = [
"windows 0.61.1",
"windows-core 0.61.0",
]
[[package]]
name = "backtrace"
version = "0.3.75"
@@ -912,6 +920,7 @@ name = "desktop_napi"
version = "0.0.0"
dependencies = [
"anyhow",
"autotype",
"base64",
"desktop_core",
"hex",
@@ -3677,7 +3686,7 @@ dependencies = [
"windows-implement 0.60.0",
"windows-interface 0.59.1",
"windows-link",
"windows-result 0.3.2",
"windows-result 0.3.4",
"windows-strings",
]
@@ -3737,9 +3746,9 @@ dependencies = [
[[package]]
name = "windows-link"
version = "0.1.1"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38"
checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a"
[[package]]
name = "windows-numerics"
@@ -3753,12 +3762,12 @@ dependencies = [
[[package]]
name = "windows-registry"
version = "0.5.1"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad1da3e436dc7653dfdf3da67332e22bff09bb0e28b0239e1624499c7830842e"
checksum = "5b8a9ed28765efc97bbc954883f4e6796c33a06546ebafacbabee9696967499e"
dependencies = [
"windows-link",
"windows-result 0.3.2",
"windows-result 0.3.4",
"windows-strings",
]
@@ -3773,18 +3782,18 @@ dependencies = [
[[package]]
name = "windows-result"
version = "0.3.2"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252"
checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6"
dependencies = [
"windows-link",
]
[[package]]
name = "windows-strings"
version = "0.4.0"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a2ba9642430ee452d5a7aa78d72907ebe8cfda358e8cb7918a2050581322f97"
checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57"
dependencies = [
"windows-link",
]

View File

@@ -1,6 +1,6 @@
[workspace]
resolver = "2"
members = ["napi", "core", "proxy", "macos_provider", "windows_plugin_authenticator"]
members = ["napi", "core", "proxy", "macos_provider", "windows_plugin_authenticator", "autotype"]
[workspace.package]
version = "0.0.0"
@@ -60,7 +60,7 @@ widestring = "=1.2.0"
windows = "=0.61.1"
windows-core = "=0.61.0"
windows-future = "=0.2.0"
windows-registry = "=0.5.1"
windows-registry = "=0.5.3"
zbus = "=5.5.0"
zbus_polkit = "=5.0.0"
zeroizing-alloc = "=0.1.0"

View File

@@ -0,0 +1,10 @@
[package]
name = "autotype"
version.workspace = true
license.workspace = true
edition.workspace = true
publish.workspace = true
[target.'cfg(windows)'.dependencies]
windows = { workspace = true, features = ["Win32_UI_Input_KeyboardAndMouse", "Win32_UI_WindowsAndMessaging"] }
windows-core = { workspace = true }

View File

@@ -0,0 +1,12 @@
#[cfg_attr(target_os = "linux", path = "linux.rs")]
#[cfg_attr(target_os = "macos", path = "macos.rs")]
#[cfg_attr(target_os = "windows", path = "windows.rs")]
mod windowing;
/// Gets the title bar string for the foreground window.
///
/// TODO: The error handling will be improved in a future PR: PM-23615
#[allow(clippy::result_unit_err)]
pub fn get_foreground_window_title() -> std::result::Result<String, ()> {
windowing::get_foreground_window_title()
}

View File

@@ -0,0 +1,3 @@
pub fn get_foreground_window_title() -> std::result::Result<String, ()> {
todo!("Bitwarden does not yet support Linux autotype");
}

View File

@@ -0,0 +1,3 @@
pub fn get_foreground_window_title() -> std::result::Result<String, ()> {
todo!("Bitwarden does not yet support Mac OS autotype");
}

View File

@@ -0,0 +1,75 @@
use std::ffi::OsString;
use std::os::windows::ffi::OsStringExt;
use windows::Win32::Foundation::HWND;
use windows::Win32::UI::WindowsAndMessaging::{
GetForegroundWindow, GetWindowTextLengthW, GetWindowTextW,
};
/// Gets the title bar string for the foreground window.
pub fn get_foreground_window_title() -> std::result::Result<String, ()> {
let Ok(window_handle) = get_foreground_window() else {
return Err(());
};
let Ok(Some(window_title)) = get_window_title(window_handle) else {
return Err(());
};
Ok(window_title)
}
/// Gets the foreground window handle.
///
/// https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getforegroundwindow
fn get_foreground_window() -> Result<HWND, ()> {
let foreground_window_handle = unsafe { GetForegroundWindow() };
if foreground_window_handle.is_invalid() {
return Err(());
}
Ok(foreground_window_handle)
}
/// Gets the length of the window title bar text.
///
/// TODO: Future improvement is to use GetLastError for better error handling
///
/// https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowtextlengthw
fn get_window_title_length(window_handle: HWND) -> Result<usize, ()> {
if window_handle.is_invalid() {
return Err(());
}
match usize::try_from(unsafe { GetWindowTextLengthW(window_handle) }) {
Ok(length) => Ok(length),
Err(_) => Err(()),
}
}
/// Gets the window title bar title.
///
/// TODO: Future improvement is to use GetLastError for better error handling
///
/// https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowtextw
fn get_window_title(window_handle: HWND) -> Result<Option<String>, ()> {
if window_handle.is_invalid() {
return Err(());
}
let window_title_length = get_window_title_length(window_handle)?;
if window_title_length == 0 {
return Ok(None);
}
let mut buffer: Vec<u16> = vec![0; window_title_length + 1]; // add extra space for the null character
let window_title_length = unsafe { GetWindowTextW(window_handle, &mut buffer) };
if window_title_length == 0 {
return Ok(None);
}
let window_title = OsString::from_wide(&buffer);
Ok(Some(window_title.to_string_lossy().into_owned()))
}

View File

@@ -14,6 +14,7 @@ default = []
manual_test = []
[dependencies]
autotype = { path = "../autotype" }
base64 = { workspace = true }
hex = { workspace = true }
anyhow = { workspace = true }

View File

@@ -208,3 +208,6 @@ export declare namespace logging {
}
export function initNapiLog(jsLogFn: (err: Error | null, arg0: LogLevel, arg1: string) => any): void
}
export declare namespace autotype {
export function getForegroundWindowTitle(): string
}

View File

@@ -865,3 +865,15 @@ pub mod logging {
fn flush(&self) {}
}
}
#[napi]
pub mod autotype {
#[napi]
pub fn get_foreground_window_title() -> napi::Result<String, napi::Status> {
autotype::get_foreground_window_title().map_err(|_| {
napi::Error::from_reason(
"Autotype Error: faild to get foreground window title".to_string(),
)
})
}
}

View File

@@ -1,3 +1,5 @@
import { autotype } from "@bitwarden/desktop-napi";
import { DesktopAutotypeService } from "../services/desktop-autotype.service";
export class MainDesktopAutotypeService {
@@ -17,6 +19,10 @@ export class MainDesktopAutotypeService {
private enableAutotype() {
// eslint-disable-next-line no-console
console.log("Enabling Autotype...");
const result = autotype.getForegroundWindowTitle();
// eslint-disable-next-line no-console
console.log("Window Title: " + result);
}
// TODO: this will call into desktop native code