目录
Manifest.json
常用结构
host_permissions
action
content_scripts
完整结构
options_ui
content_security_policy
homepage_url
minimum_chrome_version
incognito
web_a***essible_resources
侧边栏(side_panel)
其它
Manifest.json
本文将会从“常用结构”和“完整结构”两部分切入,分别讲解。
常用结构
{
"manifest_version":3,
"name":"测试插件",
"version":"1.0",
"description":"实现了一个测试方法",
"icons":{
"16":"icons/logo.png",
"48":"icons/logo.png",
"128":"icons/logo.png"
},
"action":{
"default_popup":"popup/popup.html"
},
"background":{
"service_worker":"background.js",
"type":"module"
},
"content_scripts":[{
"matches":["<all_urls>"],
"js":["content.js"],
"run_at":"document_end"
}],
"permissions":["scripting", "tabs", "storage"],
"host_permissions":["<all_urls>"]
}
- manifest_version[必填项]:manifest版本,必须是3(2已过期)
- name[必填项]:插件名字
- version[必填项]:插件版本,由您指定
- description:插件描述
- icon:插件图标
- action:浏览器动作(工具栏图标)
- permissions:权限声明
- host_permissions:主机权限
- content_scripts:内容脚本(注入到网页的脚本)
必填项(manifest_version、name、version)展现位置如下图所示:
浏览器动作(action)展现位置如下图所示:
host_permissions
作用
-
允许插件与指定网站交互:
- 访问网站的DOM
- 读取或修改网站内容
- 注入内容脚本(content-script)
-
启用特定API的网站访问权限:
- 使用chrome.cookies API访问指定网站的API
- chrome.webRequest AP监控指定网站的请求
-
跨域请求权限:
- 允许插件向指定网站发起跨域XMLHttpRequests或fetch请求
匹配语法
使用与内容脚本matches相同的模式语法
- “*”:匹配任意字符序列
- “?”:匹配任意单个字符
- “*://”:匹配所有协议(http、https等)
- “*.”:匹配所有子域名
- “/*”:匹配路径下的所有内容
示例
https://example.***/ // 只匹配example.***的HTTPS
*://example.***/* // 匹配所有协议的example.***
*://*.example.***/* // 匹配所有子域名
http://localhost/* // 匹配本地开发服务器
action
action可以在manifest.json文件里配置的参数只有两个:
- default_title:鼠标悬浮提示
- default_popup:点击插件显示的页面
content_scripts
{
"content_scripts": [
{
"matches": ["https://*.example.***/*"],
"exclude_matches": ["*://*/*admin*"],
"css": ["content-styles.css"],
"js": ["content-script.js"],
"run_at": "document_idle",
"all_frames": false,
"match_about_blank": false
}
]
}
- matches:脚本注入的URL
- exclude_matcher:排除不需要注入的URL
- css:注入的CSS文件数组
- js:注入的js文件数组
- run_at:控制脚本注入时机
- document_start:DOM加载前,CSS可用前
- document_end:DOM加载后,图片等资源未加载
- document_idle:DOMContentLaded事件后
- all_frames:控制注入位置
- true:注入到所有iframe
- false(默认):只注入到顶层框架
- match_about_blank:是否注入到about:blank页面(about:blank作为顶层页面不允许注入,在一个iframe里时允许注入)
注入的content-script是一个“半隔离”状态,具体如下:
| 特性 | 内容脚本 | 网页脚本 |
|---|---|---|
| DOM访问 | 完全访问 | 完全访问 |
| JavaScript全局对象 | 隔离的副本 | 原始对象 |
| 变量/函数共享 | 不共享 | 不共享 |
| 扩展API访问 | 有限访问(chrome.runtime等) | 无访问 |
DOM是共享的:
// content-script.js
document.body.style.backgroundColor = "red"; // 会影响网页和其他内容脚本
JavaScript环境是隔离的:
// 网页脚本中
window.pageVar = "hello";
// 内容脚本中
console.log(window.pageVar); // ❌ 输出 undefined(无法直接访问)
完整结构
{
"manifest_version": 3,
"name": "My Chrome Extension",
"version": "1.0.0",
"description": "A sample Chrome extension using Manifest V3",
"short_name": "My Extension",
"version_name": "1.0 Beta",
"icons": {
"16": "icons/icon16.png",
"48": "icons/icon48.png",
"128": "icons/icon128.png"
},
"side_panel": {
"default_path": "sidepanel.html",
"openPanelOnActionClick": true,
"matches": ["<all_urls>"]
},
"action": {
"default_icon": {
"16": "icons/icon16.png",
"48": "icons/icon48.png"
},
"default_title": "My Extension",
"default_popup": "popup.html"
},
"background": {
"service_worker": "background.js"
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["contentScript.js"],
"css": ["contentStyle.css"],
"run_at": "document_idle"
}
],
"permissions": [
"activeTab",
"storage",
"scripting",
"tabs"
],
"host_permissions": [
"https://*/*",
"http://*/*"
],
"options_ui": {
"page": "options.html",
"open_in_tab": false
},
"content_security_policy": {
"extension_pages": "script-src 'self'; object-src 'self'"
},
"homepage_url": "https://example.***",
"minimum_chrome_version": "100.0",
"incognito": "spanning",
"web_a***essible_resources": [
{
"resources": ["images/*.png", "styles/*.css"],
"matches": ["<all_urls>"]
}
]
}
options_ui
options_ui是一个对象,包含以下常用属性:
- page(必须):指定选项页面的HTML文件路径
- op_in_tab(可选):布尔值,默认为false
- false:选项页面会嵌入在Chrome的“扩展程序详情”页面中
- true:选项页面会在新标签页打开
content_security_policy
用于限制插件可以加载和执行的资源,防止XSS等安全漏洞
- extension_pages:表示该策略适用于插件自身的页面(popup、options)
- script-src 'self':限制只能执行插件自身包内的脚本(不允许加载外部脚本,也不允许内联脚本)
- object-serc 'self':限制只能加载插件自身包内的插件资源(<embed>)
homepage_url
用于指定插件的官方首页URL
- 如不设置,默认指向该插件在Chrome应用商店的页面
- 当用户在扩展管理页面点击“查看详情”时,会跳转到此URL(若设置)
minimum_chrome_version
指定支持该插件的最低Chrome版本
- 若用户的Chrome版本低于此值,会在应用商店看到“不兼容”提示,且无法安装
- 版本号可以是主版本(100)或完整版本(100.0.4896.127)
incognito
定义插件在“无痕模式”下的三个行为,支持三个值:
- spanning(默认):插件在常规模式和无痕模式共享同一个实例,数据互通(chrome.storage等存储不会同步)
- split:插件在无痕模式中运行独立实例,与常规模式完全隔离,数据不互通
- not_allowd:禁止插件在无痕模式中运行
web_a***essible_resources
指定插件内部的哪些资源文件可以被外部网页(或其它插件)访问
- resources:一个字符串数组,指定允许被外部访问的资源路径,支持通配符*匹配多个文件
- matches:一个字符串数组,指定哪些网页可以访问这些资源
侧边栏(side_panel)
侧边栏可以通过配置manifest文件实现
{
"manifest_version": 3,
"name": "我的侧边栏扩展",
"version": "1.0",
"icons":{
"16": "icons/logo.png",
"48": "icons/logo.png",
"128": "icons/logo.png"
},
"background":{
"service_worker": "background.js"
},
"side_panel": {
"default_path": "sidepanel.html",
"openPanelOnActionClick": true
},
"action": {
"default_title": "打开侧边栏"
},
"permissions": ["sidePanel"]
}
如需用户点击“插件图标”开关侧边栏,可以在background.js文件中添加如下代码:
chrome.sidePanel
.setPanelBehavior({ openPanelOnActionClick: true })
.catch((error) => console.error(error));
其它
更多Chrome插件开发学习,可以参考我的专栏:
Chrome插件_是洋洋a的博客-CSDN博客