JavaScript實(shí)現(xiàn)谷歌瀏覽器插件開發(fā)的方法詳解
對于瀏覽器插件相信大家都不陌生,誰的瀏覽器不裝幾個好用的插件呢,更是有油猴這個強(qiáng)大的神器。但是大家有沒有嘗試自己去寫一個插件呢?對于這個問題,其實(shí)很長時間以來我是一直有想法但從來沒有付出行動,直到前一段時間有朋友找我寫一些關(guān)于瀏覽器自動化的程序,當(dāng)然如果簡單的話,直接在控制臺運(yùn)行js腳本就可以了(但是真的不好用),轉(zhuǎn)念一想,瀏覽器插件也許也是一個不錯的選擇,感覺應(yīng)該不會太難,就去稍微了解了一下,有這個想法另一方面原因之前是有看到關(guān)于用c#來直接寫瀏覽器插件的,嗯,沒錯,就是Blazor。還是花了點(diǎn)時間去研究這個東西,最后發(fā)現(xiàn),極為難用。。。
隨后簡單看了下開發(fā)瀏覽器插件的原生寫法——這不是稍微會一點(diǎn)前端技術(shù)就能搞么,恰好,我就懂這么一點(diǎn)。。。
不過最后我并沒有用插件去實(shí)現(xiàn)這個需求,因?yàn)槲野l(fā)現(xiàn)了另外一個簡單且好用的東西:Selenium。但是剛剛學(xué)會這個東西,總得寫個東西來記錄一下吧,后面用到的時候也比較好找。
現(xiàn)在的瀏覽器基本都自帶密碼記住的功能。但是對于有些網(wǎng)站卻并不能做很好的識別,要么輸入的位置錯亂,要么賬號密碼錯亂。所以最終寫了這個插件出來。暫且叫做"密碼箱"吧,我們可以自己定義捕獲輸入框的標(biāo)識然后賦值進(jìn)去,來解決上面提到的問題。
這里我們使用到的開發(fā)工具是 Visual Studio Code,然后整體看下我們的框架,其實(shí)跟我們寫前端一樣的,只是多了一個manifest.json文件,這也是最重要的一個文件;不過現(xiàn)在大家都用Vue了,一套命令下來應(yīng)有盡有。

1.先來看下manifest.json文件的配置,因?yàn)槲覀冏龅谋容^簡單,所以配置的也并不多,關(guān)于每項(xiàng)配置的含義已經(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": {//插件選項(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.然后我們需要一個配置頁面,來設(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實(shí)現(xiàn)谷歌瀏覽器插件開發(fā)的方法詳解的文章就介紹到這了,更多相關(guān)JavaScript谷歌瀏覽器插件開發(fā)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
d3.js實(shí)現(xiàn)簡單的網(wǎng)絡(luò)拓?fù)鋱D實(shí)例代碼
最近一直在學(xué)習(xí)d3.js,大家都知道d3.js是一個非常不錯的數(shù)據(jù)可視化庫,我們可以用它來做一些比較酷的東西,比如可以來顯示一些簡單的網(wǎng)絡(luò)拓?fù)鋱D,這篇文中就通過實(shí)例代碼給大家介紹了如何利用d3.js實(shí)現(xiàn)簡單的網(wǎng)絡(luò)拓?fù)鋱D,有需要的朋友們可以參考借鑒,下面來一起看看吧。2016-11-11
jquery SweetAlert插件實(shí)現(xiàn)響應(yīng)式提示框
為了滿足用戶體驗(yàn)度,使用SweetAlert插件實(shí)現(xiàn)響應(yīng)式提示框效果非常好,下面通過這篇文章給大家介紹jquery SweetAlert插件實(shí)現(xiàn)響應(yīng)式提示框,需要的朋友可以參考下2015-08-08
JS網(wǎng)絡(luò)游戲-(模擬城市webgame)提供的一些例子下載
JS網(wǎng)絡(luò)游戲-(模擬城市webgame)提供的一些例子下載...2007-10-10
JS深入學(xué)習(xí)之?dāng)?shù)組對象排序操作示例
這篇文章主要介紹了JS深入學(xué)習(xí)之?dāng)?shù)組對象排序操作,結(jié)合實(shí)例形式詳細(xì)分析了JavaScript數(shù)組對象排序相關(guān)實(shí)現(xiàn)技巧與操作注意事項(xiàng),需要的朋友可以參考下2020-05-05
js實(shí)現(xiàn)創(chuàng)建刪除html元素小結(jié)
本文給大家簡單介紹了下使用javascript和jquery實(shí)現(xiàn)創(chuàng)建刪除html元素的方法,非常的實(shí)用,有需要的小伙伴可以參考下。2015-09-09
Javascript 鍵盤事件的組合使用實(shí)現(xiàn)代碼
Javascript 鍵盤事件的組合使用實(shí)現(xiàn)代碼,需要的朋友可以參考下2012-05-05
JavaScript實(shí)現(xiàn)日期格式化的方法匯總
日期是許多JavaScript應(yīng)用程序的基本組成部分,無論是在網(wǎng)頁上顯示當(dāng)前日期還是處理用戶輸入以安排事件,本文將探討在?JavaScript?中格式化日期的各種技術(shù),希望對大家有所幫助2023-06-06

