Chrome 插件開發

寫在開頭: 相當有意思的UI界面,編碼實現,瀏覽速度.對於一天瀏覽器使用超過10個小時的人來說,能夠定製自己的瀏覽器,是相當的具有誘惑力.

Getting Started
1:目前不支持標準發佈版本的Chrome插件擴展,不過也有消息馬上就開發了,對於我們這個不是問題.4.0使用中
2:創建一個所必要的文件夾,名字任意,用於存放所需文件,開發後,可以通過Chrome打包提交
3:manifest.json文件,存放描述信息,也可以理解爲插件運行的總入口,使用JSON的格式進行定義
{
"name": "My First Extension", //程序名稱
"version": "1.0", //版本
"description": "The first extension that I made.",//描述
"browser_action": {//對瀏覽器的操作
"default_icon": "icon.png"//圖標
},
"permissions": [ //權限,用於定義所需的網絡資源
"http://api.flickr.com/"
]
}
4:可以在browser_action中對功能進行添加
"popup": "popup.html"//指定點擊按鈕後觸發的行爲,

5:彈出的html擴展名文件,進行編寫彈出窗編寫,允許使用Js and css,使用的時候注意HTML必須包含在文件夾內
尤其指出,其中可以使用HTML5標準的元素
插件包含的文件
1:manifest 文件,2:任意個HTML文件,3:JavaScript文件,4:圖片Image文件
打包後會被壓縮成特殊格式的zip文件,擴展名爲.crx

background page :用於保存插件的主要邏輯,
插件的邏輯分爲: page action,browser action兩種,,background.html文件的js同時控制兩種action

action,可以理解爲動作,也就是瀏覽器表現出來的行爲,如彈出窗一樣
browser_action 包括 a tooltip, a badge, and a popup.

可以在Manifest文件中註冊所需的browser action,其中default_icon爲必須的,其他均爲可選(or)

UI部分
Icon:大多圖片格式都可以,推薦使用19像素的正方形圖片,設置的方式分爲兩種,manifest文件內的default_icon,或者調用setIcon()方法
Tooltip:設置manifest的default_title屬性,或調用setTitle()方法
Badge:用於在圖標下顯示的字符,字數限制在4個字符一下,可以通過setBadgeText() and setBadgeBackgroundColor()設置內容和背景色
Popup:點擊後彈出的窗口.定義在manifest文件中,browser_action的popup屬性

chrome.browserAction的常用方法,其中參數使用json對象,具體查看對應的API查詢key

setBadgeBackgroundColor: 設置Badge背景色
chrome.browserAction.setBadgeBackgroundColor(object details);

setBadgeText:Badge內容
chrome.browserAction.setBadgeText(object details)

setIcon:設置圖標
chrome.browserAction.setIcon(object details)

shetTitle:設置Tooltip
chrome.browserAction.setTitle(object details)

browserAction的事件
chrome.browserAction.onClicked.addListener(function(Tab tab) {...}); //將會在點擊圖標後觸發
//這裏的參數,比Js多了一種類型

2:爲插件提供對應的options選項頁面,在manifest文件中添加對應的options_page:選項,使用HTML
"options_page": "options.html",

所需的HTML可以爲一個完整格式的HTML文檔,包含所需的html元素

Override界面: 用於替換新tab界面,區別於默認的界面,在manifest文件中進行註冊
"chrome_url_overrides": {
"newtab": "newtab.html"
},

Page Actions: 用於出現在指定頁面中的圖標
"page_action": {
"default_icon": "icons/foo.png", // required
"default_title": "Do action", // optional; shown in tooltip
"popup": "popup.html" // optional
},
區別Browser action,page action並不包含badges,但是可以控制page action是否顯示,通過調用 show() and hide() methods

同樣對browser的建議也適用與page action;

一些常見Page action的方法
hide;
chrome.pageAction.hide(integer tabId)
setIcon
chrome.pageAction.setIcon(object details)
setTitle
chrome.pageAction.setTitle(object details)
show
chrome.pageAction.show(integer tabId)
事件,類似browser action的事件
onClicked
chrome.pageAction.onClicked.addListener(function(tab) {...});

