Chrome Native Message的原理网上有很多的文章介绍,本片文章就不介绍了。小编研究了一周的时间,终于完成了获取Mac地址的扩展开发。由于网上给出的例子都是跑不通的,分享给大家参考。
1、编写C++代码获取MAC地址
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
static std::string GetMACaddress(void)
{
IP_ADAPTER_INFO AdapterInfo[16]; // Allocate information for up to 16 NICs
DWORD dwBufLen = sizeof(AdapterInfo); // Save the memory size of buffer
DWORD dwStatus = GetAdaptersInfo( // Call GetAdapterInfo
AdapterInfo, // [out] buffer to receive data
&dwBufLen); // [in] size of receive data buffer
assert(dwStatus == ERROR_SUCCESS); // Verify return value is valid, no buffer overflow
PIP_ADAPTER_INFO pAdapterInfo = AdapterInfo;// Contains pointer to current adapter info
std::string outMsg = "";
do {
char acMAC[32];
sprintf(acMAC, "%02X-%02X-%02X-%02X-%02X-%02X",
int (pAdapterInfo->Address[0]),
int (pAdapterInfo->Address[1]),
int (pAdapterInfo->Address[2]),
int (pAdapterInfo->Address[3]),
int (pAdapterInfo->Address[4]),
int (pAdapterInfo->Address[5]));
outMsg.append(acMAC);
outMsg.append(",");
pAdapterInfo = pAdapterInfo->Next; // Progress through linked list
}
while(pAdapterInfo);
if(outMsg.length()>5){
outMsg = outMsg.substr(0,outMsg.length()-1);
}
return outMsg;
}
int main(int argc, _TCHAR* argv[]){
std::string outMsg = "{\"text\":\""+GetMACaddress()+"\"}";
unsigned int outLen = outMsg.length();
char *bOutLen = reinterpret_cast(&outLen);
std::cout.write(bOutLen, 4);
std::cout << outMsg << std::flush;
return 0;
}
静态编译成.exe 文件
2、编写Chrome Extensions
chrome扩展包含两个部分 host和app。
host调用C++ .exe文件,并在注册表中注册;
app可添加到chrome扩展中,供web页面调用;
2.1首先看host文件内容,host文件夹下文件列表如下图:
其中uninstall_host.bat文件是将C++程序从注册表中删除,install_host是安装c++程序到注册表中,GetMac.exe是编译后的C++程序,
最后的.json文件内容如下:
参数说明请参考: https://developer.chrome.com/extensions/nativeMessaging
{
"name": "com.google.chrome.fmb.getmac.echo",
"description": "Chrome Native Messaging API Example Host",
"path": "GetMac.exe",
"type": "stdio",
"allowed_origins": [
"chrome-extension://knldjmfmopnpolahpmmgbagdohdnhkik/"
]
}
2.2 再看app文件内容,app文件夹下文件列表如下图:
main.js和main.html 可以做测试用的,
main.js代码如下:
var port = null;
function appendMessage(text) {
document.getElementById('response').innerHTML += "" + text + "
";
}
function sendNativeMessage() {
message = {"text": document.getElementById('input-text').value};
port.postMessage(message);
appendMessage("Sent message: " + JSON.stringify(message) + "");
}
function onNativeMessage(message) {
appendMessage("Received message: " + JSON.stringify(message) + "");
}
function onDisconnected() {
appendMessage("Failed to connect: " + chrome.runtime.lastError.message);
port = null;
}
function connect() {
var hostName = "com.google.chrome.fmb.getmac.echo";
appendMessage("Connecting to native messaging host " + hostName + "")
port = chrome.runtime.connectNative(hostName);
port.onMessage.addListener(onNativeMessage);
port.onDisconnect.addListener(onDisconnected);
}
document.addEventListener('DOMContentLoaded', function () {
document.getElementById('connect-button').addEventListener(
'click', connect);
});
main.html代码如下:
background.js里面实现与host的通信,代码如下:
var port = null;
var hostName = "com.google.chrome.xxx.getmac.echo";
var mac = {};
function connect() {
port = chrome.runtime.connectNative(hostName);
port.onMessage.addListener(onNativeMessage);
port.onDisconnect.addListener(onDisconnected);
}
function onNativeMessage(message) {
mac = message;
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, mac , function(response) {
//alert("baground respone");
});
});
}
function onDisconnected() {
port = null;
}
chrome.runtime.onMessageExternal.addListener(
function(request, sender, sendResponse) {
if(request.requestType =="connect"){
if(port==null){
connect();
}
}
else{
if(port==null){
connect();
}
else{
if(mac.text!=undefined && mac.text!=null && mac.text!=""){
sendResponse(mac);
}
}
}
});
content.js能够接受background发送的消息,可以实现与应用页面交互将消息传到页面,可以在content中访问页面的dom 。 content.js代码如下:
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if(request.text != undefined && request.text!=null && request.text!=""){
document.getElementById('mac_address').value = request.text;
}
});
manifest.json配置如下,此配置文件定义扩展程序,具体参数含义参考
https://developer.chrome.com/extensions/nativeMessaging
{
//Extension ID: knldjmfmopnpolahpmmgbagdohdnhkik
"key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDcBHwzDvyBQ6bDppkIs9MP4ksKqCMyXQ/A52JivHZKh4YO/9vJsT3oaYhSpDCE9RPocOEQvwsHsFReW2nUEc6OLLyoCFFxIb7KkLGsmfakkut/fFdNJYh0xOTbSN8YvLWcqph09XAY2Y/f0AL7vfO1cuCqtkMt8hFrBGWxDdf9CQIDAQAB",
"name": "Native Messaging Example",
"version": "1.0",
"manifest_version": 2,
"description": "Send a message to a native application.",
"background" : { "scripts": ["background.js"] },
"app": {
"launch": {
"local_path": "main.html"
}
},
"icons": {
"128": "icon-128.png"
},
"content_scripts": [
{
"matches": ["http://*/*"],
"js": ["content.js"]
}
],
"externally_connectable": {"matches": ["http://test.fangmaidong.com/fmsj/*","http://localhost/fmsj/*","http://localhost:8080/fmsj/*"]},
"permissions": [
"nativeMessaging","tabs", "http://*/*", "https://*/*"
]
}
2.3应用系统页面代码实例
var editorExtensionId = "knldjmfmopnpolahpmmgbagdohdnhkik";
function sendMessage(type){
chrome.runtime.sendMessage(editorExtensionId, {requestType: type},
function(response) {
if(response.text!=undefined && response.text!=null && response.text!=""){
document.getElementById('mac_address').value = response.text;
}
});
}
sendMessage('connect');
2.4在chrome扩展设置中添加此扩展程序
3、注意事项
Chrome 的启动参数需要设置 --enable--native-messaging