介绍
浏览器插件本质上就是利用前端的 html\CSS\JavaScript 等技术, 借用浏览器对外提供的 API, 实现各种不同的功能
插件组成
首先先看一下我们要开发的插件的各个文件组成:
manifest.JSON : 我们在项目的根文件必须要有一个命名为 manifest.JSON 的文件, 它是整个插件的功能入口, 用来告诉浏览器插件的一些基本信息, 及需要加载和执行的资源文件等, 里面包含一些必填项:
name 插件的名字
version 插件版本
manifest_version manifest 的版本
description 插件的描述(选填)
- {
- "name": "hello extension",
- "description": "A Base Extension For Test",
- "version": "1.0",
- "manifest_version": 2,
- }
icons 在扩展程序管理界面, 呈现的图标, 可以设置不同的尺寸的选项, 用来适配不同的场景
- {
- "icons": {
- "16": "images/extension_icon16.png",
- "32": "images/extension_icon32.png",
- "48": "images/extension_icon48.png",
- "128": "images/extension_icon128.png"
- },
- }
background 在扩展程序被开启时, 会首先触发执行 background 选项中指定的 JS 资源, 并且一直存在于扩展程序的整个生命周期, 直到扩展程序被关闭或者删除, background 一直被用来做任务和状态的控制管理工作
- // scripts 子选项指定了需要执行的 JS 文件的路径及文件名
- {
- "background": {
- "scripts":["background.js"],
- "persistent": false
- }
- }
background.JS 通常最外层使用监听事件 Chrome.runtime.onInstalled.addListener(()=>{})初始化插件, 监听插件安装成功后, 会触发对应的逻辑开始工作
permissions 属性值为一个数组, 申请 Chrome API 的权限, 只有在这个选项中申请了才能使用 (比如通过 XMLHttpRequest 跨域请求数据, 访问浏览器选项卡(tabs), 获取当前活动选项卡(activeTab), 浏览器通知(notifications), 设置插件激活规则(declarativeContent), 类似 localStorage 的存储(storage) 等)
- {
- "permissions": [
- "http://xxx.com/api"
- "tabs",
- "activeTab",
- "notifications",
- "declarativeContent",
- "storage"
- ],
- }
定义插件的主要功能的选项有两个: browser_action,page_action 两者选择其中一个
browser_action 提供的功能面向所有网站, 插件图标一直是激活的状态
- {
- "browser_action": {
- "default_popup": "popup.html" // 指定 click 插件图标时, 展示的页面
- "default_icon": "images/icon.png", // 指定浏览器工具栏展示的插件的图标
- "default_title": "display tooltip" // 当鼠标悬浮在插件图片上方时, 展示的文字, 叫 tooltip; 如果没有这个配置选项, 则悬浮时显示 menifest.JSON 中的 name 选项值
- }
- }
page_action 只针对对应目标网站提供的功能, 插件会在 background 页设置激活插件的规则, 只有满足条件的网页的插件才是激活的, 其他网站插件是不可用的, 插件的 icon 是灰的
在 background script 里,
Chrome.runtime.onInstalled.addListener(()=>{})
初始化中使用
Chrome.declarativeContent
定义插件被激活的规则
- {
- "page_action":{
- "default_popup": "popup.html", // 指定 click 插件图标时, 展示的页面
- "default_icon": "hello_extension.png" // 指定浏览器工具栏展示的插件的图标
- "default_title": "display tooltip"
- },
- }
- Chrome.runtime.onInstalled.addListener(function() {
- // Replace all rules ...
- Chrome.declarativeContent.onPageChanged.removeRules(undefined, function() {
- // With a new rule ...
- Chrome.declarativeContent.onPageChanged.addRules([
- {
- // That fires when a page's URL contains a'g' ...
- conditions: [
- new Chrome.declarativeContent.PageStateMatcher({
- pageUrl: { urlContains: 'g' }, //url 的内容中包含字母 g 的, 插件才会被激活
- })
- ],
- // And shows the extension's page action.
- actions: [ new Chrome.declarativeContent.ShowPageAction() ]
- }
- ]);
- });
- });
popup.HTML
popup.HTML 是使用 browser_action 或者 page_action 指定的 default_popup 选项, 表示点击插件图标会触发的 HTML 资源, 其与普通的 HTML 页面的区别就是不能使用内联 script, 其他都一样 it can contain links to stylesheets and script tags, but does not allow inline JavaScript.
options_page 设置插件的选项页面, 配置了此选项后, 在插件上鼠标右键时, 会有一个'选项'按钮, 点击后会进入 options_page 对应的页面
- {
- "options_page":"options.html"
- }
chrome_url_overrides 设置可替换的 Chrome 默认页面
newtab: 新建标签时打开的页面
bookmarks: 书签页面
history: 历史记录
- {
- "chrome_url_overrides":{
- "newtab": "newTab.html"
- }
- }
常用到的 Chrome API
Chrome.tabs
Chrome.tabs.create(object createProperties, function callback) 创建新的标签. 注: 无需请求 manifest 的标签权限, 此方法也可以被使用. Parameters createProperties ( object )
windowId ( optional integer ) 创建新标签的目标窗口. 默认是当前窗口 .
index ( optional integer ) 标签在窗口中的位置. 值在零至标签数量之间.
url ( optional string ) 标签导航的初始页面. 完整的 URL 必须包含一个前缀 (如'http://www.google.com', 不能写为'www.google.com'). 相对 URL 则与扩展所在的页面相对, 默认值为新标签页面.
selected ( optional boolean ) 标签是否成为选中标签. 默认为 true.
pinned ( optional boolean ) 标签是否被固定. 默认值为 false.
callback ( optional function )
Callback function 回调 参数 应该如下定义:
function(Tab tab) {...}; tab ( Tab ) 所创建的标签的细节, 包含新标签的 ID.
Chrome.tabs.executeScript(integer tabId, object details, function callback) 向页面注入 JavaScript 脚本执行 Parameters
tabId ( optional integer ) 运行脚本的标签 ID; 默认为当前窗口所选中的标签.
details ( object ) 要执行的脚本内容, 可选 code 或者 file, 但不能同时选两者.
code ( optional string ) 要执行的脚本代码.
file ( optional string ) 要执行的脚本文件.
allFrames ( optional boolean ) true 的时候, 给所有 frame 执行脚本. 默认为 false, 只给顶级 frame 执行脚本.
callback ( optional function ) 所有脚本执行后会被调用的回调.
Chrome.contextMenus 当前页面, 选中内容后右键展示的内容
在 manifest.JSON 中设置权限
{"permissions": ["contextMenus", "storage"]}
放在 background.JS 中, 初始化之后的回调函数中, 使用
Chrome.contextMenus.create({})
创建内容目录
- Chrome.runtime.onInstalled.addListener(function() {
- //...
- Chrome.contextMenus.create({
- "id": "sampleContextMenu",
- "title": "Sample Context Menu",
- "contexts": ["selection"]
- });
- });
插件安装
进入扩展程序管理界面 Chrome://extensions
开启'开发者模式'
可以选择'加载已解压的扩展程序', 将本地开发目录上传上去即可
可以使用'打包扩展程序', 生成. ctx 后缀的扩展程序, 就可以发布到 google 应用市场了
插件调试
注意:
每次刷新页面, 都会执行 browser_action 或 page_action 指定的 popup.HTML 资源
background 指定的 JS 资源只在插件安装时执行, 之后就一直存在进程中, 不会重复执行
调试步骤
在浏览器工具栏右键插件图标
点击'审查弹出内容', 进入控制台
切换到 Source 栏, 即可看到 browser_action 或 page_action 指定的资源, 设置断点
切换到 Console 栏, 输入 location.reload(), 发现原有的页面重新进行了加载, 同时 browser_action 或 page_action 指定的资源也重新执行了一遍, 并在设置的断点处停下来, 等待 debug
参考链接
Chrome 扩展程序 https://developer.chrome.com/extensions
如何从零写一个 Chrome 扩展 https://www.zhihu.com/question/20179805
来源: https://juejin.im/post/5c834de35188257e8f616948