在上一篇中,我简单讲解了Chrome扩展开发中的内容脚本部分,现在我将演示一个稍微有意思的例子,该例子主要演示扩展页面和内容脚本之间如何通信。虽然该例子稍有意思,但并没有什么实用价值,这里的目的仅仅是为了阐述基本原理。
这个例子如下:
扩展加载后,在浏览器扩展工具栏图标显示
当访问google(http://www.google.com.hk/)的时候,显示:
在扩展页中打开的标签页(选择扩展弹出页中的open chat tab按钮,上面第一图)如下:
该例子演示可以通过在文本框中输入文本,在这两个页面之间相互发送信息。上面的截图是我已经分别在扩展页和google页里输入了文本的情况。
实现代码
先把实现代码贴出来,后面再简单介绍下基本过程。
manifest.json清单文件内容:
{
"browser_action": {
"default_icon": "icon-19.png",
"default_title": "hello chat",
"icons": [ "icon-19.png" ],
"name": "chat demo",
"popup": "popup.html"
},
"content_scripts": [ {
"js": [ "hello.js" ],
"matches": [ "http://www.google.com.hk/" ],
"run_at": "document_end"
} ],
"description": "chat demo",
"icons": {
"128": "icon-128.png"
},
"name": "chat demo",
"permissions": [ "tabs"],
"version": "1.0"
}
打开的标签页chat_tab.html文件内容:
<html><body><head><script>function sendChatMsg()
{var msgNode = document.getElementById("chat_msg");if(msgNode.value == "")
{return;
}chrome.windows.getCurrent(function(wnd){
chrome.tabs.getAllInWindow(wnd.id, function(tabs){
for(var i=0; i < tabs.length; i++){if(tabs[i].url == "http://www.google.com.hk/"){chrome.tabs.sendRequest(tabs[i].id, {msg: msgNode.value});msgNode.value="";}}});});contentNode = document.getElementById("chat_content");contentNode.value = contentNode.value + "我说:" + msgNode.value + "/r/n";contentNode.scrollTop = contentNode.scrollHeight;}chrome.extension.onRequest.addListener(function(data){
contentNode = document.getElementById("chat_content");contentNode.value = contentNode.value + "google说:" + data.msg + "/r/n";contentNode.scrollTop = contentNode.scrollHeight;});</script><head><div><textarea id="chat_content" ROWS="8" COLS="50"></textarea><div><input id="chat_msg" type="text" SIZE="46"/><input type="button" value="发送" οnclick="sendChatMsg()"/></div></div></body></html>
点击扩展图标的popup.html文件内容:
<html><body><input type="button" value="open chat tab" onclick="chrome.tabs.create({'url': 'chat_tab.html'})"/></body></html>
内容脚本hello.js文件内容:
var sendChatMsg = function(){var msgNode = document.getElementById("chat_msg");if(msgNode.value == "")
{return;
}chrome.extension.sendRequest({msg: msgNode.value});contentNode = document.getElementById("chat_content");contentNode.value = contentNode.value + "i say:" + msgNode.value + "/r/n";contentNode.scrollTop = contentNode.scrollHeight;msgNode.value="";};chatdiv = document.createElement("div");chatdiv.id = "chat_div";
chatdiv.style.zIndex = "100";
chatdiv.style.position = "absolute";
chatdiv.style.left = "560px";
chatdiv.style.top = "280px";chatdiv.style.width = "auto";
chatdiv.style.height = "auto";
chatdiv.style.border = "1px solid";
chatdiv.style.overflow = "auto";
chatdiv.style.backgroundColor = "#F7F4EC";
chatdiv.innerHTML = "<div>" +
"<textarea id=/"chat_content/" ROWS=/"8/" COLS=/"40/"></textarea>" +
"<div><input id='chat_msg' size=/"35/" type=/"text/"/><input id='sendBtn' type=/"button/" value=/"send/"/></div></div>";
document.body.appendChild(chatdiv);
document.getElementById("sendBtn").addEventListener('click',sendChatMsg,false);chrome.extension.onRequest.addListener(function(data){
contentNode = document.getElementById("chat_content");contentNode.value = contentNode.value + "extension say:" + data.msg + "/r/n";contentNode.scrollTop = contentNode.scrollHeight;});
两个图标文件,分别是19象素的icon-19.png和128象素的icon-128.png
可以自己随便找两个图标,不要图标也可,只是在扩展工具栏图标显示的时候是一个空白不容易看清楚。注意图标文件名和清单文件中描述的要一致。
以上就是该扩展例子的全部代码内容,只需要将这些文件放在同一个目录中,然后在chrome浏览器中加载即可。
例子程序打包下载
内容讲解
对于熟练的web前端开发人员,这里需要额外阐述的内容不多。
在清单文件中:
browser_action节点是用来描述该扩展实用的页面范围,browser_action表示从浏览器层面实用所有页面,除此还可以是page_action,page_action表示实用于单个页面,如果是page_action的话,图标将显示在匹配页的地址栏,而不是工具栏。
popup.html:该文件就是当点击扩展图标的时候显示的内容,在该例子中,我们显示的内容就是打开一个新tab的按钮而已,如上第一图,open chat tab按钮。
permissions节点是描述权限的,一些扩展api需要事先在清单文件中描述权限,否则无法使用。我们用到了tab相关的api调用所以里面写了“tabs”。
在chat_tab.html页中:
主要是一点js实现,其中调用chrome.tabs.sendRequest扩展api来向内容脚本发送消息,用chrome.extension.onRequest.addListener添加从内容脚本接收到消息的处理函数。
在内容脚本hello.js中:
其处理逻辑包括新增加一个div元素来作交互界面,其实现无非是标准dom接口调用document.body.appendChild一个div元素而已。消息发送部分因为是从内容脚本发给扩展页,所以调用变为chrome.extension.sendRequest。而接收从扩展发来的消息处理同样是chrome.extension.onRequest.addListener。
注意在内容脚本中增加一个div界面时,对于send按钮的事件处理,如果直接写在html代码中是不起作用的,比如写成
<input id='sendBtn' type="button" value="send" onclick=”sendChatMsg”/>
这样的写发是不会触发对sendChatMsg的调用的,因为sendChatMsg并没有在原页面中定义。正确的做法是调用
document.getElementById("sendBtn").addEventListener('click',sendChatMsg,false);
来挂接事件处理函数。始终要记住:内容脚本和原始页面之间只共享DOM,它们之间的交互只能通过DOM接口来进行。
扩展API简介
对web前端开发人员,上面的例子需要说明的仅仅是对几个扩展api的介绍:
chrome.tabs.create():调用该api将打开一个新的标签页。
chrome.windows.getCurrent(function callback):该函数是获取当前窗口,其参数是一个回调函数,在回调函数中将传递一个windows对象,通过该对象可以获取窗口的基本信息,在我们的例子中主要是利用了窗口id。
chrome.tabs.getAllInWindow(integer windowId, function callback):该接口是获取某个窗口的所有tab页,其第一个参数是窗口id,第二个参数是一个回调函数,在回调函数中将传回一个tabs数组对象,数组包含了当前窗口所打开的所有tab标签页对象。通过数组条目获取单个tab对象的基本信息,我们用到了tab的id和url属性。通过url判断,我们只将消息发送给了我们挂接了内容脚本的google首页。
chrome.tabs.sendRequest(integer tabId, any request, function responseCallback):该函数从扩展页发送消息给内容脚本,第一个参数是内容脚本所在的tab id,第二参数是消息内容,为json格式。第三为可选响应回调函数参数。
chrome.extension.onRequest.addListener(function(any request, MessageSender sender, function sendResponse) {...}):
该接口用于挂接消息处理函数,在内容脚本和扩展页中都一样。收到的消息就是sendRequest发出的json格式消息。
chrome.extension.sendRequest(string extensionId, any request, function responseCallback):从内容脚本发送消息给扩展页。第一个参数是扩展的id,为可选参数,默认表示发送给当前扩展。第二个参数为json格式消息对象,第三个参数是可选响应回调函数参数。
总结
本文主要介绍了扩展页如何和内容脚本进行通信的问题,其核心是三个API:chrome.tabs.sendRequest、chrome.extension.sendRequest和chrome.extension.onRequest.addListener。其他内容都是标准的web前端技术。
详细的api可参考官方文档介绍。官方的整个文档很精简,建议仔细阅读,并动手实践消化。我这里做的例子也仅仅是简单实践一下,加深理解而已。