前言
周末學(xué)習(xí)了下Chrome插件的開發(fā)执庐,總體來說入門還是比較容易的,動手配合一些demo就能了解基本的開發(fā)過程导梆。這篇是一個學(xué)習(xí)筆記和總結(jié)轨淌,希望對大家也有所幫助。
什么是Chrome插件
Chrome插件其實和一個普通web應(yīng)用一樣都是由html
+css
+js
打包組成的看尼,插件可以使用Chrome提供的瀏覽器API递鹉,增強(qiáng)瀏擴(kuò)展覽器的功能。
Chrome插件通常是.crx后綴的文件藏斩,通過谷歌網(wǎng)上應(yīng)用商店下載或者在開發(fā)者模式中可以直接拖入到瀏覽器進(jìn)行安裝
用戶界面網(wǎng)頁(popup)
點擊插件圖標(biāo)出來的彈窗其實就是一個html頁面躏结,彈窗要顯示的內(nèi)容,和工具欄小圖標(biāo)在manifest.json
文件中配置狰域。
彈窗在每次點擊插件開始運(yùn)行媳拴,彈窗關(guān)閉后結(jié)束,可以與background腳本交互兆览。
基礎(chǔ)用法
1.創(chuàng)建manifest.json
任何插件都必須要有這個文件屈溉,用來描述插件的元數(shù)據(jù),插件的配置信息抬探。
一個常用配置項如下:
{
// 必須
"manifest_version": 2,
"name": "插件名稱a",
"version": "1.1.2",
// 推薦
"default_locale": "en",
"description": "插件的描述",
"icons": {
"16": "img/icon.png", // 擴(kuò)展程序頁面上的圖標(biāo)
"32": "img/icon.png", // Windows計算機(jī)通常需要此大小子巾。提供此選項可防止尺寸失真縮小48x48選項。
"48": "img/icon.png", // 顯示在擴(kuò)展程序管理頁面上
"128": "img/icon.png" // 在安裝和Chrome Webstore中顯示
},
// 可選
"background": {
"page": "background/background.html",
"scripts": ["background.js"],
// 推薦
"persistent": false
},
"browser_action": {
"default_icon": "img/icon.png",
// 特定于工具欄的圖標(biāo)小压,至少建議使用16x16和32x32尺寸线梗,應(yīng)為方形,
// 不然會變形
"default_title": "懸浮在工具欄插件圖標(biāo)上時的tooltip內(nèi)容",
"default_popup": "hello.html" // 不允許內(nèi)聯(lián)JavaScript怠益。
},
"content_scripts": [ {
"js": [ "inject.js" ],
"matches": [ "http://*/*", "https://*/*" ],
"run_at": "document_start"
} ],
"permissions": [
"contextMenus",
"tabs",
"http://*/*",
"https://*/*"
],
"web_accessible_resources": [ "dist/*", "dist/**/*" ]
}
上面的配置項看起來內(nèi)容較多仪搔,主要有以下幾項:
- 定義當(dāng)前插件的名字,描述版本號等信息溉痢。
- "manifest_version":現(xiàn)在應(yīng)該總是2僻造。
- background
- content_scripts
- permissions:在background或是popup的js里使用一些chrome api,需要授權(quán)才能使用孩饼,例如要使用chrome.tabs.xxx的api髓削,就要在permissions引入“tabs”
background、content_scripts的使用后面會詳細(xì)介紹
我們先使用如下基本信息
manifest.json
{
"name": "My QrCode",
"description" : "My QrCode Extension",
"version": "1.0",
"manifest_version": 2,
"browser_action": {
"default_popup": "./popup.html",
"default_icon": "./logo.png"
},
}
2.新建popup.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h2>hello world!</h2>
</body>
</html>
并找個png的圖作為logo
3.打包擴(kuò)展程序
現(xiàn)在我們就可以看下效果了镀娶。
打包擴(kuò)展程序:
打開chrome://extensions/立膛,打開開發(fā)者模式,點擊打包擴(kuò)展程序,選擇我們的開發(fā)目錄
注意:第一次打包的時候宝泵,會生成一個pem個人密鑰文件好啰,以后再次打包的時候就需要密鑰文件了。
4.加載已解壓的擴(kuò)展程序
選擇剛剛打包出來的文件即可
現(xiàn)在我們就可以看到效果了:
實現(xiàn)一個二維碼插件
在上面的基礎(chǔ)上儿奶,我們實現(xiàn)一個簡單的當(dāng)前頁面生成二維碼插件:
popup.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script type="text/javascript" src="jquery.min.js"></script>
<script type="text/javascript" src="qrcode.min.js"></script>
</head>
<body>
<div id="qrcode"></div>
<script type="text/javascript" src="popup.js"></script>
</body>
</html>
這里我們二維碼生成用了這個開源項目:
https://github.com/davidshimjs/qrcodejs
把項目中的jquery.min.js框往、qrcode.min.js拷過來
注意:
由于popup不允許內(nèi)聯(lián)JavaScript,因此需要script標(biāo)簽引入外部腳本
popup.js
let url;
chrome.tabs.query({active: true, currentWindow: true}, function (tabs) {
url = tabs[0].url
var qrcode = new QRCode(document.getElementById("qrcode"), {
text: url,
width: 256,
height: 256,
colorDark : "#000000",
colorLight : "#ffffff",
correctLevel : QRCode.CorrectLevel.M
});
});
chrome.tabs.query()這部分用來獲取當(dāng)前頁面url
在manifest.json中加入允許:
{
"name": "My QrCode",
...
"permissions": ["activeTab"]
}
這樣闯捎,我們一個簡單的生成二維碼插件就完成了
background
問題:
我們想在彈窗中寫一個計數(shù)器椰弊,每點擊一次加1。但發(fā)現(xiàn)Popup 彈窗無法記錄數(shù)據(jù)
實現(xiàn)代碼如下:
popup.html
<input type="text" id="input" value="0">
<button id="btn">+1</button>
popup.js
var count = 0;
$(function(){
$('#input').val(count);
$('#btn').click(function(){
count = count+1;
$('#input').val(count);
});
})
當(dāng)我們點擊 “+1” 瓤鼻,輸入框中的數(shù)字就會增加秉版,然后關(guān)閉彈窗,再點開茬祷,發(fā)現(xiàn)數(shù)字又變成了0清焕,這說明當(dāng)我們關(guān)閉彈窗時,popup.html
就被銷毀了祭犯,我們在popup.js
中用count
存儲的全局變量秸妥,也被銷毀了。
解法:
由于popup在彈窗關(guān)閉后就銷毀了盹憎。如果想要在popup中記錄上次關(guān)閉后的結(jié)果的話筛峭,需要引入background
概念
background可以理解為插件運(yùn)行在瀏覽器中的一個后臺網(wǎng)站/腳本,注意它是與當(dāng)前瀏覽頁面無關(guān)的陪每。
實際上這部分內(nèi)容的配置情況也會寫在manifest里影晓,對應(yīng)的是background
配置項。單獨拿出來講檩禾,是彰顯它的分量很重挂签,也是一個插件常用的配置。從其中幾個配置項項去了解一下什么是background script
manifest.json
"background": {
"page": "background/background.html",
"scripts": ["background.js"],
// 推薦
"persistent": false
},
page
可以理解為這個后臺網(wǎng)站的主頁盼产,在這個主頁中饵婆,有引用的腳本,其中一般都會有一個專門來管理插件各種交互以及監(jiān)聽瀏覽器行為的腳本戏售,一般都起名為background.js侨核。這個主頁,不一定要求有灌灾。
scripts
這里的腳本其實跟寫在page里html引入的腳本目的一樣搓译,個人的理解是,page的html在沒有的情況下锋喜,那么腳本就需要通過這個屬性引入了些己;
如果在存在page的情況下豌鸡,一般在這里引入的腳本是專門為插件服務(wù)的腳本,而那些第三方腳本如jquery還是在page里引用比較好段标,或許這是一個眾人的“潛規(guī)則”吧
persistent
所謂的后臺腳本涯冠,在chrome擴(kuò)展中又分為兩類,分別運(yùn)行于后臺頁面(background page)和事件頁面(event page)中逼庞。兩者區(qū)別在于蛇更,
前者(后臺頁面)持續(xù)運(yùn)行,生存周期和瀏覽器相同赛糟,即從打開瀏覽器到關(guān)閉瀏覽器期間械荷,后臺腳本一直在運(yùn)行,一直占據(jù)著內(nèi)存等系統(tǒng)資源虑灰,persistent設(shè)為true;
而后者(事件頁面)只在需要活動時活動痹兜,在完全不活動的狀態(tài)持續(xù)幾秒后穆咐,chrome將會終止其運(yùn)行,從而釋放其占據(jù)的系統(tǒng)資源字旭,而在再次有事件需要后臺腳本來處理時对湃,重新載入它,persistent設(shè)為false遗淳。
保持后臺腳本持久活動的唯一場合是擴(kuò)展使用chrome.webRequest API來阻止或修改網(wǎng)絡(luò)請求拍柒。webRequest API與非持久性后臺頁面不兼容。
popup與background的通信
popup與background的交流屈暗,常見于popup要獲取background里的某些“東西”
通信方式:
popup:
var bg = chrome.extension.getBackgroundPage();
bg.someMethod(); //someMethod()是background中的一個方法
實現(xiàn)一個計數(shù)器
對于計數(shù)器的例子來說:
manifest.json
"background" : {
"scripts": ["background.js"],
"persistent": false
},
background.js
var count = 0;
popup.js
var bg = chrome.extension.getBackgroundPage();
$(function(){
$('#input').val(bg.count);
$('#btn').click(function(){
bg.count = bg.count+1;
$('#input').val(bg.count);
});
})
這樣拆讯,按鈕的點擊次數(shù)就可以記錄下來了
content script
概念
向符合條件的網(wǎng)頁插入該js腳本,對網(wǎng)頁做一些處理养叛。它具有獨立而富有包容性种呐。
獨立,指它的工作空間弃甥,命名空間爽室,域等是獨立的,不會說跟插入到的頁面的某些函數(shù)和變量發(fā)生沖突淆攻;
包容性阔墩,指插件把自己的一些腳本(content script)插入到符合條件的頁面里,作為頁面的腳本瓶珊,因此與插入的頁面共享dom的啸箫,即用dom操作是針對插入的網(wǎng)頁的,在這些腳本里使用的window對象跟插入頁面的window是一樣的艰毒。主要用在消息傳遞上(使用postMessage和onmessage)
配置也會寫在manifest里筐高,對應(yīng)的是content_scripts
配置項。
manifest.json
"content_scripts": [ {
"js": [ "inject.js" ],
"matches": [ "http://*/*", "https://*/*" ],
"run_at": "document_start"
} ],
js
要插入到頁面里的腳本。例子很常見柑土,例如在一個別人的網(wǎng)頁上蜀肘,你要打開你做的擴(kuò)展,對別人的網(wǎng)頁做一些處理或者獲取一些數(shù)據(jù)等稽屏,那怎么跟別人的頁面建立起聯(lián)系呢扮宠?就是通過把js里的這些腳本嵌入都別人的網(wǎng)頁里。
matches
必需狐榔。匹配規(guī)則組成的數(shù)組坛增,用來匹配頁面url的,符合條件的頁面將會插入js的腳本薄腻。當(dāng)然收捣,有可以匹配的自然會有不匹配的——exclude_matches。匹配規(guī)則:
developer.chrome.com/extensions/…
run_at
js配置項里的腳本何時插入到頁面里呢庵楷,這個配置項來控制插入時機(jī)罢艾。有三個選擇項:
- document_start
- document_end
- document_idle(默認(rèn))
document_ start
style樣式加載好,dom渲染完成和腳本執(zhí)行前
document_end
dom渲染完成后尽纽,即DOMContentLoaded后馬上執(zhí)行
document_idle
在DOMContentLoaded 和 window load之間咐蚯,具體是什么時刻,要視頁面的復(fù)雜程度和加載時間弄贿,并針對頁面加載速度進(jìn)行了優(yōu)化春锋。
popup與content script通信
popup與content script通信 和 background與contentscript通信用法是一致的
發(fā)送消息:
chrome.runtime.sendMessege(
message,
function(response) {…}
)
第一個參數(shù)message為發(fā)送的消息(基礎(chǔ)數(shù)據(jù)類型),回調(diào)函數(shù)里的第一個參數(shù)為background接收消息后返回的消息(如有)
接受消息:
chrome.runtime.onMessege.addListener(
function(request, sender, sendResponse) {…}
)
監(jiān)聽發(fā)來的消息差凹,request
表示發(fā)來的消息期奔,sendResponse
是一個函數(shù),用于對發(fā)來的消息進(jìn)行回應(yīng)直奋,如 sendResponse('我已收到你的消息:'+JSON.stringify(request));
這里需要注意的是能庆,默認(rèn)情況下sendResponse
函數(shù)的執(zhí)行是同步的,如果在這個監(jiān)聽消息的處理函數(shù)的同步執(zhí)行流程里沒有發(fā)現(xiàn)sendResponse
脚线,則默認(rèn)返回undefined
搁胆,假設(shè)我們是要經(jīng)過一個異步處理之后才調(diào)用sendResponse
,已經(jīng)為時已晚了邮绿。因此渠旁,我們可能需要異步執(zhí)行sendResponse
,這時我們在這個監(jiān)聽函數(shù)里的添加return true
就能實現(xiàn)了船逮。
實現(xiàn)一個搜索請求
實現(xiàn)一個向百度搜索框發(fā)送關(guān)鍵詞顾腊,并提交搜索請求。
這個功能其實沒什么用挖胃,主要是為了了解content_scripts和popup通信的流程
manifest.json
"content_scripts": [
{
"matches": ["https://www.baidu.com/*"],
"js": ["jquery.min.js","search-in-baidu.js"]
}
],
上述配置表示當(dāng)頁面 url 地址匹配到 “https://www.baidu.com/*” 模式時才向頁面中注入jquery.min.js
, search-in-baidu.js
兩個js 文件
一個插件里content-script有多個(一個頁面一個)杂靶,那么怎么向特定的content-script發(fā)送消息梆惯?
首先我們需要知道要向哪個content scripts發(fā)送消息,一般一個頁面一份content scripts吗垮,而一個頁面對應(yīng)一個瀏覽器tab垛吗,每個tab都有自己的tabId,因此首先要獲取要發(fā)送消息的tab對應(yīng)的tabId烁登。
/**
* 獲取當(dāng)前選項卡id
* @param callback - 獲取到id后要執(zhí)行的回調(diào)函數(shù)
*/
function getCurrentTabId(callback) {
chrome.tabs.query({active: true, currentWindow: true}, function (tabs) {
if (callback) {
callback(tabs.length ? tabs[0].id: null);
}
});
}
當(dāng)知道了tabId后怯屉,就使用該api進(jìn)行發(fā)送消息
chrome.tabs.sendMessage(tabId, message, function(response) {...});
其中message為發(fā)送的消息,回調(diào)函數(shù)的response為content scripts接收到消息后的回傳消息
在我們這個需求中:
popup.js
$(function(){
var state = $('#state');
$('#send').click(function () {//給對象綁定事件
chrome.tabs.query({active:true, currentWindow:true}, function (tab) {//獲取當(dāng)前tab
//向tab發(fā)送請求
chrome.tabs.sendMessage(tab[0].id, {
action: "send",
keyword: $('#keyword').val()
}, function (response) {
console.log(response);
state.html(response.state)
});
});
});
$('#submit').click(function () {
chrome.tabs.query({active:true, currentWindow:true}, function (tab) {
chrome.tabs.sendMessage(tab[0].id, {
action: "submit"
}, function (response) {
state.html(response.state)
});
});
})
})
search-in-baidu.js
var kw = $('#kw');
var form = $('#form');
chrome.runtime.onMessage.addListener(
function (request, sender, sendResponse) {
if (request.action == "send") {
kw.val(request.keyword)
sendResponse({state:'關(guān)鍵詞填寫成功饵沧!'});
}
if (request.action == "submit") {
form.submit();
sendResponse({state:'提交成功锨络!'});
}
}
);
實現(xiàn)效果:
在www.baidu.com中,使用插件狼牺,輸入想要搜索的關(guān)鍵詞羡儿,點擊發(fā)送->點擊提交,就查詢出來了是钥。
開發(fā)調(diào)試
開發(fā)過程中失受,如果有報錯,直接點擊錯誤就能看到具體報錯
修改代碼后插件沒有自動更新的話也可以手動點擊刷新按鈕
-
popup調(diào)試:
右鍵插件圖標(biāo)咏瑟,審查彈出內(nèi)容
-
backgroud script調(diào)試:
點擊背景頁,就可以看到backgroud script進(jìn)行調(diào)試了痪署,而且码泞,還能在控制臺調(diào)用chrome api。請求也可以在這里看到狼犯。
content script調(diào)試:
平常我們打開F12選擇到source選項的時候余寥,一般都會顯示在"page"下,選擇content script悯森,里邊的就是各個擴(kuò)展的內(nèi)容腳本了宋舷。
總結(jié)
chrome擴(kuò)展開發(fā)入門還是比較容易的,主要有一下幾個基本概念
- manifest.json
- popup
- background
- content script
了解后在實際開發(fā)中查閱相關(guān)資料即可
參考
更詳細(xì)的popup瓢姻、background祝蝠、content script的通信方法可以看這篇:
一篇文章教你順利入門和開發(fā)chrome擴(kuò)展程序(插件)
其他:
Chrome 擴(kuò)展開發(fā)教程(2) ——Background的用法
Chrome 擴(kuò)展開發(fā)教程(3)——content_scripts用法
官網(wǎng)教程:https://developer.chrome.com/extensions/getstarted