Extensions are software programs, built on web technologies (such as HTML, CSS, and JavaScript) that enable users to customize the Chrome browsing experience.
一、插件基本组成结构与介绍
1、manifest.json
官网中所有配置项 ;以下将对常见的部分配置项进行讲解。
{
"manifest_version": 3,
"name": "My Extension",
"version": "versionString",
// 『重点』action配置项主要用于点击图标弹出框,对于弹出框接受的是html文件
"action": {
"default_title": "Click to view a popup",
"default_popup": "popup.html"
}
// 通俗易懂
"default_locale": "en",
"description": "A plain text description",
"icons": {...},
"author": ...,
// 『重点』下面将出现的background.js 配置service work
"background": {
// Required
"service_worker": "service-worker.js",
},
// 『重点』下面将出现content_script.js 应用于所有页面上下文的js
"content_scripts": [
{
"matches": ["https://*.nytimes.com/*"],
"css": ["my-styles.css"],
"js": ["content-script.js"]
}
],
// 使用/添加devtools中的功能
"devtools_page": "devtools.html",
}
2、background.js
background script是扩展的事件处理程序; 它包含对扩展很重要的浏览器事件的侦听器。它处于休眠状态,直到触发事件,然后执行指示的逻辑。有效的后台脚本仅在需要时加载,并在空闲时卸载。
要关注两点:
- 不使用时终止,需要时重新启动(类似于事件页面)。
- 无权访问 DOM。(service worker独立于页面)
chrome.runtime.onMessage.addListener((message, callback) => {
const tabId = getForegroundTabId();
if (message.data === "setAlarm") {
chrome.alarms.create({delayInMinutes: 5})
} else if (message.data === "runLogic") {
chrome.scripting.executeScript({file: 'logic.js', tabId});
} else if (message.data === "changeColor") {
chrome.scripting.executeScript(
{func: () => document.body.style.backgroundColor="orange", tabId});
};
});
3、content_script
读取或写入网页的扩展程序使用 content_script。内容脚本包含在已加载到浏览器的页面上下文中执行的 JavaScript。内容脚本读取和修改浏览器访问的网页的 DOM。
content_script
可以通过使用storage/message API来与扩展其他部分进行通信。
注入方式
// manifest.json
{
"name": "My extension",
...
"content_scripts": [
{
// 满足matches匹配的域名
"matches": ["https://*.nytimes.com/*"],
// 注入css
"css": ["my-styles.css"],
// 注入js
"js": ["content-script.js"],
"run_at": "document_idle" | "document_start" | "document_end"
}
],
"permissions": [
"activeTab"
],
}
4、popup
运行于弹窗的html显示 & js脚本
// manifest.json 中引入popup.html
"action": {
"default_title": "Click to view a popup",
"default_popup": "popup.html"
}
// popup.html 引入相关js css等
<html>
<head>
<meta charset="UTF-8">
<title>京东揽才</title>
<link rel="stylesheet" href="./css/popup.css">
<script src="popup.js"></script>
<script src="js/axios.min.js"></script>
</head>
<body>
</body>
</html>
二、基本组成间的通信方式
JS种类 | 可访问的API | DOM访问情况 | JS访问情况 | 直接跨域 |
---|---|---|---|---|
injected script | 和普通JS无任何差别,不能访问任何扩展API | 可以访问 | 可以访问 | 不可以 |
content script | 只能访问 extension、runtime等部分API | 可以访问 | 不可以 | 不可以 |
popup js | 可访问绝大部分API,除了devtools系列 | 不可直接访问 | 不可以 | 可以 |
background js | 可访问绝大部分API,除了devtools系列 | 不可直接访问 | 不可以 | 可以 |
devtools js | 只能访问 devtools、extension、runtime等部分API | 可以访问devtools | 可以访问devtools | 不可以 |
1、content script与background的通信
- 使用
chrome.runtime.sendMessage
发送信息 - 使用
chrome.tabs.sendMessage
接收监听信息
// content_script
// 监听接收信息
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
// 可写成switch形式 监听所有
if (sender === "") {
// do something
}
if (request.from === "cc") {
// from 不是固定词,可使用其他自定义词汇
// do something
}
// 发送回传
sendResponse({number: request.number});
// 修改dom
document.querySelector("#s-usersetting-top").innerText = request.number;
// 重发信息
chrome.runtime.sendMessage({number: request.number + 1}, (response) => {
console.log(
`content script -> background infos have been received. number: ${response.number}`
);
});
});
// background
// 监听消息接收
chrome.runtime.onMessage.addListener((request, sender, sendResponse)=> {
chrome.tabs.query({active: true, currentWindow: true}, (tabs)=> {
chrome.tabs.sendMessage(tabs[0].id,{number: request.number + 1},(response) => {
console.log(
`background -> content script infos have been received. number: ${response.number}`
);
});
});
// 消息回传
sendResponse({number: request.number});
});
2、popup与background的通信
// popup
document.querySelector("#button").addEventListener("click", () => {
const val1 = document.querySelector("#input1").value || "0";
const val2 = document.querySelector("#input2").value || "0";
chrome.runtime.sendMessage({val1, val2}, (response) => {
document.querySelector("#ans").innerHTML = response.res;
});
});
// background
const dealwithBigNumber = (val1, val2) => BigInt(val1) * BigInt(val2) + "";
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
const {val1, val2} = request;
sendResponse({res: dealwithBigNumber(val1, val2)});
});
3、popup与content的通信
// content_script
// 接收popup数据并修改dom
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
// document.querySelector("body").style.setProperty("background", request.color);
$("body").css("background", request.color);
sendResponse({name: 1});
});
chrome.tabs.query(
{
active: true
},(tabs)=>{
if (tabs.length > 0) {
var current = tabs[0];
chrome.tabs.sendMessage(current.id, { action: "getData"}, function (response) {
isCanrecruit = response?response.sourceCanrecruit:null;
showContent()
})
}
});