最近項目用到瀏覽插件的開發,IE用到的是BHO,chrome打算做成擴展。
但是和ie有一點不同,chrome擴展是基於html+js+css開發的,那么就會有二個問題
1. 代碼和算法等容易被別人復制和盜用。
2. 有部份功能需要用native code來實現。
所以僅僅使用chrome擴展是不夠的。后來想到了native client,但是這個需要在chrome://flags/中開啟相應的設置。而且也不是很安全。
最后選擇了chrome的native messaging,原理我就不多說了,這里只介紹如何實現。
chrome擴展中,manifest.json有幾點要注意
"background": {
"scripts": [
"res/js/background.js"
]
},
上面個background.js,是必須要加的,后面會介紹原因
"content_scripts": [
{
"all_frames": false,
"css": [
],
"js": [
"res/js/contentscript.js"
],
"matches": [
"http://*/*",
"https://*/*"
],
"run_at": "document_end"
}
],
這個表示在頁面加載結束時調用contentscript.js
"permissions": [
"nativeMessaging"
],
權限別忘了加上。
contentscript.js中,只有一段代碼
$(function () {
chrome.extension.sendRequest("this is a request");
});
重點在background.js中了,不多說,貼代碼
var port;
function onDisconnected() {
port = null;
}
function onNativeMessage(message) {
alert(JSON.stringify(message));
}
function connect() {
port = chrome.runtime.connectNative('com.beeper2g.demo.nativemessage');
port.onMessage.addListener(onNativeMessage);
port.onDisconnect.addListener(onDisconnected);
}
chrome.extension.onRequest.addListener(function(data, sender) {
if (data.length > 0) {
connect();
port.postMessage(data);
}
});
注意方法 chrome.runtime.connectNative 是屬於content script,這個不能在頁面中調用,所以只能放在backgroud.js中,上面提到過。
擴展中的東西就這么些,講一下注冊以及調用方式
注冊和解注冊就是在注冊表中添加相應的值就OK了,發二個bat,一個install,一個uninstall
install.bat內容為
:: %~dp0 is the directory containing this bat script and ends with a backslash.
REG ADD "HKCU\Software\Google\Chrome\NativeMessagingHosts\com.beeper2g.demo.nativemessage" /ve /t REG_SZ /d "%~dp0com.beeper2g.demo.nativemessage.json" /f
uninstall.bat內容為
:: Deletes the entry created by install_host.bat
REG DELETE "HKCU\Software\Google\Chrome\NativeMessagingHosts\com.beeper2g.demo.nativemessage" /f
其中的com.beeper2g.demo.nativemessage.json中內容十分簡單
{
"name": "com.beeper2g.demo.nativemessage",
"description": "Demo程序",
"path": "X:\XXX\chromeService.exe",
"type": "stdio",
"allowed_origins": [
"chrome-extension://fkdejdpefhhjdjdlmalkegclifdofipm/"
]
}
字段自己去對應,path為絕對路徑。chrome-extension://fkdejdpefhhjdjdlmalkegclifdofipm/ 中的id別忘了與擴展一致
c++部份
// chromeHost.cpp : Defines the entry point for the console application.
//
using namespace std;
void output(const string& str)
{
unsigned int len = str.length();
cout<< char(((len>>0) & 0xFF))
<< char(((len>>8) & 0xFF))
<< char(((len>>16) & 0xFF))
<< char(((len>>24) & 0xFF));
cout << str << endl;
}
string getInput()
{
string input;
unsigned int reqLen = 0;
cin.read(reinterpret_cast<char*>(&reqLen) ,4);
for (int i = 0; i < reqLen; i++) {
input += getchar();
}
return input;
}
int main(int argc, char* argv[]) {
string input = getInput();
MessageBoxA(NULL, input.c_str(), NULL, NULL);
output("this is response");
return 0;
}
重中之重就是注意通訊中都有四個字節的包頭,表示包的大小,這個不能丟,否則不會成功。