mirror of
https://github.com/tauri-apps/plugins-workspace.git
synced 2026-09-24 21:40:48 +02:00
fix(deep-link): unregister must refresh the database
This commit is contained in:
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
deep-link: patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fixed `unregister` on Linux leaving the app as the scheme's handler: it now also removes the scheme from the `MimeType` of the handler's `.desktop` file and refreshes the desktop database, which `xdg-mime` falls back to. It also no longer fails when `mimeapps.list` does not exist.
|
||||||
@@ -3,13 +3,7 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { expect } from '@wdio/globals'
|
import { expect } from '@wdio/globals'
|
||||||
import {
|
import { tauri, tauriError, describePlugin, itOn } from '../helpers/index.js'
|
||||||
tauri,
|
|
||||||
tauriError,
|
|
||||||
describePlugin,
|
|
||||||
itOn,
|
|
||||||
platform
|
|
||||||
} from '../helpers/index.js'
|
|
||||||
|
|
||||||
// The suite launches the app without a URL, so there is no current deep link,
|
// The suite launches the app without a URL, so there is no current deep link,
|
||||||
// and it cannot open one through the OS either. `onOpenUrl` is exercised by
|
// and it cannot open one through the OS either. `onOpenUrl` is exercised by
|
||||||
@@ -48,7 +42,7 @@ describePlugin('deep-link', () => {
|
|||||||
|
|
||||||
itOn(
|
itOn(
|
||||||
['linux', 'win32'],
|
['linux', 'win32'],
|
||||||
'register makes the app the scheme handler',
|
'register and unregister toggle the scheme handler',
|
||||||
async () => {
|
async () => {
|
||||||
const result = await tauri(async (api, scheme) => {
|
const result = await tauri(async (api, scheme) => {
|
||||||
await api.deepLink.register(scheme)
|
await api.deepLink.register(scheme)
|
||||||
@@ -59,23 +53,22 @@ describePlugin('deep-link', () => {
|
|||||||
afterUnregister: await api.deepLink.isRegistered(scheme)
|
afterUnregister: await api.deepLink.isRegistered(scheme)
|
||||||
}
|
}
|
||||||
}, scheme)
|
}, scheme)
|
||||||
expect(result.registered).toBe(true)
|
expect(result).toEqual({ registered: true, afterUnregister: false })
|
||||||
// On Linux `xdg-mime` falls back to the desktop database, which still lists
|
|
||||||
// the handler after its `mimeapps.list` default is removed.
|
|
||||||
if (platform === 'win32') {
|
|
||||||
expect(result.afterUnregister).toBe(false)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
itOn('win32', 'isRegistered is false for an unknown scheme', async () => {
|
itOn(
|
||||||
expect(
|
['linux', 'win32'],
|
||||||
await tauri(
|
'isRegistered is false for an unknown scheme',
|
||||||
(api, scheme) => api.deepLink.isRegistered(scheme),
|
async () => {
|
||||||
`${scheme}-unknown`
|
expect(
|
||||||
)
|
await tauri(
|
||||||
).toBe(false)
|
(api, scheme) => api.deepLink.isRegistered(scheme),
|
||||||
})
|
`${scheme}-unknown`
|
||||||
|
)
|
||||||
|
).toBe(false)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
itOn(
|
itOn(
|
||||||
['darwin', 'android', 'ios'],
|
['darwin', 'android', 'ios'],
|
||||||
|
|||||||
@@ -148,7 +148,7 @@ mod imp {
|
|||||||
///
|
///
|
||||||
/// ## Platform-specific:
|
/// ## Platform-specific:
|
||||||
///
|
///
|
||||||
/// - **Linux**: Can only unregister the scheme if it was initially registered with [`register`](`Self::register`). May not work on older distros.
|
/// - **Linux**: Can only unregister the scheme if it was initially registered with [`register`](`Self::register`). Needs the `update-desktop-database` command available on the system. May not work on older distros.
|
||||||
/// - **macOS / Android / iOS**: Unsupported, will return [`Error::UnsupportedPlatform`](`crate::Error::UnsupportedPlatform`).
|
/// - **macOS / Android / iOS**: Unsupported, will return [`Error::UnsupportedPlatform`](`crate::Error::UnsupportedPlatform`).
|
||||||
pub fn unregister<S: AsRef<str>>(&self, _protocol: S) -> crate::Result<()> {
|
pub fn unregister<S: AsRef<str>>(&self, _protocol: S) -> crate::Result<()> {
|
||||||
Err(crate::Error::UnsupportedPlatform)
|
Err(crate::Error::UnsupportedPlatform)
|
||||||
@@ -383,7 +383,7 @@ mod imp {
|
|||||||
///
|
///
|
||||||
/// - **Windows**: Requires admin rights if the protocol is registered on local machine
|
/// - **Windows**: Requires admin rights if the protocol is registered on local machine
|
||||||
/// (this can happen when registered from the NSIS installer when the install mode is set to both or per machine)
|
/// (this can happen when registered from the NSIS installer when the install mode is set to both or per machine)
|
||||||
/// - **Linux**: Can only unregister the scheme if it was initially registered with [`register`](`Self::register`). May not work on older distros.
|
/// - **Linux**: Can only unregister the scheme if it was initially registered with [`register`](`Self::register`). Refreshes the desktop database with the `update-desktop-database` command; without it, [`is_registered`](`Self::is_registered`) may keep returning `true`. May not work on older distros.
|
||||||
/// - **macOS / Android / iOS**: Unsupported, will return [`Error::UnsupportedPlatform`](`crate::Error::UnsupportedPlatform`).
|
/// - **macOS / Android / iOS**: Unsupported, will return [`Error::UnsupportedPlatform`](`crate::Error::UnsupportedPlatform`).
|
||||||
pub fn unregister<S: AsRef<str>>(&self, _protocol: S) -> crate::Result<()> {
|
pub fn unregister<S: AsRef<str>>(&self, _protocol: S) -> crate::Result<()> {
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
@@ -401,9 +401,6 @@ mod imp {
|
|||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
{
|
{
|
||||||
let mimeapps_path = self.app.path().config_dir()?.join("mimeapps.list");
|
|
||||||
let mut mimeapps = ini::Ini::load_from_file(&mimeapps_path)?;
|
|
||||||
|
|
||||||
let file_name = format!(
|
let file_name = format!(
|
||||||
"{}-handler.desktop",
|
"{}-handler.desktop",
|
||||||
tauri::utils::platform::current_exe()?
|
tauri::utils::platform::current_exe()?
|
||||||
@@ -411,16 +408,55 @@ mod imp {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.to_string_lossy()
|
.to_string_lossy()
|
||||||
);
|
);
|
||||||
|
let mime_type = format!("x-scheme-handler/{}", _protocol.as_ref());
|
||||||
|
|
||||||
if let Some(section) = mimeapps.section_mut(Some("Default Applications")) {
|
// stop being the default handler
|
||||||
let scheme = format!("x-scheme-handler/{}", _protocol.as_ref());
|
let mimeapps_path = self.app.path().config_dir()?.join("mimeapps.list");
|
||||||
|
if mimeapps_path.exists() {
|
||||||
if section.get(&scheme).unwrap_or_default() == file_name {
|
let mut mimeapps = ini::Ini::load_from_file(&mimeapps_path)?;
|
||||||
section.remove(scheme);
|
if let Some(section) = mimeapps.section_mut(Some("Default Applications")) {
|
||||||
|
if section.get(&mime_type).unwrap_or_default() == file_name {
|
||||||
|
section.remove(&mime_type);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
mimeapps.write_to_file(&mimeapps_path)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
mimeapps.write_to_file(mimeapps_path)?;
|
// Stop declaring the scheme in the handler's `.desktop` file too: the desktop
|
||||||
|
// database indexes it, and with no default set `xdg-mime` falls back to that
|
||||||
|
// index, so the app would otherwise still be the handler.
|
||||||
|
let applications = self.app.path().data_dir()?.join("applications");
|
||||||
|
let desktop_file_path = applications.join(&file_name);
|
||||||
|
// Only the `MimeType` key is touched: the file may carry other changes.
|
||||||
|
if let Ok(mut desktop_file) = ini::Ini::load_from_file(&desktop_file_path) {
|
||||||
|
if let Some(section) = desktop_file.section_mut(Some("Desktop Entry")) {
|
||||||
|
let mime_types = section
|
||||||
|
.get("MimeType")
|
||||||
|
.unwrap_or_default()
|
||||||
|
.split(';')
|
||||||
|
.filter(|mime| !mime.is_empty() && *mime != mime_type)
|
||||||
|
.map(ToString::to_string)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
if mime_types.is_empty() {
|
||||||
|
section.remove("MimeType");
|
||||||
|
} else {
|
||||||
|
section.insert("MimeType", mime_types.join(";"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
desktop_file.write_to_file(&desktop_file_path)?;
|
||||||
|
|
||||||
|
// Without the refreshed index `xdg-mime` may keep reporting the app as the
|
||||||
|
// handler, but the scheme is unregistered as far as the app can tell, so a
|
||||||
|
// missing command is not an error.
|
||||||
|
if let Err(e) = Command::new("update-desktop-database")
|
||||||
|
.arg(&applications)
|
||||||
|
.status()
|
||||||
|
{
|
||||||
|
tracing::warn!(
|
||||||
|
"Failed to run OS command `update-desktop-database`, the desktop database may still list the app as the `{mime_type}` handler: {e}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user