Skip to main content

浏览器插件

浏览器插件概述

浏览器插件(也称为扩展程序)是基于 Web 技术(如 HTMLCSSJavaScript)的小型应用,用于增强浏览器功能。用户可以通过应用商店安装这些插件,它们的能力包括:

  • 修改网页内容:如广告拦截或样式修改。
  • 扩展浏览器能力:例如快捷键、标签管理或下载工具。
  • 数据存储与同步:通过浏览器的存储 API 保存配置或数据。
  • 调用浏览器 API:如访问书签、历史记录或拦截网络请求。

插件在用户授权的情况下运行,需要在配置清单中明确声明所需的权限,并遵循沙箱机制以保护用户隐私。

沙箱(Sandbox)

沙箱是一种安全机制,通过隔离运行环境限制程序的访问权限,使其只能在特定范围内操作,从而避免恶意脚本破坏系统或窃取数据。

Chrome 浏览器插件构建基础

要构建 Chrome 插件,需要掌握以下要素:

  • 基础技术:使用 HTML 构建界面、CSS 定义样式、JavaScript 实现逻辑。
  • 核心配置文件manifest.json 是插件的配置清单,用于定义元数据、权限和功能。
  • 核心组件:后台脚本 Service Worker、内容脚本 (Content Script) 和用户界面 (Popup/Action/Options)。
  • 消息传递:各组件之间使用 chrome.runtime.sendMessagechrome.runtime.onMessage 等接口通信。
  • 浏览器 API:通过 chrome.* 命名空间访问浏览器功能,例如 chrome.tabschrome.storage

常见功能与应用

凭借 Chrome 提供的 API,插件可以定制浏览器行为和网页内容。例如:

  • 界面自定义:可在浏览器工具栏显示按钮(action),添加右键菜单项(Menus),或在侧边栏 (Side panel) 中提供 UI 界面。
  • 控制浏览器
    • 覆盖浏览器页面和设置项,如在 manifest.json 中配置 chrome_settings_overrides
    • 使用 chrome.devtools 创建开发者工具页。
    • 使用 chrome.notifications 显示通知。
    • 操作标签页和窗口:通过 chrome.tabschrome.tabGroupschrome.windows 控制浏览器界面。
    • 管理历史记录与书签:调用 chrome.historychrome.bookmarks 等接口。
    • 自定义键盘快捷键:使用 chrome.commands
    • 身份验证:通过 chrome.identity
    • 管理其他插件:使用 chrome.management
    • 更新代理设置:调用 chrome.proxy
    • 管理下载:chrome.downloads
  • 控制网络
    • 注入 JavaScriptCSS 到页面修改行为或样式。
    • 访问当前标签页的数据。
    • 拦截和修改网络请求,通过 chrome.webRequest 或声明式网络请求 API。
    • 调用摄像头、麦克风进行录音或捕获屏幕。
    • 修改网站设置(例如定位、Cookie 权限)。

浏览器插件核心概念

Chrome 插件由多个组件组成,每个组件在沙箱中具有不同的权限:

  • Service Worker:基于事件的后台脚本,用于处理数据、协调插件各部分任务,是扩展的事件管理器。
  • 权限 (Permissions):声明插件需要的浏览器功能或数据访问权。应遵循最小化原则,仅请求必需的权限。
  • 内容脚本 (Content Script):在网页环境中运行,可访问当前页面的 DOM,用于读取或修改页面内容,但无法直接使用大部分 Chrome 扩展 API。
  • Action/Popup:用户与插件交互的界面,运行在扩展上下文中,可直接使用扩展 API,但无法直接访问网页 DOM。
  • 消息传递:由于沙箱隔离,不同组件需通过消息传递接口(如 chrome.runtime.sendMessagechrome.tabs.sendMessagechrome.runtime.onMessage)进行通信。
  • 存储 (Storage):Chrome 提供了 storage API 用于数据持久化(本地或同步)。
  • 匹配模式:用于指定哪些网页或 URL 能触发插件的内容脚本或授予主机权限。
