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。
L1 边界
宿主独占的是系统剪贴板与当前可信用户操作。guest 无法自行读取或写入其他应用共享的剪贴板;文本编辑命令、格式转换和剪贴板历史都可在 guest 中实现,不进入 L1。
能力声明
{
"capabilities": [
"host:clipboard.readText",
"host:clipboard.writeText"
]
}
读和写是独立能力;声明写入不获得读取。
Reference
- clipboard.readText()
-> string | null - clipboard.writeText()
-> void
用户取消或剪贴板没有纯文本类型时返回 null,不抛异常;存在的空文本返回空字符串,不能与 null 混同。两种方法都接受末尾 CallOptions;取消与剪贴板读取/写入提交点线性排序,取消先发生则以 cancelled 失败且不读写,提交先发生则返回正常结果,后到的取消不改写结果。
原生 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;符合 v0.1 的宿主必须同时执行长度/速率预算、纯文本形状校验和逐次审计,否则不支持该方法。
- 页面隐藏或焦点丢失时调用必须失败为
activation-required。
格式与校验
v0.1 只接受有 UTF-8 字节上限的纯 Unicode 文本。NUL 是普通字符;宿主不得把文本解释为 HTML、URL 或命令,也不得正规化 Unicode、改写换行或更改任何标量值。绑定必须明确实际长度,不能依赖 NUL 终止。
安全与预算
- v0.1 预算键为
clipboard.maxTextBytes、clipboard.readsPerMinute、clipboard.writesPerMinute。 - 写入内容不得被平台偷偷附加追踪标识。
- 读取结果不得进入宿主日志、遥测或错误详情。
- 系统剪贴板变化本身不触发 guest 事件。
错误与测试
特有错误包括 activation-required、denied、cancelled、sink-too-small、invalid-data 和 limit-exceeded。一致性测试至少覆盖空剪贴板、用户取消与调用取消的区分、提交竞态、失焦、超长文本、NUL、无效 Unicode、原生 sink、读写权限分离和调用预算。