从站点调用Chrome扩展的后台功能 [英] Call background function of Chrome extension from a site
问题描述
想象一下 http://www.example.com/test.html 包含:
<脚本>
hello();
< / script>
我的后台页面包含 hello $ c $的定义c> function:
函数hello(){
alert(test);
}
如何确保Chrome扩展程序的后台页面 test.html
调用 hello();
?
在网页能够调用背景页面的函数之前,需要解决以下问题:
- 能够从网页中使用
hello();
。这是通过使用内容脚本注入一个定义hello
的脚本。注入的函数使用自定义事件或postMessage
与内容脚本进行通信。 - 内容脚本需要与后台进行通信。这是通过
chrome.runtime.sendMessage $ c $如果网页也需要收到回复:
- 发送来自后台的回复页面(
sendMessage
/onMessage
,见下文)。 - 脚本,创建自定义事件或使用
postMessage
向网页发送消息。 - 在网页中处理此消息。
所有这些方法都是异步的,必须通过回调函数来实现。
这些步骤需要仔细设计。这是一个实现上述所有步骤的通用实现。你需要知道的实现:
sendMessage
sendMessage(< mixed message> [,< function callback>])
方法在需要联系内容脚本时使用。 code>
contentscript.js
//随机唯一名称,用于最小化冲突:
var EVENT_FROM_PAGE ='__rw_chrome_ext_'+ new Date()。getTime();
var EVENT_REPLY ='__rw_chrome_ext_reply_'+ new Date()。getTime();
var s = document.createElement('script');
s.textContent ='('+ function(send_event_name,reply_event_name){
//注意:这个函数被序列化并且运行在页面的上下文中
//页面函数的开始
window.hello = function(string){
sendMessage({
type:'sayhello',
data:string
},function(response){
alert('Background说:'+ response);
});
};
//结束你的逻辑,开始执行消息传递:
function sendMessage (message,callback){
var transporter = document.createElement('dummy');
// Handles reply:
transporter.addEventListener(reply_event_name,function(event){
var this result = this.getAttribute('result');
if(this.parentNode)this.parentNode.removeChild(this);
//清理完毕后,根据需要发送回调函数:
如果(类型callback =='function'){
result = JSON.parse(result);
回调(结果);
}
});
//通知内容脚本的功能
var event = document.createEvent('Events');
event.initEvent(send_event_name,true,false);
transporter.setAttribute('data',JSON.stringify(message));
(document.body || document.documentElement).appendChild(transporter);
transporter.dispatchEvent(event); $'$'$'$'$'$'$'$'$'$'$'$'$'$'$'$'$'$'$'$'''') ;';
document.documentElement.appendChild(s);
s.parentNode.removeChild(s);
//处理/发送页面消息:
document.addEventListener(EVENT_FROM_PAGE,function(e){
var transporter = e.target;
if(transporter){
var request = JSON.parse(transporter.getAttribute('data'));
//处理示例:将消息发送到后台并等待回复
chrome。 runtime.sendMessage({
type:'page',
request:request
},function(data){
//接收到来自后台的消息,传递给页面
var event = document.createEvent('Events');
event.initEvent(EVENT_REPLY,false,false);
transporter.setAttribute('result',JSON.stringify(data));
transporter.dispatchEvent(event);
});
}
});
background.js
chrome.runtime.onMessage.addListener(function(message,sender,sendResponse){
if(message&& message.type =='page'){
var page_message = message.message;
//简单示例:从扩展的本地存储获取数据
var result = localStorage.getItem('whatever');
//将结果返回给内容脚本
sendResponse(result);
}
});
如果没有清单文件,Chrome扩展程序并不完整,所以这里是清单.json
我用来测试答案的文件:
{
name :
version:1,
manifest_version:2,
background:{
scripts:[ background.js]
},
content_scripts:[{
matches:[http://jsfiddle.net/jRaPj/show/*],
js:[contentscript.js],
all_frames:true,
run_at:document_start
}]
}
此扩展程序已在 http://jsfiddle.net/jRaPj/show/ (包含 hello();
,如问题所示),并显示一个对话框说Background said:null。
打开背景页面,使用 localStorage.setItem('whatever','Hello!');
看到邮件正确更改。
I am looking for a function inside a webpage te activate a chrome extension.
Imagine that http://www.example.com/test.html contains:
<script>
hello();
</script>
And my background page contains the definition of the hello
function:
function hello() {
alert("test");
}
How can I make sure that the Chrome extension's background page's hello
is called when test.html
calls hello();
?
Before a web page is able to call a background page's function, the following problems need to be solved:
- Be able to use
hello();
from a web page. This is done by injecting a script defininghello
using Content scripts. The injected function communicates with the content script using a custom event orpostMessage
. - The content script needs to communicate with the background. This is implemented through
chrome.runtime.sendMessage
.
If the web page needs to receive a reply as well: - Send a reply from the background page (
sendMessage
/onMessage
, see below). - In the content script, create a custom event or use
postMessage
to send a message to the web page. - In the web page, handle this message.
All of these methods are asynchronous, and have to be implemented through callback functions.
These steps need to be designed carefully. Here's a generic implementation which implements all of the above steps. What you need to know about the implementation:
- In the code-to-be-injected, use the
sendMessage
method whenever the content script need to be contacted.
Usage:sendMessage(<mixed message> [, <function callback>])
contentscript.js
// Random unique name, to be used to minimize conflicts:
var EVENT_FROM_PAGE = '__rw_chrome_ext_' + new Date().getTime();
var EVENT_REPLY = '__rw_chrome_ext_reply_' + new Date().getTime();
var s = document.createElement('script');
s.textContent = '(' + function(send_event_name, reply_event_name) {
// NOTE: This function is serialized and runs in the page's context
// Begin of the page's functionality
window.hello = function(string) {
sendMessage({
type: 'sayhello',
data: string
}, function(response) {
alert('Background said: ' + response);
});
};
// End of your logic, begin of messaging implementation:
function sendMessage(message, callback) {
var transporter = document.createElement('dummy');
// Handles reply:
transporter.addEventListener(reply_event_name, function(event) {
var result = this.getAttribute('result');
if (this.parentNode) this.parentNode.removeChild(this);
// After having cleaned up, send callback if needed:
if (typeof callback == 'function') {
result = JSON.parse(result);
callback(result);
}
});
// Functionality to notify content script
var event = document.createEvent('Events');
event.initEvent(send_event_name, true, false);
transporter.setAttribute('data', JSON.stringify(message));
(document.body||document.documentElement).appendChild(transporter);
transporter.dispatchEvent(event);
}
} + ')(' + JSON.stringify(/*string*/EVENT_FROM_PAGE) + ', ' +
JSON.stringify(/*string*/EVENT_REPLY) + ');';
document.documentElement.appendChild(s);
s.parentNode.removeChild(s);
// Handle messages from/to page:
document.addEventListener(EVENT_FROM_PAGE, function(e) {
var transporter = e.target;
if (transporter) {
var request = JSON.parse(transporter.getAttribute('data'));
// Example of handling: Send message to background and await reply
chrome.runtime.sendMessage({
type: 'page',
request: request
}, function(data) {
// Received message from background, pass to page
var event = document.createEvent('Events');
event.initEvent(EVENT_REPLY, false, false);
transporter.setAttribute('result', JSON.stringify(data));
transporter.dispatchEvent(event);
});
}
});
background.js
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
if (message && message.type == 'page') {
var page_message = message.message;
// Simple example: Get data from extension's local storage
var result = localStorage.getItem('whatever');
// Reply result to content script
sendResponse(result);
}
});
A Chrome extension is not complete without a manifest file, so here's the manifest.json
file which I used to test the answer:
{
"name": "Page to background and back again",
"version": "1",
"manifest_version": 2,
"background": {
"scripts": ["background.js"]
},
"content_scripts": [{
"matches": ["http://jsfiddle.net/jRaPj/show/*"],
"js": ["contentscript.js"],
"all_frames": true,
"run_at": "document_start"
}]
}
This extension was tested at http://jsfiddle.net/jRaPj/show/ (containing hello();
as seen in the question), and shows a dialog saying "Background said: null".
Open the background page, use localStorage.setItem('whatever', 'Hello!');
to see that the message is correctly changed.
这篇关于从站点调用Chrome扩展的后台功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!