文章目录

  • 这里先插播一条消息
  • chrome插件应该包含哪些文件及文件夹
  • 重要配置说明
  • 开始手撸一个插件
    • 准备工作
      • 创建一个文件夹,如我的叫 extensions (之后说的根目录都是指这个目录下)
      • 文件夹下创建一个 img 目录,用于存放一些logo之类的图片
      • 文件夹下创建一个 html 目录,用于存放html文件
      • 文件夹下创建一个 js 目录,用于存放js文件
      • 文件夹下创建一个 css 目录,用于存放css文件
    • 文件夹根目录下创建一个 manifest.json 文件
    • pupup部分
    • background部分
    • content部分
    • 去广告插件
    • 页面跳转和cookie
  • 过程中问题记录
  • 代码地址

这里先插播一条消息

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_CNmessages.json
  1. html:存放html页面
  2. images:存放插件图标
  3. scripts:存放js文件
  4. styles:存放样式
  5. _locales:存放多语言文件
  6. manifest.json:用来配置所有和插件相关的配置,作为chrome入口文件,必须放在根目录(必须存在

分析

  1. 目录结构像一个web网页,他的本质上就是一个网站类应用,是一个webapp
  2. 相对于普通的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部分

  1. /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>
    
  2. 在css和js目录中分别新建popup.csspopup.js文件

    /* popup.css */
    .btn{width: 100px;height: 30px;font-size: large;
    }
    
    //popup.js
    $(".checkbtn").click(function(){alert($(this).attr('id'));
    });
    
  3. 然后重载扩展程序

    点击插件,效果如下

  4. 待解决问题

    每次勾选的checkbox都会被还原,所以接下来需要做一个本地存储来保存popup的改变

background部分

  1. manifest.json中加入service_worker的配置路径和permissions

    "background":{"service_worker":"background.js"
    },
    "permissions":["storage"]
    

    注意:service_worker说明

    1. 这个是一直伴随插件运行的后台脚本
    2. 没有前端页面,不支持dom,所以不能引入jQuery和其他js
    3. 所有需要保持运行的脚本都需要直接卸载background.js文件里
    4. 同样也不支持XMLHttpRequest,所以需要使用fetch来替代xhr请求
    5. 一定要放在根目录(扩展文件根目录,不是电脑磁盘根目录),否则在使用的时候会出现service worker(无效)提示
    6. 可以在扩展程序=>查看视图点击弹出的控制台查看输出
  2. 在根目录写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();}
    }
    
  3. 打开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) {//监听backgroundconsole.log(receivedPortMsg);//这是background发来的内容if(receivedPortMsg&&receivedPortMsg.Direct){$(".checkbtn").prop({'checked': false});//初始化按钮$("#"+receivedPortMsg.Direct).prop({'checked': true});}});
    });
    
  4. 打开background.js,在其中加入监听popup的脚本(这里不要删除原来的哦,加到后面即可)

    //background.js
    chrome.runtime.onConnect.addListener(function(port) {//接收到popupport.onMessage.addListener(function(receivedMsg) {//监听popup发来的内容receivedMsgif(receivedMsg.fromPopup&&receivedMsg.fromPopup=='getDB'){//如果接收到了getDB,这里读取数据并返回相当于初始化popup页面DBdata('get',function(res){port.postMessage(res.LocalDB);//发送到popup});}else{//如果不是,则说明是收到来自popup手动点击设置的数据,存入以用于popup打开时展示DBdata('set','',receivedMsg)}})
    });
    
  5. 重载插件

    1. 这个时候会发现有两个报错

      发现是用script引入的jquery报跨域

      那么就改为文件引入呗

      1. 在js目录下新建jquery.js

        到https://jquery.com/download/去下载production版本的js

        然后把他的内容放到jquery.js

      2. 修改popup.html文件中的jquery引入

        <script src="../js/jquery.js"></script>
        
    2. 重载插件,发现报错都好了

  6. 测试

    每次重置勾选的问题已经好了

content部分

content可以注入到浏览的网页,操作dom,所以就可以实现很多功能了

  1. manifest.json中加入content的配置
"content_scripts":[{"js":["js/jquery.js","js/content.js"],/*content可以随意引入js,因为其内容会在浏览的网页上直接运行*/"matches":["*://localhost/*"],/*在哪些网页上运行*/"run_at":"document_end"/* 在页面加载完成时运行 */
}]

