JavaScript實(shí)現(xiàn)谷歌瀏覽器插件開發(fā)的方法詳解
對(duì)于瀏覽器插件相信大家都不陌生,誰(shuí)的瀏覽器不裝幾個(gè)好用的插件呢,更是有油猴這個(gè)強(qiáng)大的神器。但是大家有沒有嘗試自己去寫一個(gè)插件呢?對(duì)于這個(gè)問題,其實(shí)很長(zhǎng)時(shí)間以來(lái)我是一直有想法但從來(lái)沒有付出行動(dòng),直到前一段時(shí)間有朋友找我寫一些關(guān)于瀏覽器自動(dòng)化的程序,當(dāng)然如果簡(jiǎn)單的話,直接在控制臺(tái)運(yùn)行js腳本就可以了(但是真的不好用),轉(zhuǎn)念一想,瀏覽器插件也許也是一個(gè)不錯(cuò)的選擇,感覺應(yīng)該不會(huì)太難,就去稍微了解了一下,有這個(gè)想法另一方面原因之前是有看到關(guān)于用c#來(lái)直接寫瀏覽器插件的,嗯,沒錯(cuò),就是Blazor。還是花了點(diǎn)時(shí)間去研究這個(gè)東西,最后發(fā)現(xiàn),極為難用。。。
隨后簡(jiǎn)單看了下開發(fā)瀏覽器插件的原生寫法——這不是稍微會(huì)一點(diǎn)前端技術(shù)就能搞么,恰好,我就懂這么一點(diǎn)。。。
不過最后我并沒有用插件去實(shí)現(xiàn)這個(gè)需求,因?yàn)槲野l(fā)現(xiàn)了另外一個(gè)簡(jiǎn)單且好用的東西:Selenium。但是剛剛學(xué)會(huì)這個(gè)東西,總得寫個(gè)東西來(lái)記錄一下吧,后面用到的時(shí)候也比較好找。
現(xiàn)在的瀏覽器基本都自帶密碼記住的功能。但是對(duì)于有些網(wǎng)站卻并不能做很好的識(shí)別,要么輸入的位置錯(cuò)亂,要么賬號(hào)密碼錯(cuò)亂。所以最終寫了這個(gè)插件出來(lái)。暫且叫做"密碼箱"吧,我們可以自己定義捕獲輸入框的標(biāo)識(shí)然后賦值進(jìn)去,來(lái)解決上面提到的問題。
這里我們使用到的開發(fā)工具是 Visual Studio Code,然后整體看下我們的框架,其實(shí)跟我們寫前端一樣的,只是多了一個(gè)manifest.json文件,這也是最重要的一個(gè)文件;不過現(xiàn)在大家都用Vue了,一套命令下來(lái)應(yīng)有盡有。
1.先來(lái)看下manifest.json文件的配置,因?yàn)槲覀冏龅谋容^簡(jiǎn)單,所以配置的也并不多,關(guān)于每項(xiàng)配置的含義已經(jīng)在文件中注釋了。
{ "name": "密碼箱",//插件名稱 "description": "密碼箱",//插件描述 "version": "1.0.0",//插件版本 "manifest_version": 3,//文件版本2或者3,2目前是主流,3是趨勢(shì),谷歌瀏覽器目前是使用3版本的 "background": { //常駐后臺(tái)服務(wù) "service_worker": "/js/background.js" }, "permissions": ["storage", "activeTab", "scripting", "contextMenus", "tabs"], //需要的權(quán)限 "homepage_url": "https://www.baidu.com",//插件主頁(yè)地址 "action": { "default_popup": "html/popup.html",//可交互頁(yè)面 "default_icon": { "16": "/img/icon.png", "32": "/img/icon.png", "48": "/img/icon.png", "128": "/img/icon.png" } }, "options_ui": {//插件選項(xiàng)配置 "page": "/html/options.html", "open_in_tab": true }, "icons": {//圖標(biāo) "16": "/img/icon.png", "32": "/img/icon.png", "48": "/img/icon.png", "128": "/img/icon.png" }, "host_permissions": ["*://*/*"]//主機(jī)權(quán)限 }
2.然后我們需要一個(gè)配置頁(yè)面,來(lái)設(shè)置我們需要保存的賬號(hào)信息以及表單元素即options.html和options.js。主要代碼都在options.js中了,所以這里主要放下js的代碼
let btn_save = document.getElementById("btn_save"); let btn_add = document.getElementById("btn_add"); init(); function add_row(id){ let element_str = ` <div class="form"> <div class="form-item"> <label>賬號(hào):</label> <input type="text" class="user"/> </div> <div class="form-item"> <label>密碼:</label> <input type="text" class="pwd" /> </div> <div class="form-item"> <label>網(wǎng)址:</label> <input type="text" class="url"/> </div> </div> <div class="form"> <div class="form-item"> <label>賬號(hào)元素:</label> <input type="text" class="user_tag" /> </div> <div class="form-item"> <label>密碼元素:</label> <input type="text" class="pwd_tag" /> </div> <div class="form-item"> <button class="btn_del">刪除</button> </div> </div> <div class="line"></div> </div>`; let element = document.createElement("div"); element.setAttribute("class", "row"); element.setAttribute("id", "row" + id); element.innerHTML = element_str; document.getElementById("main").appendChild(element); return element; } function bind_rowdel(element,id){ let btn_del = element.getElementsByClassName("btn_del")[0]; btn_del.addEventListener("click", function () { let row = document.getElementById("row" + id); document.getElementById("main").removeChild(row); btn_save.click(); }); } function init(){ chrome.storage.sync.get("pwd_box", function (result) { let save_list = result.pwd_box; if (save_list==undefined||save_list.length == 0) { save_list=[]; save_list.push({ user: "", pwd: "", url: "", user_tag: "", pwd_tag: "", }); } for (let i = 0; i < save_list.length; i++) { let element=add_row(i); element.getElementsByClassName("user")[0].value = save_list[i].user; element.getElementsByClassName("pwd")[0].value = save_list[i].pwd; element.getElementsByClassName("url")[0].value = save_list[i].url; element.getElementsByClassName("user_tag")[0].value = save_list[i].user_tag; element.getElementsByClassName("pwd_tag")[0].value = save_list[i].pwd_tag; bind_rowdel(element,i); } }); } btn_save.addEventListener("click", async () => { let items = document.getElementsByClassName("row"); let save_list = []; for (let i = 0; i < items.length; i++) { save_list.push({ user: items[i].getElementsByClassName("user")[0].value, pwd: items[i].getElementsByClassName("pwd")[0].value, url: items[i].getElementsByClassName("url")[0].value, user_tag: items[i].getElementsByClassName("user_tag")[0].value, pwd_tag: items[i].getElementsByClassName("pwd_tag")[0].value, }); } await chrome.storage.sync.set({ pwd_box: save_list }, null); alert("操作成功"); }); btn_add.addEventListener("click", async () => { let id=new Date().getTime(); let element=add_row(id); bind_rowdel(element,id); });
3.最后就是我們需要做一個(gè)主動(dòng)賦值的操作了。即上面提到的可交互的頁(yè)面:popup.js。當(dāng)然我們也可以寫在background.js中,自動(dòng)監(jiān)聽然后直接賦值,但我這里沒有使用這種方式。
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)); } }
到此,我們這個(gè)插件就寫完了;
到此這篇關(guān)于JavaScript實(shí)現(xiàn)谷歌瀏覽器插件開發(fā)的方法詳解的文章就介紹到這了,更多相關(guān)JavaScript谷歌瀏覽器插件開發(fā)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
jquery中validate與form插件提交的方式小結(jié)
這篇文章主要介紹了jquery中validate與form插件提交的方式小結(jié),需要的朋友可以參考下2016-03-03JS實(shí)現(xiàn)彈出浮動(dòng)窗口(支持鼠標(biāo)拖動(dòng)和關(guān)閉)實(shí)例詳解
這篇文章主要介紹了JS實(shí)現(xiàn)彈出浮動(dòng)窗口,可支持鼠標(biāo)拖動(dòng)和關(guān)閉的功能,界面美觀大方,涉及javascript動(dòng)態(tài)創(chuàng)建對(duì)話框的相關(guān)技巧,需要的朋友可以參考下2015-08-08JS關(guān)于?replace?取值、替換第幾個(gè)匹配項(xiàng)問題小結(jié)
這篇文章主要介紹了JS關(guān)于replace取值、替換第幾個(gè)匹配項(xiàng),本文針對(duì)字符串的替換、截取知識(shí)點(diǎn)做詳細(xì)介紹,結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-05-05個(gè)人總結(jié)的一些JavaScript技巧、實(shí)用函數(shù)、簡(jiǎn)潔方法、編程細(xì)節(jié)
這篇文章主要介紹了個(gè)人總結(jié)的一些JavaScript技巧、實(shí)用函數(shù)、簡(jiǎn)潔方法、編程細(xì)節(jié),本文講解了變量轉(zhuǎn)換、取整同時(shí)轉(zhuǎn)換成數(shù)值型、日期轉(zhuǎn)數(shù)值、類數(shù)組對(duì)象轉(zhuǎn)數(shù)組、進(jìn)制之間的轉(zhuǎn)換等方法技巧,需要的朋友可以參考下2015-06-06批量實(shí)現(xiàn)面向?qū)ο蟮膶?shí)例代碼
本文為大家詳細(xì)介紹下面向?qū)ο蟮睦^承以及如何實(shí)現(xiàn)批量實(shí)現(xiàn)面向?qū)ο?,感興趣的可以參考下哈,希望對(duì)大家有所幫助2013-07-07一文教你用純JS實(shí)現(xiàn)一個(gè)五子棋游戲
實(shí)現(xiàn)一個(gè)五子棋游戲, 簡(jiǎn)要分析其原理, 頁(yè)面并沒有很花哨, 原理搞懂了, 后面的就是很輕松的事了,本文給大家介紹了如何用純JS實(shí)現(xiàn)一個(gè)五子棋游戲,文中通過代碼示例給大家介紹的非常詳細(xì),具有一定的參考價(jià)值,需要的朋友可以參考下2023-12-12Atitit.js的鍵盤按鍵事件捆綁and事件調(diào)度
這篇文章主要介紹了Atitit.js的鍵盤按鍵事件捆綁and事件調(diào)度的相關(guān)資料,需要的朋友可以參考下2016-04-04