Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >从头开始写一个 Chrome 插件

从头开始写一个 Chrome 插件

作者头像
王兵
发布于 2018-06-14 08:23:51
发布于 2018-06-14 08:23:51
98900
代码可运行
举报
文章被收录于专栏:程序员笔记程序员笔记
运行总次数:0
代码可运行
插件功能
  • 平时对我来说最浪费时间的莫过于刷「知乎」,但是手贱停不下来呀。Chrome 上面装了个 StayFocusd,设定十分钟之后就屏蔽 zhihu 域名。但有时候是真的要上知乎查些东西,每次还得关掉,可一关掉就会「忘记」打开。
  • 我希望能有个人能每隔5分钟就提醒我一次,你今天刷了5分钟了,你今天刷了10分钟了,你今天刷了15分钟了。。。讲真,我觉得这种提醒既温和又有效,当然,也可以变得很不温和,比如把提醒直接发给老板。
  • 本文代码已经放在 github 上了:dingding_robort/chrome_extension
文件结构
  • manifest.json(插件注册 metadata)
  • bg.js(主程序)
  • jquery-3.2.1.min.js(发送 ajax 请求用)
manifest.json
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
  "name": "block zhihu",
  "version": "0.1",
  "description": "Notify dingding every 5 minuntes for browsing zhihu",
  "permissions": [
    "tabs",
    "storage",
    "alarms",
    "idle",
    "https://oapi.dingtalk.com/"
  ],
  "background": {
    "scripts": ["jquery-3.2.1.min.js","bg.js"]
  },
  "manifest_version": 2
}
  • manifest.json:是 chrome 插件必须的一个说明文件,命名也不用改。
  • name、version、description,这些可以随便写。
  • "manifest_version": 2 这个也不用改,是 chrome 的 manifest 文件格式版本。
  • permissions:chrome 插件要调用 chrome 的接口,就需要在这里声明权限,tabs、alarms、idle 都是 chrome API。storage 是 localStorage 存储。下面那个钉钉地址是跨域请求权限。
  • background:这个列表里面的脚本会在后台运行。要知道后台运行的脚本和网页本身的脚本并不在一个进程里,所以直接打开网页审查是看不到这个后台脚本的,如果要调试插件程序的话,要去 extension - inspect views 里面找。如果需要跟网页脚本本身做交互的话,需要增加 content_scripts ​​项。
