谷歌扩展程序--------------Message
转载:https://developer.chrome.com/extensions/messaging#external-webpage
Message Passing
Since content scripts run in the context of a web page and not the extension, they often need some way of communicating with the rest of the extension. For example, an RSS reader extension might use content scripts to detect the presence of an RSS feed on a page, then notify the background page in order to display a page action icon for that page.
Communication between extensions and their content scripts works by using message passing. Either side can listen for messages sent from the other end, and respond on the same channel. A message can contain any valid JSON object (null, boolean, number, string, array, or object). There is a simple API for one-time requests and a more complex API that allows you to have long-lived connections for exchanging multiple messages with a shared context. It is also possible to send a message to another extension if you know its ID, which is covered in the cross-extension messages section.
Simple one-time requests
If you only need to send a single message to another part of your extension (and optionally get a response back), you should use the simplified runtime.sendMessage or tabs.sendMessage . This lets you send a one-time JSON-serializable message from a content script to extension , or vice versa, respectively . An optional callback parameter allows you handle the response from the other side, if there is one.
Sending a request from a content script looks like this:
chrome.runtime.sendMessage({greeting: "hello"}, function(response) {
console.log(response.farewell);
});
Sending a request from the extension to a content script looks very similar, except that you need to specify which tab to send it to. This example demonstrates sending a message to the content script in the selected tab.
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {greeting: "hello"}, function(response) {
console.log(response.farewell);
});
});
On the receiving end, you need to set up an runtime.onMessage event listener to handle the message. This looks the same from a content script or extension page.
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"});
});
In the above example, sendResponse was called synchronously. If you want to asynchronously use sendResponse, add return true; to the onMessage event handler.
Note: If multiple pages are listening for onMessage events, only the first to call sendResponse() for a particular event will succeed in sending the response. All other responses to that event will be ignored.
Note: The sendResponse callback is only valid if used synchronously, or if the event handler returns true to indicate that it will respond asynchronously. The sendMessagefunction's callback will be invoked automatically if no handlers return true or if thesendResponse callback is garbage-collected.
Long-lived connections
Sometimes it's useful to have a conversation that lasts longer than a single request and response. In this case, you can open a long-lived channel from your content script to an extension page , or vice versa, using runtime.connect or tabs.connect, respectively . The channel can optionally have a name, allowing you to distinguish between different types of connections.
One use case might be an automatic form fill extension. The content script could open a channel to the extension page for a particular login, and send a message to the extension for each input element on the page to request the form data to fill in. The shared connection allows the extension to keep shared state linking the several messages coming from the content script.
When establishing a connection, each end is given a runtime.Port object which is used for sending and receiving messages through that connection.
Here is how you open a channel from a content script, and send and listen for messages:
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"});
});
Sending a request from the extension to a content script looks very similar, except that you need to specify which tab to connect to. Simply replace the call to connect in the above example with tabs.connect.
In order to handle incoming connections, you need to set up a runtime.onConnect event listener. This looks the same from a content script or an extension page. When another part of your extension calls "connect()", this event is fired, along with the runtime.Port object you can use to send and receive messages through the connection. Here's what it looks like to respond to incoming connections:
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."});
});
});
Port lifetime
Ports are designed as a two-way communication method between different parts of the extension, where a (top-level) frame is viewed as the smallest part.
Upon calling tabs.connect, runtime.connect or runtime.connectNative, a Port is created. This port can immediately be used for sending messages to the other end via postMessage.
If there are multiple frames in a tab, calling tabs.connect results in multiple invocations of the runtime.onConnect event (once for each frame in the tab). Similarly, if runtime.connect is used, then the onConnect event may be fired multiple times (once for every frame in the extension process).
You may want to find out when a connection is closed, for example if you are maintaining separate state for each open port. For this you can listen to the runtime.Port.onDisconnect event. This event is fired when there are no valid ports at the other side of the channel. This happens in the following situations:
- There are no listeners for runtime.onConnect at the other end.
- The tab containing the port is unloaded (e.g. if the tab is navigated).
- The frame from where
connectwas called has unloaded. - All frames that received the port (via runtime.onConnect) have unloaded.
- runtime.Port.disconnect is called by the other end. Note that if a
connectcall results in multiple ports at the receiver's end, anddisconnect()is called on any of these ports, then theonDisconnectevent is only fired at the port of the sender, and not at the other ports.
Cross-extension messaging
In addition to sending messages between different components in your extension, you can use the messaging API to communicate with other extensions. This lets you expose a public API that other extensions can take advantage of.
Listening for incoming requests and connections is similar to the internal case, except you use theruntime.onMessageExternal or runtime.onConnectExternal methods. Here's an example of each:
// For simple requests:
chrome.runtime.onMessageExternal.addListener(
function(request, sender, sendResponse) {
if (sender.id == blocklistedExtension)
return; // 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.runtime.onConnectExternal.addListener(function(port) {
port.onMessage.addListener(function(msg) {
// See other examples for sample onMessage handlers.
});
});
Likewise, sending a message to another extension is similar to sending one within your extension. The only difference is that you must pass the ID of the extension you want to communicate with. For example:
// The ID of the extension we want to talk to.
var laserExtensionId = "abcdefghijklmnoabcdefhijklmnoabc"; // Make a simple request:
chrome.runtime.sendMessage(laserExtensionId, {getTargetData: true},
function(response) {
if (targetInRange(response.targetData))
chrome.runtime.sendMessage(laserExtensionId, {activateLasers: true});
}); // Start a long-running conversation:
var port = chrome.runtime.connect(laserExtensionId);
port.postMessage(...);
Sending messages from web pages
Similar to cross-extension messaging, your app or extension can receive and respond to messages from regular web pages. To use this feature, you must first specify in your manifest.json which web sites you want to communicate with. For example:
"externally_connectable": {
"matches": ["*://*.example.com/*"]
}
This will expose the messaging API to any page which matches the URL patterns you specify. The URL pattern must contain at least a second-level domain - that is, hostname patterns like "*", "*.com", "*.co.uk", and "*.appspot.com" are prohibited. From the web page, use the runtime.sendMessage or runtime.connect APIs to send a message to a specific app or extension. For example:
// The ID of the extension we want to talk to.
var editorExtensionId = "abcdefghijklmnoabcdefhijklmnoabc"; // Make a simple request:
chrome.runtime.sendMessage(editorExtensionId, {openUrlInEditor: url},
function(response) {
if (!response.success)
handleError(url);
});
From your app or extension, you may listen to messages from web pages via the runtime.onMessageExternalor runtime.onConnectExternal APIs, similar to cross-extension messaging. Only the web page can initiate a connection. Here is an example:
chrome.runtime.onMessageExternal.addListener(
function(request, sender, sendResponse) {
if (sender.url == blocklistedWebsite)
return; // don't allow this web page access
if (request.openUrlInEditor)
openUrl(request.openUrlInEditor);
});
Native messaging
Extensions and apps can exchange messages with native applications that are registered as a native messaging host. To learn more about this feature, see Native messaging.
Security considerations
When receiving a message from a content script or another extension, your background page should be careful not to fall victim to cross-site scripting. Specifically, avoid using dangerous APIs such as the below:
chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, function(response) {
// WARNING! Might be evaluating an evil script!
var resp = eval("(" + response.farewell + ")");
});
chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, function(response) {
// WARNING! Might be injecting a malicious script!
document.getElementById("resp").innerHTML = response.farewell;
});
Instead, prefer safer APIs that do not run scripts:
chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, function(response) {
// JSON.parse does not evaluate the attacker's scripts.
var resp = JSON.parse(response.farewell);
});
chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, function(response) {
// innerText does not let the attacker inject HTML elements.
document.getElementById("resp").innerText = response.farewell;
});
Examples
You can find simple examples of communication via messages in the examples/api/messaging directory. The native messaging sample demonstrates how a Chrome app can communicate with a native app. For more examples and for help in viewing the source code, see Samples.
Content available under the CC-By 3.0 license
谷歌扩展程序--------------Message的更多相关文章
- 在别家网站上执行自己的js代码(谷歌浏览器)(谷歌扩展程序)
@参考文章1 @参考文章2 日前针对一家投标网站进行了程序干预,且一定程度的干预成功,把方法给大家提取分享出来,感谢上述两篇博文 测试网站:百度https://www.baidu.com/ 测试步骤 ...
- 谷歌扩展程序设置ajax请求允许跨域(极少人知道的解决方案)
前言: 跨域问题一直是个老生常谈的问题,在实际开发过程中,跨域的问题常常会让开发者非常的头疼. 常用的几种跨域解决方案: 1.代理 2.XHR2 HTML5中提供的XMLHTTPREQUEST Lev ...
- Chrome扩展程序的二次开发:把它改得更适合自己使用
我当然知道未经作者允许修改别人程序是不道德的了,但作为学习研究之用还是无可厚非,这里仅供交流. 一切都是需求驱动的 话说某天我在网上猎奇的时候无意间发现这么一款神奇的谷歌浏览器插件:Extension ...
- 在谷歌安装扩展程序Axure RP Extension for Chrome后,经常无故损坏,无法使用
最近因为要看需求给的原型图,但需求只给了html格式的文件,没有给可以在Axure软件里看的格式, 所以在谷歌安装了一个Axure RP Extension for Chrome扩展程序在谷歌浏览器看 ...
- 谷歌应用商店chrome扩展程序和APP的发布流程
互联网上有很多大牛,他们再工作中需要一些难题,再找到解决办法后,如果会使用js的话,大多数人就可以自己动手写一个chrome插件,而且非常容易.开发人员都喜欢与大家分享自己的成就!google是一个全 ...
- chromevue扩展 vue-devtools-master 谷歌vue的扩展程序
1,在百度网盘中下载压缩包,网盘地址:https://pan.baidu.com/s/1BnwWHANHNyJzG3Krpy7S8A ,密码:xm6s 2,将压缩包解压到F盘,F:\chromeVue ...
- Web 开发人员必备的12款 Chrome 扩展程序
之前已经分享过一些帮助 Web 开发人员和设计师的 Chrome 扩展,这次我们继续展示一组很有用的 Chrome 应用程序.这些免费的 Chrome 应用程序可以简化您的工作流程,为了加快您的工作流 ...
- 【前端工具】Chrome 扩展程序的开发与发布 -- 手把手教你开发扩展程序
关于 chrome 扩展的文章,很久之前也写过一篇.清除页面广告?身为前端,自己做一款简易的chrome扩展吧. 本篇文章重在分享一些制作扩展的过程中比较重要的知识及难点. 什么是 chrome 扩展 ...
- chrome总是提示“请停用开发者模式运行的扩展程序”
方法1:通过组策略的扩展白名单.要下载一个组策略管理模板 1.开始 -> 运行 -> 输入gpedit.msc -> 回车确定打开计算机本地组策略编辑器(通过Win + R快捷键可以 ...
随机推荐
- php上传文件限制
客户端限制(客户端限制在实际上是无法阻止上传): 通过表单隐藏域限制上传文件的最大值 <input type=’hidden’ name=’MAX_FILE_SIZE’ value=’字节数’ ...
- Restful Framework (四)
目录 一.分页 二.视图 三.路由 四.渲染器 一.分页 回到顶部 试问如果当数据量特别大的时候,你是怎么解决分页的? 方式a.记录当前访问页数的数据id 方式b.最多显示120页等 方式c.只显示上 ...
- 【hdoj_2152】Fruit(母函数)
题目:http://acm.hdu.edu.cn/showproblem.php?pid=2152 本题采用母函数模板求解,母函数模板如下: http://blog.csdn.net/ten_sory ...
- 前端组件化-Web Components【转】
以下全部转自:http://www.cnblogs.com/pqjwyn/p/7401918.html 前端组件化的痛点在前端组件化横行的今天,确实极大的提升了开发效率.不过有一个问题不得不被重视,拟 ...
- java 连接 kerberos 认证的 HBase 和 HDFS
这是两个功能,都很简单就写一块了.. 简单到什么程度呢,简单到只贴代码就可以了... HBase package com.miras.data; import org.apache.hadoop.co ...
- 转:fortios 5.4后门植入
提示: 1.经过实验,fortios 5.4 beta4也是可以的. 2.在实验时,选择先下载fortios 5.2(做了快照),再升级5.4,则虚拟机挂载需要选择FortiGate-VM-disk1 ...
- Bzoj1486/洛谷P3199 最小圈(0/1分数规划+spfa)/(动态规划+结论)
题面 Bzoj 洛谷 题解(0/1分数规划+spfa) 考虑\(0/1\)分数规划,设当前枚举到的答案为\(ans\) 则我们要使(其中\(\forall b_i=1\)) \[ \frac{\sum ...
- 【POJ 3974】Palindrome
http://poj.org/problem?id=3974 Manacher模板题.Menci的博客讲得很好 有一点:Menci的代码中的right我感觉是代表能延伸到的最右端点的右边的点,因为r( ...
- SQL中on和where的使用及其差异
在编写SQL脚本中,多表连接查询操作需要使用到on和where条件,但是经常会混淆两者的用法,从而造成取数错误.为此,使用测试数据进行总结如下: 1.现有两张测试表,table_a和table_b. ...
- 【20181024T3】小C的宿舍【分治】
题面 [错解] 好像就是\(|i-j|+|a_i - b_i|\)唉 嗯开始都加i-1,跑一遍,1~(i-1)加1,i~n 减1,线段树维护. 过样例了呢 哎大样例怎么多了那么多啊 跑了个暴力,多得更 ...