博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Chrome 消息传递机制
阅读量:4950 次
发布时间:2019-06-11

本文共 5363 字,大约阅读时间需要 17 分钟。

Chrome插件开发入门(二)——消息传递机制

 2014-03-31 
9538 阅读
 

由于插件的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)

如果只是想简单的给扩展的其它页面发送一次消息,那么可以使用  或者  方法,它允许你发送单次的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) {}) 来替代。

在消息接收完毕时,需要设置一个   事件监听器来处理消息,这部分在 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 和扩展页面之间保持一个长期的通讯信道,那么你可以分别使用  和  来建立长连接信道。可以选择性地给信道命名,方便你区分不同类型的连接。

每个连接建立完成后都会返回一个  对象,用来在连接之间发送和接收消息。

下面的例子展示了如何从 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。最简单地可以把上面的连接的代码改成  即可。

为了能够处理连接请求,需要设置一个   事件监听器,在 content script 和扩展页面中中都是一样的。当扩展的某一部分调用了 “connect() ”,该事件即被触发,然后就可以使用  对象来发送和接收消息了。响应连接的代码大致如下所示:

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."}); }); });

或许有时你还想知道连接何时关闭,那么你可以监听  事件,当通讯的任意一端调用  ,或者包含该端口的页面已被卸载。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

             bg 

这里引用了一个后台处理程序,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地址:

The post  appeared first on .

转载于:https://www.cnblogs.com/developer-ios/p/5925680.html

你可能感兴趣的文章
debounce、throttle、requestAnimationFrame
查看>>
linux下的C语言快速学习—进程和文件
查看>>
电源防反接保护电路
查看>>
stm32 堆和栈(stm32 Heap & Stack)
查看>>
SpringMVC从入门到精通之第三章
查看>>
JS基础-dom操作
查看>>
【转】Android详细的对话框AlertDialog.Builder使用方法
查看>>
Unite Beijing 2015大型活动
查看>>
loading加载的代码
查看>>
PHP框架CI CodeIgniter 的log_message开启日志记录方法
查看>>
arraylist
查看>>
关于poi导出excel三种方式HSSFWorkbook,SXSSFWorkbook,csv的总结
查看>>
zoj 1649 Rescue (BFS)(转载)
查看>>
371. Sum of Two Integers java solutions
查看>>
2124: 等差子序列 - BZOJ
查看>>
3529: [Sdoi2014]数表 - BZOJ
查看>>
字符串匹配算法综述
查看>>
Linux centosVMware shell 管道符和作业控制、shell变量、环境变量配置文件
查看>>
在程序被送入后台时,向 iOS 借点时间,来完成一个长期任务
查看>>
【设计模式】工厂模式
查看>>