最近学习了Chrome插件的开发,总体来说上手还是很容易的,因为浏览器插件本质上依旧是网页,写几个demo基本就了解了他的开发过程。

什么是Chrome插件

正如开头所说的,Chrome插件实际上就是一个网页,由HTML、CSS、JS、图片等资源组成,与网页不同的是,Chrome插件是用来增强浏览器功能的,同时它还有一套属于自己的开发规则和API。

每个插件都由不同的组件构成,这些组件大都包括background scripts,content scripts,options page,UI以及各种逻辑文件,当然,这些文件是否需要是根据插件的功能所决定的。

接下来我将通过开发一个获取页面图片并保存的插件来介绍如何开发一个Chrome插件。

获取页面上的图片

首先,我们需要一个目录来存放这个插件的各个文件。

创建manifest

manifest.json是一个Chrome插件必不可少的文件,它包含了你插件的所有信息。

{
"name": "获取图片",
"description": "获取页面上的所有图片",
"version": "1.0",
"manifest_version": 3
}

只要在目录中包含manifest.json,这个目录就可以被作为一个Chrome插件添加到Chrome当中。

  1. 在浏览器地址栏中输入chrome://extensions,回车以打开浏览器的扩展程序界面
  2. 打开开发人员模式
  3. 点击加载已解压的扩展程序,选择manifest文件所在的目录

这样我们就成功安装了一个扩展,接下来我们要在此基础上完善它。

用户界面

一个插件可以有多种形式的用户界面,这里我们选择弹出层作为用户界面,在插件根目录下创建一个popup.html,这个页面需要包含两个按钮分别用来触发获取图片和保存图片的事件,以及一个用来展示图片的盒子。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<style>
body,
img {
width: 400px;
}
</style>
</head>
<body>
<button id="get">获取</button>
<button id="save">保存</button>
<div id="app"></div>
</body>
</html>

注意,如果在popup.html中有中文出现,一定要在head标签中添加<meta charset="UTF-8" />,以防止出现乱码。

创建完成后,我们需要在manifest.json中声明该页面,以保证浏览器能够正确的读取到它。添加一个action对象,同时将popup.html设置为该对象的default_popup

{
"name": "获取图片",
"description": "获取页面上的所有图片",
"version": "1.0",
"manifest_version": 3,
"action": {
"default_popup": "popup.html",
},
}

为了让我们的插件像个正经的插件,给他添加上图标。我们需要准备16x16、32x32、48x48以及128x128四种大小的图标图片,将它们放到目录中,之后将它们的路径写入manifest.json中。

{
"name": "获取图片",
"description": "获取页面上的所有图片",
"version": "1.0",
"manifest_version": 3,
"action": {
"default_popup": "popup.html",
"default_icon": {
"16": "/images/logo16.png",
"32": "/images/logo32.png",
"48": "/images/logo48.png",
"128": "/images/logo128.png"
}
},
}

为了让图标能够在扩展程序管理页面显示,我们还需要添加一个icons对象。

{
"name": "获取图片",
"description": "获取页面上的所有图片",
"version": "1.0",
"manifest_version": 3,
"action": {
"default_popup": "popup.html",
"default_icon": {
"16": "/images/logo16.png",
"32": "/images/logo32.png",
"48": "/images/logo48.png",
"128": "/images/logo128.png"
}
},
"icons": {
"16": "/images/logo16.png",
"32": "/images/logo32.png",
"48": "/images/logo48.png",
"128": "/images/logo128.png"
}
}

点击扩展程序管理页面中的更新按钮,即可看到添加完用户界面的插件信息了。

功能逻辑

之后我们要为插件添加它应有的功能——获取页面图片。

首先我们先简单梳理一下需求:

  1. 点击popup.html中的获取按钮,拿到当前页面的图片
  2. 点击popup.html中的保存按钮,将拿到的图片保存下来

实际上我们的插件与当前正在活动的页面并不是同一个页面,因此我们需要通过某种方式来将获取图片的js代码发送到当前活动页上,并且还需要这段js代码能够在获取到图片之后将图片发送到popup.html中。