Themes皮膚
也是打包成標準的擴展組件,但是並不包含對應的JS和HTML代碼,只用主要的manifest.json文件進行設置
{
"version": "2.6",
"name": "camo theme",
"theme": {
"images" : {
"theme_frame" : "images/theme_frame_camo.png",
"theme_frame_overlay" : "images/theme_frame_stripe.png",
"theme_toolbar" : "images/theme_toolbar_camo.png",
"theme_ntp_background" : "images/theme_ntp_background_norepeat.png",
"theme_ntp_attribution" : "images/attribution.png"
},
"colors" : {
"frame" : [71, 105, 91],
"toolbar" : [207, 221, 192],
"ntp_text" : [20, 40, 0],
"ntp_link" : [36, 70, 0],
"ntp_section" : [207, 221, 192],
"button_background" : [255, 255, 255]
},
"tints" : {
"buttons" : [0.33, 0.5, 0.47]
},
"properties" : {
"ntp_background_alignment" : "bottom"
}
}
}

默認皮膚,可以通過下面的鏈接進行查看
http://src.chromium.org/viewvc/chrome/trunk/src/chrome/browser/browser_theme_provider.cc

其中tints中,使用 Hue-Saturation-Lightness 灰度 飽和 亮度進行設置,值都是在0-1之間

瀏覽器交互: Browser Interaction
Bookmarks,Events,Tabs,Windows等

Bookmarks,收藏夾,可以創建,組織和管理收藏夾
設置權限: manifest文件中
"permissions": [
"bookmarks"
],
收藏夾使用tree的形式保存對象,其中主要使用 BookmarkTreeNode對象進行訪問,常用的屬性有:index, title, and url.

注:樹結構本身比較繁瑣一些,可以使用下面方法參考進行訪問
function btnclick(){
chrome.bookmarks.getTree(function(ass){
console.log(ass[0].children[0]);
for(obj in ass[0].children[0].children){
console.log(ass[0].children[0].children[obj].title);
}
})
}
建議先查看debug方法(ps:比較繁瑣,但是配合console.log比較方便查看對象結構)

其中的id使用的也是自增,由0開始
常見的方法
create , get getChildren getTree move remove removeTree search update
常見的事件

常見的事件
onChanged onChildrenReordered onCreated onMoved onRemoved

使用的例子:
chrome.bookmarks.onMoved.addListener(...)
chrome.bookmarks.getTree(...) //具體請查看API

Event事件的使用例子
chrome.tabs.onCreated.addListener(function(tab) {
appendToLog('tabs.onCreated --'
+ ' window: ' + tab.windowId
+ ' tab: ' + tab.id
+ ' index: ' + tab.index
+ ' url: ' + tab.url);
});
注意加載對應的permissions權限 tabs
事件的全部操作方法:
void addListener(function callback(...))
void removeListener(function callback(...))
bool hasListener(function callback(...))

Tabs 用於控制每個標籤 , 調用時爲chrome.tabs
常見的方法:
captureVisibleTab connect create detectLanguage executeScript get getAllInWindow getSelected insertCSS move remove sendRequest update

常見的事件:
onAttached onCreated onDetached onMoved onRemoved onSelectionChanged onUpdated

Windows Chrome中的多窗口

方法調用中可選的windowId參數,默認爲當前窗口

調用對象: chrome.windows

常見的方法: create get getAll getCurrent getLastFocused remove update
常見的事件:onCreated onFocusChanged onRemoved

Background Pages, 註冊在manifest文件中,用於保存長時間運行的腳本,運行在插件所在的進程中,多用於類似守護線程一樣的作用,用於狀態的更新
獲取頁面的方式:
var views = chrome.extension.getViews(); //獲取到的數組,通過循環或者索引得到指定的view也就是js的windows對象,不過這裏只侷限配置在manifest中的html元素
"background_page": "background.html",

Content Scripts 用於對指定頁面的內容進行腳本調用
同樣 需要在manifest文件中進行註冊
"content_scripts": [
{
"matches": ["http://www.google.com/*"],
"css": ["mystyles.css"],
"js": ["jquery.js", "myscript.js"]
}
],

常見的屬性:
matches, 字符串數組,根據制定的匹配模式進行對指定URL頁面的注入
js:指定的腳本文件將會被注入到符合的頁面中去 可選
css:需要被嵌入的css,可選
run_at:用於設置何時進行注入,默認爲document_idle,還有其他的:document_start,document_end,
all_frames:boolean 默認爲false

