剪贴板 API 改进
剪贴板 API 提供了一种机制,允许网站访问系统剪贴板(剪贴板在 macOS 和 iOS 中称为“粘贴板”,对应 Windows 和 Linux 中的“剪贴板”)。复制和粘贴是现代操作系统中最基本的操作之一。我们将其用于各种目的,从在一个网站上复制超链接到另一个网站,到将本机文字处理应用程序中键入的博客文章复制到网络上的博客平台。因此,在 Web 上创建引人注目的生产力应用程序(如文字处理器和演示文稿应用程序)需要像其他本机应用程序一样与系统剪贴板进行交互。
在过去的几个月里,我们增加了对新 API 的支持,以更好地与其他浏览器互操作,并改进了我们的实现,以允许 WebKit 的 macOS 和 iOS 端口支持更多用例。这些更改可在 Safari 11.1 和 iOS 11.3 测试版程序中供您审查。
首先,我们对 DataTransfer API 进行了现代化改进。我们增加了对项(items)的支持,并修复了macOS 和 iOS 上的许多bug。由于大多数网站不支持上传 TIFF 文件,WebKit 现在会自动将 TIFF 图像转换为 PNG 图像,并在系统剪贴板中存在图像时将 PNG 图像作为文件暴露出来。
目录上传
在 r221177 中,我们增加了通过 DataTransfer.webkitGetAsEntry()
和 input.webkitdirectory
上传目录的支持,以与 Chrome、Firefox 和 Edge 等已实现此 WebKit 前缀功能的其他浏览器互操作。这个新 API 允许用户将整个目录上传到 iCloud 和 Dropbox 等云存储和文件共享服务。在 iOS 上,从“文件”应用拖动文件夹并拖放到网页时支持目录上传。
自定义 MIME 类型
由于系统剪贴板被其他本机应用程序使用,通过剪贴板 API 将数据暴露给 Web 内容存在严重的安全和隐私问题。如果一个网站可以向系统剪贴板插入任意内容,那么该网站就可以利用任何读取剪贴板内容的本机应用程序中的安全漏洞——例如,一个显示剪贴板内容的实用程序应用程序。同样,如果一个网站可以在任何给定时间读取系统剪贴板,它可能会窃取敏感信息,例如用户正在复制的真实全名和邮件地址。
因此,我们以前在 DataTransfer 对象中只允许读取纯文本和 URL。我们在 r222595 中放宽了这一限制,允许在相同来源的网页之间读写任意 MIME 类型。这一更改允许来自单个来源的 Web 应用程序使用它们自己的 MIME 类型和我们不支持的 MIME 类型无缝共享信息,同时仍然隐藏其他本机应用程序可能放入系统剪贴板的隐私和安全敏感信息。因为网站使用的自定义 MIME 类型被捆绑在 WebKit 控制的特殊 MIME 类型下,所以网页不能在系统剪贴板中放置任意 MIME 类型的恶意负载以利用本机应用程序中的 bug。
获取和设置数据
除了自定义 MIME 类型外,Web 应用程序现在可以在 copy
或 dragstart
事件期间使用 DataTransfer.setData
或 DataTransfer.items.add
将 text/html
、text/plain
和 text/uri-list
写入系统剪贴板。这些内容将使用 macOS 和 iOS 相应的 UTI 写入,因此粘贴到已支持粘贴 HTML 标记、纯文本字符串或 URL 的本机应用程序中将按预期工作。
在读取方面,Web 应用程序现在还可以在 paste
和 drop
事件期间使用 DataTransfer.getData
和 DataTransfer.items
从系统剪贴板读取 text/html
、text/plain
和 text/uri-list
数据。如果任何文件被写入剪贴板(例如,在 Finder 中复制 PDF 文件时),这些信息将通过 DataTransfer.files
和 DataTransfer.items
访问;为了向后兼容,“Files”类型也将添加到 DataTransfer.types
的类型列表中,以指示页面可能请求文件数据。
一个重要的注意事项是,本机应用程序在复制文件时可能会将文件路径作为 URL 或纯文本写入剪贴板。这可能导致用户在不知情的情况下将文件路径暴露给本机应用程序的主目录和私人容器。因此,WebKit 实现了启发式算法,以在此类情况下通过 DataTransfer
API 抑制对此类数据的访问。如果剪贴板包含至少一个文件并且请求了 text/uri-list
,则 URL 的方案必须是 http
、https
、data
或 blob
,WebKit 才能将其暴露给页面。其他方案,如 file
或 ftp
,将导致空字符串。同样,当剪贴板上有文件时,对 text/plain
的请求将返回空字符串。
读写 HTML 内容
在其他 MIME 类型中,HTML 内容在网络上最为普遍。不幸的是,允许任意网站将 HTML 内容写入系统剪贴板是有问题的,因为 HTML 可能包含脚本标签和事件处理程序,这些可能会在读取内容的应用程序中执行恶意脚本。允许网站读取系统剪贴板中的任意 HTML 内容也存在问题,因为某些文字处理器和电子表格应用程序会将隐私敏感信息(如本地文件路径和用户信息)放入系统剪贴板中的 HTML 中。例如,如果用户在未保存的电子表格中输入了 12345,并复制粘贴到一个随机网站,如果我们将其他本机应用程序放入剪贴板的原始 HTML 内容暴露出来,该网站可能能够获取用户本地主目录路径。因此,我们以前不允许通过 DataTransfer 对象读写 HTML 内容。相反,网站必须等待 WebKit 的原生编辑代码粘贴内容并随后进行处理。
在 r223440 中,我们引入了一种机制来 清理 从系统剪贴板读取和写入的 HTML,从而解除了这一限制。当网站尝试将 HTML 写入剪贴板时,我们将其粘贴到虚拟文档中,重新序列化为 HTML,然后将重新序列化的 HTML 写入系统剪贴板。此过程确保任何脚本元素、事件处理程序和其他潜在危险内容都将被剥离。我们还将 HTML 中所有必要的子资源(例如图像)打包到 WebArchive 中,以便读取剪贴板内容的本机应用程序在粘贴后无需重新获取这些资源。同样,当网站尝试读取其他本机应用程序放置的 HTML 内容时,我们执行相同的步骤:将内容粘贴到虚拟文档中并重新序列化 HTML,剥离用户不打算包含在粘贴内容中的任何私人信息。当 HTML 内容在不同来源之间复制和粘贴时也会发生清理,但不在相同来源的网页内进行。因此,网站可以通过剪贴板 API 写入任意 HTML 内容,并在单个来源内稍后读取完全相同的内容。
粘贴带图像的 HTML 内容
我们还在处理粘贴的 HTML 内容中包含的本地文件的方式上做出了重大改变。以前,子资源(例如粘贴内容中的图像文件)使用 webkit-fake-url://<filename>
形式的 URL,其中 <filename>
是子资源的文件名。由于这不是网站可以访问的标准协议,因此粘贴的图像数据对网站来说是不可访问的。即使 WebKit 能够加载这些图像,网站也无法将图像保存到其服务或浏览器存储 API 中。r223440 将这些伪造 URL 替换为 blob URL,以便网站可以保存图像。自 r222839 起,我们在粘贴 RTFD 内容时也使用 blob URL 而不是伪造 URL。
这一改变提供了一种机制,允许 Web 应用程序使用 Blob API 保存粘贴内容中包含的图像。例如,在线电子邮件编辑器现在能够保存用户从 iOS 和 macOS 上的 TextEdit 或 Microsoft Word 复制和粘贴的图像。我们很高兴成为第一个为 Web 开发者提供这种强大平台集成能力的浏览器。
结论
我们很高兴通过更新的剪贴板 API,使 Web 上的生产力应用程序能够更无缝地与 macOS 和 iOS 上的原生应用程序集成。我们还要特别感谢 TinyMCE 的开发者,他们与我们 tirelessly 合作,解决了许多涉及从 Microsoft Word 复制和粘贴到使用 TinyMCE 的高知名度网站的 bug。