说明
使用 offscreen
API 创建和管理屏幕外文档。
权限
offscreen
如需使用 Offscreen API,请在扩展程序清单中声明 "offscreen"
权限。例如:
{
"name": "My extension",
...
"permissions": [
"offscreen"
],
...
}
可用性
概念和用法
Service Worker 没有 DOM 访问权限,而且许多网站都有内容安全政策,限制内容脚本的功能。借助 Offscreen API,该扩展程序可以在隐藏的文档中使用 DOM API,而不会因打开新的窗口或标签页而影��用户体验。runtime
API 是屏幕外文档唯一支持的扩展程序 API。
作为屏幕外文档加载的页面的处理方式与其他类型的扩展程序页面不同。
扩展程序的权限会沿用到屏幕外的文档,但扩展程序 API 访问权限会受到限制。例如,由于 chrome.runtime
API 是屏幕外文档唯一支持的扩展程序 API,因此必须使用该 API 的成员处理消息传递。
以下是屏幕外文档与普通页面行为方式不同的其他方面:
- 屏幕外文档的网址必须是与扩展名捆绑的静态 HTML 文件。
- 无法聚焦屏幕外的文档。
- 屏幕外文档是
window
的实例,但其opener
属性的值始终为null
。 - 虽然一个扩展程序软件包可以包含多个屏幕外文档,但一个已安装的扩展程序一次只能打开一个。如果扩展程序在分屏模式下运行且具有有效的无痕模式个人资料,则普通个人资料和无痕模式个人资料可以各自有一个屏幕外文档。
使用 chrome.offscreen.createDocument()
和 chrome.offscreen.closeDocument()
创建和关闭屏幕外文档。createDocument()
需要文档的 url
、原因和理由:
chrome.offscreen.createDocument({
url: 'off_screen.html',
reasons: ['CLIPBOARD'],
justification: 'reason for needing the document',
});
原因
如需查看正当原因列表,请参阅原因部分。原因可在文档创建期间设置,以确定文档的有效期。AUDIO_PLAYBACK
原因将文档设置为在无音频播放 30 秒后关闭。所有其他原因均无法设置生命周期上限。
示例
维护屏幕外文档的生命周期
以下示例展示了如何确保屏幕外文档存在。setupOffscreenDocument()
函数会调用 runtime.getContexts()
以查找现有的屏幕外文档,或者创建该文档(如果尚无文档)。
let creating; // A global promise to avoid concurrency issues
async function setupOffscreenDocument(path) {
// Check all windows controlled by the service worker to see if one
// of them is the offscreen document with the given path
const offscreenUrl = chrome.runtime.getURL(path);
const existingContexts = await chrome.runtime.getContexts({
contextTypes: ['OFFSCREEN_DOCUMENT'],
documentUrls: [offscreenUrl]
});
if (existingContexts.length > 0) {
return;
}
// create offscreen document
if (creating) {
await creating;
} else {
creating = chrome.offscreen.createDocument({
url: path,
reasons: ['CLIPBOARD'],
justification: 'reason for needing the document',
});
await creating;
creating = null;
}
}
在向屏幕外文档发送消息之前,请调用 setupOffscreenDocument()
以确保该文档存在,如以下示例所示。
chrome.action.onClicked.addListener(async () => {
await setupOffscreenDocument('off_screen.html');
// Send message to offscreen document
chrome.runtime.sendMessage({
type: '...',
target: 'offscreen',
data: '...'
});
});
如需查看完整示例,请参阅 GitHub 上的 offscreen-clipboard 和 offscreen-dom 演示。
Chrome 116 之前:检查屏幕外文档是否已打开
Chrome 116 中添加了 runtime.getContexts()
。在早期版本的 Chrome 中,使用 clients.matchAll()
检查现有的屏幕外文档:
async function hasOffscreenDocument() {
if ('getContexts' in chrome.runtime) {
const contexts = await chrome.runtime.getContexts({
contextTypes: ['OFFSCREEN_DOCUMENT'],
documentUrls: [OFFSCREEN_DOCUMENT_PATH]
});
return Boolean(contexts.length);
} else {
const matchedClients = await clients.matchAll();
return await matchedClients.some(client => {
client.url.includes(chrome.runtime.id);
});
}
}
类型
CreateParameters
属性
-
理由
string
开发者提供的字符串,用于更详细地说明对后台上下文的需求。用户代理 _可以_ 向用户显示它。
-
个原因
原因[]
该扩展程序创建屏幕外文档的原因。
-
网址
string
要在文档中加载的(相对)网址。
Reason
枚举
"TESTING"
仅用于测试的原因。
"AUDIO_PLAYBACK"
指定由屏幕外文档负责播放音频。
"IFRAME_SCRIPTING"
指定屏幕外文档需要嵌入 iframe 并为其编写脚本,以便修改 iframe 的内容。
"DOM_SCRAPING"
指定屏幕外文档需要嵌入 iframe 并爬取其 DOM 来提取信息。
"BLOBS"
指定屏幕外文档需要与 Blob 对象(包括 URL.createObjectURL()
)交互。
"DOM_PARSER"
指定屏幕外文档需要使用 DOMParser API。
"USER_MEDIA"
指定屏幕外文档需要与用户媒体(例如 getUserMedia()
)中的媒体流进行交互。
"DISPLAY_MEDIA"
指定屏幕外文档需要与来自显示媒体(例如 getDisplayMedia()
)的媒体流进行交互。
"WEB_RTC"
指定屏幕外文档需要使用 WebRTC API。
"CLIPBOARD"
指定屏幕外文档需要与 Clipboard API 交互。
"LOCAL_STORAGE"
指定屏幕外文档需要访问 localStorage。
"WORKERS"
指定屏幕外文档需要生成 worker。
"BATTERY_STATUS"
指定屏幕外文档需要使用 navigator.getBattery。
"MATCH_MEDIA"
指定屏幕外文档需要使用 window.matchMedia。
"GEOLOCATION"
指定屏幕外文档需要使用 navigator.geolocation。
方法
closeDocument()
chrome.offscreen.closeDocument(
callback?: function,
)
关闭扩展程序当前打开的屏幕外文档。
参数
-
callback
函数(可选)
callback
参数如下所示:() => void
返回
-
Promise<void>
Manifest V3 及更高版本支持 promise,但提供回调以实现向后兼容性。您不能在同一个函数调用中同时使用这两者。promise 使用传递给回调函数的同一类型进行解析。
createDocument()
chrome.offscreen.createDocument(
parameters: CreateParameters,
callback?: function,
)
为扩展程序创建新的屏幕外文档。
参数
-
描述要创建的屏幕外文档的参数。
-
callback
函数(可选)
callback
参数如下所示:() => void
返回
-
Promise<void>
Manifest V3 及更高版本支持 promise,但提供回调以实现向后兼容性。您不能在同一个函数调用中同时使用这两者。promise 使用传递给回调函数的同一类型进行解析。