fix(windows): use webview2_com built-in handler instead of #[implement]
Build Lotus Chat Desktop / build-linux (push) Failing after 17m40s
Build Lotus Chat Desktop / build-windows (push) Failing after 22m16s
Build Lotus Chat Desktop / update-manifest (push) Has been skipped

The previous approach used windows::core::implement to manually implement
ICoreWebView2PermissionRequestedEventHandler_Impl, but the sealed
IUnknownImpl constraint in webview2-com prevents external #[implement]
usage — you must use the crate's own pre-built handler types.

Replace with PermissionRequestedEventHandler::create() which wraps the
closure and handles COM ref-counting internally. Also removes the now-
unused windows = "0.61" direct dependency.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-09 23:31:03 -04:00
parent 26bd0722bc
commit eadd3bfc48
2 changed files with 27 additions and 45 deletions
-1
View File
@@ -44,7 +44,6 @@ tauri-plugin-updater = "2"
[target.'cfg(target_os = "windows")'.dependencies]
webview2-com = "0.38"
windows = { version = "0.61", features = [] }
[lib]
name = "app_lib"
+27 -44
View File
@@ -3,46 +3,9 @@
windows_subsystem = "windows"
)]
// mod menu;
use tauri::{webview::{NewWindowResponse, WebviewWindowBuilder}, WebviewUrl};
use tauri_plugin_opener::OpenerExt;
// Automatically grant camera and microphone permissions in WebView2 (Windows).
// macOS handles this via Info.plist; Windows requires an explicit PermissionRequested handler.
#[cfg(target_os = "windows")]
mod win_permissions {
use webview2_com::Microsoft::Web::WebView2::Win32::{
ICoreWebView2, ICoreWebView2PermissionRequestedEventArgs,
ICoreWebView2PermissionRequestedEventHandler,
ICoreWebView2PermissionRequestedEventHandler_Impl,
COREWEBVIEW2_PERMISSION_KIND_CAMERA, COREWEBVIEW2_PERMISSION_KIND_MICROPHONE,
COREWEBVIEW2_PERMISSION_STATE_ALLOW,
};
use windows::core::implement;
#[implement(ICoreWebView2PermissionRequestedEventHandler)]
pub struct PermissionHandler;
impl ICoreWebView2PermissionRequestedEventHandler_Impl for PermissionHandler {
fn Invoke(
&self,
_sender: Option<&ICoreWebView2>,
args: Option<&ICoreWebView2PermissionRequestedEventArgs>,
) -> windows::core::Result<()> {
if let Some(args) = args {
let kind = unsafe { args.PermissionKind() }?;
if kind == COREWEBVIEW2_PERMISSION_KIND_MICROPHONE
|| kind == COREWEBVIEW2_PERMISSION_KIND_CAMERA
{
unsafe { args.SetState(COREWEBVIEW2_PERMISSION_STATE_ALLOW) }?;
}
}
Ok(())
}
}
}
pub fn run() {
let port: u16 = 44548;
let context = tauri::generate_context!();
@@ -71,19 +34,39 @@ pub fn run() {
NewWindowResponse::Deny
});
// Grant camera and microphone to WebView2 automatically.
// Windows requires an explicit PermissionRequested COM event handler;
// macOS uses Info.plist.
#[cfg(target_os = "windows")]
let builder = builder.with_webview(|webview| {
use webview2_com::Microsoft::Web::WebView2::Win32::ICoreWebView2PermissionRequestedEventHandler;
use windows::core::EventRegistrationToken;
use win_permissions::PermissionHandler;
use webview2_com::{
Microsoft::Web::WebView2::Win32::{
COREWEBVIEW2_PERMISSION_KIND_CAMERA,
COREWEBVIEW2_PERMISSION_KIND_MICROPHONE,
COREWEBVIEW2_PERMISSION_STATE_ALLOW,
},
PermissionRequestedEventHandler,
};
let controller = webview.controller();
if let Ok(core) = unsafe { controller.CoreWebView2() } {
let handler: ICoreWebView2PermissionRequestedEventHandler =
PermissionHandler.into();
let mut token = EventRegistrationToken(0);
let handler = PermissionRequestedEventHandler::create(Box::new(
|_sender, args| {
if let Some(args) = args {
let kind = unsafe { args.PermissionKind() }?;
if kind == COREWEBVIEW2_PERMISSION_KIND_MICROPHONE
|| kind == COREWEBVIEW2_PERMISSION_KIND_CAMERA
{
unsafe {
args.SetState(COREWEBVIEW2_PERMISSION_STATE_ALLOW)
}?;
}
}
Ok(())
},
));
let mut token = Default::default();
let _ = unsafe { core.add_PermissionRequested(&handler, &mut token) };
std::mem::forget(handler);
}
});