iTerm2 WebExtensions 框架 content_scripts 字段完全指南:从 manifest 声明到注入执行
2026/9/21 1:53:20 网站建设 项目流程

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_versionnameversion为必填项,完整字段清单见 manifest-v3-spec.md)。

  • TypeArray of Objects(对象数组)
  • RequiredNo(可以不声明该字段)
  • 作用:指示扩展宿主(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>是匹配httphttpsfile等协议的全量通配写法。

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" } }

有两点值得注意:

  1. 枚举约束了取值run_at被建模为ContentScriptRunAt枚举(documentStart/documentEnd/documentIdle),world被建模为ContentScriptWorld枚举(isolated/main),非法取值会在解码阶段直接失败,从源头保证配置合法性(见 ExtensionManifest.swift)。
  2. snake_case ↔ camelCase 自动转换:通过CodingKeys显式映射,manifest 中的run_atall_framesexclude_matchesmatch_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_atworld决定注入时机与上下文,这一整套信息最终由注入脚本生成器(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_workercontent_scripts,展示内容脚本与后台 Service Worker 协同的完整形态;
  • 单元测试 RedBoxExtensionTests.swift 直接用与 manifest 完全一致的 JSON 做解码断言,并校验ManifestValidator校验通过;
  • ExtensionManifestTests.swift 覆盖了三种典型场景:完整解码、字段整体可选(未声明时contentScriptsnil)、最小必填(仅matchesjs/css/run_at均为nil)——这印证了原文档"只有matches必填"的规则。

七、最佳实践与注意事项

  1. 先写matches,再考虑收窄:大范围匹配(如<all_urls>)配合exclude_matches/exclude_globs收窄,比逐条列举 URL 更易维护;
  2. 依赖顺序敏感:多个 JS 文件存在依赖时,被依赖文件必须排在js数组前面;
  3. 尽早注入用document_start:需要拦截网络请求或最早挂载监听器时使用;默认的document_idle对页面性能影响最小;
  4. 非必要不使用MAIN世界ISOLATED隔离了页面与扩展的变量空间,可避免与页面脚本冲突,也防止页面篡改扩展逻辑;
  5. match_about_blankmatch_origin_as_fallback按需开启:它们应对的是about:blankdata:/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),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询