bg.js
  • 要写这个程序首先需要掌握一些概念:
    • JavaScript:chrome 的插件是由 JavaScript 写的。
    • tabs 行为:这里会用到 chrome tab 的更新(onUpdate)和激活(onActivated)两个行为。也就是 tab 里刷新页面和点击某个 tab。
    • windows 行为:这个程序会用到 windows 焦点状态改变(onFocusChanged)行为。也就是当我切换程序,比如把 chrome 切到后台,把微信切到前台这样的行为。
    • idle 行为:这个程序会用到 idle 的状态变换(onStateChanged)行为,电脑休眠之类的状态。
    • alarms:定时触发某项任务。
    • ajax 请求:发送 get、post 等请求,这里是为了给发送消息给钉钉机器人。
    • localStorge:chrome 的本地储存,可以看做为一个有键值对的字典,值只有 string 一种形式。
  • 程序逻辑结构:
    1. 判断我是不是在去刷知乎了:当一个标签页刷新了 zhihu.com 域名(tab.onUpdate),或者我点到了开着 zhihu.com 的标签页(tab.onActivated),就说明我开始刷知乎了,计时开始。
    2. 判读我刷了多久:当我从 zhihu.com 域名离到别的域名时(tab.onUpdate),或者当我去到别的 tab(tab.onActivated),或者干脆我焦点不在 chrome 上了(windows.onFocusChanged)或者甚至休眠、关机(idle.onStateChanged)算作计时终止。
    3. 发送钉钉请求:如果刷超过一定时间了,直接让钉钉机器人钉你一下。或者也可以简单的使用 alert 在 chrome 上面弹窗。
  • 代码实现:全局常量和初始化本地存储 // 这里其实可以增加更多的域名,比如 youtube.com 、weibo.com之类的,毕竟能刷的又不止知乎。 var track_sites = ["zhihu.com"] // 时间按东八区的时间来算,主要是为了在每天零点清空数据用的。 var GMT = +8 var MINUTE_PER_DAY = 1440 // 每刷几分钟就给出提醒,这里是每 5 分钟就提醒一次。 var TIMEPACE = 5 * 60 //发送钉钉机器人的链接 var NOTIFY_URL = "https://oapi.dingtalk.com/robot/send?access_token=" + "c6d5a2936381dfc29394f3c336bea5fad962d90ffd31809e92d95xxxxxxx" var MOBILE_NUMBER = "176xxxxx619" initLocalStorage(); function initLocalStorage(){ //初始化 localStorage localStorage.clear(); localStorage["is_idle"] = "false"; localStorage["last_site"] = "null"; localStorage["last_time"] = timeNow(); localStorage["total_elapsed_time"] = 0; localStorage["next_alarm_time"] = TIMEPACE; //以每个域名为 key 的每个域名访问了多少时间 //虽然逻辑上并不需要用这个字典,但将来可以扩展成特定的网站每天或者每周给予特定的访问时长。 for (var i in track_sites){ localStorage[track_sites[i]] = JSON.stringify({"elapsed_time": 0}); } } function timeNow(){ // 返回当前时间戳 return Math.round(Date.now()/1000) + GMT * 3600; }
    • track_sites:这里其实可以增加更多的域名,比如 youtube.comweibo.com之类的,毕竟能刷的又不止知乎。
    • GMT:时间按东八区的时间来算,主要是为了在每天零点清空数据用的。
    • MINUTE_PER_DAY:每天有 1440 分钟,不解释。
    • TIMEPACE:每刷几分钟就给出提醒,这里是每 5 分钟就提醒一次。
    • NOTIFY_URLMOBILE_NUMBER:发送钉钉机器人的链接,为什么要用钉钉机器人: http://www.jianshu.com/p/418e4ffbb4e3
    • 强迫症问为什么为什么track_sites这个是小写,其他都是大写?因为(忘记改了,划掉)这个以后做个接口在前台手动增加域名的话,会是个变量。
    • initLocalStorage():清空本地存储,然后增加一些变量,比如 is_idle 电脑是不是在休眠,last_site 上一个访问的站点,total_elapsed_time 总共浪费了多少时间,next_alarm_time 刷到这个时间点就提醒,然后就是以每个域名为 key 的每个域名访问了多少时间的表,虽然逻辑上并不需要用这个字典,但将来可以扩展成特定的网站每天或者每周给予特定的访问时长。
    • timeNow():获取当前时间戳。
  • 代码实现:事件监听 function classifyDomin(domain){ // 检查域名是不是在黑名单里面 var in_list = false; for (var i in track_sites){ if(domain.match(track_sites[i])){ addTimeDelta(track_sites[i]); in_list = true; break } } // 不在黑名单里面的域名作为 null 处理 if(in_list == false){ addTimeDelta("null"); } } function getCurrentTabDomin(){ // 获取当前活跃 tab 的域名 chrome.tabs.query({active: true, lastFocusedWindow: true}, function(tabs){ if (tabs.length == 1){ var url = new URL(tabs[0].url); var domain = url.hostname; classifyDomin(domain); } else if (tabs.length == 0){ addTimeDelta("null"); } else { console.log("奇怪,找到不止一个 tabs active?"); console.log(tabs); } }) } chrome.tabs.onUpdated.addListener(getCurrentTabDomin) chrome.tabs.onActivated.addListener(getCurrentTabDomin) chrome.windows.onFocusChanged.addListener(getCurrentTabDomin) chrome.idle.onStateChanged.addListener(function(idleState){ if (idleState == "active"){ // is_idle 状态记录是为了下面每分钟定时 check 事件,如果 idle 了,就不再 check localStorage["is_idle"] = false; getCurrentTabDomin(); }else{ localStorage["is_idle"] = true; addTimeDelta("null"); } })
    • checkCurrentTab(),获取当前活跃的 tab 的域名,然后去 updateDomin() 去确认这个域名是不是在黑名单里面,然后再去 addTimeDelta()「更新浏览时间」,注:代码中 addTimeDelta() 会在下文实现。
    • tab Update,Activated,还有 windows focus Changed,把checkCurrentTab() 函数绑到这三个事件上。
    • idle.onStateChanged 从电脑休眠中苏醒和恢复时,记录一下 idle 状态,同时如果是从休眠到 active 的状态,等同于 windows focus Changed 事件。
  • 代码实现:更新浏览时间 function updateLocalStorageTime(){ // 更新 localStorage 里的访问时间 var domain = localStorage["last_site"]; var site_log = JSON.parse(localStorage[domain]); timedelta = timeNow() - parseInt(localStorage["last_time"]); site_log["elapsed_time"] = parseInt(site_log["elapsed_time"]) + timedelta; console.log(domain, "elapsed_time: ", site_log["elapsed_time"]); localStorage[domain] = JSON.stringify(site_log); localStorage["total_elapsed_time"] = parseInt(localStorage["total_elapsed_time"]) + timedelta; if(parseInt(localStorage["total_elapsed_time"]) > parseInt(localStorage["next_alarm_time"])){ fireNotification(); } localStorage["last_time"] = timeNow(); } function isElapsedTime(domain){ // 判断刚刚过去的时间段是不是在刷知乎 if(localStorage["last_site"] == "null" && domain != "null"){ localStorage["last_site"] = domain; localStorage["last_time"] = timeNow(); }else if(localStorage["last_site"] != "null"){ updateLocalStorageTime(); localStorage["last_site"] = domain; } }
    • isElapsedTime() 根据上一次事件时正在访问的站点域名,来判断上一段时间是不是在刷知乎。
    • updateLocalStorageTime() 更新一下 localStorage 的各站点访问时间。
  • 代码实现:定时程序 function minLeftMidnight(){ // 距离 0 点还剩下多少分钟,每日清空定时任务 init 时要用 return MINUTE_PER_DAY - Math.round(timeNow()/60) % MINUTE_PER_DAY } chrome.alarms.create("mignight_clear", {delayInMinutes: minLeftMidnight(), periodInMinutes: MINUTE_PER_DAY}); // 每天零点清空 localStorage chrome.alarms.create("minute_check", {periodInMinutes: 1}) // 每分钟检查一下正在浏览的网站,超时发送提醒 chrome.alarms.onAlarm.addListener(function(alarm){ if (alarm.name == "mignight_clear"){ console.log("clear localStorage"); initLocalStorage(); }else if (alarm.name == "minute_check"){ if(localStorage["is_idle"] == true){ console.log("minute_check"); getCurrentTabDomin(); } } })
    • 每天零点触发清空 localStorage 程序
    • 除了特定事件发生会触发检查当前 tab domin 以外,每分钟也触发一次。
  • 代码实现:发送提醒 function notifyDingding(msg){ // 发送 msg 到钉钉提醒 $.ajax({ type: "POST", beforeSend: function(request) { request.setRequestHeader("Content-Type", "application/json; charset=utf-8"); }, url: NOTIFY_URL, data: JSON.stringify({ "msgtype": "text", "text": { "content": msg }, "at": { "atMobiles": [MOBILE_NUMBER] } }), success: function(return_msg){ console.log(return_msg); } }); } function fireNotification(){ // 拼接 msg,弹窗并请求钉钉 let elapsed_time = parseInt(localStorage["next_alarm_time"]) / 60 msg = "今天你已经刷了" + elapsed_time + "分钟知乎了。" console.log(msg); alert(msg); notifyDingding(msg); localStorage["next_alarm_time"] = parseInt(localStorage["next_alarm_time"]) + TIMEPACE; }
    • 钉钉模块跟 python 的差不多,不过是用 ajax 发送的。
    • fireNotification 会直接在浏览器上弹窗提醒,不用钉钉一样能收到。
  • 全部代码可以去 github 看到:
  • 为了看一下效果,我特地刷了半小时的知乎(捂脸):

WX20170823-151825.png

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017.08.23 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
干货 | 盘点 Chrome 插件开发中那些关键的点!
最近在开发者模式下调试 Chrome 插件,发现安装扩展后默认会报错误,提示 v2 版本已经废弃,相关 API 功能将在明年不可使用,建议升级到 v3 版本
AirPython
2022/04/06
7820
干货 | 盘点 Chrome 插件开发中那些关键的点!
全网最详细的谷歌插件开发小册📚
可能是全网最详细的谷歌插件开发小册👏🏻,之前写谷歌插件的时候绕了一圈网上的教程,没有发现比较好的文档教程,索性根据官方文档梳理一遍,避免后面学习的同学继续踩坑!!!
linwu
2023/07/26
1.4K0
chrome extension develop
打开extension调试模式,加载文件目录,在chrome extension按钮出现后,右键inspect popup,添加调试断点,F5进入断点
sofu456
2019/08/29
9030
chrome插件的通讯
2.然后在background.js里面接受,并且进行api访问,拿到结果再回传给contentScript
biaoblog.cn 个人博客
2022/08/11
5940
写一个chrome插件到底有多难?
这周刚好看到一个大眼的玩具,感觉非常有意思。但是只能放在自己的网页上又感觉缺乏使用场景。因此我想到能把他翻成chrome插件,注入到平常浏览的网页上,这样使用场景就丰富了。
4cos90
2022/12/26
5790
Chrome Extension
Chrome插件是一个用Web技术开发、用来增强浏览器功能的软件,它其实就是一个由HTML、CSS、JS、图片等资源组成的一个.crx后缀的压缩包
江米小枣
2020/06/15
2.9K0
【Chrome】931- 何从零开始开发一个 Chrome 插件?
简单来说浏览器插件,是浏览器上的一种工具,可以提供一些浏览器没有的功能,帮你做一些有趣的事情。开发者可以根据自己的喜欢,去实现一些功能。插件基于Web技术(html、css、js)构建。
pingan8787
2021/04/26
1.9K0
【Chrome】931- 何从零开始开发一个 Chrome 插件?
从0开始开发一个chrome插件(3)
});从background.js直接发送消息给content.script.js
JQ实验室
2022/05/05
9880
提高工作效率的神器:基于前端表格实现Chrome Excel扩展插件
Chrome插件,官方名称extensions(扩展程序);为了方便理解,以下都称为插件。 我们开发的插件需要在浏览器里面运行,打开浏览器,通过右上角的三个点(自定义及控制)-更多工具-拓展程序-打开开发者模式。点击"加载已解压的拓展程序,选择项目文件夹,就可将开发中的插件加载进来。 插件是基于Web技术构建的,例如HTML、JavaScript和CSS。它们在单独的沙盒执行环境中运行并与Chrome浏览器进行交互。插件允许我们通过使用API修改浏览器行为和访问Web内容来扩展和增强浏览器的功能。 相信使用Chrome(谷歌浏览器)的小伙伴们都在用Chrome扩展插件(Chrome Extension),类似一键翻译、批量下载网页图片、OneTab、甚至大名鼎鼎的 ”油猴” 等。
葡萄城控件
2022/10/31
3.5K0
提高工作效率的神器:基于前端表格实现Chrome Excel扩展插件
【干货】Chrome插件(扩展)开发全攻略
严格来讲,我们正在说的东西应该叫Chrome扩展(Chrome Extension),真正意义上的Chrome插件是更底层的浏览器功能扩展,可能需要对浏览器源码有一定掌握才有能力去开发。鉴于Chrome插件的叫法已经习惯,本文也全部采用这种叫法,但读者需深知本文所描述的Chrome插件实际上指的是Chrome扩展。
winty
2020/07/23
11.9K1
【干货】Chrome插件(扩展)开发全攻略
如何为豆瓣FM写一个chrome的歌词插件
对于喜欢豆瓣FM的同学来说,没有歌词是件令人苦恼的事,下面我就来总结下怎样为豆瓣FM写一个chrome的歌词插件。 1.需要的技能 首先,你要会javascript,其次你要掌握一点chrome的hack,最后要有一个可以根据歌曲名查到歌词的API。 2.localStorage localStorage与cookie类似,它是存储在客户端浏览器中的数据,它与cookie不同的一点是它没有时间限制。localStorage属于html5中的新特性。因为我们要做chrome的插件,所以按F12弹出开发者模式,
forrestlin
2018/05/23
5720
边开发边测试--故事从闹钟讲起
你开发过alarm相关的应用吗? 你测试过alarm相关的应用吗? 如果答案是肯定的,建议看官停下来拍拍砖。 手机管家新年运营功能有一个招牌:红包闹钟。 功能发布后,最常见的质疑当属:闹钟准吗? 为了回答这个问题,才有了这篇文章,也希望此文对那些闹钟的开发和测试者,有点用。 一. Android Alarm的技术背景 (一)基础API 1.关于闹钟的4个最常用api以及精准性: (1)set(int type,long startTime,PendingIntent pi); Beginning in A
腾讯移动品质中心TMQ
2018/02/02
1.8K0
边开发边测试--故事从闹钟讲起
写html页面没意思,来挑战chrome插件开发
谷歌浏览器插件开发是指开发可以在谷歌浏览器中运行的扩展程序,可以为用户提供额外的功能和定制化的体验。谷歌浏览器插件通常由HTML、CSS和JavaScript组成,非常利于前端开发者。 开发者可以利用这些技术在浏览器中添加新的功能、修改现有功能或者与网页进行交互。
winty
2024/04/25
4970
写html页面没意思,来挑战chrome插件开发
Chrome插件开发
你只需要看完上面那篇文章和掌握一些前端开发基础,就足以自行编写一个 Chrome 插件。本文也是基于上面文章加上自己之前写的插件所记。
愧怍
2022/12/27
4K0
Chrome插件开发
15分钟手摸手教你写个可以操控 Chrome 的插件
友人 A: 通过后端服务或者 python 脚本通信 chrome 插件能够操作浏览器
童欧巴
2021/08/20
1.6K1
15分钟手摸手教你写个可以操控 Chrome 的插件
用Python写了一个不起床让你后悔的闹钟,周末还敢赖床吗
导读 哎 😡 ,别提了自从回到家整个人都懒散了,总被人嫌弃不说还觉得生活没有了盼头,还好在社区认识了一些大佬让我想重新来过做回自己,不在做小丑,于是乎我就想用个东西来提醒我别睡懒觉,然后这篇文章就诞生了。 来吧看看今天的故事。 闹钟 有人说程序员的日常就是反复造轮子,我觉得能在原来的基础上玩出新花样来帮到一些人,做这些事还是挺有趣的。 没有什么高深的学问就是给大家在枯燥的夏日带来一点欢愉。 使用的模块 import time from datetime import datetime from playso
周萝卜
2022/09/28
5370
从 0 开始入门 Chrome Ext 安全(二)-- 安全的 Chrome Ext
在2019年初,微软正式选择了Chromium作为默认浏览器,并放弃edge的发展。并在19年4月8日,Edge正式放出了基于Chromium开发的Edge Dev浏览器,并提供了兼容Chrome Ext的配套插件管理。再加上国内的大小国产浏览器大多都是基于Chromium开发的,Chrome的插件体系越来越影响着广大的人群。
Seebug漏洞平台
2019/12/17
1.5K0
从 0 开始入门 Chrome Ext 安全(二)-- 安全的 Chrome Ext
BiugleJS
老猫-Leo
2023/12/11
1710
Chrome Extension 历史记录、下载记录和存储管理
在现代浏览器扩展开发中,如何高效地管理历史记录、优化下载体验,以及构建灵活的数据存储方案,已经成为开发者们关注的焦点。今天,我们将深入探讨 Chrome 提供的 历史浏览记录 API、下载管理 API 和 存储管理 API,并通过一个实用项目带你快速上手这些功能,让你的插件不仅智能,还贴心。
FunTester
2025/01/23
1510
Chrome Extension 历史记录、下载记录和存储管理
如何快速地开发一个chrome扩展插件
说到现如今最流行的浏览器,那么一定是chrome,无论是它的速度,还是它的稳定性,还是它的简洁,都让人爱不释手,此外,更多的人选择它的理由是它有着丰富的扩展插件,这些扩展插件让你的浏览器变得异常强大,让你的浏览器不仅仅是浏览器。
程序那些事儿
2023/07/24
5730
如何快速地开发一个chrome扩展插件
推荐阅读
相关推荐
干货 | 盘点 Chrome 插件开发中那些关键的点!
更多 >
领券
💥开发者 MCP广场重磅上线!
精选全网热门MCP server,让你的AI更好用 🚀
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验