这里我们就需要用到一开始提到的content scripts组件以及content script与popup之间通信的API。content scripts简单来说就是插入页面的脚本,虽说是插入页面的脚本,实际上它与页面原本的js是分割开的,双方不能获取到对方的变量、函数等内容。不过content scripts还是可以获取到dom的。

获取图片

首先添加一个content-script.js,这个脚本主要有两个功能,一是获取图片,二是监听popup传来的消息,然后将获取到的图片作为回信传回去。

chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
// message的数据格式取决于发送时的数据
const { start } = message; if (start) {
const images = document.getElementsByTagName('img');
const imgSrcList = Array.from(images).map((img) => img.src);
sendResponse(imgSrcList);
}
});

之后我们要在manifest.json中声明配置它

{
...
"content_scripts": [
{
"matches": [
"<all_urls>"
],
"js": [
"js/content-script.js"
]
}
]
}

matches声明了content scripts要注入的页面,<all_urls>表示所有页面,js属性声明了要注入的js脚本,除此之外还有css属性声明要注入的css代码、run_at属性声明注入时机等都可以在官方文档中找到。

之后添加一个popup.js为界面上的按钮注册点击事件,并在popup.html中引入它

let srcList;
const getImageBtn = document.getElementById('get'); getImageBtn.addEventListener('click', async () => {
// 获取当前活动页
chrome.tabs.query({ active: true, currentWindow: true }, ([tab]) => {
let message = { start: true };
// 向content scripts发送消息
chrome.tabs.sendMessage(tab.id, message, (res) => {
srcList = Array.from(new Set(res));
// popup中展示图片
const imgList = srcList.map((src) => `<img src="${src}" />`).join(''); document.getElementById('app').innerHTML = imgList;
});
});
}); const saveImageBtn = document.getElementById('save'); saveImageBtn.addEventListener('click', () => {
// 保存图片
});
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<style>
body,
img {
width: 400px;
}
</style>
</head>
<body>
<button id="get">获取</button>
<button id="save">保存</button>
<div id="app"></div>
<script src="./js/popup.js"></script>
</body>
</html>

这里我们需要注意,插件要想和当前活动页面通信就需要首先获取它的tabId,而要获取当前活动页面的tabId则需要给予插件对应的权限,因此我们需要在manifest.json中声明所需要的权限。

{
...
"permissions": [
"activeTab"
]
}

完成后更新一下插件,然后打开想要获取图片的页面点击获取按钮即可(如果页面已经提前打开请刷新一下)

保存图片

js可以通过a标签设置href和download属性来实现批量保存图片,但是这里我们要通过调用chrome的download API来实现。

...

saveImageBtn.addEventListener('click', () => {
chrome.tabs.query({ active: true, currentWindow: true }, ([tab]) => {
if (!srcList) {
document.getElementById('app').innerHTML = '未获取图片';
return;
} srcList.forEach((src) => {
chrome.downloads.download({
url: src,
});
});
});
});

与获取活动页面相同,download API同样也需要获取权限

{
...
"permissions": [
"activeTab",
"downloads"
]
}

这样一个获取当前页面图片的插件就完成了。

参考文章

