print 非正式提议
本页不属于任何正式 Host API 版本,名字、边界和签名均未冻结。当前宿主只做词法检查,没有隔离、受预算的 PDF 结构解析器;在解析、渲染和临时资源清理完成端到端验证前,本提议不得进入 manifest、SDK 或运行时能力表。
print 把 guest 已有的静态文档交给系统打印界面。宿主验证格式、在可信页面中预览并让用户选择打印机;guest 不获得打印设备、驱动、真实临时 URL 或后台打印权。
基本示例
async function printInvoice() {
const pdf = buildInvoicePdf();
const result = await host.print.open(pdf);
if (result === null) showMessage('已取消打印');
}
调用必须来自用户点击等可信操作。返回成功只表示系统打印流程已接受,不保证纸张最终输出。
适用场景
- 发票、报告、标签和静态画布结果。
- 让用户在系统界面选择打印机、页数和份数。
- 不需要 guest 观察设备信息的本地交付。
后台静默打印、打印机枚举、驱动设置、队列状态、原始打印协议和网络打印机发现不在本提议内。
L1 边界
宿主独占的是可信系统打印界面和向系统打印设施交付文档的效果。guest 无法靠内存取得该系统集成;PDF 生成、模板、分页和业务文档模型都由 guest 完成,不进入 L1。
能力声明
{
"capabilities": ["host:print.open"]
}
Reference
print.open(document: ByteSource, options?) -> { accepted: true } | null
候选契约唯一格式是 application/pdf,因此方法没有 MIME 参数。用户关闭可信打印 UI 时返回 null;options?: CallOptions 可取消尚未交给系统打印设施的流程。
取消与系统交付必须线性排序:取消先发生则以 cancelled 失败且不得交付文档;交付先发生则返回 { accepted: true },后到的取消不撤回系统打印任务。
文档必须声明 PDF 版本 1.7 或更早、至少含一页且自包含。候选契约拒绝加密、数字签名、增量更新、附件、表单提交、JavaScript、Launch/URI/GoToR 动作、外部文件引用和多媒体;字体与图像资源必须嵌入文档。除这些限制外,页面绘制遵循 PDF 1.7,最终光栅化和打印色彩由可信系统打印设施负责。
guest 负责形成完整、自包含文档;宿主不解析 HTML、执行脚本或加载文档中的外部 URL。
原生 WASM 示例
uint8_t *pdf;
size_t pdf_len = build_report_pdf(&pdf);
PrintResult result = host_print_open(
byte_source(pdf, pdf_len),
NO_CANCEL
);
调用期间绑定层可以复制或流式交付数据,但不能在返回后继续引用 guest 可变内存。
用户流程
- guest 在可信用户操作中提交自包含文档。
- 宿主验证 PDF 魔数、结构、禁用特性和预算。
- 宿主在可信 UI 中显示预览与应用身份。
- 用户选择打印或取消。
- 宿主把文档交给系统打印设施,只向 guest 返回接受/取消。
guest 不能传回跳 URL、窗口特征、打印机名或任意系统选项。
安全与预算
- 信任档位固定为 green;符合候选契约的宿主必须保证用户可见、本地、write-only、无内容回程且有预算与逐次审计。
- 候选契约预算键为
print.maxDocumentBytes、print.maxPages、print.flowsPerMinute。 - PDF 解析在隔离、受预算的组件中完成;只接受上面冻结的 PDF 1.7 子集。
- 临时文档和预览 URL 不返回 guest,流程结束后及时销毁。
- 审计记录应用、时间和结果,不记录文档内容。
错误与测试
特有错误包括 activation-required、invalid-document、cancelled、limit-exceeded 和 platform-unavailable。一致性测试至少覆盖取消、损坏 PDF、版本上限、加密/签名/增量更新、动作与外部引用、超大页、解码炸弹、重复点击、页面失焦、临时文件清理和无返回通道。