chrome.tabs 调用的方式与其他代码没有区别。它真正改变的是你在开发期间实际运行的那份 manifest,而这个差异里藏着一个坑。
开发期会注入 tabs 权限
开发循环重载 content script 的方式,是把它们注入到已经打开的标签页里。这需要你的扩展可能并未声明的权限,所以 Extension.js 会把它们加进写入dist/ 的那份 manifest。
对于 manifest v3 项目,开发期会往 permissions 里加上:
host_permissions。
对于 manifest v2 项目,开发期加的是 tabs 和 storage,外加那些匹配模式,因为 manifest v2 没有 host_permissions 这个键。
这些都不会进入生产。extension build 输出的,正好是你声明过的那些权限。
这个差异你可以自己看到。在 manifest.json 里只声明 storage,然后对比两次构建:
dist/chromium/manifest.json
dist/chromium/manifest.json
这个坑,以及怎么绕开
因为开发期注入了tabs,即便 manifest.json 从没申请过这个权限,chrome.tabs.query 在 extension dev 里也照样成功。同一个调用在 extension build 之后就会失败。
对一部分 API,Extension.js 会就此发出警告。用了 chrome.management 却没声明它,构建就会告诉你:
storage、scripting 和 management。它不覆盖 tabs。 一个调用 chrome.tabs 却没有声明权限的项目,编译干净、开发期运行干净,然后在打包后的扩展里坏掉。
用了什么就声明什么:
manifest.json
dist/chromium 作为未打包扩展加载,再把功能实际跑一遍。
你真的需要 tabs 权限吗?
很多扩展并不需要。tabs 权限的存在是为了读取受保护的字段,而不是为了调用这个 API。
activeTab 是更小的请求。它授予的是用户操作过的那个标签页的访问权,有效期就是那一次访问。商店对它的审核态度,比 tabs 加 <all_urls> 要宽厚得多。
完整清单请阅读 权限与主机权限。
跨浏览器的命名
Firefox 与 Safari 提供基于 Promise 的browser.tabs。Chromium 提供基于回调的 chrome.tabs。Extension.js 通过 webextension-polyfill 在 Chromium 上提供 browser 命名空间,所以一种写法处处可用:
从终端指定单个标签页
有几个 CLI 子命令作用于单个标签页。先列出打开的标签页:--tab 只接受数字形式的标签页 id,别的都不行。如果想改用地址来匹配,请用 --url,它接受一个匹配模式或者一段普通的子串:
reload 上,--tab 选择的是作用对象。在 logs 上,它过滤的是已经记录下来的事件。
extension storage 没有 --tab 选项。请改用 --context 选择界面。
失败信息
最后一条在
chrome:// 页面和 Web Store 上很常见,任何扩展都碰不了那些页面。
最佳实践
- 要读取标签页 URL 时就声明
tabs。开发期不会提醒你。 - 当工作由用户手势发起时,优先选择
activeTab。 - 对着生产构建校验权限,而不是开发构建。
- 永远不要假设标签页 id 能挺过浏览器重启。请重新查询一次。
下一步
- 回顾 权限与主机权限。
- 用 eval 命令 从终端驱动浏览器。
- 阅读 content script 相关内容。

