clipboard
clipboard 在可信用户操作中读写系统剪贴板。读操作把其他应用或系统中的内容带入 guest;写操作把 guest 已有内容交给用户可见的系统剪贴板,两者分别授权和定档。
基本示例
async function pasteIntoEditor() {
const text = await host.clipboard.readText();
if (text !== null) editor.insert(text);
}
async function copySelection() {
await host.clipboard.writeText(editor.selectedText());
}
两个函数都必须直接由点击、快捷键等可信用户操作触发。
适用场景
- 文本编辑器的复制与粘贴。
- 绘图应用复制/粘贴静态栅格图。
- 用户主动把应用结果交给另一个应用。
剪贴板历史、后台监听、自定义私有格式、HTML、文件列表和无交互轮询不在 v0.1。
能力声明
{
"capabilities": [
"host:clipboard.readText",
"host:clipboard.writeText"
]
}
文本和图像、读和写都是独立能力;声明写入不获得读取。
Reference
- clipboard.readText()
-> string | null - clipboard.writeText()
-> void - clipboard.readImage()
-> ImageReadResult | null - clipboard.writeImage()
-> void
用户取消、剪贴板没有相应类型或当前内容为空时返回 null,不抛异常。
图像示例
const buffer = new Uint8Array(16 * 1024 * 1024);
const image = await host.clipboard.readImage(buffer);
if (image) {
const bytes = buffer.subarray(0, image.written);
editor.insertImage(bytes, image.mime);
}
如果返回 required 大于 sink,应用可以在预算范围内重新分配并再执行一次用户已授权的读取;宿主不能把第二次调用变成无限期的后台读取授权。
写入图像:
const png = encodeSelectionAsPng();
await host.clipboard.writeImage(png, 'image/png');
原生 WASM 示例
char text[MAX_PASTE_BYTES];
ClipboardTextResult r = host_clipboard_read_text(utf8_sink(text, sizeof(text)));
if (r.present) editor_insert_utf8(text, r.written);
宿主必须验证 UTF-8 并明确返回实际写入长度,不能依赖 NUL 终止。
授权与生命周期
- 每次方法调用都必须继承当前可信用户操作。
- 用户的一次点击只授权当前调用,不产生可持久化剪贴板句柄。
- 读操作的 provenance 为
external-resource,信任档位为 lime。 - 写操作只有在长度、速率、数据形状和逐次审计全部成立时才可为 green。
- 页面隐藏或焦点丢失时调用必须失败为
activation-required。
格式与校验
v0.1 文本是有长度上限的 Unicode 字符串。图像只接受封闭的静态栅格 MIME 白名单;宿主根据魔数和完整解码重新判断类型,不能信任 guest 或系统剪贴板自报的 MIME。
安全与预算
- 预算覆盖文本长度、图像压缩字节、解码像素、调用速率和解码内存。
- SVG、HTML、脚本、动画图和包含外部引用的格式不在白名单。
- 写入内容不得被平台偷偷附加追踪标识。
- 读取结果不得进入宿主日志、遥测或错误详情。
- 系统剪贴板变化本身不触发 guest 事件。
错误与测试
特有错误包括 activation-required、denied、unsupported-format、sink-too-small、invalid-data 和 limit-exceeded。一致性测试至少覆盖空剪贴板、取消、失焦、超长文本、伪造 MIME、解码炸弹、部分 sink、读写权限分离和调用预算。