注意这里现在只是匹配的localhost

  1. 新建js/content.js,在content.js中写入

    //content.js   manifest匹配地址的页面在刷新时会直接执行这里的代码
    chrome.runtime.sendMessage(chrome.runtime.id, {//当页面刷新时发送到bgfromContent: 'getDB'
    });chrome.runtime.onMessage.addListener(function(senderRequest, sender, sendResponse) {//接收到bgconsole.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返回值');
    });
    
  2. 然后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:getDBDBdata('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这个方法,有的没有在回调中加上这个参数,导致找不到

  3. 重载插件

  4. 代码执行顺序

    1. 插件初始化阶段

      1. 先执行插件初始化监听background.jsonInstalled,清除本地数据
    2. 手动点击插件图标,勾选插件

      1. 执行popue.jsready方法进行初始化
      2. 点击按钮触发click方法修改本地数据
    3. 网页刷新阶段

      1. 执行content.jssendMessage方法
      2. 执行background.jsonMessage方法
      3. 读取本地数据
      4. 根据本地数据决定是否sendMessagecontent

去广告插件

说明:这里对于广告的判断是类名为 .ad 的元素

如我的vue页面

<div><h2 class="ad">第一条广告</h2><h2 class="ad">第二条广告</h2><h2 class="ad">第三条广告</h2><h2>这里是正常的数据</h2>
</div>
  1. popup.html中增加一个去广告按钮

    <div class="btn">去广告<input id="removeAD" class="checkbtn" type="checkbox" />
    </div>
    
  2. 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;
    
  3. content.js中监听background.js部分增加removeAD的判断

    case 'removeAD'://隐藏含有ad的元素,来达到去广告的效果$(".ad").hide();break;
    
  4. 重载插件,勾选页面中的去广告,然后刷新页面,发现广告已经没有了

页面跳转和cookie

popup一样,content关闭之后也不会保存数据,当我们在A页面获取数据之后想要放到B页面上去,在content直接跳转是不会把获取到的数据传过去的,所以和background链接保存本地数据就派上用场了

案例:将csdn的cookie的UserNick显示在localhost:8081

  1. 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

  2. popup.html中增加按钮

    <div class="btn">csdn<input id="checkCsdnUserNick" class="checkbtn" type="checkbox" />
    </div>
    
  3. background.js中增加对于csdn按钮的判断

    case 'checkCsdnUserNick':console.log('LocalDB', LocalDB)//popup设置数据的时候有个step属性,在多步操作的时候就开始发挥作用了if(LocalDB.step==0){LocalDB.step = 1;//将step设置成1chrome.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设置成2chrome.storage.local.set({//获取到cookie之后跳转到第二个页面LocalDB: LocalDB//保存到本地数据},function() {chrome.tabs.update(null, {//将前台页面跳转到设置的urlurl: 'http://localhost:8081/'});});});}else if(LocalDB.step==2){//第二步chrome.tabs.query({active: true, currentWindow: true}, function(tabs){//发送到contentchrome.tabs.sendMessage(tabs[0].id, {LocalDB: LocalDB});       });}break;
    
  4. content.js中增加对于csdn按钮的判断

    case 'checkCsdnUserNick':if(LocalDB.step==2){$("body").append('<h1>'+LocalDB.cookie+'</h1>');}break;
    
  5. 重载插件,到csdn.net中开启插件,勾选csdn,然后刷新页面就能看到效果

    会获取csdn.netcookie中的昵称,然后跳转到localhost:8081,进行显示

过程中问题记录

  1. Unchecked runtime.lastError: The message port closed before a response was received.

    这个问题通常是由于其他插件引起的,注意排查,找到受影响的插件禁用即可

    大多数人是由于【迅雷】插件或者【油猴】插件引起的

  2. 扩展【移除】旁边多了一个【错误】的按钮

    1. 如果有错误提示,根据提示排查即可

    2. 如果没有错误提示,尝试将扩展移除重新加载即可

    3. 检查是否没有把sendMessagesendResponse配套使用

      每一个sendMessage都需要和sendResponse进行呼应

      也就是说,在每一个chrome.runtime.onMessage.addListener的回调函数中,需要使用sendResponse进行返回

      可以参见https://blog.csdn.net/m0_37729058/article/details/89186257

  3. service worker看不到content.jsconsole.log

    原因是因为这个js是嵌入到页面中的,所以需要在使用的网页的控制台查看,而不是service worker

  4. 无法获取到cookie

    可能原因如下

    1. 没有授权host_permissions,控制台会报错Unchecked runtime.lastError: No host permissions for cookies at url: "https://www.csdn.net/".

      检查manifest.json中的此项配置,没有添加或者没有匹配上都会造成这个问题

    2. 检查chrome.cookies.get这个方法中的url是否完全正确

代码地址

github跳转

chrome插件开发入门-保姆级攻略相关推荐

  1. 使用全包通票游玩纽约,这篇保姆级攻略必须收藏

    准备去纽约旅游,你的出行.景点和门票已经规划好了吗?纽约通票(The New York Pass)给大家带来全包通票游玩纽约的保姆级攻略,从签证入境,到景点选择,再到通票购买和使用,手把手教你体验一场 ...

  2. 35岁学嵌入式合适吗_保姆级攻略来了!嵌入式冰箱该怎么选?看这篇就够了

    现在市场上的电冰箱太多了!特别是最近很流行的嵌入式冰箱,让人眼前一亮的现代简约设计下,与家装风格.布局相统一的视觉舒适感让人颇为惊艳. 不过品牌琳琅满目,功能五花八门,硬生挑花了眼.冰箱买了就不会轻易 ...

  3. 软件测试保姆级攻略(第一期 软件的结构组成和网络基础)

    目录 前言 一.软件的组成结构 1.1 软件的定义 1.2常见软件的表达形式(可执行程序,app,网页) 1.3应用程序的架构模式(C/S,B/S) 1.4 软件的组成 1.4.1前后端的交互模式(以 ...

  4. RPD出品:Superpower Squad 保姆级攻略

    一.游戏介绍 1.游戏简介 Superpower Squad是一款基于区块链技术的TPS游戏,以超级英雄主题,由MOBA,RPG,Roguelike和Social Features等游戏玩法组成.超级 ...

  5. 新电脑到手如何验机?保姆级攻略来了

    新买的笔记本电脑到手了怎么验机呢?有什么注意事项?如果买到了翻新机和退货机怎么办? 别担心,小葱今天为大家整理了超全的保姆级新机开荒教程,小白必看哦! 1. 包装检查 首先,我们收到新电脑后,记得先观 ...

  6. 上海交通大学电院夏令营直博保姆级攻略

    目录 写在前面 个人情况 报名[5月25日至6月26日] 面试[7月9日or7月10日] 面试结果通知与双选竞争[8月1日至9月初] 双选的一些TIPS 福(广)利(告)时间:Top1%室友的保研大宝 ...

  7. 一起玩转算法面试,保姆级攻略(附高清无码算法总结导图),建议收藏

    本文已收录至启舰的电子书<逆天改命-程序员的成神之路>,github地址:https://github.com/harvic/FightingCoder  欢迎star.点击[阅读原文]也 ...

  8. 家庭全光纤万兆网络搭建保姆级攻略

    随着时代的进步,万兆设备已经降价到可以被家庭用户接受的程度了,所以部分家庭已经开始考虑10G甚至40G的光网了,但是从电网到光网,有很多不一样的部分. 分名词.设备.施工三部分,光网需要注意的部分全覆 ...

  9. 山东大学软件工程应用与实践——GMSSL开源库(一) ——WINDOWS下GMSSL的安装与编译的超详细保姆级攻略

    2021SC@SDUSC GMSSL简介 GmSSL是一个开源的密码工具箱,支持SM2/SM3/SM4/SM9/ZUC等国密(国家商用密码)算法.SM2国密数字证书及基于SM2证书的SSL/TLS安全 ...

  10. 大型项目废弃fastjson迁移至Gson保姆级攻略

    前言 大家好,又双叒叕见面了,我是天天放大家鸽子的蛮三刀. 在被大家取关之前,我立下一个"远大的理想",一定要在这周更新文章.现在看来,flag有用了... 本篇文章是我这一个多月 ...

最新文章

  1. 死磕Java多线程(五)---理解CPU高速缓存的工作原理 《JAVA性能优化权威指南》 提到过CPU高速缓存未命中率影响线程切换频率
  2. 数字化转型将迎提速黄金期,金融行业如何转型?
  3. app中html静态页面缓存,移动端index.html被缓存问题
  4. 用java api 实现查询 Hive 数据
  5. 如何使用PyCharm调试Python代码
  6. php 将数据库导出为csv,php – 将数据库转换为CSV并将文件保存到服务器上的文件夹 - 程序园...
  7. 三维重构 c++_桐柏3d打印模型生产厂家【博通三维】-博通三维
  8. es6 日期字符串转日期_小数转成百分数,日期字符串互相转换,这几个SQL问题该如何解决?...
  9. 如何用命令行运行python程序_如何使用运行python代码命令行.exe从C应用程序?
  10. QT添加资源和样式表(设计窗口背景图)
  11. PS安装失败解决方法
  12. 使用DOM,SAX解析XML文档
  13. 贝叶斯网络和马尔科夫的冷知识
  14. 身份证真伪的验证(C# / ASP.NET /JS代码)及算法说明
  15. 记一次ASP绕过WTS-WAF
  16. VCL界面控件DevExpress VCL发布v18.1.7|附下载
  17. 汇编语言学习篇2——MASM的环境搭建(win10与Ubuntu1604下的配置)【有问题,待更正】
  18. 接到个商城任务需要接入个微信或者QQ客服,找到了两篇解决文章
  19. java 开发之商品规格属性(SKU)组合算法
  20. tensorflow机器学习之利用CNN卷积神经网络进行面部表情识别的实例代码

热门文章

  1. JsonView 使用方法
  2. C#固高运动控制卡PT模式使用
  3. hbuilder版本更新失败_HbuilderX ios无法自定义安装调试基座
  4. python程序代码大全-Python编程代码示例 - 全文
  5. 常用代码大全(新手入门必备)
  6. 计算机常用代码大全,常用电脑命令大全【图文】
  7. MATLAB 2015B中文安装激活破解方法图文教程
  8. 第三方应用软件检测实验室质量管理体系需要符合哪些要求?
  9. 【虚幻4】浅析UE4中的C++
  10. python前端用什么写_Python 竟然也可以写网页前端了