【转载】从零深入Chrome插件开发
Chrome插件简介
Chrome插件,官方名称extensions(扩展程序);为了方便理解,以下都称为Chrome插件,或者简称插件,那么什么是Chrome插件呢?
扩展程序是自定义浏览体验的小型软件程序。它们让用户可以通过多种方式定制
Chrome
的功能和行为。
插件程序提供了以下几个功能:
- 生产力工具:
- 网页内容丰富
- 信息聚合
- 乐趣和游戏
我们可以通过点击更多工具 -> 扩展程序
来查看我们所有安装的插件,或者直接打开插件标签页。
那么学习开发插件有什么意义呢?我们为什么要来学习插件开发呢?个人总结下,有以下几方面的意义:
- 增强浏览器功能,实现属于自己的定制插件功能
- 了解现有的插件,对其功能进行优化改进
获取插件
大多数Chrome用户从Chrome网上应用店获得插件程序。世界各地的开发人员会在Chrome网上应用店中发布他们的插件,经过Chrome的审查并向最终用户提供。
但是由于一些众所周知的原因,我们并不能访问网上应用店,但同时Chrome又要求插件必须从它的Chrome应用商店下载安装,这仿佛是一个绕不开的死循环,不过俗话说魔高一尺道高一尺一
,下面我们会讲解如何从本地加载插件,绕开网上应用店的限制。
插件如何工作?
插件是基于Web技术构建的,例如HTML、JavaScript和CSS。它们在单独的沙盒执行环境中运行并与Chrome浏览器进行交互。
插件允许我们通过使用API修改浏览器行为和访问Web内容来扩展和增强浏览器的功能。插件通过最终用户UI和开发人员API进行操作:
- 扩展用户界面,这为用户提供了一种一致的方式来管理他们的扩展。
- 扩展的API允许浏览器本身的扩展的代码访问功能:激活标签,修改网络请求等等。
要创建插件程序,我们需要组合构成插件程序的一些资源清单,例如JS文件和HTML文件、图像等。对于开发和测试,可以使用扩展开发者模式将这些“解压”加载到Chrome中。如果我们对自己开发出来的插件程序感到满意,就可以通过网上商店将其打包并分享给其他的用户。
插件的原则
我们编写的插件想要发布到Chrome网上应用店
中,就必须遵守网上应用店政策,它规定了以下几点:
- 插件必须满足一个定义狭窄且易于理解的单一目的。单个插件可以包含多个组件和一系列功能,只要一切都有助于实现一个共同的目的。
- 用户界面应该是最小的并且有意图。它们的范围可以从简单的图标到打开一个带有表单的新窗口。
一个简单的小插件
Chrome插件并没有很严格的项目结构要求,比如src、public、components等等,因此我们如果去看很多插件的源码,会发现每个插件的项目结构,甚至项目下的文件名称都大相径庭;但是在根目录下我们都会找到一个manifest.json
文件,这是插件的配置文件,说明了插件的各种信息;它的作用等同于小程序的app.json和前端项目的package.json。
我们在项目中创建一个最简单的manifest.json
配置文件:
{
// 插件名称
"name": "Hello Extensions",
// 插件的描述
"description" : "Base Level Extension",
// 插件的版本
"version": "1.0",
// 配置插件程序的版本号,主流版本是2,最新是3
"manifest_version": 2
}
我们经常会点击右上角插件图标时弹出一个小窗口的页面,焦点离开时就关闭了,一般做一些临时性的交互操作;在配置文件中新增browser_action
字段,配置popup弹框:
{
"name": "Hello Extensions",
"description" : "Base Level Extension",
"version": "1.0",
"manifest_version": 2,
// 新增popup弹框
"browser_action": {
"default_popup": "popup.html",
"default_icon": "popup.png"
}
}
然后创建我们的弹框页面popup.html:
<html>
<body>
<h1>Hello Extensions</h1>
</body>
</html>
点击图标后,插件显示popup.html。
为了用户方便点击,我们还可以在manifest.json中设置一个键盘快捷键的命令,通过快捷键来弹出popup页面:
{
"name": "Hello Extensions",
"description" : "Base Level Extension",
"version": "1.0",
"manifest_version": 2,
"browser_action": {
"default_popup": "popup.html",
"default_icon": "popup.png"
},
// 新增命令
"commands": {
"_execute_browser_action": {
"suggested_key": {
"default": "Ctrl+Shift+F",
"mac": "MacCtrl+Shift+F"
},
"description": "Opens popup.html"
}
}
}
这样我们的插件就可以通过按键盘上的Ctrl+Shift+F
来弹出。
加载及调试插件
我们开发的插件需要在浏览器里面运行,打开插件标签页
,打开开发者模式
,点击加载已解压的扩展程序
,选择项目文件夹,就可将开发中的插件加载进来。
开发中更改了代码,点击插件右下角刷新按钮即可重新加载
如果我们的代码中有错误,加载插件后,会显示红色的错误按钮
点击错误按钮以查看错误的日志:
我们上面说过Chrome插件只能从网上应用店中下载安装,但是第三方平台也提供了下载的渠道,下载下来的文件后缀是.crx
的压缩包,现在的问题就是如何将crx文件进行安装了。
从Chrome 73版本开始,谷歌修改了插件策略,不可以随意安装crx文件:如果直接将crx文件拖拽安装可能会提示一下报错:
程序包无效:"CRX_HEADER_INVALID"
我们可以尝试以下几种方法,第一种方法:将crx后缀改为zip,解压后加载已解压的扩展程序
的方式,将插件用开发者模式进行加载。
第二种办法,通过Chrome插件伴侣
,将crx提取到桌面,然后还是用开发者模式进行加载。
使用插件伴侣提取插件后,插件内容默认会被放在你的电脑桌面上,可以把它剪切/复制到任意位置;加载插件选择的文件夹路径时,一定要包含manifest.json文件;加载后请勿删除提取的文件夹。
第三种方法就是用梯子了,直接去网上应用店下载,没有梯子的同学可以使用插件伴侣进行代理,插件伴侣的获取方式下文会给出。
后台background
我们的插件安装后,popup页面也运行了;但是我们也发现了,popup页面只能做临时性的交互操作,用完就关了,不能存储信息或者和其他标签页进行交互等等;这时就需要用到background(后台),它是一个常驻的页面,它的生命周期是插件中所有类型页面中最长的;它随着浏览器的打开而打开,随着浏览器的关闭而关闭,所以通常把需要一直运行的、启动就运行的、全局的代码放在background里面。
background也是需要在manifest.json
中进行配置,可以通过page
指定一张网页,或者通过scripts
直接指定一个js数组,Chrome会自动为js生成默认网页:
{
"background": {
// "page": "background.html",
"scripts": ["background.js"],
"persistent": true
}
}
需要注意的是,page属性和scripts属性只需要配置一个即可,如果两个同时配置,则会报以下错误信息:
Only one of 'background.page', 'background.scripts', and 'background.service_worker' can be specified.
我们给background设置一个监听事件,当插件安装时打印日志:
// background.js
chrome.runtime.onInstalled.addListener(function () {
console.log("插件已被安装");
});
点击查看视图
旁边的背景页
,看到我们设置的background:
storage存储
我们在插件安装时在storage中设置一个值,这将允许多个插件组件访问该值并进行更新操作:
//background.js
chrome.runtime.onInstalled.addListener(function () {
// storage中设置值
chrome.storage.sync.set({ color: "#3aa757" }, function () {
console.log("storage init color value");
});
// 为特定的网址显示图标
chrome.declarativeContent.onPageChanged.removeRules(undefined, function () {
chrome.declarativeContent.onPageChanged.addRules([
{
conditions: [
new chrome.declarativeContent.PageStateMatcher({
pageUrl: { hostEquals: "baidu.com" },
}),
],
actions: [new chrome.declarativeContent.ShowPageAction()],
},
]);
});
});
chrome.declarativeContent
用于精确地控制什么时候显示我们的页面按钮,或者需要在用户单击它之前更改它的外观以匹配当前标签页。
这里调用的chrome.storage和我们常用的localStorage和sessionStorage不是一个东西;由于调用到了storage和declarativeContent的API,因此我们需要在manifest中给插件注册使用的权限:
{
// 新增
"permissions": ["storage", "declarativeContent"],
"background": {
"scripts": ["background.js"],
"persistent": true
}
}
再次查看背景页的视图,我们就能看到打印的日志了;既然可以存储,那也能取出来,我们在popup中添加事件进行获取,首先我们新增一个触发的button:
<!-- popup.html -->
<html>
<head>
<style>
button {
width: 60px;
height: 30px;
outline: none;
}
</style>
</head>
<body>
<button id="changeColor">change</button>
<script src="popup.js"></script>
</body>
</html>
我们再创建一个popup.js
的文件,用来从storage存储中拿到颜色值,并将此颜色作为按钮的背景色:
let changeColor = document.getElementById("changeColor");
changeColor.onclick = function (el) {
chrome.storage.sync.get("color", function (data) {
changeColor.style.backgroundColor = data.color;
});
};
如果需要调试popup页面,可以在弹框中右击 => 检查,在DevTools中进行调试查看。
我们多次打开popup页面,发现页面每次点开按钮都会恢复最开始的默认状态。
获取浏览器tabs
现在,我们获取到了storage中的值,需要逻辑来进一步与用户交互;更新popup.js中的交互代码:
// popupjs
changeColor.onclick = function (el) {
chrome.storage.sync.get("color", function (data) {
let { color } = data;
chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
chrome.tabs.executeScript(tabs[0].id, {
code: 'document.body.style.backgroundColor = "' + color + '";',
});
});
});
};
chrome.tabs
的API主要是和浏览器的标签页进行交互,通过query
找到当前的激活中的tab,然后使用executeScript
向标签页注入脚本内容。
manifest同样需要activeTab
的权限,来允许我们的插件使用tabs
的API。
{
"name": "Hello Extensions",
// ...
"permissions": ["storage", "declarativeContent", "activeTab"],
}
热门推荐
-
浏览(104)
-
浏览(80)
-
浏览(78)
-
浏览(78)
-
浏览(77)