组件权限范围
内容脚本 (Content Script)可访问当前网页的 DOM;无法直接调用大部分扩展 API;需要通过消息与后台脚本通信。
后台脚本 (Service Worker)可访问所有扩展 API,包括操作标签页、存储、网络请求等;无法访问网页 DOM;事件驱动、非持久运行。
弹出页/选项页 (Popup/Options)运行在扩展上下文,可直接使用扩展 API;不能直接访问网页 DOM,如需与页面交互需通过内容脚本。

浏览器插件架构概览

插件项目由多个文件和资源组成,通常包括:

  • 配置清单 (manifest.json):每个插件都必须包含此文件,声明插件名称、版本、权限、图标等信息。
  • 后台脚本 (Service Worker):负责处理事件并在后台运行逻辑。在 Manifest V3 中,后台脚本通过 service_worker 指定,并以懒加载方式响应事件后自动休眠。
  • 界面元素:包括工具栏按钮 (popup)、侧边栏 (side panel)、选项页 (options_page)、开发者工具页 (devtools_page) 等。
  • 内容脚本 (content_scripts):可注入到指定网页,对页面内容进行读取或修改。
  • 设置页 (options_page):供用户配置插件参数的页面。

插件的核心组成关系如图所示(示意图):后台脚本、弹出界面与内容脚本三者通过消息传递协作完成功能,其中 backgroundpopup 通过 chrome.runtime.sendMessage 通讯,而发送给特定页面中的 content script 需使用 chrome.tabs.sendMessage 并指定标签页 ID。

Manifest V3 配置清单

每个插件都需要一个 manifest.json 文件,它提供插件的基本信息,例如名称、版本和权限等。Chrome 目前最新的配置清单版本为 Manifest V3 (MV3)。MV3 更注重安全与用户隐私,提升性能,并改善开发体验。

以下是一个示例 manifest.json,展示了常见的配置项:

{
"manifest_version": 3,
"name": "My Extension",
"version": "0.0.1",
"action": {
// 配置工具栏按钮相关属性
},
"default_locale": "en",
"description": "A plain text description",
"icons": {
"16": "images/icon-16.png",
"32": "images/icon-32.png",
"48": "images/icon-48.png",
"128": "images/icon-128.png"
},
"background": {
"service_worker": "service-worker.js",
"type": "module"
},
"devtools_page": "devtools.html",
"externally_connectable": {
"matches": ["*://*.example.com/*"]
},
"file_system_provider_capabilities": {
"configurable": true,
"multiple_mounts": true,
"source": "network"
},
"homepage_url": "https://path/to/homepage",
"host_permissions": [],
"incognito": "spanning",
"options_page": "options.html",
"permissions": ["tabs"],
"storage": {
"managed_schema": "schema.json"
},
"version_name": "aString",
"web_accessible_resources": []
}

在 MV3 中,某些属性如 background.service_worker 必须指定后台脚本名称。更多配置项请参考官方文档。

权限管理

大多数浏览器 API 调用都需要在 manifest.jsonpermissions 字段中声明。权限分为几类:

  • permissions:需要在安装时授予的权限,例如 tabsstorage 等。
  • optional_permissions:可选权限,用户在运行时选择授予。
  • content_scripts.matches:包含一个或多个 匹配模式,用于指定内容脚本可以注入到哪些主机。
  • host_permissions:声明对某些主机的访问权,也使用匹配模式。例如访问 https://*.example.com/*
  • optional_host_permissions:可选主机权限,用户在运行时授权。

声明权限可以有效限制插件被滥用,如果插件被恶意软件入侵,较小的权限范围可以降低风险。安装或运行时浏览器会根据权限显示警告提示。

一个包含权限的 manifest.json 示例:

{
"name": "Permissions Extension",
"permissions": [
"activeTab",
"contextMenus",
"storage"
],
"optional_permissions": [
"topSites"
],
"host_permissions": [
"https://www.developer.chrome.com/*"
],
"optional_host_permissions": [
"https://*/*",
"http://*/*"
],
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content.js"]
}
],
"manifest_version": 3
}

主机权限

