iTerm2 WebExtensions 框架 content_scripts 字段完全指南:从 manifest 声明到注入执行
【免费下载链接】iTerm2iTerm2 is a terminal emulator for Mac OS X that does amazing things.项目地址: https://gitcode.com/gh_mirrors/it/iTerm2
content_scripts是 WebExtensions Manifest 中用于声明"内容脚本"的核心字段,它告诉浏览器/扩展宿主在哪些 URL 匹配的网页中加载并执行自定义 JavaScript 与 CSS。本文以 iTerm2 仓库内置的 WebExtensionsFramework(位于 WebExtensionsFramework)为背景,完整讲解content_scripts字段的每个属性、取值含义、JSON 示例,并结合 ExtensionManifest.swift 的 Swift 模型与仓库内测试用例,从 manifest 解析、校验到脚本加载的完整链路,帮助你写出可复制、可运行的扩展配置。
一、字段概览:类型、必填性与作用
在 Manifest V3 规范中,content_scripts属于可选顶层字段(manifest_version、name、version为必填项,完整字段清单见 manifest-v3-spec.md)。
- Type:
Array of Objects(对象数组) - Required:
No(可以不声明该字段) - 作用:指示扩展宿主(browser/宿主应用)将内容脚本加载到URL 与 match pattern 匹配的网页中,从而在页面上下文中注入样式与行为代码。
"content_scripts": [ { "matches": ["<all_urls>"], "js": ["content.js"], "css": ["styles.css"], "run_at": "document_idle" } ]数组中的每个对象代表一个独立的内容脚本注册(registration),可以针对不同的 URL 模式、注入时机分别配置。
二、对象属性详解
每个内容脚本对象由 1 个必填属性和 9 个可选属性组成,下面逐一说明。
2.1 必填属性:matches
- 类型:
Array of strings(match patterns,URL 匹配模式数组) - 约束:至少提供一个模式,否则该注册无效
- 作用:声明内容脚本要注入到的 URL 范围
matches是内容脚本的"准入名单",最常见的取值是<all_urls>(匹配所有 http/https 页面),也可以精确到某个站点,例如:
"matches": [ "https://example.com/*", "https://*.github.com/*", "*://localhost/*" ]模式语法遵循标准的 match patterns 规则:*可匹配任意子串,<all_urls>是匹配http、https、file等协议的全量通配写法。
2.2 可选属性
js(注入的 JavaScript 文件)
- 类型:
Array of strings(文件路径数组) - 作用:列出要注入到匹配页面中的 JS 文件。路径相对于扩展包的根目录。
css(注入的 CSS 文件)
- 类型:
Array of strings(文件路径数组) - 作用:列出要注入的样式文件,用于在页面加载早期统一"打补丁"式地修改外观。
all_frames
- 类型:
Boolean,默认值false - 作用:
true时注入所有 frame(包括 iframe 等子框架);false时仅注入顶层 frame。
run_at(注入时机)
- 类型:
String,默认值"document_idle" - 可选值:
"document_start":文档开始加载、DOM 尚未构建时注入(适合尽早挂载事件监听);"document_end":DOM 解析完成、图片等子资源仍在加载时注入;"document_idle":文档加载完成后的空闲时机注入(默认值,性能影响最小)。
world(脚本执行上下文)
- 类型:
String,默认值"ISOLATED" - 可选值:
"ISOLATED":在隔离的 JavaScript 世界中执行,页面自身脚本无法直接访问扩展注入的变量,安全性更高(默认);"MAIN":在主世界(页面自身环境)中执行,可访问/修改页面的全局对象。
exclude_matches(排除模式)
- 类型:
Array of strings(match patterns) - 作用:即使 URL 命中
matches,若同时命中exclude_matches中的模式,则不注入。用于在大范围匹配时精确排除少数页面。
include_globs(额外包含通配)
- 类型:
Array of strings(glob patterns) - 作用:在
matches基础之上,用更灵活的 glob 通配额外圈入符合条件的 URL。
exclude_globs(排除通配)
- 类型:
Array of strings(glob patterns) - 作用:用 glob 通配进一步排除不需要注入的 URL。
match_about_blank
- 类型:
Boolean - 作用:
true时允许注入到about:blank页面(前提是导航源页面本身匹配注入条件)。
match_origin_as_fallback
- 类型:
Boolean - 作用:
true时允许注入到**不透明来源(opaque origin)**的页面——例如通过data:、blob:等协议创建的文档,其来源无法用常规 match pattern 描述,需要该开关兜底。
三、完整 JSON 示例与关键行为
原文档给出的最小可用示例(也是仓库测试扩展实际采用的配置):
"content_scripts": [{ "matches": ["<all_urls>"], "js": ["content.js"], "run_at": "document_end" }]在此基础上,把上述可选属性全部用上,可得到一份覆盖面完整的配置:
"content_scripts": [{ "matches": ["https://*.example.com/*", "https://example.org/*"], "exclude_matches": ["https://example.org/help/*"], "js": ["lib/utils.js", "content.js"], "css": ["content.css"], "run_at": "document_idle", "all_frames": false, "world": "ISOLATED", "include_globs": ["*example*"], "exclude_globs": ["*test*"], "match_about_blank": false, "match_origin_as_fallback": false }]原文档明确的三个注入行为要点,务必牢记:
- 脚本按数组顺序注入:
js数组中靠前的文件先注入,因此依赖关系要按书写顺序排列; - CSS 先于 JavaScript 应用:样式注入发生在 JS 之前,JS 执行时页面已带有注入样式;
- 每个对象是独立注册:同一
content_scripts数组中的不同对象互不影响,可分别面向不同页面/时机配置。
四、源码级解析:Swift 模型与 JSON 映射
iTerm2 的 WebExtensionsFramework 用 SwiftCodable结构体精确建模了该字段,实现位于 ExtensionManifest.swift:
public struct ContentScript: Codable { public let matches: [String] // 必填:URL 匹配模式 public let js: [String]? // 可选:注入的 JS 文件 public let css: [String]? // 可选:注入的 CSS 文件 public let runAt: ContentScriptRunAt? // 可选:注入时机 public let allFrames: Bool? // 可选:是否注入所有 frame public let world: ContentScriptWorld? // 可选:执行上下文 public let excludeMatches: [String]? // 可选:排除的 URL 模式 public let includeGlobs: [String]? // 可选:额外包含 glob public let excludeGlobs: [String]? // 可选:排除 glob public let matchAboutBlank: Bool? // 可选:about:blank 注入 public let matchOriginAsFallback: Bool? // 可选:不透明来源注入 enum CodingKeys: String, CodingKey { case matches case js case css case runAt = "run_at" case allFrames = "all_frames" case world case excludeMatches = "exclude_matches" case includeGlobs = "include_globs" case excludeGlobs = "exclude_globs" case matchAboutBlank = "match_about_blank" case matchOriginAsFallback = "match_origin_as_fallback" } }有两点值得注意:
- 枚举约束了取值:
run_at被建模为ContentScriptRunAt枚举(documentStart/documentEnd/documentIdle),world被建模为ContentScriptWorld枚举(isolated/main),非法取值会在解码阶段直接失败,从源头保证配置合法性(见 ExtensionManifest.swift)。 - snake_case ↔ camelCase 自动转换:通过
CodingKeys显式映射,manifest 中的run_at、all_frames、exclude_matches、match_about_blank等 JSON 字段与 Swift 属性一一对应,顶层ExtensionManifest则通过contentScripts = "content_scripts"挂载该数组(见 ExtensionManifest.swift)。
五、注入与加载链路:从 manifest 到页面脚本
content_scripts不只是一份声明,框架会在扩展加载阶段真正读取并缓存脚本内容。相关逻辑位于 BrowserExtension.swift:
loadContentScripts():遍历 manifest 中的每个ContentScript,逐个调用loadContentScriptResource加载资源;若 manifest 未声明该字段,则安全返回空数组(contentScriptResources = []);loadContentScriptResource(_:):按js数组顺序逐个读取文件内容,组装为ContentScriptResource(包含原始ContentScript配置与已加载的 JS 文本);- 文件缺失会抛出
ContentScriptLoadingError.fileNotFound,IO 失败抛出ioError(见 BrowserExtension.swift)。
也就是说,从配置结构看,matches决定注入范围、js决定注入内容、run_at与world决定注入时机与上下文,这一整套信息最终由注入脚本生成器(BrowserExtensionContentScriptInjectionGeneratorProtocol,见 BrowserExtensionActiveManager.swift)转换为实际的页面注入操作。
六、仓库内真实用例与测试验证
仓库中的测试扩展是理解content_scripts的最佳活教材:
- red-box/manifest.json:在
<all_urls>的每个页面顶部注入一个红色方框,采用run_at: "document_end",是"每页注入 UI"的经典最小案例; - storage-ui-demo/manifest.json:同时声明
permissions(storage)、background.service_worker与content_scripts,展示内容脚本与后台 Service Worker 协同的完整形态; - 单元测试 RedBoxExtensionTests.swift 直接用与 manifest 完全一致的 JSON 做解码断言,并校验
ManifestValidator校验通过; - ExtensionManifestTests.swift 覆盖了三种典型场景:完整解码、字段整体可选(未声明时
contentScripts为nil)、最小必填(仅matches,js/css/run_at均为nil)——这印证了原文档"只有matches必填"的规则。
七、最佳实践与注意事项
- 先写
matches,再考虑收窄:大范围匹配(如<all_urls>)配合exclude_matches/exclude_globs收窄,比逐条列举 URL 更易维护; - 依赖顺序敏感:多个 JS 文件存在依赖时,被依赖文件必须排在
js数组前面; - 尽早注入用
document_start:需要拦截网络请求或最早挂载监听器时使用;默认的document_idle对页面性能影响最小; - 非必要不使用
MAIN世界:ISOLATED隔离了页面与扩展的变量空间,可避免与页面脚本冲突,也防止页面篡改扩展逻辑; match_about_blank与match_origin_as_fallback按需开启:它们应对的是about:blank与data:/blob:等特殊文档来源,普通站点注入无需开启。
八、延伸阅读
- 相邻字段规范:background.md、permissions.md、host_permissions.md;
- Manifest V3 全字段清单:manifest-v3-spec.md;
- 扩展包结构约定:package-structure.md;
- 后台脚本实现规划:Background_Scripts_Implementation_Plan.md;
- 可运行的测试扩展目录:test-extensions。
【免费下载链接】iTerm2iTerm2 is a terminal emulator for Mac OS X that does amazing things.项目地址: https://gitcode.com/gh_mirrors/it/iTerm2
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考