使用的方式可以參考官方文檔,不過注意並不能簡單的替換同名function來達到注入替換事件的效果,不過可以直接使用document.getElementById獲取指定的dom組件,並進行修改.
作用域的問題上: 對於原有的變量並不能訪問到,如果需要進行替換,需要進行完整的事件,變量進行重新聲明替換
比較特殊的作用域:對於注入的代碼,將會有一個封閉的作用域,並不會與原有的進行衝突,當卻可以修改頁面的DOM元素

爲頁面元素添加插件內圖片的例子
var imgURL = chrome.extension.getURL("images/myimage.png");
document.getElementById("someImage").src = imgURL;

Cross-Origin XMLHttpRequest 跨站點的異步調用,用於使用插件訪問其他網站的API
分爲本地與外部數據兩種方面

本地插件內數據:不需要設置權限
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = handleStateChange; // Implemented elsewhere.
xhr.open("GET", chrome.extension.getURL('/config_resources/config.json'), true);
xhr.send();
注:0表示本地請求成功

外部網站,需要設置manifest文件中permissions,添加對應的網站地址,更多使用在插件內部功能上
"permissions": [
"http://www.google.com/"
],
對於匹配的URL也可以使用模糊匹配
"http://*.google.com/"
"http://*/" 表示允許訪問所有的網站 ,這裏注意對https也要獨立的編寫
內置的json轉換 JSON.parse(....);可以用於將制定的字符串,轉換成所需的js對象

再次提示,如果需要訪問其他網站,一定注意添加權限permissions

Message Passing 消息傳遞

Simple one-time requests:發送一個簡單的json數據從一個content script發送到插件的background.html文件中,反之亦然
chrome.extension.sendRequest() 或 chrome.tabs.sendRequest() methods
可選的一個回調函數,可以用於接收返回的內容
如:定義在content script文件中
chrome.extension.sendRequest({greeting: "hello"}, function(response) {
console.log(response.farewell);
});
在background發送使用特殊一些,需要使用getSelected獲取選中的tab後,然後發送請求
chrome.tabs.getSelected(null, function(tab) {
chrome.tabs.sendRequest(tab.id, {greeting: "hello"}, function(response) {
console.log(response.farewell);
});
});

接收的代碼爲:
chrome.extension.onRequest.addListener(
function(request, sender, sendResponse) {
console.log(sender.tab ?
"from a content script:" + sender.tab.url :
"from the extension");
if (request.greeting == "hello")
sendResponse({farewell: "goodbye"});
else
sendResponse({}); // snub them.
});

Long-lived connections 長週期連接
能夠保持連接,持續的進行數據收發
從content script 連接到background(插件)的代碼
var port = chrome.extension.connect({name: "knockknock"});
port.postMessage({joke: "Knock knock"});
port.onMessage.addListener(function(msg) {
if (msg.question == "Who's there?")
port.postMessage({answer: "Madame"});
else if (msg.question == "Madame who?")
port.postMessage({answer: "Madame... Bovary");
});

如果要從background插件處發起連接,需要稍作修改,去獲取指定的id
chrome.tabs.connect(tabId, {name: "knockknock"}).
設置監聽連接的監聽器
chrome.extension.onConnect.addListener(function(port) {
console.assert(port.name == "knockknock");
port.onMessage.addListener(function(msg) {
if (msg.joke == "Knock knock")
port.postMessage({question: "Who's there?"});
else if (msg.answer == "Madame")
port.postMessage({question: "Madame who?"});
else if (msg.answer == "Madame... Bovary")
port.postMessage({question: "I don't get it."});
});
});

對應的監聽斷開方法Port.disconnect(),和對應的事件Port.onDisconnect

Cross-extension messaging 跨插件消息
主要使用chrome.extension.onRequestExternal or chrome.extension.onConnectExternal
方法的細節與上述的連接事件一致

這裏還是提到一下跨站點Js攻擊的問題,少使用eval轉換返回的字符串,而建議使用專門的JSON.parse方法

NPAPI Plugins 用於提供Js調用本地二進制代碼 ,建議最後使用,也許功能很強大.

Autoupdating和Packaging章節略過

因爲Chrome開發自WebKit,所以可以調用其特有的API
V8 Js引擎也爲chrome提供了JSON對象
可以在插件內部集成所需的JS插件,如jQuery

暫時結束,有空再研究...開始GWT2.0
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章