当前位置:网站首页>chrome插件开发入门-保姆级攻略
chrome插件开发入门-保姆级攻略
2022-08-11 10:35:00 【蓝枫秋千】
文章目录
这里先插播一条消息
Manifest version 2 is deprecated, and support will be removed in 2023. See https://developer.chrome.com/blog/mv2-transition/ for more details.
MV2版本的chrome插件在2023年停止支持
chrome插件应该包含哪些文件及文件夹
D:.
│ manifest.json
│
├─html
│ index.html
│
├─images
│ icon-128.png
│ icon-16.png
│
├─scripts
│ background.js
│
├─styles
│ main.css
│
└─_locales
├─en
│ messages.json
│
└─zh_CN
messages.json
- html:存放html页面
- images:存放插件图标
- scripts:存放js文件
- styles:存放样式
- _locales:存放多语言文件
- manifest.json:用来配置所有和插件相关的配置,作为chrome入口文件,必须放在根目录(
必须存在
)
分析
- 目录结构像一个web网页,他的本质上就是一个网站类应用,是一个webapp
- 相对于普通的webapp,还可以调用更多的浏览器层面的api,包括数钱、历史记录、网络请求拦截、截获用户输入等等
重要配置说明
manifest.json
额外的配置参见https://blog.csdn.net/sysuzjz/article/details/51648163
{
"manifest_version": 3, // 清单版本号,建议使用 版本 3,版本 1和2 是旧的,已弃用,不建议使用
"name": "first-test-plugin", // 插件名称
"version": "0.0.1", // 插件版本
"description": "这里是第一个测试插件", // 描述,可写可不写
"icons":
{
"16": "images/custom/16x16.png",
"48": "images/custom/48x48.png",
"128": "images/custom/128x128.png"
},
// !!!browser_action和page_action只能添加一个
"browser_action": //浏览器级别行为,所有页面均生效
{
"default_icon": "images/custom/16x16.png", // 图标的图片
"default_title": "Hello lanfengqiuqian", // 鼠标移到图标显示的文字
"default_popup": "html/popup.html" // 单击图标后弹窗页面
},
"page_action": //页面级别的行为,只在特定页面下生效
{
"default_icon":
{
"24": "images/custom/24x24.png",
"38": "images/custom/38x38.png"
},
"default_popup": "html/popup.html",
"default_title": "Hello lanfengqiuqian"
},
"author": "lanfengqiuqian", // 可选填写
"automation": false, // 是否开启自动化
"background": // 背景页的脚本路径,一般为插件目录的相对地址
{
"scripts": [
"scripts/background.js",
"scripts/devtools-page.js"
]
},
"devtools_page": "html/devtools-page.html", // 在开发工具中的页面
"content_scripts": [ // 内容脚本一般植入会被植入到页面中, 并且可以控制页面中的dom
{
"js": ["js/else-insert.js"], // 这里面的数组都是可以放多个的
"css": ["css/else-insert.css"],
"matches": ["<all_urls>"] // 被植入到页面,只在这些站点下 content_scripts会运行
}
],
"permissions": [ // 安装的时候提示㤇的权限
"cookies", // 使用cookies
"webRequest", // 使用web请求
"http://*", // 可以通过executeScript或者insertCSS访问的网站地址。如: https://*.google.com/
"management", //
"storage", // 使用本地存储
"tabs", // 操作标签
"contextMenus" //右键菜单
]
"default_locale ": "zh_CN" //默认语言(比如"zh_CN")
}
开始手撸一个插件
准备工作
创建一个文件夹,如我的叫 extensions (之后说的根目录都是指这个目录下)
文件夹下创建一个 img 目录,用于存放一些logo之类的图片
放入一张图片,如logo.png
文件夹下创建一个 html 目录,用于存放html文件
文件夹下创建一个 js 目录,用于存放js文件
这里如果你想先放一个jquery
文件用于加载也是可以的,我后面为了方便使用的是script
引入
文件夹下创建一个 css 目录,用于存放css文件
文件夹根目录下创建一个 manifest.json 文件
{
"manifest_version":3,
"name":"这是插件名称",
"version":"0.0.1",
"description":"这是插件描述",
"action":{
"default_title":"这是鼠标移上去时提示文字",
"default_popup":"html/popup.html"
},
"icons":{
"16":"img/logo.png",
"32":"img/logo.png",
"48":"img/logo.png",
"128":"img/logo.png"
}
}
然后chrome扩展程序【加载已解压的扩展程序】选择刚才创建的extensions
目录
效果如下
pupup部分
在
/html
新建一个popup.html
文件,然后在manifest.json
中的action
配置popup
的路径"action":{ "default_title":"这是鼠标移上去时提示文字", "default_popup":"html/popup.html" }
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <link rel="stylesheet" type="text/css" href="../css/popup.css" /> </head> <body> <div class="btn"> 测试<input id="TEST" class="checkbtn" type="checkbox" /> </div> </body> <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script> <script src="../js/popup.js"></script> </html>
在css和js目录中分别新建
popup.css
和popup.js
文件/* popup.css */ .btn{ width: 100px; height: 30px; font-size: large; }
//popup.js $(".checkbtn").click(function(){ alert($(this).attr('id')); });
然后重载扩展程序
点击插件,效果如下
待解决问题
每次勾选的checkbox都会被还原,所以接下来需要做一个本地存储来保存popup的改变
background部分
在
manifest.json
中加入service_worker
的配置路径和permissions
"background":{ "service_worker":"background.js" }, "permissions":["storage"]
注意:
service_worker
说明- 这个是一直伴随插件运行的后台脚本
- 没有前端页面,不支持dom,所以不能引入jQuery和其他js
- 所有需要保持运行的脚本都需要直接卸载
background.js
文件里 - 同样也不支持
XMLHttpRequest
,所以需要使用fetch
来替代xhr请求 - 一定要放在
根目录
(扩展文件根目录,不是电脑磁盘根目录),否则在使用的时候会出现service worker(无效)
提示 - 可以在
扩展程序
=>查看视图
点击弹出的控制台查看输出
在根目录写
background.js
文件//background.js chrome.runtime.onInstalled.addListener(() => { DBdata("clear");//清除插件保存的本地数据 }); //插件用的数据都存储在storage.local中 function DBdata(mode,callback,data){ //操作本地存储的函数 if(mode=="set"){ //保存本地数据 console.log('set-LocalDB'); chrome.storage.local.set({ LocalDB: data}); }else if(mode=="get"){ //获取 chrome.storage.local.get('LocalDB', function(response) { typeof callback == 'function' ? callback(response) : null; }); }else if(mode=="clear"){ //清空 chrome.storage.local.clear(); } }
打开
popup.js
,把原来的点击事件删掉,在其中加入初始化和连接service_worker的脚本//popup.js window.bgCommunicationPort = chrome.runtime.connect();//初始化bgCommunicationPort $(".checkbtn").click(function(){ bgCommunicationPort.postMessage({ //发送到bg,键值可以自由设置 Direct : $(this).attr('id'),//目标 Content : '测试内容',//内容 step : 0//步骤 }); }); $(document).ready(function(){ //打开popup时触发,读取之前存储的参数 bgCommunicationPort.postMessage({ fromPopup:'getDB'});//向background发送消息 bgCommunicationPort.onMessage.addListener(function(receivedPortMsg) { //监听background console.log(receivedPortMsg);//这是background发来的内容 if(receivedPortMsg&&receivedPortMsg.Direct){ $(".checkbtn").prop({ 'checked': false});//初始化按钮 $("#"+receivedPortMsg.Direct).prop({ 'checked': true}); } }); });
打开
background.js
,在其中加入监听popup的脚本(这里不要删除原来的哦,加到后面即可)//background.js chrome.runtime.onConnect.addListener(function(port) { //接收到popup port.onMessage.addListener(function(receivedMsg) { //监听popup发来的内容receivedMsg if(receivedMsg.fromPopup&&receivedMsg.fromPopup=='getDB'){ //如果接收到了getDB,这里读取数据并返回相当于初始化popup页面 DBdata('get',function(res){ port.postMessage(res.LocalDB);//发送到popup }); }else{ //如果不是,则说明是收到来自popup手动点击设置的数据,存入以用于popup打开时展示 DBdata('set','',receivedMsg) } }) });
重载插件
这个时候会发现有两个报错
发现是用
script
引入的jquery
报跨域那么就改为文件引入呗
在js目录下新建
jquery.js
到https://jquery.com/download/去下载
production
版本的js然后把他的内容放到
jquery.js
中修改
popup.html
文件中的jquery引入<script src="../js/jquery.js"></script>
重载插件,发现报错都好了
测试
每次重置勾选的问题已经好了
content部分
content可以注入到浏览的网页,操作dom,所以就可以实现很多功能了
manifest.json
中加入content
的配置
"content_scripts":[{
"js":["js/jquery.js","js/content.js"],/*content可以随意引入js,因为其内容会在浏览的网页上直接运行*/
"matches":["*://localhost/*"],/*在哪些网页上运行*/
"run_at":"document_end"/* 在页面加载完成时运行 */
}]
注意这里现在只是匹配的localhost
哦
新建
js/content.js
,在content.js
中写入//content.js manifest匹配地址的页面在刷新时会直接执行这里的代码 chrome.runtime.sendMessage(chrome.runtime.id, { //当页面刷新时发送到bg fromContent: 'getDB' }); chrome.runtime.onMessage.addListener(function(senderRequest, sender, sendResponse) { //接收到bg console.log('demo已运行'); var LocalDB=senderRequest.LocalDB; console.log(LocalDB); switch(LocalDB.Direct){ case 'TEST': console.log(123123); break; default: break; } // 不写会报错 Unchecked runtime.lastError: The message port closed before a response was received. sendResponse('这里是content返回值'); });
然后
background.js
中加入监听content
的代码//background.js chrome.runtime.onMessage.addListener(function (senderRequest, sender, sendResponse) { //接收到content // 不写会报错 Unchecked runtime.lastError: The message port closed before a response was received. sendResponse({ msg: '接收到content' }); console.log(senderRequest); if (senderRequest.fromContent && senderRequest.fromContent == 'getDB') { //接收到fromContent:getDB DBdata('get', function (res) { //从本地取数据 if (res.LocalDB) { var LocalDB = res.LocalDB; switch (LocalDB.Direct) { //如果是存入的TEST按钮 case 'TEST': chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) { chrome.tabs.sendMessage(tabs[0].id, { LocalDB: LocalDB }, function (res) { console.log('接收content的回调', res); });//发送到content }); break; default: break; } } }); } });
这里注意
sendResponse
这个方法,有的没有在回调中加上这个参数,导致找不到重载插件
代码执行顺序
插件初始化阶段
- 先执行插件初始化监听
background.js
中onInstalled
,清除本地数据
- 先执行插件初始化监听
手动点击插件图标,勾选插件
- 执行
popue.js
的ready
方法进行初始化 - 点击按钮触发
click
方法修改本地数据
- 执行
网页刷新阶段
- 执行
content.js
的sendMessage
方法 - 执行
background.js
的onMessage
方法 - 读取本地数据
- 根据本地数据决定是否
sendMessage
到content
- 执行
去广告插件
说明:这里对于广告的判断是类名为 .ad
的元素
如我的vue页面
<div>
<h2 class="ad">第一条广告</h2>
<h2 class="ad">第二条广告</h2>
<h2 class="ad">第三条广告</h2>
<h2>这里是正常的数据</h2>
</div>
在
popup.html
中增加一个去广告按钮
<div class="btn"> 去广告<input id="removeAD" class="checkbtn" type="checkbox" /> </div>
在
background.js
中监听content部分增加对于removeAD
的判断//如果是存入的removeAD按钮 case 'removeAD': chrome.tabs.query({ active: true, currentWindow: true }, function(tabs){ chrome.tabs.sendMessage(tabs[0].id, { LocalDB: LocalDB});//发送到content }); break;
在
content.js
中监听background.js
部分增加removeAD
的判断case 'removeAD': //隐藏含有ad的元素,来达到去广告的效果 $(".ad").hide(); break;
重载插件,勾选页面中的
去广告
,然后刷新页面,发现广告已经没有了
页面跳转和cookie
和popup
一样,content
关闭之后也不会保存数据,当我们在A页面获取数据之后想要放到B页面上去,在content
直接跳转是不会把获取到的数据传过去的,所以和background
链接保存本地数据就派上用场了
案例:将csdn的cookie的UserNick
显示在localhost:8081
中
在
manifest.json
中配置【域名脚本匹配】、【权限】和【主机权限】"permissions":["storage", "cookies"], "host_permissions": [ "*://www.csdn.net/*" ], "content_scripts":[{ "js":["js/jquery.js","js/content.js"], "matches":["*://localhost/*", "*://www.csdn.net/*"], "run_at":"document_end" }]
这里千万要注意的是一定要能够匹配上的url,否则可能引起
页面脚本无反应
或者获取不到cookie
在
popup.html
中增加按钮<div class="btn"> csdn<input id="checkCsdnUserNick" class="checkbtn" type="checkbox" /> </div>
在
background.js
中增加对于csdn按钮
的判断case 'checkCsdnUserNick': console.log('LocalDB', LocalDB) //popup设置数据的时候有个step属性,在多步操作的时候就开始发挥作用了 if(LocalDB.step==0){ LocalDB.step = 1;//将step设置成1 chrome.storage.local.set({ LocalDB: LocalDB//保存到本地数据 },function() { chrome.tabs.update(null, { //将前台页面跳转到设置的url // 这里的url不用带斜杠 / url: 'https://www.csdn.net' }); }); }else if(LocalDB.step==1){ //因为csdn的地址我们也匹配了所以content在跳转到csdn之后会还是会回来,不同的是step已经是1了 chrome.cookies.get({ //获取cookie 'url': "https://www.csdn.net", 'name': 'UserNick' }, function(cookie) { console.log('cookie', cookie); console.log(cookie.value);//获取到的值 LocalDB.cookie=cookie.value;//把获取到的值放到本地数据的cookie属性里 LocalDB.step = 2;//将step设置成2 chrome.storage.local.set({ //获取到cookie之后跳转到第二个页面 LocalDB: LocalDB//保存到本地数据 },function() { chrome.tabs.update(null, { //将前台页面跳转到设置的url url: 'http://localhost:8081/' }); }); }); }else if(LocalDB.step==2){ //第二步 chrome.tabs.query({ active: true, currentWindow: true}, function(tabs){ //发送到content chrome.tabs.sendMessage(tabs[0].id, { LocalDB: LocalDB}); }); } break;
在
content.js
中增加对于csdn按钮
的判断case 'checkCsdnUserNick': if(LocalDB.step==2){ $("body").append('<h1>'+LocalDB.cookie+'</h1>'); } break;
重载插件,到
csdn.net
中开启插件,勾选csdn
,然后刷新页面就能看到效果会获取
csdn.net
中cookie
中的昵称,然后跳转到localhost:8081
,进行显示
过程中问题记录
Unchecked runtime.lastError: The message port closed before a response was received.
这个问题通常是由于其他插件引起的,注意排查,找到受影响的插件禁用即可
大多数人是由于【迅雷】插件或者【油猴】插件引起的
扩展【移除】旁边多了一个【错误】的按钮
如果有错误提示,根据提示排查即可
如果没有错误提示,尝试将扩展移除重新加载即可
检查是否没有把
sendMessage
和sendResponse
配套使用每一个
sendMessage
都需要和sendResponse
进行呼应也就是说,在每一个
chrome.runtime.onMessage.addListener
的回调函数中,需要使用sendResponse
进行返回可以参见https://blog.csdn.net/m0_37729058/article/details/89186257
service worker看不到
content.js
的console.log
原因是因为这个js是嵌入到页面中的,所以需要在使用的网页的控制台查看,而不是
service worker
无法获取到cookie
可能原因如下
没有授权
host_permissions
,控制台会报错Unchecked runtime.lastError: No host permissions for cookies at url: "https://www.csdn.net/".
检查
manifest.json
中的此项配置,没有添加或者没有匹配上都会造成这个问题检查
chrome.cookies.get
这个方法中的url
是否完全正确
代码地址
边栏推荐
- 【应用SLAM技术建立二维栅格化地图】
- 运动健康服务场景事件订阅,让应用推送“更懂用户”
- 【luogu CF1286E】Fedya the Potter Strikes Back(字符串)(KMP)(势能分析)(线段树)
- 疫情当前,如何提高远程办公的效率,远程办公工具分享
- Typora and basic Markdown syntax
- VideoScribe卡死解决方案
- The mathematical knowledge required for neural networks, the mathematical foundation of neural networks
- collect awr
- HDRP shader to get shadows (Custom Pass)
- 安装nodejs
猜你喜欢
漫画手绘之临摹篇
卷积神经网络梯度消失,神经网络中梯度的概念
Primavera Unifier custom report creation and print sharing
大疆2022秋招笔试 —— 最小时间差、数组的最小偏移量
LeetCode·每日一题·1417.重新格式化字符串·模拟
How to analyze the neural network diagram, draw the neural network structure diagram
STM32入门开发 LWIP网络协议栈移植(网卡采用DM9000)
【中央任务调度系统—通信开发】
如何给女朋友解释什么是缓存穿透、缓存击穿、缓存雪崩?
神经痛分类图片大全,神经病理性疼痛分类
随机推荐
使用.NET简单实现一个Redis的高性能克隆版(七-完结)
&gt; 家乡旅游景点网页作业制作 网页代码运用了DIV盒子的使用方法,如盒子的嵌套、浮动、margin、border、backgro
当科学家决定搞点“花里胡哨”的东西
Have you encountered this kind of error? flink-sql writes to clickhouse
训练一个神经网络要多久,神经网络训练时间过长
Segmentation Learning (loss and Evaluation)
Algorithm---Jumping Game (Kotlin)
错误代码: 1118 - Row size too large (> 8126). Changing some columns to TEXT or BLOB may help. In current
【无标题】(完美解决)uni-app 小程序下拉刷新后刷新图标无法正常恢复的问题
SAP Product Enhancement Technology Review
[Central Task Scheduling System - Communication Development]
HStreamDB v0.9 released: Partition model extension, support for integration with external systems
华为WLAN技术:AC/AP 实验
VMWare中安装的win10,新增其他盘符,如:E盘,F盘等
SAP 产品增强技术回顾
数据库的索引和其底层数据结构
logstash/filebeat只接收最近一段时间的数据
The mathematical knowledge required for neural networks, the mathematical foundation of neural networks
解决 Pocess finished with exit code 1 Class not found 和 Command line is too long. Shorten the command
Database Basics