1.chrome.storage API實(shí)現(xiàn)的瀏覽器存儲(chǔ)
Chrome瀏覽器擴(kuò)展通過(guò)chrome.storage.* API,可以存取數(shù)據(jù)或監(jiān)聽(tīng)數(shù)據(jù)的變化。
在manifest.json文件中注冊(cè)storage如下:
{
"permissions": [
"storage"
],
}
1.1 chrome.storage.local
只能夠?qū)?shù)據(jù)存儲(chǔ)在當(dāng)前登錄的設(shè)備本地。
1.2 chrome.storage.sync
方式實(shí)現(xiàn)了自動(dòng)數(shù)據(jù)同步,相同的用戶(hù)無(wú)論使用什么物理設(shè)備,只要以相同的賬戶(hù)登錄即可訪(fǎng)問(wèn)存儲(chǔ)的數(shù)據(jù)。設(shè)備離線(xiàn)時(shí)數(shù)據(jù)存儲(chǔ)在本地,一旦設(shè)備上線(xiàn)則同步數(shù)據(jù)。如果用戶(hù)禁止了數(shù)據(jù)同步,則采用chrome.storage.local方式。
1.3 chrome.storage.managed
方式是只讀存儲(chǔ),只有域管理員能夠在其中存儲(chǔ)數(shù)據(jù),Chrome瀏覽器擴(kuò)展只能讀取其中的數(shù)據(jù)。
chrome.storage機(jī)制采用一系列的存儲(chǔ)格子(tubes)存儲(chǔ)數(shù)據(jù),存儲(chǔ)空間有限。存儲(chǔ)數(shù)據(jù)時(shí)只能一個(gè)一進(jìn)行寫(xiě)入操作,并發(fā)性能不高。
下面以chrome.storage.sync為例介紹具體方法的使用:
存儲(chǔ)一個(gè)或多個(gè)數(shù)據(jù)
chrome.storage.sync.set(object items, function() {...})
其中的items對(duì)象包含若干“鍵值對(duì)”的映射,一個(gè)鍵值對(duì)就是一個(gè)存儲(chǔ)的數(shù)據(jù)項(xiàng)。
獲取指定key的數(shù)據(jù)項(xiàng)
chrome.storage.sync.get(string or array of string or object keys, function(object items) {...})
其中的keys如果為null則返回全部存儲(chǔ)的數(shù)據(jù)項(xiàng),如果為””或[]將返回空對(duì)象{}。
回調(diào)函數(shù)中的items對(duì)象就是獲取的數(shù)據(jù)項(xiàng),其中包含“鍵值對(duì)”的映射。
刪除指定key的一個(gè)或多個(gè)數(shù)據(jù)項(xiàng)
chrome.storage.sync.remove(string or array of string keys, function() {...})
清空存儲(chǔ)的所有數(shù)據(jù)項(xiàng)
chrome.storage.sync.clear(function(){…})
獲取當(dāng)前已經(jīng)被使用的存儲(chǔ)空間的數(shù)量(以字節(jié)為單位)
chrome.storage.sync.getBytesInUse(string or array of string keys, function(integer bytesInUse) {...})
其中的keys屬性是數(shù)據(jù)項(xiàng)的key,如果為null表示取全部數(shù)據(jù)項(xiàng)的使用空間,””或[]將返回0
1.4 chrome.storage.onChanged.addListener
此外,對(duì)于某些敏感數(shù)據(jù)的變化,可以通過(guò)onChanged事件進(jìn)行監(jiān)聽(tīng)。存儲(chǔ)格子中的任何變化都將觸發(fā)該事件,示例如下:
chrome.storage.onChanged.addListener(function(changes, namespace) {
for (key in changes) {
var storageChange = changes[key];
console.log('Storage key "%s" in namespace "%s" changed. ' + 'Old value was "%s", new value is "%s".', key, //數(shù)據(jù)的索引key
namespace, //數(shù)據(jù)的存儲(chǔ)空間類(lèi)型,枚舉值`"sync"`, `"local"`, `"managed"`
storageChange.oldValue, //變化前的值
storageChange.newValue); //變化后的值
}
});
1.5 一次性請(qǐng)求與響應(yīng)模式
對(duì)于一次性請(qǐng)求與響應(yīng)模式,chrome.runtime.sendMessage(obj, function(response){})是從content scripts發(fā)生請(qǐng)求消息給Google Chrome擴(kuò)展程序頁(yè)面。
從Google Chrome擴(kuò)展程序頁(yè)面發(fā)送請(qǐng)求消息給content scripts的時(shí)候,需要給出當(dāng)前tab的ID。
chrome.tabs.query({
active: true,
currentWindow: true
}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {
greeting: "hello"
}, function(response) {
console.log(response.farewell);
});
});
監(jiān)聽(tīng)消息時(shí),需要注冊(cè)要監(jiān)聽(tīng)的消息。
chrome.runtime.onMessage.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"
});
});
注意:如果為同一個(gè)消息注冊(cè)了多個(gè)監(jiān)聽(tīng)器,則只有第一個(gè)監(jiān)聽(tīng)器能夠調(diào)用sendResponse()方法,其他的監(jiān)聽(tīng)器將被忽略。
1.6 保持長(zhǎng)期連接的模式
對(duì)于保持長(zhǎng)期連接的模式,在content scripts與Chrome擴(kuò)展程序頁(yè)面之間建立通道(可以為通道命名),可以處理多個(gè)消息。在通道的兩端分別擁有一個(gè)chrome.runtime.Port對(duì)象,用以收發(fā)消息。
在content scripts主動(dòng)建立通道如下:
var port = chrome.runtime.connect({
name: "yisheng"
}); //通道名稱(chēng)
port.postMessage({
joke: "Knock knock"
}); //發(fā)送消息
port.onMessage.addListener(function(msg) { //監(jiān)聽(tīng)消息
if (msg.question == "Who's there?") port.postMessage({
answer: "yisheng"
});
else if (msg.question == "Madame who?") port.postMessage({
answer: "Madame... Bovary"
});
});
在Google Chrome擴(kuò)展程序頁(yè)面主動(dòng)建立通道如下:
chrome.tabs.query({
active: true,
currentWindow: true
}, function(tabs) {
var port = chrome.tabs.connect( //建立通道
tabs[0].id, {
name: "yisheng"
} //通道名稱(chēng)
);
});
在content scripts或Google Chrome擴(kuò)展程序頁(yè)面,監(jiān)聽(tīng)建立連接的請(qǐng)求如下:
chrome.runtime.onConnect.addListener(function(port) {
console.assert(port.name == "yisheng");
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."
});
});
});
在content scripts或Google Chrome擴(kuò)展程序頁(yè)面的任一端,調(diào)用chrome.runtime.Port.disconnect()則關(guān)閉連接,同時(shí)出發(fā)disconnect事件。這時(shí),只有另一端監(jiān)聽(tīng)chrome.runtime.Port.onDisconnect事件,則可以知道連接關(guān)閉。
1.7 Google Chrome擴(kuò)展程序之間消息模式
還可以在不同的Google Chrome擴(kuò)展程序之間發(fā)送消息,只要知道Google Chrome擴(kuò)展程序的ID。這使得Google Chrome擴(kuò)展程序可以發(fā)布服務(wù)為其他擴(kuò)展程序所用。
這種Google Chrome擴(kuò)展程序之間的消息也分為一次性請(qǐng)求與響應(yīng)模式和保持長(zhǎng)期連接的模式。
Google Chrome擴(kuò)展程序監(jiān)聽(tīng)調(diào)用其服務(wù)的消息如下:
//一次性請(qǐng)求與響應(yīng)模式:
chrome.runtime.onMessageExternal.addListener(function(request, sender, sendResponse) {
if (sender.id == blacklistedExtension) //黑名單
return; // don't allow this extension access
else if (request.getTargetData) sendResponse({
targetData: targetData
});
else if (request.activateLasers) {
var success = activateLasers();
sendResponse({
activateLasers: success
});
}
});
//保持長(zhǎng)期連接的模式:
chrome.runtime.onConnectExternal.addListener(function(port) {
port.onMessage.addListener(function(msg) {
// See other examples for sample onMessage handlers.
});
});
發(fā)送調(diào)用服務(wù)的消息如下:
// The ID of the extension we want to talk to.
var laserExtensionId = "abcdefghijklmnoabcdefhijklmnoabc";
// Make a simple request:
chrome.runtime.sendMessage(laserExtensionId, {
getTargetData: true
}, function(response) {
if (targetInRange(response.targetData)) chrome.runtime.sendMessage(laserExtensionId, {
activateLasers: true
});
});
// Start a long-running conversation:
var port = chrome.runtime.connect(laserExtensionId);
port.postMessage(...);
1.8 Google Chrome擴(kuò)展程序接收指定的Web頁(yè)面發(fā)送的消息
Google Chrome擴(kuò)展程序可以與一些指定地點(diǎn)Web頁(yè)面直接收發(fā)消息。
首先,在Google Chrome擴(kuò)展程序的manifest.json文件設(shè)置可以通信的Web頁(yè)面范圍:
"externally_connectable": {
"matches": ["*://*.example.com/*"]
}
其次,在Google Chrome擴(kuò)展程序中監(jiān)聽(tīng)Web頁(yè)面的消息如下:
chrome.runtime.onMessageExternal.addListener(function(request, sender, sendResponse) {
if (sender.url == blacklistedWebsite) return; // don't allow this web page access
if (request.openUrlInEditor) openUrl(request.openUrlInEditor);
});
最后,在指定的Web頁(yè)面中,發(fā)送消息如下:
// The ID of the extension we want to talk to.
var editorExtensionId = "abcdefghijklmnoabcdefhijklmnoabc";
// Make a simple request:
chrome.runtime.sendMessage(editorExtensionId, {
openUrlInEditor: url
}, function(response) {
if (!response.success) handleError(url);
});
通過(guò)將瀏覽器所在客戶(hù)端的本地應(yīng)用注冊(cè)為Chrome瀏覽器擴(kuò)展的“本地消息主機(jī)(native messaging host)”,Chrome瀏覽器擴(kuò)展還可以與客戶(hù)端本地應(yīng)用之間收發(fā)消息。
客戶(hù)端的本地應(yīng)用注冊(cè)為Chrome瀏覽器擴(kuò)展的“本地消息主機(jī)”之后,Chrome瀏覽器會(huì)在獨(dú)立的進(jìn)程中啟動(dòng)該本地應(yīng)用,并通過(guò)標(biāo)準(zhǔn)輸入/輸出流(stdin/stdout)進(jìn)行消息通信。
\1) 本地應(yīng)用的配置文件的內(nèi)容
本地應(yīng)用要能夠成為“本地消息主機(jī)”,必須有一個(gè)manifest.json配置文件(文件名任意),該文件是一個(gè)有效的JSON文件,示例如下。
{
"name": "com.my_company.my_application",
"description": "My Application",
"path": "C:\\Program Files\\My Application\\chrome_native_messaging_host.exe",
"type": "stdio",
"allowed_origins": ["chrome-extension://knldjmfmopnpolahpmmgbagdohdnhkik/"]
}
其中的屬性含義及用法如下。
| 屬性名 | 含義 |
|---|---|
| name | 標(biāo)識(shí)名稱(chēng)。只能由小寫(xiě)字母、數(shù)字、_和.組成;首尾不能是.且不能有. 連續(xù)出現(xiàn) |
| description | 描述 |
| path | 本地應(yīng)用的完整路徑,Linux和OS X上必須是絕對(duì)路徑,Windows上可以是基于配置文件所在位置的相對(duì)路徑 |
| type | 與本地消息主機(jī)進(jìn)行通信的接口類(lèi)型。目前只支持stdio,表示Chrome瀏覽器通過(guò)stdin和stdout與本地消息主機(jī)通信 |
| allowed_origins | 授權(quán)與本地消息主機(jī)進(jìn)行通信的Chrome瀏覽器擴(kuò)展。不能使用通配符 |
\2) 本地應(yīng)用的配置文件的路徑
配置文件的具體位置與操作系統(tǒng)有關(guān)。在Windows操作系統(tǒng)上,配置文件可以位于任何路徑,只需在安裝本地應(yīng)用時(shí)修改注冊(cè)表指明其位置即可。
創(chuàng)建key:
**HKEY_LOCAL_MACHINE**``\SOFTWARE\Google\Chrome\NativeMessagingHosts\com.my_company.my_application
或
**HKEY_CURRENT_USER**``\SOFTWARE\Google\Chrome\NativeMessagingHosts\com.my_company.my_application
設(shè)置默認(rèn)值Default為配置文件所在的絕對(duì)路徑:
C:\path\to\nmh-manifest.json
也可以直接創(chuàng)建注冊(cè)表文件.reg如下,安裝時(shí)執(zhí)行即可:
1 Windows Registry Editor Version 5.00
2 [HKEY_CURRENT_USER\Software\Google\Chrome\NativeMessagingHosts\com.my_company.my_application]
3 @="C:\\path\\to\\nmh-manifest.json"
對(duì)于Linux和OS X操作系統(tǒng),本地應(yīng)用的配置文件的位置首先與安裝的Chrome瀏覽器(Google Chrome或Chromium)有關(guān)。其次,如果是系統(tǒng)級(jí)別的本地應(yīng)用,其配置文件應(yīng)該位于固定位置。如果是用戶(hù)級(jí)別的本地應(yīng)用,則其配置文件位于用戶(hù)主目錄下的名為NativeMessagingHosts的子目錄中。具體位置如下表所示。
| Google Chrome | Chromium | |
|---|---|---|
| Linux系統(tǒng)應(yīng)用 | /etc/opt/chrome/native-messaging-hosts/com.my_company.my_application.json | /etc/chromium/native-messaging-hosts/com.my_company.my_application.json |
| Linux用戶(hù)應(yīng)用 | ~/.config/google-chrome/NativeMessagingHosts/com.my_company.my_application.json | ~/.config/chromium/NativeMessagingHosts/com.my_company.my_application.json |
| OS X系統(tǒng)應(yīng)用 | /Library/Google/Chrome/NativeMessagingHosts/com.my_company.my_application.json | /Library/Application Support/Chromium/NativeMessagingHosts/com.my_company.my_application.json |
| OS X用戶(hù)應(yīng)用 | ~/Library/Application Support/Google/Chrome/NativeMessagingHosts/com.my_company.my_application.json | ~/Library/Application Support/Chromium/NativeMessagingHosts/com.my_company.my_application.json |
\3) Chrome瀏覽器擴(kuò)展與本地應(yīng)用之間的消息通信
Chrome瀏覽器擴(kuò)展要與客戶(hù)端本地應(yīng)用進(jìn)行通信,首先必須在Chrome瀏覽器擴(kuò)展的manifest.json配置文件中聲明權(quán)限如下:
1 {
2 "permissions": [
3 "nativeMessaging"
4 ],
5 }
Chrome瀏覽器擴(kuò)展與客戶(hù)端本地應(yīng)用之間的消息通信非常類(lèi)似于不同Chrome瀏覽器擴(kuò)展之間的通信,示例如下。
在Chrome瀏覽器擴(kuò)展中創(chuàng)建端口,監(jiān)聽(tīng)來(lái)自本地應(yīng)用的多個(gè)消息:
1 var port = chrome.runtime.connectNative('com.my_company.my_application');
2 //參數(shù)為本地應(yīng)用在其配置文件中聲明的標(biāo)識(shí)名稱(chēng)
3
4 port.onMessage.addListener(function(msg) {//收到消息后的處理函數(shù)
5 console.log("Received" + msg);
6 });
7 port.onDisconnect.addListener(function() {
8 console.log("Disconnected");
9 });
10
11 port.postMessage({ text: "Hello, my_application" }); //發(fā)送一條消息
在Chrome瀏覽器擴(kuò)展中也可以不打開(kāi)端口,發(fā)送一次性消息如下:
1 chrome.runtime.sendNativeMessage(
2 'com.my_company.my_application',
3 { text: "Hello" },
4 function(response) {//收到返回消息后的處理函數(shù)
5 console.log("Received " + response);
6 });
如果Chrome瀏覽器擴(kuò)展在調(diào)用本地應(yīng)用時(shí)發(fā)生異常,將會(huì)在stderr輸出錯(cuò)誤信息。如果因違反了本地消息的協(xié)議約束而出錯(cuò),將會(huì)在Chrome瀏覽器的錯(cuò)誤日志文件輸出錯(cuò)誤信息。Linux和OS X操作系統(tǒng)上,通過(guò)命令行啟動(dòng)Chrome瀏覽器,就可以在命令行窗口看到錯(cuò)誤信息。Windows操作系統(tǒng)上,啟動(dòng)Chrome瀏覽器時(shí)帶上--enable-logging參數(shù)(在chrome.exe的右鍵屬性菜單中,General面板頂部的文本框中,chrome.exe后面直接跟上參數(shù)即可),就可以在Chrome瀏覽器的日志文件中看到錯(cuò)誤信息。
- 本地消息的協(xié)議約束
客戶(hù)端的本地應(yīng)用注冊(cè)為Chrome瀏覽器擴(kuò)展的“本地消息主機(jī)”之后,Chrome瀏覽器會(huì)在獨(dú)立的進(jìn)程中啟動(dòng)該本地應(yīng)用,并通過(guò)標(biāo)準(zhǔn)輸入/輸出流(stdin/stdout)進(jìn)行消息通信。
Chrome瀏覽器擴(kuò)展與客戶(hù)端的本地應(yīng)用之間的雙向通信采用消息機(jī)制,該消息以JSON格式,UTF-8編碼,帶32位(操作系統(tǒng)本地字節(jié)序)的消息長(zhǎng)度作為前綴。從本地應(yīng)用發(fā)送到Chrome瀏覽器擴(kuò)展的消息,最大尺寸是1M字節(jié)。從Chrome瀏覽器擴(kuò)展發(fā)送到本地應(yīng)用的消息,最大尺寸是4G字節(jié)。
1.9 chrome.tabs API中的常用方法:
創(chuàng)建一個(gè)新的瀏覽器窗口
chrome.windows.create(object createData, function(Window window){…})
createData對(duì)象是可選的,表示采用默認(rèn)值創(chuàng)建窗口。createData對(duì)象的屬性同chrome.windows.Window對(duì)象。
關(guān)閉一個(gè)指定的瀏覽器窗口
chrome.windows.remove(integer windowId, function(){…})
修改一個(gè)指定的瀏覽器窗口的參數(shù)
chrome.windows.update(integer windowId, object updateInfo, function(Window window){…})
updateInfo對(duì)象是必選的,其中未涉及的Window屬性則保持不變。
獲取指定ID的窗口對(duì)象
chrome.windows.get(integer windowId, object getInfo, function(Window window){…})
getInfo對(duì)象是可選的,其有兩個(gè)參數(shù)。一個(gè)是名為populate的布爾型參數(shù),true表示該方法得到的chrome.windows.Window對(duì)象里包含chrome.tabs.Tab類(lèi)型的數(shù)組。另一個(gè)名為windowTypes的WindowType型參數(shù),表示通過(guò)windowTypes進(jìn)行篩選窗口。
獲取所有的窗口對(duì)象
chrome.windows.getAll(object getInfo, function(array of Window){…})
getInfo對(duì)象是可選的,其有兩個(gè)參數(shù)。一個(gè)是名為populate的布爾型參數(shù),true表示該方法得到的chrome.windows.Window對(duì)象里包含chrome.tabs.Tab類(lèi)型的數(shù)組。另一個(gè)名為windowTypes的WindowType型參數(shù),表示通過(guò)windowTypes進(jìn)行篩選窗口。
復(fù)制一個(gè)新tab
chrome.tabs.duplicate(integer tabId, function(Tab tab){…})
修改tab的屬性
chrome.tabs.update(integer tabId, object updateProperties, function(Tab tab){…})
updateProperties對(duì)象是必選的,其中未涉及的tab屬性則保持不變。
根據(jù)指定的若干屬性查找tabs
chrome.tabs.query(object queryInfo, function(array of Tab){…})
1.10 chrome.tabs API中的常用方法:
chrome.events中定義了一些常見(jiàn)的事件類(lèi)型,可以供Chrome瀏覽器擴(kuò)展程序發(fā)出對(duì)應(yīng)的事件對(duì)象。
對(duì)于關(guān)注的事件,首先要通過(guò)addListener()在對(duì)應(yīng)的事件上注冊(cè)監(jiān)聽(tīng)器,示例如下:
chrome.alarms.onAlarm.addListener(function(alarm) {
appendToLog('alarms.onAlarm --' + ' name: ' + alarm.name + ' scheduledTime: ' + alarm.scheduledTime);
});
addListener()總是帶一個(gè)參數(shù),這就是事件處理函數(shù)。一旦事件發(fā)生,監(jiān)聽(tīng)器即調(diào)用事件處理函數(shù)。
事件處理函數(shù)還可以有參數(shù),具體參數(shù)的數(shù)量和類(lèi)型與監(jiān)聽(tīng)的事件相關(guān)。
chrome.events中,事件沒(méi)有任何屬性,只包含如下的常用方法:
| 方法名 | 返回值類(lèi)型 | 注釋 |
|---|---|---|
| addListener(function() {...}) | 無(wú) | 為事件注冊(cè)監(jiān)聽(tīng)器,并給出事件處理函數(shù) |
| removeListener(function() {...}) | 無(wú) | 刪除事件的監(jiān)聽(tīng)器 |
| hasListener(function() {...}) | boolean | 判斷事件上是否注冊(cè)有監(jiān)聽(tīng)器 |
| hasListeners() | boolean | 判斷事件上是否注冊(cè)有監(jiān)聽(tīng)器,沒(méi)有回調(diào)函數(shù) |
| addRules(array of Rule rules, function (array of Rule rules) {...}) | 無(wú) | 為事件注冊(cè)規(guī)則如果第一個(gè)參數(shù)的數(shù)組中有無(wú)效規(guī)則,則不會(huì)注冊(cè)任何規(guī)則 |
| removeRules(array of string ruleIdentifiers, function() {...}) | 無(wú) | 刪除事件上注冊(cè)的所有規(guī)則。如果有第一個(gè)參數(shù)(可以沒(méi)有),則只刪除注冊(cè)的、在范圍內(nèi)的規(guī)則 |
| getRules(array of string ruleIdentifiers, function (array of Rule rules) {...}) | 無(wú) | 返回事件上注冊(cè)的所有規(guī)則。如果有第一個(gè)參數(shù)(可以沒(méi)有),則只返回注冊(cè)的、在范圍內(nèi)的規(guī)則 |
有這樣一種場(chǎng)景,對(duì)于發(fā)生的事件,只有當(dāng)滿(mǎn)足某些條件時(shí)才進(jìn)行處理,即并非要對(duì)發(fā)生的該事件都進(jìn)行處理。對(duì)于這種情況,可以通過(guò)為事件處理函數(shù)附加過(guò)濾條件實(shí)現(xiàn),也可以采用全新的事件規(guī)則機(jī)制。下面分別討論。
過(guò)濾事件
過(guò)濾事件,就是對(duì)于監(jiān)聽(tīng)的事件,只有當(dāng)其符合過(guò)濾條件時(shí),才會(huì)調(diào)用事件處理函數(shù)。多個(gè)過(guò)濾條件之間是“或”的關(guān)系。示例如下:
chrome.webNavigation.onCommitted.addListener(function(e) {
// ...
}, {
url: [{
hostSuffix: 'google.com'
}, //過(guò)濾條件1
{
hostSuffix: 'google.com.au'
}
]
} //過(guò)濾條件2
);
聲明式事件處理器(事件規(guī)則)
聲明式事件處理器就是為事件定義處理規(guī)則。注冊(cè)了規(guī)則的事件對(duì)象,當(dāng)事件對(duì)象發(fā)生時(shí),不會(huì)再調(diào)用事件處理函數(shù),而是檢測(cè)注冊(cè)的規(guī)則的條件是否有匹配,如果匹配則執(zhí)行規(guī)則的行為。
通常,規(guī)則必須包含聲明條件和處理行為。示例如下:
var rule = {
id: "my rule", // 標(biāo)識(shí)符可選, 沒(méi)有則自動(dòng)生成
priority: 100, // 優(yōu)先級(jí)可選, 默認(rèn)為100
conditions: [ /* my conditions */ ],
actions: [ /* my actions */ ]
};
一個(gè)規(guī)則可以擁有多個(gè)條件,條件之間是“或”的關(guān)系,即任意一個(gè)條件滿(mǎn)足則表示匹配規(guī)則。
一個(gè)規(guī)則可以擁有多個(gè)處理行為,行為之間是“與”的關(guān)系,即所有的行為作為一個(gè)整體,在條件匹配的時(shí)候一起執(zhí)行。
chrome.events.Rule對(duì)象的屬性如下:
| 屬性名 | 類(lèi)型 | 必選/****可選 | 注釋 |
|---|---|---|---|
| id | string | 可選 | 標(biāo)識(shí)符 |
| tags | array of string | 可選 | 規(guī)則的標(biāo)簽,多個(gè)規(guī)則可以根據(jù)標(biāo)簽分組 |
| conditions | array of any | 必選 | 觸發(fā)處理行為的條件 |
| actions | array of any | 必選 | 任一條件匹配時(shí)觸發(fā)的處理行為 |
| priority | integer | 可選 | 規(guī)則的優(yōu)先級(jí),默認(rèn)100 |
一個(gè)規(guī)則在整個(gè)瀏覽器的會(huì)話(huà)中都是有效得到,所以通常在安裝Chrome擴(kuò)展的chrome.runtime.onInstalled事件處理函數(shù)中安裝規(guī)則。而在Chrome擴(kuò)展升級(jí)時(shí)也會(huì)觸發(fā)chrome.runtime.onInstalled事件,所以要注意在該事件處理函數(shù)中,先判斷是否有已經(jīng)安裝了的規(guī)則,如果有則首先刪除已經(jīng)安裝的規(guī)則,然后再安裝規(guī)則。
聲明式條件的檢查由瀏覽器直接進(jìn)行,而無(wú)需JavaScript引擎,所以減少了延遲。
聲明式事件處理器往往用于chrome.declarativeWebRequest API(目前還不穩(wěn)定)和chrome.declarativeContent API。
事件規(guī)則的最佳實(shí)踐:
- 以數(shù)組的方式批量注冊(cè)規(guī)則,而非逐個(gè)注冊(cè)規(guī)則;
- 規(guī)則的條件是URL時(shí),將URL分成若干個(gè)子字符串進(jìn)行匹配,而非整個(gè)URL的表達(dá)式;(對(duì)URL的過(guò)濾,有一個(gè)專(zhuān)用的chrome.events.UrlFilter可用,此處略。)
- 如果幾個(gè)條件對(duì)應(yīng)相同的處理行為,則將這些條件放進(jìn)一個(gè)規(guī)則中