Chrome 消息传递机制
Chrome插件开发入门(二)——消息传递机制
由于插件的js运行环境有区别,所以消息传递机制是一个重要内容。阅读了很多博文,大家已经说得很清楚了,直接转一篇@姬小光 的博文,总结的挺好。后面附一个自己写过的demo,基本就对消息传递能够熟悉了。
在开发 Chrome 扩展时经常需要在页面之间进行通讯,比如 background 与 content script 之间,background 与 popup 之间等等,本文结合官方文档中的例子介绍了 chrome 扩展开发中消息传递的基本实现。
一般情况下,我们会让 background 来控制一切,将扩展的主要逻辑都放在 background 中比较便于管理。其它页面可以通过消息传递的机制与 background 进行通讯。
理论上 content script 与 popup 之间也可以传递消息,但不建议这么做。
对于 background 和 popup 之间,其实可以直接相互调用对方的方法,也不需要消息传递。那么消息传递其实主要就是 content script 和 background 之间进行的了。
在 Chrome 扩展内部的消息传递分为两种,一种是单次的消息请求,另外一种是长连接。下面详细举例说明。
简单的单次请求(Simple one-time requests)
如果只是想简单的给扩展的其它页面发送一次消息,那么可以使用 runtime.sendMessage 或者 tabs.sendMessage 方法,它允许你发送单次的JSON序列化后的数据,可以从 content script 发送给扩展页面,反之亦然。也可以选择性地传入一个处理响应的回调函数。
从 content script 发送请求代码如下:
contentscript.js
================
chrome.runtime.sendMessage({greeting: "hello"}, function(response) {
console.log(response.farewell);
});
从扩展页面发送给 content script 也很类似,只是需要指定发送给那个 tab,下面的例子即为向选中的 tab 发送消息:
background.html
===============
chrome.tabs.getSelected(null, function(tab) {
chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, function(response) {
console.log(response.farewell);
});
});
注:官方例子中的 getSelected 方法已经被废弃了,可以使用 chrome.tabs.query({active:true}, function(tab) {}) 来替代。
在消息接收完毕时,需要设置一个 runtime.onMessage 事件监听器来处理消息,这部分在 content script 和扩展页面种都是一样的:
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"});
});
注意:如果有多个页面同时监听 onMessage 事件,那么只有第一个调用 sendResponse() 的页面可以成功返回响应信息,其它的都会被忽略。
小技巧:当事件监听器返回时函数就不可用了,不过如果让函数 return: true 的话,可以让该函数异步响应,直到调用 sendResponse 后才结束,具体说明请见文档。
长连接(Long-lived connections)
有时候我们需要在 content script 和扩展页面之间保持一个长期的通讯信道,那么你可以分别使用 runtime.connect 和 tabs.connect 来建立长连接信道。可以选择性地给信道命名,方便你区分不同类型的连接。
每个连接建立完成后都会返回一个 runtime.Port 对象,用来在连接之间发送和接收消息。
下面的例子展示了如何从 content script 建立连接,并发送和接收消息:
contentscript.js
================
var port = chrome.runtime.connect({name: "knockknock"});
port.postMessage({joke: "Knock knock"});
port.onMessage.addListener(function(msg) {
if (msg.question == "Who's there?")
port.postMessage({answer: "Madame"});
else if (msg.question == "Madame who?")
port.postMessage({answer: "Madame... Bovary"});
});
从扩展页面建立连接也很类似,只是要指定要连接到哪个tab。最简单地可以把上面的连接的代码改成 tabs.connect 即可。
为了能够处理连接请求,需要设置一个 runtime.onConnect 事件监听器,在 content script 和扩展页面中中都是一样的。当扩展的某一部分调用了 “connect() ”,该事件即被触发,然后就可以使用 runtime.Port 对象来发送和接收消息了。响应连接的代码大致如下所示:
chrome.runtime.onConnect.addListener(function(port) {
console.assert(port.name == "knockknock");
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."});
});
});
或许有时你还想知道连接何时关闭,那么你可以监听 runtime.Port.onDisconnect 事件,当通讯的任意一端调用 runtime.Port.disconnect,或者包含该端口的页面已被卸载。onDisconnect 事件可以保证在每个端口上只触发一次。
另外,消息传递还包括不同扩展之间的消息传递,还有 Chrome 与本地程序之间的消息传递,这里就不介绍了,感兴趣的同学可以直接查看官方文档。
—————————————–分割线——————————————-
demo:
几个最基本的文件
在这里,先假设大家对chrome插件开发的最基本知识已有所掌握。例如什么是manifest.json,什么是background.html等。
manifest.json
{
"name": "A browser action with a popup that changes the page color.",
"version": "1.0",
"permissions":["tabs","<all_urls>"],
"browser_action": {
"default_icon": "icon.png"
},
"background": {
"page": "background.html"
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js" : ["jquery-1.7.1.js","injectscript.js"]
}
],
"manifest_version": 2
}
background.html
<!DOCTYPE html>
<html>
<head>
<title>bg</title>
<script type="text/javascript" src="http://blog.chenqiushi.com/2014/03/31/chrome%e6%8f%92%e4%bb%b6%e5%bc%80%e5%8f%91%e5%85%a5%e9%97%a8%ef%bc%88%e4%ba%8c%ef%bc%89-%e6%b6%88%e6%81%af%e4%bc%a0%e9%80%92%e6%9c%ba%e5%88%b6/bg.js"><script>
</head>
<body>
hello
<body>
</html>
这里引用了一个后台处理程序,bg.js,后面会讲到。
扩展程序发送请求数据到内容脚本,内容脚本给出回应
扩展程序后台脚本bg.js
(function(){
chrome.browserAction.onClicked.addListener(function(tab) {
// 扩展向内容脚本发送消息
chrome.tabs.sendMessage(tab.id,{
greeting: "hello to content script!"
}, function(response) {
console.log(response.farewell);
});
});
})();
内容脚本injectscript.js
(function(){
console.log("injected");
var resOK = {
farewell: "content script send response back..."
};
var resError = {
farewell: "content script hasError!"
};
chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
console.log("Request comes from extention " + sender.tab.url);
if (request.greeting === "hello to content script!"){
sendResponse(resOK);
}else{
sendResponse(resError);
}
});
})();
扩展程序向内容脚本发送一条消息hello to content script!
,内容脚本接收到这条消息后去判断是不是那句话,如果是,就返回resOK
对象,如果不是,就返回resError
对象。
这时,扩展程序收到内容脚本的一条回应,至此,此番通话就结束了。
看一下结果截图
内容脚本发送请求数据到扩展程序,扩展程序给出回应
扩展程序后台脚本bg.js
(function(){
var resOK = {
farewell: "extension send response back..."
};
var resError = {
farewell: "extension hasError!"
};
chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
console.log("Request comes from content script " + sender.tab.url);
if (request.greeting === "hello to extention!"){
sendResponse(resOK);
}else{
sendResponse(resError);
}
});
})();
内容脚本injectscript.js
(function(){
console.log("injected");
chrome.extension.sendMessage({greeting: "hello to extention!"}, function(response) {
console.log(response.farewell);
});
})();
内容脚本向扩展程序发送一条消息hello to extention!
,扩展程序接收到这条消息后去判断是不是那句话,如果是,就返回resOK
对象,如果不是,就返回resError
对象。
这时,内容脚本收到扩展程序的一条回应,至此,此番通话就结束了。
特别应该注意的是:扩展程序向内容脚本发送请求数据时用的是chrome.tabs.sendMessage
,反过来,用的是chrome.extension.sendMessage
。
看一下结果截图
如果以后还有一些chrome插件的学习总结,还会写在这里。
demo地址:
点击下载demo
The post Chrome插件开发入门(二)——消息传递机制 appeared first on Blog | Qiushi Chen.
Chrome 消息传递机制的更多相关文章
- Chrome插件开发入门(二)——消息传递机制
Chrome插件开发入门(二)——消息传递机制 由于插件的js运行环境有区别,所以消息传递机制是一个重要内容.阅读了很多博文,大家已经说得很清楚了,直接转一篇@姬小光 的博文,总结的挺好.后面附一 ...
- Storm内部的消息传递机制
作者:Jack47 转载请保留作者和原文出处 欢迎关注我的微信公众账号程序员杰克,两边的文章会同步,也可以添加我的RSS订阅源. 一个Storm拓扑,就是一个复杂的多阶段的流式计算.Storm中的组件 ...
- 我理解的Hanlder--android消息传递机制
每一个学习Android的同学都会觉得Handler是一个神奇的东西,我也一样,开始我以为我懂了Handler的机制,后来发现自己是一知半解,昨天想想,我能否自己实现一个Handler,让子线程与Ac ...
- Handler消息传递机制
引言: 出于性能优化考虑,Android的UI操作并不是线程安全的,这意味着如果有多个线程并发操作UI组件,可能导致线程安全问题. 为了解决这个问题,Android制定了一条简单的规则:只允许UI线程 ...
- Android学习之Handler消息传递机制
Android只允许UI线程修改Activity里的UI组件.当Android程序第一次启动时,Android会同时启动一条主线程(Main Thread),主线程主要负责处理与UI相关的事件,如用户 ...
- ios 消息传递机制
引用文章 一.KVO 1.当对象中的某个属性值发生了改变,可以对这些值的观察者做出通知. 2.接受者(会接收到值发生改变的消息) 必须知道发送者(值将发生改变的那个对象). 3.接收者同样还需要知道发 ...
- iOS开发——OC篇&消息传递机制(KVO/NOtification/Block/代理/Target-Action)
iOS开发中消息传递机制(KVO/NOtification/Block/代理/Target-Action) 今晚看到了一篇好的文章,所以就搬过来了,方便自己以后学习 虽然这一期的主题是关于Fou ...
- Android异步消息传递机制源码分析
1.Android异步消息传递机制有以下两个方式:(异步消息传递来解决线程通信问题) handler 和 AsyncTask 2.handler官方解释的用途: 1).定时任务:通过handler.p ...
- (Android数据传递)Intent消息传递机制 “Intent”“数据传递”
Intent类的继承关系: 需要注意的是,该类实现了Parcelable(用于数据传递)和Cloneable接口. Intent是一种(系统级别的)消息传递机制,可以在应用程序内使用,也可以在应用 ...
随机推荐
- Java 参数传递都是值传递
Java 参数传递都是值传递,验证代码如下 public class ParamTransferTest { public static void swap(int a, int b) { int t ...
- 开始玩mondrian
官网:http://community.pentaho.com/projects/mondrian/ 官方编译的包:https://sourceforge.net/projects/mondrian/ ...
- linux NFS服务器安装与配置 思路
一,nfs服务优缺点 NFS 是Network File System的缩写,即网络文件系统,可以让不同的客户端挂载使用同一个目录,作为共享存储使用,这样可以保证不同的节点客户端数据一致性,在集群架构 ...
- MFC 网络编程 -- 总结
原文链接:http://www.cnblogs.com/lidabo/archive/2012/07/19/2598734.html 1.基于 TCP 的 socket 编程 /* 服务器端程序流程: ...
- linux编译安装MySQL
最近就想搞搞hadoop,然后装个MySQL,测试一下那个sqoop. MySQL这种东西,既然是开放源码的,那就源码安装吧. 下面是我的测试环境说明: VMware10+Ubuntu14.04 Ky ...
- Sping mvc 环境下使用kaptcha 生成验证码
一.kaptcha 的简介 kaptcha 是一个非常实用的验证码生成工具.有了它,你可以生成各种样式的验证码,因为它是可配置的.kaptcha工作的原理是调用 com.google.code.kap ...
- mod_rewrite
一.简介 http://www.07fly.net/a/wangluobiancheng/Phpbiancheng/201501/58393.html 二.实现原理: 只有当用户的WE ...
- Ubuntu 安装JDK并配置成为默认的JDK
Ubuntu安装JDK 系统版本:Ubuntu 15.04 x64 JDK版本:jdk-8u60-linux-x64 1.查看系统位数,输入以下命令即可 getconf LONG_BIT 2.下载对应 ...
- Js脚本选取iframe中的元素
遇到个小问题,需要用到原生Js处理页面中的元素,以往一个document.getElementById就完活的选取元素,这次却不好使了.. 仔细看代码发现要选取元素外面多了一个iframe标签 < ...
- zookeeper适用场景:分布式锁实现
问题导读:1.zookeeper如何实现分布式锁?2.什么是羊群效应?3.zookeeper如何释放锁? 在zookeeper应用场景有关于分布式集群配置文件同步问题的描述,设想一下如果有100台机器 ...