周日在家無聊狞玛,研究了下chrome的擴展程序(extensions),所謂的擴展程序其實沒那么難锭亏,基本會html慧瘤、js锅减、css的很容易上手
簡單的例子:獲取特定網(wǎng)頁上的信息伐坏,生成一維條碼圖片和預覽頁面桦沉,并打印預覽頁面
基本概念
一個應用(擴展)其實是壓縮在一起的一組文件金闽,包括HTML代芜,CSS挤庇,Javascript腳本罚随,圖片文件淘菩,還有其它任何需要的文件屠升。 應用(擴展)本質(zhì)上來說就是web頁面腹暖,它們可以使用所有的瀏覽器提供的API,從XMLHttpRequest到JSON到HTML5全都有糕殉。
應用(擴展)可以與Web頁面交互阿蝶,或者通過content script或cross-origin XMLHttpRequests與服務器交互羡洁。應用(擴展)還可以訪問瀏覽器提供的內(nèi)部功能爽丹,例如標簽或書簽等粤蝎。
應用(擴展)的界面
很多應用(不包括WebApp)會以browser action或page action的形式在瀏覽器界面上展現(xiàn)出來初澎。每個應用(擴展)最多可以有一個browser action或page action。當應用(擴展)的圖標是否顯示出來是取決于單個的頁面時卧檐,應當選擇page action焰宣;當其它情況時可以選擇browser action匕积。
應用也可以通過其它方式提供界面,比如加入到上下文菜單盅粪,提供一個選項頁面或者用一個content script改變頁面的顯示等票顾〉旖荆可以在"開發(fā)指南"中找到應用(擴展)特性的完整列表以及實現(xiàn)的細節(jié)含鳞。
文件
每個應用(擴展)都應該包含下面的文件:
- 一個manifest文件
- 一個或多個html文件(除非這個應用是一個皮膚)
- 可選的一個或多個javascript文件
- 可選的任何需要的其他文件芹务,例如圖片
在開發(fā)應用(擴展)時枣抱,需要把這些文件都放到同一個目錄下。發(fā)布應用(擴展)時磁滚,這個目錄全部打包到一個應用(擴展)名是.crx的壓縮文件中。如果使用Chrome Developer Dashboard,上傳應用(擴展)淤刃,可以自動生成.crx文件吱型。
引用文件
任何需要的文件都可以放到應用(擴展)中,但是怎么使用它們呢灼伤?一般的說狐赡,可以像在普通的HTML文件中那樣使用相對地址來引用一個文件颖侄。下面的例子演示了如何引用images子目錄下的文件myimage.png
![](images/myimage.png)
如果使用chrome開發(fā)者工具享郊,可以看到每一個應用(擴展)中的文件也可以用一個絕對路徑來表示:
chrome-extension://<extensionID>/<pathToFile>
在這個URL中炊琉,是為每一個應用(擴展)生成的唯一ID。從chrome://extensions頁面中可以看到已經(jīng)安裝的所有應用(擴展)的唯一ID玄货。是文件在應用(擴展)目錄下的路徑松捉,也就是它的相對路徑馆里。
在這個URL中鸠踪,名為manifest.json的文件包含了應用(擴展)的基本信息,例如最重要的文件列表械媒,應用(擴展)所需要的權(quán)限等评汰。
基本架構(gòu)
絕大多數(shù)應用(擴展)都包含一個背景頁面(background page),用來執(zhí)行應用(擴展)的主要功能主儡。
上圖顯示了安裝了兩個應用(擴展)的瀏覽器糜值。兩個應用(擴展)分別是黃色圖標代表的browser action和藍色圖標代表的page action寂汇。在background.html文件里定義了browser action和javascript代碼。在兩個窗口里browser action都可以工作停巷。
頁面
背景頁面并不是應用(擴展)中唯一的頁面累贤。例如臼膏,一個browser action可以包含一個彈窗(popup),而彈窗就是用html頁面實現(xiàn)的嚷硫。應用(擴展)還可以使用chrome.tabs.create()或者window.open()來顯示內(nèi)部的HTML文件仔掸。
應用(擴展)里面的HTML頁面可以互相訪問各自DOM樹中的全部元素起暮,或者互相調(diào)用其中的函數(shù)会烙。
下圖顯示了一個browser action的彈窗的架構(gòu)。彈窗的內(nèi)容是由HTML文件(popup.html)定義的web頁面纸厉。它不必復制背景頁面(background.html)里的代碼,因為它可以直接調(diào)用背景頁面中的函數(shù)颗品。
Content scripts
如果一個應用(擴展)需要與web頁面交互躯枢,那么就需要使用一個content script闺金。Content script腳本是指能夠在瀏覽器已經(jīng)加載的頁面內(nèi)部運行的javascript腳本峰档〖パ玻可以將content script看作是網(wǎng)頁的一部分,而不是它所在的應用(擴展)的一部分槽棍。
Content script可以獲得瀏覽器所訪問的web頁面的詳細信息炼七,并可以對頁面做出修改布持。下圖顯示了一個content script可以讀取并修改當前頁面的DOM樹。但是它并不能修改它所在應用(擴展)的背景頁面的DOM樹按傅。
Content script與它所在的應用(擴展)并不是完全沒有聯(lián)系唯绍。一個content script腳本可以與所在的應用(擴展)交換消息枝誊,如下圖所示叶撒。例如,當一個content script從頁面中發(fā)現(xiàn)一個RSS種子時皮壁,它可以發(fā)送一條消息蛾魄〉涡耄或者由背景頁面發(fā)送一條消息,要求content script修改一個網(wǎng)頁的內(nèi)容扔水。
頁面間的通信
一個應用(擴展)中的HTML頁面間經(jīng)常需要互相通信主届。由于一個應用(擴展)的所有頁面是在同一個進程的同一個線程中運行的待德,因此它們之間可以直接互相調(diào)用各自的函數(shù)将宪。
可以使用chrome.extension中的方法來獲取應用(擴展)中的頁面较坛,例如getViews()和getBackgroundPage()。一旦一個頁面得到了對應用(擴展)中其它頁面的引用华嘹,它就可以調(diào)用被引用頁面中的函數(shù)除呵,并操作被引用頁面的DOM樹颜曾。
保存數(shù)據(jù)和隱身模式
應用(擴展)可以使用HTML5的 Web Storage API(例如localStorage)來保存數(shù)據(jù)泛豪,或者向服務器發(fā)出請求來保存數(shù)據(jù)侦鹏。當需要保存數(shù)據(jù)的時候略水,首先需要確定是否從隱身模式窗口中發(fā)出的請求。缺省情況下慎璧,應用(擴展)是不會運行在隱身模式下的胸私,而webapp是會的鳖谈。需要明確用戶在隱身模式下究竟需要應用(擴展)或webapp做什么缆娃。
隱身模式保證在該窗口下瀏覽不會留下痕跡瑰排。當處理隱身窗口的數(shù)據(jù)時凶伙,一定要遵循這個前提。例如显押,如果一個的應用(擴展)的功能是將瀏覽歷史保存在云端(服務器)乘碑,那么不要保存隱身模式下的瀏覽歷史兽肤。另一方面,任何窗口下都可以保存應用(擴展)的數(shù)據(jù)电禀,不論是否隱身尖飞。
重要規(guī)則:如果一條數(shù)據(jù)可能表明用戶在網(wǎng)上看了什么或做了什么政基,不要在隱身模式下保存它闹啦。
要檢查窗口是否在隱身模式下沮明,檢查Tab或Window對象的incognito屬性。例如:
var bgPage = chrome.extension.getBackgroundPage();
function saveTabData(tab, data) {
if (tab.incognito) {
bgPage[tab.url] = data; // Persist data ONLY in memory
} else {
localStorage[tab.url] = data; // OK to store data
}
}
具體實現(xiàn)思路
//manifest.json
{
"manifest_version": 2,
"name": "條碼打印插件",
"version": "0.0.1",
"background": {
//"page":"background.html"
"scripts": ["jquery2.1.1.min.js", "background.js"]
},
"page_action": {
"default_icon": {
"19": "cnblogs_19.png",
"38": "cnblogs_38.png"
},
"default_title": "條碼預覽", // shown in tooltip
"default_popup": "popup.html"
},
"permissions": ["tabs", "http://localhost/"],
"content_scripts": [{
"matches": ["http://localhost/*"],
"js": ["jquery2.1.1.min.js", "content_script.js"]
}]
}
content獲取頁面的數(shù)據(jù)窍奋,傳給background荐健,popup從background獲取信息并生成條碼和預覽頁面,打印popup
但實際做的過程中發(fā)現(xiàn)费变,popup頁面無法調(diào)用打印函數(shù)print();網(wǎng)上查閱資料未果摧扇。
于是換種思路,數(shù)據(jù)可以傳給服務器挚歧,由服務器生成打印頁面扛稽。
翻閱文檔,發(fā)現(xiàn)還可以覆寫特定頁面滑负,這樣連服務端也省了在张。
Override替代頁
使用替代頁,可以將Chrome默認的一些特定頁面替換掉,改為使用擴展提供的頁面。這讓擴展開發(fā)者可以開發(fā)更多有趣或者實用的基本功能頁面虽惭。替代頁通常會有大量的CSS和JavaScript代碼。
擴展可以替代如下頁面:
書簽管理器:從工具菜單上點擊書簽管理器時訪問的頁面,或者從地址欄直接輸入 chrome://bookmarks。
歷史記錄:從工具菜單上點擊歷史記錄時訪問的頁面,或者從地址欄直接輸入 chrome://history傀蚌。
新標簽頁:當創(chuàng)建新標簽的時候訪問的頁面库继,或者從地址欄直接輸入 chrome://newtab。
注意:一個擴展只能替代一個頁面。
注意:如果你替代隱身窗口的頁面藤抡,請注意要在manifest中將 incognito 屬性指定為 "spanning"。
注意:你不能替代隱身窗口的新標簽頁。
Manifest
下面是在extension manifest中注冊替代頁的寫法。
{
"name": "My extension",
...
"chrome_url_overrides" : {
"pageToOverride": "myPage.html"
},
...
}
對于示例中的pageToOverride颊埃,可替換成如下關(guān)鍵字
- bookmarks
- history
- newtab