一、拓展程序的实现
- 拓展程序项目的构成
和前端项目一样,拓展程序也是有Html、CSS、JS文件实现的,现在看来它就是一个静态的前端页面。但是不同的是,拓展程序中还需要额外的一个清单文件,就是manifest.json,清单文件可以理解为一个拓展程序的配置文件,它可以配置你的拓展程序的权限,ICON路径、JS导入路径等。
- 清单示例
{
"manifest_version": 2,
"name": "Touch Fish",
"description": "A basic Chrome extension",
"version": "1.0",
"icons": {
"32": "icon/icon32.png",
"128": "icon/icon128.png"
},
"browser_action": {
"default_popup": "popup.html"
},
"background": {
"scripts": ["js/background.js"]
},
"permissions": [
"activeTab",
"storage",
"webRequest",
"webRequestBlocking",
"notifications",
"<all_urls>",
"proxy"
],
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["js/content-script.js", "js/axios.js","js/encrypt.js","js/basic.js","js/common.js","js/login.js","js/modify_password.js","js/route.js",
"js/utils.js","js/website.js","js/sina.js","js/file.js","js/email.js","js/network.js","js/endpoint.js"
],
"run_at": "document_end",
"all_frames":true
}
]
}
- 清单说明
manifest_version #清单的版本,当前最新的是3版本
description: #如果不上传到应用商店,这个字段随便填
icons: #icon集合
browser_action:
default_popup: #定义拓展程序窗口页面
background: #定义拓展程序后台脚本
permissions: #定义拓展程序的权限
content_scripts: #定义内容脚本
devtools_page: #定义开发者工具页面
二、常用脚本释义
- Content_scripts内容脚本
说明:Content_scripts配置的JS会被注入到浏览器中,它可以获取到整个页面DOM,可以发起HTTP请求,可以控制页面路由,使用浏览器api
实现:通过manifest.json中的content_scripts添加的脚本就是内容脚本。
- Popup.js页面脚本
说明:页面脚本即拓展程序页面所用的脚本,它和前端页面一样,通过script标签注入到popup.html中
实现:通过manifest.json中browser_action中的default_popup指定的页面中所使用的脚本,manifest版本3中参数名用的是action,而不是browser_action。
- 后台脚本Background.js/有默认的html页面
说明:后台脚本是一直运行的,可以通过match_url配置使用该脚本的网站,popup.js中可以直接调用background.js的方法。
实现:通过manifest.json的background参数配置的脚本就是后台脚本。
- Dev.html/dev.js
说明:开发者工具脚本,它是开发者工具面板的页面,通过Devtools的api来创建panels,它和panel.html其实都是以iframe的方式嵌入到devtools.html的页面中的,devtools.html是默认的。
实现:dev.html页面通过manifest.json的devtools_page配置指定。
- Panel.html/panel.js
说明:自定义面板脚本及页面
实现:面板页面引用的js
- Inject脚本
说明:通过background.js向特定页面注入脚本或者manifest的web_accessible_resources参数配置的脚本,可以访问网页dom,不可以使用浏览器api
实现:通过background.js注入或者配置注入
三、通信
Send:
- 短连接
chrome.tabs.sendMessage()
chrome.runtime.sendMessage()
- 长连接
chrome.tabs.connect()
chrome.runtime.connect()
Receive:
chrome.runtime.onConnect.addListener(callback)
chrome.runtime.onMessage.addListener(callback)
说明:长连接与短连接不多说,大家都懂,说下tabs和runtime两个方法的差异,tabs在消息传递时需要tabId,runtime在消息传递需要extensionId。
- 各脚本环境之间通信
- content_scripts与popup之间通信
长连接示例
popup.js发送消息
chrome.tabs.query({active: true, currentWindow: true}, function (tabs) {
var p = chrome.tabs.connect(tabs[0].id, {name:"connect"});
p.postMessage({message:'hello connected'})
});
- content_scripts接收消息
chrome.runtime.onConnect.addListener(p=>{
console.log(p)
p.onMessage.addListener(function(message) {
console.log("Message received from Background.js:", message.message);
// 在这里添加处理消息的逻辑 });
})
短连接示例
popup.js发送消息
chrome.tabs.query({active: true, currentWindow: true}, function (tabs) {
chrome.tabs.sendMessage(tabs[0].id, {message:' hello pop'});
});
content_scripts接收消息
chrome.runtime.onMessage.addListener(p=>{
console.log(p.message)})
- popup.js和background.js通信
长连接示例
popup.js发送
chrome.runtime.connect(extensionId,{name:"con"})
.postMessage({message:'hello111'})
background.js接收
chrome.runtime.onConnect.addListener(function(p) {
p.onMessage.addListener(message=>{
console.log(message.message) })
});
注:为什么第一个示例中没有用runtime.connect,因为runtime.connect是与后台脚本交互的,但是如果popup.js中使用tabs.connect的话,那么background.js和content_scripts都可以接收到消息。
短连接示例
popup.js发送
chrome.runtime.sendMessage({message:'hi'});
background.js接收
chrome.runtime.onMessage.addListener(function (request) {
console.log(request.message)})
注:和长连接不同,如果使用tabs发送,那么background.js就无法收到消息。
- 调用
Popup.js可以直接调用background.js中的方法
var background = chrome.extension.getBackgroundPage()
background.test()
- dev.js | panels.js和background.js直接通信
dev.js发送
var backgroundPageConnection = chrome.runtime.connect({
name: "devtools-page"});
backgroundPageConnection.onMessage.addListener(function (message) {
// Handle responses from the background page, if any
});
backgroundPageConnection.postMessage({
tabId: chrome.devtools.inspectedWindow.tabId,
// scriptToInject: "test.js",
message:'hello'
});
background.js和popup.js都可以收到消息,panels.js和dev.js由于都是以iframe的形式嵌套在devtools.html中的,所以它俩发送消息是一样的。
但是dev.js是面向开发者的,panel.js是面向用户的。
- dev.js和content_scripts
dev.js和content_scripts处于不同的环境中,它们之间如果需要通信,需要使用background.js作为中介。
另:dev.js可以直接访问Dom资源、页面的静态资源、http请求。
chrome.devtools.inspectedWindow.eval('performance', function(result, exceptionInfo) {
if (exceptionInfo) {
console.error('Error:', exceptionInfo);
} else {
console.log('DOM:', result);
}
});
参考文档:API 参考 | Chrome for Developers