如果你仅仅需要给你自己的扩展的另外一部分发送一个消息(可选的是否得到答复),你可以使用简单的chrome.extension.sendRequest()或者chrome.tabs.sendRequest()方法。这个方法可以帮助你传送一次JSON序列化消息从content script到扩展,反之亦然。如果接受消息的一方存在的话,可选的回调参数允许处理传回来的消息。
像下面这个例子一样,可以从content script 发起一个请求:
contentscript.js
================
chrome.extension.sendRequest({greeting: "hello"}, function(response) {
console.log(response.farewell);
});
传递一个请求到扩展很容易,你需要指定哪个标签发起这个请求。下面这个例子展示了如何指定标签发起一个请求。
background.html
===============
chrome.tabs.getSelected(null, function(tab) {
chrome.tabs.sendRequest(tab.id, {greeting: "hello"}, function(response) {
console.log(response.farewell);
});
});
接受消息的一方,需要启动一个chrome.extension.onRequest事件监听器用来处理消息。这个方法在content script和扩展中都是一样的。这个请求将会保留直到你做出了回应。下面的这个例子是一个很好的做法调用一个空对象请求然后得到答复的例子。
chrome.extension.onRequest.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"});
else
sendResponse({}); // snub them.
});
小提示:如果多个页面都发起了相同的请求,都在等待答复,只有第一个发起请求的页面会得到响应,其他的将会被忽略。
长时间的保持连接
有时候持续长时间的保持会话会比一次简单的请求有用。你可以建立一个长时间存在的通道从content script到扩展, 反之亦然,使用chrome.extension.connect()或者chrome.tabs.connect()方法,你可以把这个通道命名,为了更方便区分不同类型的连接。
一个有用的例子就是自动填写表单扩展。content script可以建立一个通道在登录页面和扩展之间,同时发出一条消息给扩展,告诉扩展需要填写的内容。共享的连接允许扩展保持共享状态,从而连接几个来自content script.的消息。
当建立连接,两端都有一个Port 对象通过这个连接发送和接收消息。
下面展示了如何从content script建立一个通道,发送和接受消息:
contentscript.js
================
var port = chrome.extension.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"});
});
从扩展到content script发送一个请求看起来非常简单,除了你需要指定哪个标签需要连接, 简单的办法就是上面例子中的chrome.tabs.connect(tabId, {name: "knockknock"}).
为了处理正在等待的连接,你需要用chrome.extension.onConnect 事件监听器,对于content script或者扩展页面,这个方法都是一样的,但你的扩展的另外一个部分调用"connect()", 这个事件一旦被触发,通过这个连接你可以利用Port对象进行发送和接收消息,下面的例子展示了如何处理连接:
chrome.extension.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."});
});
});
你可能想知道这个连接什么时候被关闭。例如,如果你在为每个开放的端口维护分开的状态,如果你想知道它什么时候关闭,因此,需要监听Port.onDisconnect 事件,这个事件被激发,要么是通道调用了Port.disconnect()这个方法,要么这个页面包含的端口没有被加载(例如这个标签是个导航栏) ,onDisconnect()保证仅仅被激发一次。
扩展之间的消息传递
除了在扩展的组件之间传送消息,你还可以使用消息API来和其他的扩展之间进行通信,你可以使用一个其他扩展也可以利用的公共API。
对于扩展内部来说,监听一个传入的请求和连接是一样的,你可以使用chrome.extension.onRequestExternal或者chrome.extension.onConnectExternal方法,如下面的例子所示:
// For simple requests:
chrome.extension.onRequestExternal.addListener(
function(request, sender, sendResponse) {
if (sender.id == blacklistedExtension)
sendResponse({}); // don't allow this extension access
else if (request.getTargetData)
sendResponse({targetData: targetData});
else if (request.activateLasers) {
var success = activateLasers();
sendResponse({activateLasers: success});
}
});
// For long-lived connections:
chrome.extension.onConnectExternal.addListener(function(port) {
port.onMessage.addListener(function(msg) {
// See other examples for sample onMessage handlers.
});
});
同样,传递一个消息到另外一个扩展和把消息传递给自己扩展的另外一部分是一样的,唯一不同的是你必须知道你要传给消息的扩展的ID例如:
// The ID of the extension we want to talk to.
var laserExtensionId = "abcdefghijklmnoabcdefhijklmnoabc";
// Make a simple request:
chrome.extension.sendRequest(laserExtensionId, {getTargetData: true},
function(response) {
if (targetInRange(response.targetData))
chrome.extension.sendRequest(laserExtensionId, {activateLasers: true});
});
// Start a long-running conversation:
var port = chrome.extension.connect(laserExtensionId);
port.postMessage(...);
安全策略
无论是从content script还是从扩展接收消息,你的页面不应该cross-site scripting,特别是避免使用那些不安全的API例如下面的例子:
background.html
===============
chrome.tabs.sendRequest(tab.id, {greeting: "hello"}, function(response) {
// WARNING! Might be evaluating an evil script!
var resp = eval("(" + response.farewell + ")");
});
background.html
===============
chrome.tabs.sendRequest(tab.id, {greeting: "hello"}, function(response) {
// WARNING! Might be injecting a malicious script!
document.getElementById("resp").innerHTML = response.farewell;
});
相反的,选择更安全的API而不是运行脚本。
background.html
===============
chrome.tabs.sendRequest(tab.id, {greeting: "hello"}, function(response) {
// JSON.parse does not evaluate the attacker's scripts.
var resp = JSON.parse(response.farewell);
});
background.html
===============
chrome.tabs.sendRequest(tab.id, {greeting: "hello"}, function(response) {
// innerText does not let the attacker inject HTML elements.
document.getElementById("resp").innerText = response.farewell;
});
范例
你可以在这个examples/api/messaging 目录下找到消息传递的例子,也可以找到contentscript_xhr (contents script和扩展之间传递消息的例子),更多的内容和源码,请查看Smples.
分享到:
相关推荐
在使用JavaScript的Ajax请求时,如果在Ajax请求完成后没有阻止按钮的默认行为,即表单提交,就会发生“一次点击两次提交”的情况。下面详细探讨两种常用的解决办法。 ### 解决方案一:更改按钮的type属性 第一种...
- ** Volley/ Retrofit**: 这是两个流行的网络请求库,Volley适合简单的HTTP请求,而Retrofit提供了一种基于注解的简洁API来构建网络服务接口。 2. **SpringBoot后端服务**: - **Spring Boot简介**: SpringBoot...
这个资源提供的是一个最简单的二次解析源码,它附带了一次解析接口,方便开发者快速搭建二次解析站点。下面将详细讲解这个过程及相关知识点。 首先,我们关注的是"一次解析接口"。一次解析通常是针对原始视频链接...
在IT行业中,尤其是在Web开发领域,限制用户在一定时间内只能发送一次请求是非常常见的需求,这通常用于防止重复提交、刷票、恶意攻击等场景。以下将详细解释如何实现这一功能,以及涉及的相关知识点。 首先,我们...
本项目“自定义网络请求,对网络请求的简单封装”旨在提供一种通用的解决方案,使得在网络请求框架变更时,应用的核心逻辑能够保持稳定,减少因更换库而带来的代码修改工作。 首先,我们需要理解网络请求的基本概念...
Requests是Python编程语言中的一款非常流行的HTTP客户端库,由 Kenneth Reitz 创建,旨在使网络请求变得简单、直观。这个库的出现,极大地降低了开发者在处理HTTP请求时的复杂度,无论是进行网页抓取还是API调用,都...
如果请求是在某个事件触发后执行的,比如按钮点击,确保事件处理函数是幂等的,即多次执行应该得到相同的结果,不会因为上一次操作的影响而产生问题。 其次,Vue中使用axios发送请求时,对于非简单请求(比如POST、...
总的来说,"win定时请求网址"是一个实用的Windows应用程序,为需要定期访问网络资源的用户提供了一个简单而有效的解决方案。通过自动化定时任务,用户可以释放手动操作的时间,专注于其他更重要的工作。
在IT领域,定时任务执行是常见的一种自动化操作方式,它允许我们按照预设的时间间隔执行特定的任务,例如请求一个网址。这个"很小的一个exe程序"就是实现这一功能的可执行文件,它简单易用,只需设定要访问的网址和...
1. **限制并发数**:一次只发送有限数量的请求,而不是一次性处理所有URL。这可以通过使用多线程或者异步处理来实现。 2. **设置延迟**:在每次请求之间添加短暂的延时,如`sleep(1)`,以减缓请求速率。 3. **使用...
这个是我自己集成框架的时候写的一个HTTP请求的辅助类,主要是通过HttpURLConnection 来实现JAVA的HTTP请求,有的人会问、为什么有些网站发请求没问题,有些网站发请求却返回数据,在给网站发送请求的时候,请看清楚...
在浏览器的F12调试页面中,我们可以看到,只有一次请求,/requestDemo5请求,然后将请求转发到RequestDemo6。这说明了RequestDispatcher可以实现请求的转发,而不是重定向。 在使用Postman进行post请求时,我们可以...
在.net 中查询Sql Server 一次请求执行多条sql语句很简单 拼接起来就好了 初次接触oracle 在网上寻找了很多方法终于被我解决了 我把问题想复杂了 例子中提供了2种解决方案 一种是用游标 还有一种就是很简单的...
### 使用CURL发送HTTP请求详解 ...无论是简单的GET请求,还是复杂的POST数据提交,CURL都能胜任。此外,其丰富的调试选项使得开发者能够轻松排查问题,优化网络应用。掌握CURL,无疑将极大提升网络开发的效率和质量。
本项目提供的“javaweb简单的一次性验证码”是一个基于Servlet实现的简单验证码系统,旨在帮助初学者理解验证码的工作原理及其在Web应用中的应用。 验证码的主要目的是防止恶意机器人或爬虫进行自动化注册、登录或...
其中,"Android-DailyNet简单易用的Android网络请求框架自动绑定生命周期调度请求"是一个专为Android设计的轻量级网络请求库,它以其易用性和对生命周期的智能管理脱颖而出。 DailyNet框架的核心特性在于其自动绑定...
然而,requests的默认行为是串行发送请求,这意味着一次只能发送一个请求,并且需要等待前一个请求响应后才能继续发送下一个。 2. 串行请求的局限性:由于requests发送请求是串行的,这在需要大量发送请求时将导致...
封装好的axios重复点击取消上一次请求方法,不仅在单个Vue实例中有效,也可以在多实例中复用,只需在相应实例中加入同样的逻辑。这种方式大大简化了在开发过程中对请求的管理,使得代码更加清晰易维护。 总结来说,...
对于GET请求,AmHttpSocket可能提供了简单的接口,只需要提供URL即可。而对于POST请求,可能需要额外提供请求体数据和相关的Content-Type头。 了解这些基础知识后,开发者可以根据具体需求使用AmHttpSocket库来构建...