JavaScript實現(xiàn)谷歌瀏覽器插件開發(fā)的方法詳解
對于瀏覽器插件相信大家都不陌生,誰的瀏覽器不裝幾個好用的插件呢,更是有油猴這個強大的神器。但是大家有沒有嘗試自己去寫一個插件呢?對于這個問題,其實很長時間以來我是一直有想法但從來沒有付出行動,直到前一段時間有朋友找我寫一些關(guān)于瀏覽器自動化的程序,當(dāng)然如果簡單的話,直接在控制臺運行js腳本就可以了(但是真的不好用),轉(zhuǎn)念一想,瀏覽器插件也許也是一個不錯的選擇,感覺應(yīng)該不會太難,就去稍微了解了一下,有這個想法另一方面原因之前是有看到關(guān)于用c#來直接寫瀏覽器插件的,嗯,沒錯,就是Blazor。還是花了點時間去研究這個東西,最后發(fā)現(xiàn),極為難用。。。
隨后簡單看了下開發(fā)瀏覽器插件的原生寫法——這不是稍微會一點前端技術(shù)就能搞么,恰好,我就懂這么一點。。。
不過最后我并沒有用插件去實現(xiàn)這個需求,因為我發(fā)現(xiàn)了另外一個簡單且好用的東西:Selenium。但是剛剛學(xué)會這個東西,總得寫個東西來記錄一下吧,后面用到的時候也比較好找。
現(xiàn)在的瀏覽器基本都自帶密碼記住的功能。但是對于有些網(wǎng)站卻并不能做很好的識別,要么輸入的位置錯亂,要么賬號密碼錯亂。所以最終寫了這個插件出來。暫且叫做"密碼箱"吧,我們可以自己定義捕獲輸入框的標(biāo)識然后賦值進去,來解決上面提到的問題。
這里我們使用到的開發(fā)工具是 Visual Studio Code,然后整體看下我們的框架,其實跟我們寫前端一樣的,只是多了一個manifest.json文件,這也是最重要的一個文件;不過現(xiàn)在大家都用Vue了,一套命令下來應(yīng)有盡有。
1.先來看下manifest.json文件的配置,因為我們做的比較簡單,所以配置的也并不多,關(guān)于每項配置的含義已經(jīng)在文件中注釋了。
{ "name": "密碼箱",//插件名稱 "description": "密碼箱",//插件描述 "version": "1.0.0",//插件版本 "manifest_version": 3,//文件版本2或者3,2目前是主流,3是趨勢,谷歌瀏覽器目前是使用3版本的 "background": { //常駐后臺服務(wù) "service_worker": "/js/background.js" }, "permissions": ["storage", "activeTab", "scripting", "contextMenus", "tabs"], //需要的權(quán)限 "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": {//圖標(biāo) "16": "/img/icon.png", "32": "/img/icon.png", "48": "/img/icon.png", "128": "/img/icon.png" }, "host_permissions": ["*://*/*"]//主機權(quán)限 }
2.然后我們需要一個配置頁面,來設(shè)置我們需要保存的賬號信息以及表單元素即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>賬號:</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>賬號元素:</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.最后就是我們需要做一個主動賦值的操作了。即上面提到的可交互的頁面:popup.js。當(dāng)然我們也可以寫在background.js中,自動監(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)); } }
到此,我們這個插件就寫完了;
到此這篇關(guān)于JavaScript實現(xiàn)谷歌瀏覽器插件開發(fā)的方法詳解的文章就介紹到這了,更多相關(guān)JavaScript谷歌瀏覽器插件開發(fā)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
jquery中validate與form插件提交的方式小結(jié)
這篇文章主要介紹了jquery中validate與form插件提交的方式小結(jié),需要的朋友可以參考下2016-03-03JS實現(xiàn)彈出浮動窗口(支持鼠標(biāo)拖動和關(guān)閉)實例詳解
這篇文章主要介紹了JS實現(xiàn)彈出浮動窗口,可支持鼠標(biāo)拖動和關(guān)閉的功能,界面美觀大方,涉及javascript動態(tài)創(chuàng)建對話框的相關(guān)技巧,需要的朋友可以參考下2015-08-08JS關(guān)于?replace?取值、替換第幾個匹配項問題小結(jié)
這篇文章主要介紹了JS關(guān)于replace取值、替換第幾個匹配項,本文針對字符串的替換、截取知識點做詳細(xì)介紹,結(jié)合實例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-05-05個人總結(jié)的一些JavaScript技巧、實用函數(shù)、簡潔方法、編程細(xì)節(jié)
這篇文章主要介紹了個人總結(jié)的一些JavaScript技巧、實用函數(shù)、簡潔方法、編程細(xì)節(jié),本文講解了變量轉(zhuǎn)換、取整同時轉(zhuǎn)換成數(shù)值型、日期轉(zhuǎn)數(shù)值、類數(shù)組對象轉(zhuǎn)數(shù)組、進制之間的轉(zhuǎn)換等方法技巧,需要的朋友可以參考下2015-06-06Atitit.js的鍵盤按鍵事件捆綁and事件調(diào)度
這篇文章主要介紹了Atitit.js的鍵盤按鍵事件捆綁and事件調(diào)度的相關(guān)資料,需要的朋友可以參考下2016-04-04