对于浏览器插件相信大家都不陌生,谁的浏览器不装几个好用的插件呢,更是有油猴这个强大的神器。但是大家有没有尝试自己去写一个插件呢?对于这个问题,其实很长时间以来我是一直有想法但从来没有付出行动,直到前一段时间有朋友找我写一些关于浏览器自动化的程序,当然如果简单的话,直接在控制台运行js脚本就可以了(但是真的不好用),转念一想,浏览器插件也许也是一个不错的选择,感觉应该不会太难,就去稍微了解了一下,有这个想法另一方面原因之前是有看到关于用c#来直接写浏览器插件的,嗯,没错,就是Blazor。还是花了点时间去研究这个东西,最后发现,极为难用。。。
随后简单看了下开发浏览器插件的原生写法——这不是稍微会一点前端技术就能搞么,恰好,我就懂这么一点。。。
不过最后我并没有用插件去实现这个需求,因为我发现了另外一个简单且好用的东西:Selenium。但是刚刚学会这个东西,总得写个东西来记录一下吧,后面用到的时候也比较好找。
现在的浏览器基本都自带密码记住的功能。但是对于有些网站却并不能做很好的识别,要么输入的位置错乱,要么账号密码错乱。所以最终写了这个插件出来。暂且叫做"密码箱"吧,我们可以自己定义捕获输入框的标识然后赋值进去,来解决上面提到的问题。
这里我们使用到的开发工具是 Visual Studio Code,然后整体看下我们的框架,其实跟我们写前端一样的,只是多了一个manifest.json文件,这也是最重要的一个文件;不过现在大家都用Vue了,一套命令下来应有尽有。
- {
- "name": "密码箱",//插件名称
- "description": "密码箱",//插件描述
- "version": "1.0.0",//插件版本
- "manifest_version": 3,//文件版本2或者3,2目前是主流,3是趋势,谷歌浏览器目前是使用3版本的
- "background": { //常驻后台服务
- "service_worker": "/js/background.js"
- },
- "permissions": ["storage", "activeTab", "scripting", "contextMenus", "tabs"], //需要的权限
- "homepage_url": "https://www.baidu.com",//插件主页地址
- "action": {
- "default_popup": "html/popup.html",//可交互页面
- "default_icon": {
- "16": "/img/icon.png",
- "32": "/img/icon.png",
- "48": "/img/icon.png",
- "128": "/img/icon.png"
- }
- },
- "options_ui": {//插件选项配置
- "page": "/html/options.html",
- "open_in_tab": true
- },
- "icons": {//图标
- "16": "/img/icon.png",
- "32": "/img/icon.png",
- "48": "/img/icon.png",
- "128": "/img/icon.png"
- },
- "host_permissions": ["*://*/*"]//主机权限
- }
- let btn_save = document.getElementById("btn_save");
- let btn_add = document.getElementById("btn_add");
-
-
- init();
-
- function add_row(id){
- let element_str = `
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- `;
- let btn = document.getElementById("btn");
-
- async function getCurrentTab() {
- let queryOptions = { active: true, lastFocusedWindow: true };
- let [tab] = await chrome.tabs.query(queryOptions);
- return tab;
- }
-
- btn.addEventListener("click", async () => {
- let tab = await getCurrentTab();
- chrome.scripting.executeScript({
- target: { tabId: tab.id },
- func: inputs,
- args: [tab.url],
- });
- });
-
-
-
-
- function inputs(url) {
- chrome.storage.sync.get("pwd_box", async (result) => {
-
- let model = result.pwd_box.find((s) => {
- return s.url == url;
- });
-
- if (model != undefined) {
- let user_selector, pwd_selector;
-
- let utag = model.user_tag.split(":", 2);
- switch (utag[0].toLowerCase()) {
- case "id":
- user_selector = document.getElementById(utag[1]);
- break;
- case "class":
- user_selector = document.getElementsByClassName(utag[1])[0];
- break;
- case "name":
- user_selector = document.getElementsByName(utag[1])[0];
- break;
- default:
- break;
- }
-
- user_selector.value = model.user;
- //await sleep(1000);
- let ptag = model.pwd_tag.split(":", 2);
- switch (ptag[0].toLowerCase()) {
- case "id":
- pwd_selector = document.getElementById(ptag[1]);
- break;
- case "class":
- pwd_selector = document.getElementsByClassName(ptag[1])[0];
- break;
- case "name":
- pwd_selector = document.getElementsByName(ptag[1])[0];
- break;
- default:
- break;
- }
- pwd_selector.value = model.pwd;
- }
- });
-
- function sleep(ms) {
- return new Promise((resolve) => setTimeout(resolve, ms));
- }
- }
到此,我们这个插件就写完了;
说实话,我前端技术确实不怎么会,如果有前端大佬的话,发现语法问题希望不吝赐教。(我觉得我写js的方式都比较偏向C#)
最后我们来看下效果吧!
实现效果:
我这个插件做的处理比较简单。大家有兴趣可以自己完善下。最后提一下,V2和V3的写法有很多地方还是不一样的,这里我再推荐几个网址,大家可以去学习下,写的很详细:
【干货】Chrome插件(扩展)开发全攻略 - 我是小茗同学 - 博客园
https://developer.chrome.com/extensions/manifest
最后一个是官网。写的很全面,需要vpn访问。
由简入繁,拿来即用
更多精彩,请搜索公 Z 号:Csharp 小记