某些 API 除了自身权限还需要主机权限,包括:

  • 从后台脚本或扩展页面发起 fetch() 请求。
  • 通过 chrome.tabs 读取或查询敏感标签页属性(如 URL、标题、faviconUrl)。
  • 以编程方式注入内容脚本。
  • 使用 chrome.webRequest 监控和控制网络请求。
  • 通过 chrome.cookies 访问 Cookie。
  • 使用 chrome.declarativeNetRequest 重定向或修改请求及响应头。

包含警告的权限

如果插件请求多项高风险权限,Chrome 安装界面会向用户显示警告。常见的警告包括:

权限警告说明
http://*/*https://*/**://*/*<all_urls>读取和更改所有网站的数据
https://HostName.com/读取和更改指定网站的数据
accessibilityFeatures.modify更改无障碍设置
clipboardRead / clipboardWrite读取或修改剪贴板数据
debugger访问页面调试后端,读取和更改所有网站数据
downloads管理下载内容
geolocation检测实际位置
history读取和更改浏览历史
notifications显示通知
proxy读取和更改所有网站数据
sessions / history读取和更改所有登录设备上的浏览记录
tabs读取浏览记录

请求较多权限会降低用户信任,因此开发时应尽量采用可选权限或使用功能较弱但无需警告的 API。

Service Worker(后台脚本)

在 Manifest V3 中,Chrome 扩展的后台脚本采用 Service Worker 取代了旧版的 background page。Service Worker 充当插件的“后台大脑”,主要作用包括:

  • 事件响应中心:响应多种事件,例如 chrome.runtime.onInstalled(安装时)、chrome.runtime.onMessage(收到消息时)、chrome.alarms.onAlarm(定时器事件)、chrome.webRequest.onBeforeRequest(监听网络请求)以及 chrome.action.onClicked(点击插件图标时)。
  • 无需打开页面即可在后台运行:Service Worker 与页面无关,当事件触发时被唤醒执行任务,任务完成后自动休眠,提高性能。
  • 协调组件通信:通过 chrome.runtime.sendMessagechrome.runtime.onMessage 协调 popup、content script、options page 等各组件之间的数据交换。
  • 增强安全性:Service Worker 运行在无 DOM 的独立线程中,更难被注入恶意脚本,提高安全性和性能。

匹配模式

匹配模式用于指定一组 URL,以决定内容脚本在哪些页面注入,或授予哪些主机权限。其基本结构为:

<scheme>://<host>/<path>

scheme:必须为 httphttpsfile 或通配符 *(匹配 httphttps)。

host:主机名(如 www.example.com)。可以使用通配符 * 匹配子域名,例如 *.example.com 或仅使用 * 匹配所有域名。通配符必须是第一个字符,紧跟 ./

path:URL 路径(如 /example)。主机权限中路径是必需的但会被忽略,一般使用 /*

匹配模式常用于以下场景:

  • 注入内容脚本。
  • 声明主机权限(某些 API 还需要此权限)。
  • 授予通过网络访问的资源权限(web_accessible_resources)。
  • 设置 externally_connectable.matches 以允许跨站消息发送。

特殊情况

  • "<all_urls>":匹配所有可允许的 URL,会影响所有托管方,因此使用时审核可能更严格。
  • "file:///":允许扩展在本地文件上运行,用户需手动授予此权限。注意使用三个斜杠。
  • 本地主机和 IP 地址:开发时可以使用 http://localhost/* 匹配任何端口的本地主机;IP 地址可以使用 http://127.0.0.1/*http://*:*/* 可匹配任意端口。
  • 顶级域名:Chrome 不支持仅匹配顶级域名,应在各个 TLD 下分别声明,例如 http://google.es/*http://google.fr/*

示例格式

  • https://*/*https://*/:匹配使用 https 协议的所有 URL。
  • https://*/foo*:匹配任意主机上,路径以 foo 开头的 https URL,例如 https://example.com/foo/bar.html
  • https://*.google.com/foo*bar:匹配 google.com 下路径以 foo 开头并以 bar 结尾的 URL。
  • file:///foo*:匹配路径以 foo 开头的任何本地文件。
  • http://127.0.0.1/*http://127.0.0.1/:匹配 IP 地址 127.0.0.1 上的 http URL。
  • http://localhost/*:匹配任何端口的本地主机。
  • *://mail.google.com/*:匹配 http://mail.google.comhttps://mail.google.com

