统一桌面外链打开 helper

让桌面 WebView 外链和 HostBridge 外链共用 opener helper

用配置检查禁止 HostBridge 直接调用 opener

同步桌面壳外链 helper 共用决策记录
This commit is contained in:
2026-06-19 17:47:24 +08:00
parent 8f8c379685
commit cba6e29d1d
5 changed files with 44 additions and 6 deletions
@@ -83,6 +83,14 @@ const desktopShellNetworkSource = fs.readFileSync(
desktopShellNetworkPath,
'utf8',
);
const desktopShellNavigationPath = new URL(
'../src-tauri/src/shell/navigation.rs',
import.meta.url,
);
const desktopShellNavigationSource = fs.readFileSync(
desktopShellNavigationPath,
'utf8',
);
const productionSourceRoots = [
new URL('../package.json', import.meta.url),
new URL('../src-tauri/Cargo.toml', import.meta.url),
@@ -1589,6 +1597,26 @@ if (desktopHostBridgeDispatchSource.includes('json!(HostBridgeRuntime {')) {
throw new Error('desktop shell host.getRuntime must be built by desktop_runtime()');
}
if (
!desktopShellNavigationSource.includes('pub(crate) fn open_normalized_desktop_external_url') ||
!desktopShellNavigationSource.includes(
'open_normalized_desktop_external_url(app, external_url)',
)
) {
throw new Error(
'desktop shell WebView external navigation must use the shared external opener helper',
);
}
if (
!desktopHostBridgeDispatchSource.includes('open_normalized_desktop_external_url(&app, url)') ||
desktopHostBridgeDispatchSource.includes('app.opener().open_url(')
) {
throw new Error(
'desktop shell app.openExternalUrl must use the shared external opener helper',
);
}
if (config.build?.frontendDist !== '../../../dist') {
throw new Error('desktop shell must package the root H5 dist');
}
@@ -1930,6 +1958,7 @@ const requiredRustHostSnippets = [
'desktop_main_window_config(app)?',
'should_allow_desktop_webview_navigation',
'desktop_external_navigation_url',
'open_normalized_desktop_external_url',
'open_desktop_external_navigation',
'.on_navigation(move |url|',
'.on_new_window(move |url, _features|',
@@ -12,14 +12,13 @@ use crate::host_bridge::protocol::{
use crate::host_bridge::share::{share_text_from_request, DesktopShareState};
use crate::shell::webview::{
color_scheme_from_theme, desktop_platform, normalize_external_url, normalize_native_page_url,
resolve_desktop_network_status,
open_normalized_desktop_external_url, resolve_desktop_network_status,
};
use serde_json::{json, Value};
use tauri::Manager;
use tauri_plugin_clipboard_manager::ClipboardExt;
use tauri_plugin_dialog::DialogExt;
use tauri_plugin_notification::{NotificationExt, PermissionState};
use tauri_plugin_opener::OpenerExt;
const BADGE_COUNT_MAX: i64 = 99999;
const LOCAL_NOTIFICATION_TITLE_MAX_LENGTH: usize = 80;
@@ -192,7 +191,7 @@ pub(super) async fn execute_host_bridge_request(
}
};
match app.opener().open_url(url, None::<&str>) {
match open_normalized_desktop_external_url(&app, url) {
Ok(()) => ok(request.id, json!(true)),
Err(error) => failed(request.id, "host_error", error.to_string()),
}
@@ -149,11 +149,20 @@ pub(crate) fn desktop_external_navigation_url(url: &Url) -> Option<String> {
normalize_external_url(url.as_str())
}
pub(crate) fn open_normalized_desktop_external_url(
app: &tauri::AppHandle,
external_url: String,
) -> Result<(), String> {
app.opener()
.open_url(external_url, None::<&str>)
.map_err(|error| error.to_string())
}
pub(crate) fn open_desktop_external_navigation(app: &tauri::AppHandle, url: &Url) {
let Some(external_url) = desktop_external_navigation_url(url) else {
return;
};
let _ = app.opener().open_url(external_url, None::<&str>);
let _ = open_normalized_desktop_external_url(app, external_url);
}
pub(crate) fn should_allow_desktop_webview_download(event: &DownloadEvent<'_>) -> bool {
@@ -5,8 +5,8 @@ pub(crate) use crate::shell::lifecycle::{
};
pub(crate) use crate::shell::navigation::{
normalize_external_url, normalize_native_page_url, open_desktop_external_navigation,
register_desktop_navigation_events, should_allow_desktop_webview_download,
should_allow_desktop_webview_navigation,
open_normalized_desktop_external_url, register_desktop_navigation_events,
should_allow_desktop_webview_download, should_allow_desktop_webview_navigation,
};
pub(crate) use crate::shell::network::{
register_desktop_network_events, resolve_desktop_network_status,