Google chrome浏览器中通过扩展调用本地应用程序以及和程序相互通讯(C++)

最近项目用到浏览插件的开发,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;
}

重中之重就是注意通讯中都有四个字节的包头,表示包的大小,这个不能丢,否则不会成功。

posted @ 2015-01-19 10:59  KAME  阅读(8374)  评论(0编辑  收藏  举报