数据存储

Chrome 提供多种 API 用于持久化存储数据,常用的有 chrome.storagechrome.cookies

chrome.storage 模块

chrome.storage 用于在插件内部持久化数据,支持本地存储和云同步。常用方法包括:

方法说明
chrome.storage.local.get(keys)获取本地数据
chrome.storage.local.set(items)设置本地数据
chrome.storage.local.remove(keys)删除指定键
chrome.storage.local.clear()清空全部本地数据
chrome.storage.sync.get/set/remove/clear与本地方法类似,但会同步到云端(空间有限制)
chrome.storage.onChanged.addListener(cb)监听数据变化

示例代码:

// 保存数据到本地
chrome.storage.local.set({ theme: 'dark' });

// 获取数据
chrome.storage.local.get(['theme'], (result) => {
console.log('当前主题:', result.theme);
});

// 删除数据
chrome.storage.local.remove(['theme']);

// 监听变化
chrome.storage.onChanged.addListener((changes, area) => {
if (area === 'local' && changes.theme) {
console.log('主题变更为:', changes.theme.newValue);
}
});

使用 chrome.storage 需要在 manifest.json 中声明权限:

"permissions": [ "storage" ],
localsync 的区别
特性chrome.storage.localchrome.storage.sync
存储位置本地云端同步(需登录 Google 账户)
空间限制较大(约 5 MB)较小(约 100 KB)
是否同步是(可跨设备)
适合用途缓存数据、用户偏好等插件设置项、用户登录信息

如果有特殊需求,可添加 unlimitedStorage 权限取消 chrome.storage.local 的容量限制:

"permissions": ["storage", "unlimitedStorage"]

chrome.cookies 模块

chrome.cookies 允许插件读取、设置和监听网页的 Cookie,可操作当前标签页或指定域名下的 Cookie。常用方法:

方法说明
chrome.cookies.get(details)获取指定 Cookie
chrome.cookies.getAll(details)获取匹配的一组 Cookie
chrome.cookies.set(details)设置 Cookie(可跨域)
chrome.cookies.remove(details)删除 Cookie
chrome.cookies.onChanged.addListener(cb)监听 Cookie 改变事件

示例代码:

// 获取某个 cookie
chrome.cookies.get({ url: 'https://example.com', name: 'session' }, (cookie) => {
console.log(cookie?.value);
});

// 设置 cookie
chrome.cookies.set({
url: 'https://example.com',
name: 'session',
value: 'abc123',
expirationDate: Math.floor(Date.now() / 1000) + 3600,
});

// 删除 cookie
chrome.cookies.remove({ url: 'https://example.com', name: 'session' });

使用 chrome.cookies 需要在 manifest.json 中声明权限,并为访问的域名授予主机权限:

"permissions": ["cookies", "https://example.com/"],

打包发布指南

要发布 Chrome 扩展,需要注册开发者账号并支付一次性费用,然后上传扩展包并通过审核。流程如下:

注册开发者账号

  1. 使用 Google 账号登录 Chrome 网上应用店的开发者信息中心。
  2. 按提示填写个人信息并支付一次性注册费用(约 5 美元)。
  3. 注册完成后即可进入开发者控制台管理扩展。

付费成为开发者

完成账号注册后,需要支付费用以激活开发者资格。支付时可使用国内发行的国际信用卡,选择合适的地区和地址信息即可。

发布流程

  1. 在开发者中心上传扩展的压缩包(包含 manifest.json 和所有资源文件)。
  2. 根据提示配置扩展的描述、图标等元数据。
  3. 如果提示需要验证,请完成 Google 账号的两步验证。
  4. 上传成功后等待审核,审核通过后即可在 Chrome 网上应用店上线。

整个流程需要一定时间,请耐心等待审核结果。