Chrome 平台 API
一天学会Chrome插件开发
30分钟开发一款抓取网站图片资源的浏览器插件
manifest.json参数详解
Content Security Policy 入门教程
github地址:一款提取网页图片数据的浏览器插件
秒杀插件(seckill)
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入口文件,必须放在根目录
看目录结构,像不像一个网站?Bingo! Chrome插件就是一个网站类的应用,它是用html、javascript、css组成的一个webapp; 相比于通常的webapp, Chrome插件还可以调用更多浏览器层面的api,包括书签、历史记录、网络请求拦截、截获用户输入等等。(PS:插件不要随便乱装哦,很危险滴!)。
要想开发一款浏览器插件,必修有manifest.json文件
如前所述,它包含了一些插件的元数据,作为chrome的入口文件,可以理解为插件的程序清单,那么它到底做了什么事情呢? 结合示例,我们细细来看:
{
// 清单版本号,建议使用 版本 2,版本 1 是旧的,已弃用,不建议使用
"manifest_version": 2,
"name": "chome-plugin", // 插件名称
"version": "1.8.6", // 插件版本
// 这里写些废话,举个栗子,‘应产品要求,杀个程序祭天’
"description": "This is an extension for your chrome",
"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 ELSE", //鼠标移到图标显示的文字
"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 ELSE"
},
// 可选
"author": "ELSE TEAM",
"automation": "...",
// 背景页的脚本路径,一般为插件目录的相对地址
"background":
{
"scripts": [
"scripts/background.js",
"scripts/devtools-page.js"
]
},
"devtools_page": "html/devtools-page.html",
// 内容脚本一般植入会被植入到页面中, 并且可以控制页面中的dom.
"content_scripts": [
{
"js": ["js/else-insert.js"],
"css": ["css/else-insert.css"],
"matches": ["" ]// 被植入到页面,只在这些站点下 content_scripts会运行
}
],
// 数组,声明插件所需要的权限,这里就是很危险的存在了,想干坏事的你是不是很激动!
"permissions": [
"cookies", // 使用cookies
"webRequest", //使用web请求
"http://*", //可以通过executeScript或者insertCSS访问的网站地址。如: https://*.google.com/
"management", //
"storage", //使用本地存储
"tabs", //操作标签
"contextMenus" //右键菜单
]
"default_locale ": "zh_CN" //默认语言(比如"zh_CN")
}
更详细的请看 manifest.json参数详解
content-scripts
内容脚本一般植入会被植入到页面中, 并且可以控制页面中的dom. 我们可以利用它实现屏蔽网页广告, 定制页面皮肤等操作. 在manifest.json中的基本配置如下:
{
"content_scripts": [{
"matches": [
"http://*/*",
"https://*/*"
],
"js": [
"lib/jquery3.4.min.js",
"content_script.js"
],
"css": ["base.css"]
}],
}
以上代码中我们定义了content_scripts允许注入的页面范围, 插入页面的js以及css, 这样我们就能轻松改变某一个页面的样式.比如我们可以在页面中注入一个按钮:
popup是用户点击插件图标时打开的一个小窗口,当失去焦点后窗口就立即关闭,我们一般用它来处理一些简单的用户交互和插件说明。
由于popup窗口也是一个网页,所以我们一般会建立一个popup.html和popup.js用来控制popup的页面展示和交互.我们在manifest.json中配置如下:
{
"page_action": {
"default_title": "小夕图片提取插件",
"default_popup": "popup.html"
},
}
这里要注意一点的是,我们在popup.html中不能直接使用script脚本,需要用引入脚本文件的方式.如下:
<html>
<head>
<title>在线图片提取工具title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
head>
<body>
<div class="pop-wrap">
div>
<script src="lib/jquery3.4.min.js">script>
<script src="popup.js">script>
body>
html>
background页面主要用来提供一些全局配置, 事件监听, 业务转发等.举几个常用案例:
1,定义右键菜单
,background.js 文件
const systems =
{
a: '趣谈前端',
b: '掘金',
c: '微信'
}
// 谷歌浏览器加载监听事件
chrome.runtime.onInstalled.addListener(function (){
for (let key of Object.keys(systems)){
// 上下文菜单
chrome.contextMenus.create({
id: key,
title: systems[key],
type: 'normal',
contexts: ['selection'],
});
}
});
manifest.json 添加 右键菜单 权限
{
"permissions": ["contextMenus"]
}
在您的浏览器中访问 chrome://extensions 或者 浏览器 --> 设置 --> 更多工具 --> 扩展程序 进入扩展程序管理页面。
对于一个相对复杂的浏览器插件来说,我们不仅仅只操作dom或者提供基本的功能就行了,我们还需要向第三方或者自己的服务器抓取有用的页面数据,这个时候就需要用到插件的通信机制了.
因为content_script脚本存在于当前页面,受同源策略影响,导致我们无法将捕获到的数据传给第三方平台或者自己的服务器, 所以我们需要基于浏览器的通信API.一下是谷歌浏览器插件的通信流程:
由官方文档可知popup可以直接访问background页的方法,所以popup可以直接与其通信:
background.js
var getData = (data) =>{
console.log('拿到数据:' + data)
}
popup.js
let bgObj = chrome.extension.getBackgroundPage();
bgObj.getData(); // 访问bg的函数
1,使用chrome的tabs API进行消息通知
参数请看 chrome.tabs
popup.js : 发送消息给content_script和接收消息
// 给当前标签页的 content_script 发送消息给
chrome.tabs.query({
active: true, currentWindow: true}, function (tabs){
chrome.tabs.sendMessage(tabs[0].id, "activeBtn", function (response){
console.log(response);
});
}
);
// 接收消息
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse){
console.log(sender.tab ?
"from a content script:" + sender.tab.url :
"from the extension");
if (request.greeting == "hello")
sendResponse({
farewell: "goodbye"});
});
content_script接收和发送消息:
// 接收消息
chrome.runtime.onMessage.addListener(function (message, sender, sendResponse){
if (message == "activeBtn"){
// ...
sendResponse( {
farewell: "激活成功"
});
}
});
// 主动发送消息
chrome.runtime.sendMessage({
greeting: "hello"}, function (response){
console.log(response, document.body);
// document.body.style.backgroundColor="orange"
});
2,采用如下方式进行长连接
content_script.js
var port = chrome.runtime.connect( {
name: "徐小夕"
});
port.postMessage({
Ling: "你好"
});
port.onMessage.addListener(function (msg)
{
if (msg.question == "你是做什么滴?")
port.postMessage({
answer: "搬砖"
} );
else if (msg.question == "搬砖有钱吗?")
port.postMessage( {
answer: "木有"
} );
});
popup.js
chrome.runtime.onConnect.addListener(function (port){
port.onMessage.addListener(function (msg){
if (msg.Ling == "你好")
port.postMessage({
question: "你是做什么滴?"
});
else if (msg.answer == "搬砖")
port.postMessage({
question: "搬砖有钱吗?"
});
else if (msg.answer == "木有")
port.postMessage({
question: "太难了."
} );
});
});
3,数据存储传递消息
chrome.storage用来针对插件全局进行数据存储,我们在任何一个页面(popup或content_script或background)下存储了数据,我们在以上三个页面都可以获取到, 具体用法如下:
获取数据
chrome.storage.sync.get('imgArr', function (data){
console.log(data)
});
// 保存数据
chrome.storage.sync.set({
'imgArr': imgArr}, function (){
console.log('保存成功');
});
// 另一种方式
chrome.storage.local.set({
key: value}, function (){
console.log('Value is set to ' + value);
});
作者:徐小夕
链接:https://www.imooc.com/article/303109
来源:慕课网
本文大部分内容首次发布于慕课网