首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >浏览器操作、后台脚本和chrome扩展的内容脚本之间的通信上下文和方法?

浏览器操作、后台脚本和chrome扩展的内容脚本之间的通信上下文和方法?
EN

Stack Overflow用户
提问于 2013-06-22 08:28:12
回答 3查看 11.2K关注 0票数 29

我认为chrome扩展总体上是非常简单和强大的,但有一件事总是让我感到困惑,那就是试图在代码可能运行的各种脚本之间进行通信。其中有从浏览器操作的"default_popup“页面引用时运行的代码、"background”的" scripts“属性中的代码和内容脚本。

这些类别中的脚本在什么上下文中运行,以及每个脚本如何与其他类别进行通信?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-06-24 21:17:41

三种不同的上下文

作为一名Chrome扩展开发人员,您可以区分三种不同的环境。

  1. Extension代码弹出窗口,在您的Chrome扩展

)中的文档

在选项卡的process.

  • Non-extension代码中运行的
  1. ,在选项卡的进程(injected by content scripts).

中运行的

请注意,非扩展页面中的<iframe src="chrome-extension://EXTENSIONID/page.htm">通常被视为第二种情况(内容脚本),因为框架是在非特权选项卡进程中加载的。由于out-of-process iframes是为Chrome56中的扩展而启动的,因此这些页面由扩展进程处理,因此它们可能使用相同的全套扩展API。这个change in behavior (allowing extension frames to use privileged extension APIs) is intentional

在扩展进程中访问window对象

因为所有扩展代码都运行在同一进程中,所以它们可以相互访问全局window对象。这个特性并不为人所熟知,但它允许人们在同一扩展过程中直接操作JavaScript和DOM对象。通常情况下,最好不要使用此方法,而是使用message passing API。

代码语言:javascript
运行
复制
// To access the `window` of a background page, use
var bgWindowObject = chrome.extension.getBackgroundPage();
// To access the `window` of an event or background page, use:
chrome.runtime.getBackgroundPage(function(bgWindowObject) {
    // Do something with `bgWindow` if you want
});

// To access the `window` of the badge's popup page (only if it's open!!!), use
var popupWindowObject = chrome.extension.getViews({type:'popup'})[0];

// To access the `window` of the options page (called /options.html), use
var allWindowObjects = chrome.extension.getViews({type:'tab'});
var popupWindowObjects = allWindowObjects.filter(function(windowObject) {
    return windowObject.location.pathname == '/options.html';
});
// Example: Get the `window` object of the first options page:
var popupWindowObject = popupWindowObjects[0];

为了保持本节的简短,我有意将代码示例限制为访问其他全局window对象的演示。您可以使用这些方法来定义全局方法、设置全局变量、调用全局函数等。

..。如果页面是打开的。有人thought说弹出窗口的window总是可用的。这不是真的,当弹出窗口关闭时,全局对象将被释放!

通过message passing进行通信

消息通道总是有两个端点:发送者和接收者。

要成为接收方,请使用chrome.runtime.onMessage.addListener方法绑定事件侦听器。这可以通过扩展代码和内容脚本来完成。

要在扩展中传递消息,请使用chrome.runtime.sendMessage。如果要将消息发送到另一个选项卡,请调用chrome.tabs.sendMessage。通过将整数(tabId)作为其第一个参数来指定目标选项卡。请注意,背景页只能将消息发送到一个选项卡。要访问所有选项卡,必须为每个选项卡调用该方法。例如:

代码语言:javascript
运行
复制
chrome.tabs.query({}, function(tabs) {
    for (var i=0; i<tabs.length; i++) {
        chrome.tabs.sendMessage(tabs[i].id, "some message");
    }
});

内容脚本只能调用chrome.runtime.sendMessage向扩展代码发送消息。如果您想要将消息从一个内容脚本发送到另一个内容脚本,则应该需要一个背景/事件页面,该页面接受消息并将其发送到所需的选项卡。有关示例,请参阅this answer

sendMessage方法接受一个可选函数,该函数作为onMessage事件的第三个参数接收。

代码语言:javascript
运行
复制
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
    if (message === 'message') sendResponse('the response');
});
chrome.runtime.sendMessage('message', function(response) {
    console('sendResponse was called with: ' + response);
});

前面的示例显示了明显的行为。当您想要异步发送响应时,事情会变得更加棘手,例如,如果您想要执行一个AJAX请求来获取一些数据。当onMessage函数在没有调用sendResponse的情况下返回时,Chrome将立即调用sendResponse。由于sendResponse只能调用一次,因此您将收到以下错误:

无法发送响应:如果要在监听器返回后发送响应,则chrome.runtime.onMessage监听器必须返回true (此处消息是通过分机ID发送的)

按照错误提示操作,在onMessage事件侦听器中添加return true;

代码语言:javascript
运行
复制
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
    setTimeout(function() { // Example: asynchronous invocation of sendResponse
        sendResponse('async response');
    }, 200);
    return true;
});

我已经在本节中解释了简单的一次性消息传递的实际应用。如果您想了解有关长期消息通道或跨扩展消息传递的更多信息,请阅读tutorial from the official documentation

消息传递API经历了几次名称更改。如果你阅读旧的例子,请记住这一点。历史记录和兼容性说明可以在here上找到。

内容脚本和页面之间的通信

可以与页面进行通信。Apsillers已经创建了一个很好的答案,它解释了如何在(非扩展)页面和内容脚本之间建立通信通道。在Can a site invoke a browser extension?上阅读他的回答。

one from the documentation相比,apsiller方法的优点是使用了自定义事件。文档使用window.postMessage向页面发送消息,但这可能会导致与编码不良的页面发生冲突,因为这些页面并不需要消息事件。

票数 77
EN

Stack Overflow用户

发布于 2013-06-24 05:47:52

Google文档包含了所有内容,但很难将所有信息集中在一起。有两种主要类型的脚本:

  1. 后台脚本可以完全访问Chrome api,但不能与目标webpage.
  2. Content脚本交互。its脚本可以相互交互,也可以与网页的DOM交互(但不能与其脚本交互,因为它是独立的),但对Chrome api的访问权限有限。

当您加载新页面时,这两个脚本都会运行(除非您使用"matches“来限制内容脚本的运行位置)。

您可以通过message passing在两者之间进行通信。这在内容脚本中比在后台脚本中更容易完成,因为您需要知道后者的选项卡id。

其他脚本(browserAction.jspageAction.jsoptionsPage.js)只有在其相应的html页面打开时才会运行(就像在浏览器窗口中打开网页一样,而这正是您真正要做的)。它们在限制和能力上与后台脚本相似。

尽量避免需要与页面的脚本交互。据我所知,最好的方式是通过共享DOM进行交互(字面意思是在html注释中编写javascript代码)。但是您的扩展目标不是为此而设计的,因此您必须在网页中包含您自己的脚本来完成此任务。使用内容脚本将脚本元素写入文档(其src

chrome.extension.getURL("myscript.js")

而且你需要有

"web_accessible_resources": ["myscript.js"]

在你的载货单上。

票数 3
EN

Stack Overflow用户

发布于 2013-06-22 08:53:07

自从我不得不处理chrome的扩展已经有一段时间了。我记得,在我了解事情的原理之前,那是一场相当艰难的斗争。为了让你的扩展与浏览器通信,你可以很容易地使用你的javascript/后台文件,而要与网页通信,你需要使用chrome.tabs.executeScript,但这真的很棘手,可能是一个真正的痛苦。我建议你使用google's tour on extensions,给他们的api一个非常好的视角,所有的东西都在里面!祝你好运,我希望这个答案对你有帮助!

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17246133

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档