Article Directory
-
-
- Here is a message
- What files and folders should the chrome plugin contain
- Important Configuration Notes
- Start a plugin
-
- Preparation
-
- Create a folder, such as mine called extensions (the root directory mentioned later refers to this directory)
- Create an img directory under the folder to store some pictures such as logo
- Create an html directory under the folder to store html files
- Create a js directory under the folder to store js files
- Create a css directory under the folder to store css files
- Create a manifest.json file in the root directory of the folder
- pupup part
- background part
- content part
- Go to adware
- Page redirection and cookies
- Record of problems in the process
- code address
-
Here is a message
Manifest version 2 is deprecated, and support will be removed in 2023. See https://developer.chrome.com/blog/mv2-transition/ for more details.
The MV2 version of the chrome plugin will stop supporting in 2023
What files and folders should the chrome plugin contain
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: store html pages
- images: store plugin icons
- scripts: store js files
- styles: storage style
- _locales: store multilingual files
- manifest.json: used to configure all plugin-related configurations, as a chrome entry file, it must be placed in the root directory (
必须存在
)
analyze
- The directory structure is like a web page, which is essentially a website application, a webapp
- Compared with ordinary webapp, more browser-level APIs can be called, including counting money, history records, network request interception, interception of user input, etc.
Important Configuration Notes
manifest.json
For additional configuration, see 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")
}
Start a plugin
Preparation
Create a folder, such as mine called extensions (the root directory mentioned later refers to this directory)
Create an img directory under the folder to store some pictures such as logo
Put in an image likelogo.png
Create an html directory under the folder to store html files
Create a js directory under the folder to store js files
Here, if you want to put a jquery
file for loading first, it is also possible. I will script
import it later for convenience.
Create a css directory under the folder to store css files
Create a manifest.json file in the root directory of the folder
{
"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"
}
}
Then the chrome extension [load the unzipped extension] select extensions
the directory you just created
The effect is as follows
pupup part
-
Create
/html
a newpopup.html
file, and then configure the pathmanifest.json
inaction
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>
-
popup.css
Create new files andpopup.js
files in the css and js directories respectively/* popup.css */ .btn{ width: 100px; height: 30px; font-size: large; }
//popup.js $(".checkbtn").click(function(){ alert($(this).attr('id')); });
-
then reload the extension
Click on the plug-in, the effect is as follows
-
outstanding issues
The checked checkbox will be restored every time, so you need to make a local storage to save the popup changes
background part
-
manifest.json
The config path added inservice_worker
andpermissions
"background":{ "service_worker":"background.js" }, "permissions":["storage"]
Note:
service_worker
instructions- This is a background script that always runs with the plugin
- There is no front-end page and dom is not supported, so jQuery and other js cannot be introduced
- All scripts that need to keep running need to be uninstalled directly
background.js
in the file - It is also not supported
XMLHttpRequest
, so it needs to be usedfetch
instead of xhr request - Be sure to put it in (the extension file root directory, not the computer disk root directory), otherwise a prompt
根目录
will appear when usingservice worker(无效)
- You can view the output in
扩展程序
=>查看视图
click the pop-up console
-
background.js
write files in the root directory//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(); } }
-
Open
popup.js
, delete the original click event, and add scripts to initialize and connect to 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}); } }); });
-
Open it
background.js
and add a script to monitor popup (don’t delete the original one here, just add it later)//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) } }) });
-
reload plugin
-
At this time, you will find two errors
It was found that the
script
importedjquery
report cross-domainThen change to file import
-
Create a new one in the js directory
jquery.js
Go to https://jquery.com/download/ to download
production
version jsand put his content
jquery.js
in -
Modify
popup.html
the jquery import in the file<script src="../js/jquery.js"></script>
-
-
Reload the plug-in and find that the error is fine
-
-
test
The problem of resetting the check every time is already fixed
content part
content can be injected into the browsed webpage and manipulate the dom, so many functions can be realized
manifest.json
content
The configuration added in
"content_scripts":[{
"js":["js/jquery.js","js/content.js"],/*content可以随意引入js,因为其内容会在浏览的网页上直接运行*/
"matches":["*://localhost/*"],/*在哪些网页上运行*/
"run_at":"document_end"/* 在页面加载完成时运行 */
}]
localhost
Note that this is only matching now
-
new
js/content.js
,content.js
write in//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返回值'); });
-
Then
background.js
add the monitoringcontent
code in//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; } } }); } });
Pay attention to this method here
sendResponse
, some do not add this parameter in the callback, resulting in not being able to find -
reload plugin
-
code execution order
-
Plugin initialization phase
- First execute the plug-in initialization monitoring
background.js
andonInstalled
clear the local data
- First execute the plug-in initialization monitoring
-
Manually click the plug-in icon and check the plug-in
- Execute method
popue.js
toready
initialize - Click the button to trigger
click
the method to modify the local data
- Execute method
-
page refresh phase
- method
content.js
of executionsendMessage
- method
background.js
of executiononMessage
- read local data
sendMessage
Determine whether to arrive based on local datacontent
- method
-
Go to adware
Explanation: The judgment for the advertisement here is 类名为 .ad
the element
Such as my vue page
<div>
<h2 class="ad">第一条广告</h2>
<h2 class="ad">第二条广告</h2>
<h2 class="ad">第三条广告</h2>
<h2>这里是正常的数据</h2>
</div>
-
popup.html
add one in去广告按钮
<div class="btn"> 去广告<input id="removeAD" class="checkbtn" type="checkbox" /> </div>
-
In
background.js
the monitoring content part, increaseremoveAD
the judgment of//如果是存入的removeAD按钮 case 'removeAD': chrome.tabs.query({ active: true, currentWindow: true }, function(tabs){ chrome.tabs.sendMessage(tabs[0].id, { LocalDB: LocalDB});//发送到content }); break;
-
The judgment added in
content.js
the monitoringbackground.js
partremoveAD
case 'removeAD': //隐藏含有ad的元素,来达到去广告的效果 $(".ad").hide(); break;
-
Reload the plug-in, check the page
去广告
, and then refresh the page, and found that the advertisement is gone
Page redirection and cookies
And popup
the same, content
the data will not be saved after closing. When we want to put the data on the B page after getting the data on the A page, the content
obtained data will not be passed in the direct jump, so it is background
easy to save the local data with the link. came in handy
UserNick
Case: Display the cookie of csdn localhost:8081
in
-
manifest.json
Configure [domain name script matching], [authority] and [host authority] in"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" }]
What must be paid attention to here is that it must be able to match the url, otherwise it may cause
页面脚本无反应
or获取不到cookie
-
popup.html
add button in<div class="btn"> csdn<input id="checkCsdnUserNick" class="checkbtn" type="checkbox" /> </div>
-
background.js
Addcsdn按钮
judgment forcase '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
Addcsdn按钮
judgment forcase 'checkCsdnUserNick': if(LocalDB.step==2){ $("body").append('<h1>'+LocalDB.cookie+'</h1>'); } break;
-
Reload the plug-in,
csdn.net
open the plug-in in the middle, check itcsdn
, and then refresh the page to see the effectIt will get the nickname in
csdn.net
Zhongzhongcookie
, and then jump to itlocalhost:8081
for display
Record of problems in the process
-
Unchecked runtime.lastError: The message port closed before a response was received.
This problem is usually caused by other plugins, pay attention to troubleshooting, find the affected plugins and disable them
Most people are caused by [Xunlei] plug-in or [Oil Monkey] plug-in
-
There is an additional [Error] button next to the extension [Remove]
-
If there is an error message, just follow the prompts to troubleshoot
-
If there is no error message, try to remove the extension and reload it
-
Check whether it is not used together
sendMessage
withsendResponse
Each
sendMessage
needs andsendResponse
respondsThat is to say, in each
chrome.runtime.onMessage.addListener
callback function, you need to usesendResponse
to returnSee https://blog.csdn.net/m0_37729058/article/details/89186257
-
-
service worker can't
content.js
seeconsole.log
The reason is because this js is embedded in the page, so it needs to be viewed in the console of the web page used instead of
service worker
-
Can't get cookie
The possible reasons are as follows
-
Without authorization
host_permissions
, the console will report an errorUnchecked runtime.lastError: No host permissions for cookies at url: "https://www.csdn.net/".
Check
manifest.json
this configuration, if it is not added or not matched, it will cause this problem -
Check
chrome.cookies.get
that this methodurl
is completely correct
-