Chrome擴(kuò)展
我的第一個(gè)Chrome擴(kuò)展:Search-faster
原文地址:http://www.aneasystone.com/archives/2015/06/my-first-chrome-extension-search-faster.html
June 7, 2015我的第一個(gè)Chrome擴(kuò)展:Search-faster
花了兩周左右的時(shí)間將Chrome擴(kuò)展的開發(fā)文檔看了一遍,把所有官方的例子也都順便一個(gè)個(gè)的安裝玩了一遍,真心感覺Chrome瀏覽器的博大精深。Chrome瀏覽器的現(xiàn)有功能已經(jīng)足夠強(qiáng)大,再配合Chrome擴(kuò)展幾乎可以說是“只有想不到,沒有做不到”。于是利用業(yè)余時(shí)間做了一個(gè)簡單的擴(kuò)展Search-faster,可以加快Google的搜索速度,算是對(duì)近一段時(shí)間學(xué)習(xí)的總結(jié)。
一、Chrome擴(kuò)展綜述
Chrome擴(kuò)展有兩種不同的表現(xiàn)形式:擴(kuò)展(Extension)和應(yīng)用(WebApp),我們這里不討論WebApp,但是擴(kuò)展的大多數(shù)技巧對(duì)于WebApp來說也是適用的。Chrome擴(kuò)展實(shí)際上就是壓縮在一起的一組文件,包括HTML,CSS,Javascript,圖片,還有其它任何需要的文件。它從本質(zhì)上來說就是一個(gè)Web頁面,可以使用所有的瀏覽器提供的API,可以與Web頁面交互,或者通過content script或cross-origin XMLHttpRequests與服務(wù)器交互。還可以訪問瀏覽器提供的內(nèi)部功能,例如標(biāo)簽或書簽等。
擴(kuò)展在Chrome瀏覽器中又有著兩種不同的表現(xiàn)形式:browser_action和page_action,browser_action在工具欄右側(cè)添加一個(gè)圖標(biāo),page_action在URL輸入欄右側(cè)添加一個(gè)圖標(biāo),如下圖所示。這兩個(gè)action唯一的區(qū)別在于:當(dāng)你的擴(kuò)展是否顯示取決于單個(gè)頁面時(shí),該使用page_action,page_action默認(rèn)是不顯示的。
1.1 manifest.json
每一個(gè)Chrome擴(kuò)展都有一個(gè)清單文件包含了這個(gè)擴(kuò)展的所有重要信息,這個(gè)文件的名稱固定為manifest.json,文件內(nèi)容為JSON格式。下面是一個(gè)manifest.json文件的實(shí)例(來自JSONView擴(kuò)展)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
{
"background": {
"scripts": [ "background.js" ]
},
"content_scripts": [ {
"all_frames": true,
"js": [ "content.js" ],
"matches": [ "
"run_at": "document_end"
} ],
"description": "Validate and view JSON documents",
"icons": {
"128": "jsonview128.png",
"16": "jsonview16.png",
"48": "jsonview48.png"
},
"key": "...",
"manifest_version": 2,
"name": "JSONView",
"options_page": "options.html",
"permissions": [ "clipboardWrite", "
"update_url": "
"version": "0.0.32.2",
"web_accessible_resources": [
"jsonview.css", "jsonview-core.css", "content_error.css",
"options.png", "close_icon.gif", "error.gif"
]
}
其中name、version和manifest_version三個(gè)字段是必選的,每個(gè)字段的含義顯而易見,另外在當(dāng)前版本下manifest_version的值推薦為2,版本1已經(jīng)被棄用。
除這三個(gè)字段之外,description為對(duì)擴(kuò)展的一句描述,雖然是可選的,但是建議使用。
icons為擴(kuò)展的圖標(biāo),一般情況下需要提供三種不同尺寸的圖標(biāo):16*16的圖標(biāo)用于擴(kuò)展的favicon,在查看擴(kuò)展的option頁面時(shí)可以看到;48*48的圖標(biāo)在擴(kuò)展的管理頁面可以看到;128*128的圖標(biāo)用于WebApp。這三種圖標(biāo)分別如下所示:
圖標(biāo)建議都使用png格式,因?yàn)閜ng對(duì)透明的支持最好。要注意的是:icons里的圖標(biāo)和browser_action或page_action里的default_icon可能是不一樣的,default_icon顯示在工具欄或URL輸入欄右側(cè),建議采用19*19的圖標(biāo)。
key字段為擴(kuò)展的唯一標(biāo)識(shí),這個(gè)字段是瀏覽器在安裝.crx文件時(shí)自動(dòng)生成的,通常不需要手工指定。
permissions為擴(kuò)展所需要的權(quán)限列表,列表中的每一項(xiàng)要么是一個(gè)已知的權(quán)限名稱,要么是一個(gè)URL匹配模式。一些常見的權(quán)限名稱有background、bookmarks、contextMenus、cookies、experimental、geolocation、history、idle、management、notifications、tabs、unlimitedStorage等;URL匹配模式用于指定訪問特定的主機(jī)權(quán)限,譬如:"http://*.google.com/"、"http://www.baidu.com/"。關(guān)于permissions字段可以參考
這里的文檔。
update_url用于擴(kuò)展的自動(dòng)升級(jí),默認(rèn)情況下Chrome瀏覽器會(huì)每隔一小時(shí)檢測一次是否需要升級(jí),也可以點(diǎn)擊擴(kuò)展管理頁面的“立即更新”按鈕強(qiáng)制升級(jí)。
另外background、content_scripts、options_page這三字段,還有這個(gè)例子里沒包含的browser_action/page_action字段是構(gòu)成Chrome擴(kuò)展的核心元素。下面分別進(jìn)行介紹。
1.2 background
背景頁通常是Javascript腳本,是一個(gè)在擴(kuò)展進(jìn)程中一直保持運(yùn)行的頁面。它在你的擴(kuò)展的整個(gè)生命周期都存在,在同一時(shí)間只有一個(gè)實(shí)例處于活動(dòng)狀態(tài)。在manifest.json中像下面這樣使用scripts字段注冊(cè)背景頁:
1
2
3
4
5
6
7
8
{
"name": "My extension",
// ...
"background": {
"scripts": ["background.js"]
},
// ...
}
也可以使用page字段注冊(cè)HTML頁面:
1
2
3
4
5
6
7
8
{
"name": "My extension",
// ...
"background": {
"page": ["background.html"]
},
// ...
}
背景頁和browser_action/page_action是運(yùn)行在同一個(gè)環(huán)境下的,可以通過chrome.extension.getBackgroundPage()和chrome.extension.getViews()進(jìn)行兩者之間的互相通信。
背景頁也常常需要和content_scripts之間進(jìn)行通信,要特別注意的是背景頁和content_scripts是運(yùn)行在兩個(gè)獨(dú)立的上下文環(huán)境中的,只能通過messages機(jī)制來通信,這個(gè)通信可以是雙向的,首先寫下消息的監(jiān)聽方:
1
2
3
4
5
chrome.extension.onRequest.addListener(function(request, sender, callback) {
console.log(JSON.stringify(request));
// deal with the request...
sendResponse({success: true});
});
然后寫下消息的發(fā)送方:
1
2
3
4
5
chrome.tabs.sendRequest(tabId, cron, function(response) {
if (response.success) {
// deal with the response...
}
});
1.3 content_scripts
content scripts是一個(gè)很酷的東西,它可以讓我們?cè)赪eb頁面上運(yùn)行我們自定義的Javascript腳本。content scripts可以訪問或操作Web頁面上的DOM元素,從而實(shí)現(xiàn)和Web頁面的交互。但是要注意的是,它不能訪問Web頁面中的Javascript變量或函數(shù),content scripts是運(yùn)行在一個(gè)獨(dú)立的上下文環(huán)境中的,類似于沙盒技術(shù),這樣不僅可以確保安全性,而且不會(huì)導(dǎo)致頁面上的腳本沖突(譬如Web頁面上使用了jquery 1.9版本,而content scripts中使用了jquery 2.0版本,這兩個(gè)版本的jquery其實(shí)運(yùn)行在兩個(gè)獨(dú)立的上下文環(huán)境中互不影響)。content scripts除了不能訪問Web頁面中Javascript變量和函數(shù)外,還有其他的一些限制:
不能使用除了chrome.extension之外的chrome.* 的接口
不能訪問它所在擴(kuò)展中定義的函數(shù)和變量
不能做cross-site XMLHttpRequests
但這些限制其實(shí)并不影響content scripts實(shí)現(xiàn)其強(qiáng)大功能,因?yàn)榭梢允褂肅hrome擴(kuò)展的messages機(jī)制來和其所在的擴(kuò)展進(jìn)行通信,從而間接的實(shí)現(xiàn)上面的功能;而且,content scripts甚至可以通過操作DOM來間接的和Web頁面進(jìn)行通信。
使用content scripts在Web頁面注入自定義腳本可以通過兩種方法來實(shí)現(xiàn):第一種方法是在manifest.json文件中使用content_scripts字段來指定,還有一種方法是通過編程的方式調(diào)用chrome.tabs.executeScript()函數(shù)動(dòng)態(tài)的注入。
這里有詳細(xì)的介紹。
1.4 options_page
當(dāng)你的擴(kuò)展擁有眾多參數(shù)可供用戶選擇時(shí),可以通過選項(xiàng)頁來實(shí)現(xiàn)。選項(xiàng)頁就是一個(gè)單純的HTML文件,可以引用腳本,CSS,圖片等其他資源。這在Web開發(fā)中是家常便飯,只要你會(huì)制作網(wǎng)頁,那么制作一個(gè)選項(xiàng)頁肯定也沒問題,這并沒有什么好說的。但是,如果我們仔細(xì)想一想,當(dāng)用戶在選項(xiàng)頁點(diǎn)擊保存修改后,修改后的配置信息保存在哪兒呢?如何做到選項(xiàng)頁中的配置在重啟瀏覽器后甚至是清除瀏覽器數(shù)據(jù)后仍然存在呢?這就需要我們將配置信息保存到硬盤上的某個(gè)文件中,而瀏覽器Web腳本中的Javascript代碼很顯然是不能訪問物理文件的。
這就是chrome.storage.local的由來,chrome.storage.local是Chrome瀏覽器提供的存儲(chǔ)API,這個(gè)接口用來將擴(kuò)展中需要保存的數(shù)據(jù)寫入本地磁盤。Chrome提供的存儲(chǔ)API可以說是對(duì)localStorage的改進(jìn),它與localStorage相比有以下區(qū)別:
如果儲(chǔ)存區(qū)域指定為sync,數(shù)據(jù)可以自動(dòng)同步
在隱身模式下仍然可以讀出之前存儲(chǔ)的數(shù)據(jù)
讀寫速度更快
用戶數(shù)據(jù)可以以對(duì)象的類型保存
清除瀏覽器數(shù)據(jù)后仍然可以訪問
1.5 browser_action vs. page_action
上面已經(jīng)說過,browser_action和page_action是擴(kuò)展在Chrome瀏覽器中的兩種不同的表現(xiàn)形式,browser_action顯示在工具欄右側(cè),page_action顯示在URL輸入欄右側(cè)。下面的代碼示例說明了如何注冊(cè)一個(gè)browser_action(page_action的注冊(cè)方法類似,只要將browser_action替換成page_action即可):
1
2
3
4
5
6
7
8
9
10
{
"name": "My extension",
// ...
"browser_action": {
"default_icon": "images/icon19.png", // optional
"default_title": "Google Mail", // optional; shown in tooltip
"default_popup": "popup.html" // optional
},
// ...
}
一個(gè)browser_action可以擁有一個(gè)icon,一個(gè)tooltip,一個(gè)badge和一個(gè)popup,page_action沒有badge,也可以擁有一個(gè)icon,一個(gè)tooltip和一個(gè)popup。icon是action的圖標(biāo),一般情況下是一個(gè)19*19的png圖片,也可以是HTML5中的一個(gè)canvas元素可以實(shí)現(xiàn)任意的自定義圖片;tooltip是提示信息,當(dāng)鼠標(biāo)移到action圖標(biāo)上時(shí)會(huì)顯示出來;popup是當(dāng)用戶點(diǎn)擊action圖標(biāo)時(shí)彈出的窗口;badge是寫在圖標(biāo)上文字,譬如下圖中顯示在RSS Feed Reader這個(gè)擴(kuò)展圖標(biāo)上的67就是一個(gè)badge,由于badge空間有限,一般不會(huì)超過4個(gè)字符,超出部分會(huì)被截?cái)唷?div style="height:15px;">