跳转至

什么是url scheme handler?

在操作系统中,不同的应用之间可以相互拉起,但又不知道自己拉起的应用到底是谁。

比如说 你想拉起邮件客户端,但又不确定系统里安装了哪个邮件客户端,比如说你可能有thunderbird, 也可能是outlook。如何能无差别地拉起一个邮件客户端?

你可以这样:

xdg-open mailto:zhangfuwen@foxmail.com

mailto:zhangfuwen@foxmail.com就是一个url scheme。

系统里有一个映射关系,这个映射关系可能通过任何方式维护,在不同的操作系统可能不一样。或者同一个操作系统中也存在不同的机制。

Linux

1 通过desktop file声明

[Desktop Entry]
Version=1.0
Type=Application
Name=dnfurl
Exec=dnfurl %U
Terminal=false
NoDisplay=true
MimeType=x-scheme-handler/dnf

https://blog.kagesenshi.org/2021/02/custom-url-scheme-handler.html

显示每次查一下所有的desktop文件是不太可能的,其实OS会维护一个cache,可以通过命令更新:

cd /usr/share/applications/
update-desktop-database

2 直接修改cache文件

所谓的cache文件可能就是下面的几个文件:

/usr/share/applications/defaults.list
~/.local/share/applications/mimeapps.list
~/.config/mimeapps.list

我们修改文件可以直接达到效果:

sudo su

echo "x-scheme-handler/ddg=org.gnome.Totem.desktop" >> /usr/share/applications/defaults.list

xdg-open ddg:asdfadfl

以上代码可以打开totem,当然了,totem并不认识ddg:asdfadf1是什么,所以它会报错。

3 应用如何响应呢?

如果我们自己写一个应用,建立了映射关系,我们如何收到这个请求呢?

其实它就是做为命令行参数传给我们的应用的。

我们看看totem的desktop file:

➜  Code head /usr/share/applications/org.gnome.Totem.desktop
[Desktop Entry]
Name=Videos
Comment=Play movies
Exec=totem %U
Icon=org.gnome.Totem
DBusActivatable=true
````

可以看到Exec字段跟的是`totem %U`,这里的'%U'就是url list的意思,这个可以参考:https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html#exec-variables

# mime type

与url scheme handler 紧密相关的是mime type。

mime type的处理有一个通用的脚本,叫xdg-mime,它实际上是先检测一下DE,如果是kde就调用`kbuildsycoca`这个软件,如果是gnome就调用update-mime-database这个软件。

xdg-mine这个脚本是`xdg-utils`包的一部分,这个包里面只是几个脚本,可以通过`apt source xdg-utils`下载代码看一下,也可以在[github上直接看](https://github.com/freedesktop/xdg-utils/tree/master/scripts)。

## 4 update-mime-database

update-mime-database是一个可执行文件,它存在于包`shared-mime-info`里,可以通过`apt source shared-mime-info`查看代码,也可以[在github上直接查看](https://github.com/freedesktop/xdg-shared-mime-info/tree/master/src)。

它接受一个目录做为参数,这个目录就是存放mime定义文件的地方,这个目录包括:
~/.local/share/mime/ /usr/share/mime

里面通过一个xml文件描述了一些mime类型,主要是它的名字和识别方法,识别方法包括通过后缀名识别和通过文件头部识别两种方法。
举个例子:

 cat ~/.local/share/mime/packages/view3dscene.xml

VRML document VRML sənədi Документ — VRML document VRML Dokument VRML Dogfen VRML VRML-dokument VRML-Dokument έγγραφο VRML VRML document VRML-dokumento documento VRML VRML dokumentua VRML-asiakirja document VRML VRML-dokumentum Documento VRML VRML ドキュメント VRML 문서 VRML dokumentas Dokumen VRML VRML-dokument VRML-document VRML-dokument Dokument VRML documento VRML Documento VRML документ VRML Dokument VRML VRML документ VRML-dokument Документ VRML Tài liệu VRML VRML 文档 VRML 文件

<!-- Gzip compressed -->
<glob pattern="*.wrz"/>
<glob pattern="*.wrl.gz"/>

3DS model 3D Studio rəsmi Изображение — 3D Studio imatge de 3D Studio Obrázek 3D Studio Delwedd "3D Studio" 3D Studio-billede 3D Studio-Bild εικόνα 3D Studio 3D Studio image bildo de 3D Studio imagen de 3D Studio 3D Studio-ko irudia 3D Studio -kuva image 3D Studio 3D Studio-kép Immagine 3D Studio 3D Studio 画像 3D Studio 그림 3D Studio paveikslėlis Imej 3D Studio 3D Studio-bilde 3D-Studio-afbeelding 3D Studio-bilete Obraz 3D Studio imagem 3D Studio Imagem do 3D Studio изображение 3D Studio Figurë 3D Studio 3D Studio слика 3D Studio-bild Зображення 3D Studio Ảnh xuởng vẽ 3D 3D Studio 图像 3D Studio 圖片

X3D model (classic VRML encoding)

X3D model (XML encoding)

X3D model (binary compressed)

COLLADA model

Inventor model

MD3 (Quake 3 engine) model

Wavefront OBJ model

Videoscape GEO model

Castle Game Engine animation

JSON document

glTF

glTF Binary

## 5 update-mime-database代码

### 5.1 下载代码

找个目录,然后`apt source shared-mime-info`, 里面只有几个文件,`find . -name update-mime-database.c`得到结果`./shared-mime-info-2.2/src/update-mime-database.c
`。

打开它,`write_cache`函数是它写入cache文件的地方,
{ FILE *stream; char *path;

    path = g_strconcat(mime_dir, "/mime.cache.new", NULL);
    stream = fopen_gerror(path, error);
    if (!stream)
        goto out;
    write_cache(stream);
    if (!fclose_gerror(stream, error))
        goto out;
    if (!atomic_update(path, error))
        goto out;
    g_free(path);
}

写的cache文件的名字为`mime.cache`,存放在:
~/.local/share/mime/ /usr/share/mime ```

它们是二进制可映射到内存为map的文件格式,所以查询速度非常的快。

6 kbuildsycoca

kbuildsycoca是kservice的一部分,代码可以在这里看。

这里有一个文档,介绍了sycoca的用法。 sycoca的意思是system configuration cache,三个单词各取了两个字母。