Chrome插件开发入门的更多相关文章

  1. Chrome插件开发入门(二)——消息传递机制

    Chrome插件开发入门(二)——消息传递机制   由于插件的js运行环境有区别,所以消息传递机制是一个重要内容.阅读了很多博文,大家已经说得很清楚了,直接转一篇@姬小光 的博文,总结的挺好.后面附一 ...

  2. [Chrome插件开发]001.入门

    Chrome插件开发入门 Chrome扩展文件 Browser Actions(扩展图标) Page Actions(地址栏图标) popup弹出窗口 Background Pages后台页面 实战讲 ...

  3. vue.js 初体验— Chrome 插件开发实录

    欢迎大家关注腾讯云技术社区-博客园官方主页,我们将持续在博客园为大家推荐技术精品文章哦~ 作者:陈纬杰 背景 对于经常和动画开发打交道的开发者对于Animate.css这个动画库不会陌生,它把一些常见 ...

  4. chrome插件开发-消息机制中的bug与解决方案

    序言 最近开发chrome插件,涉及到消息传递机时按照教程去敲代码,结果总是不对.研究了大半天终于找到原因,现在记录下. 程序 插件程序参考官网 chrome官网之消息传递机制, 不能FQ的同事也可以 ...

  5. Chrome插件开发,美化网页上的文件列表。chrome-extension,background

    上一篇文章 通过“content-scripts”的方式向页面注入js和css来美化页面,但是有一个弊端:一旦配置好需要注入的页面,之后如果这个页面地址以后发生变化,或者要新加一些URL进来,那么得修 ...

  6. Chrome插件开发,美化网页上的文件列表。chrome-extension,content-scripts

    趁着2018年还剩最后几天,发几篇博客,荒废太久了,惭愧. 最近也是需求驱动,研究了下Chrome插件开发.来看一下我们公司运维提供的日志查看页面 所有项目的日志都参杂在一起,每次去找都很痛苦.慢慢发 ...

  7. chrome插件开发学习(一)

    两个不错的网址: 360chrome插件开发文档:http://open.chrome.360.cn/extension_dev/manifest.html 图灵 chrome插件开发于应用 电子书: ...

  8. 入门chrome插件开发教程和经验总结,一篇就搞掂!

    版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/weixin_44244857/articl ...

  9. Vue插件开发入门

    相对组件来说,Vue 的插件开发受到的关注要少一点.但是插件的功能是十分强大的,能够完成许多 Vue 框架本身不具备的功能. 大家一般习惯直接调用现成的插件,比如官方推荐的 vue-router.vu ...

随机推荐

  1. [报错集]ubuntu中安装oracle java报错

    1.因为版本更新,JAVA15以前的版本都已经没办法下载了,所以要使用oracle java必须使用最近的java15 $ sudo apt-get install oracle-java15-ins ...

  2. 【不在混淆的C】指针函数、函数指针、回调函数

    一.指针函数 函数的返回值是指针类型. int* fun(int a,int b); 指针函数使用: 返回字符串 这里要注意,"1234567890abc"是字符串常量,*p指向的 ...

  3. Linux graphics stack

    2D图形架构 早期Linux图形系统的显示全部依赖X Server,X Client调用Xlib提供的借口向 X Server发送渲染命令,X Server根据 X Client的命令请求向硬件设备绘 ...

  4. MySQL注入流程

    目录 确认注入点 信息收集 数据获取 提权 写个MySQL注入流程的大纲,类似一份全局地图,能指导下一步工作.MySQL注入流程分为四步: 确认注入点 信息收集 数据获取 提权 确认注入点 参考:ht ...

  5. 心脏滴血(CVE-2014-0160)检测与防御

    用Nmap检测 nmap -sV --script=ssl-heartbleed [your ip] -p 443 有心脏滴血漏洞的报告: ➜ ~ nmap -sV --script=ssl-hear ...

  6. 【转载】几张图轻松理解String.intern()

    出处:https://blog.csdn.net/soonfly/article/details/70147205 在翻<深入理解Java虚拟机>的书时,又看到了2-7的 String.i ...

  7. c#(NPOI)DataTable导出execl,execl(支持解析公式)导入DataTable

    NPOI(C#)DataTable导出execl using NPOI.HSSF.UserModel; using NPOI.SS.UserModel; using NPOI.XSSF.UserMod ...

  8. Java 集合框架 04

    集合框架·Map 和 Collections集合工具类 Map集合的概述和特点 * A:Map接口概述 * 查看API可知: * 将键映射到值的对象 * 一个映射不能包含重复的键 * 每个键最多只能映 ...

  9. Windows下用户手册

      (1)net user(查看系统用户) (2)net user 用户名(查看具体某个系统用户详细信息) (3)net user 用户名 密码 /add(在本地组成员创建新用户,此时为Users组) ...

  10. 关于djangorestframework

    djangorestframework技术文档 restfrmework规范 开发模式 普通开发为前端和后端代码放在一起写 前后端分离为前后端交互统统为ajax进行交互 前后端分离 优点:分工明细,节 ...