当前位置: 首页 > 面试题库 >

在chrome扩展程序的浏览器操作,后台脚本和内容脚本之间进行通信的上下文和方法?

华知
2023-03-14
问题内容

我认为chrome扩展程序总体而言非常简单且非常强大,但始终令我困惑的一件事是尝试在可能运行代码的各种脚本之间进行通信。当从浏览器操作的“default_popup”页面中引用该代码时,“背景”的“脚本”属性中的代码以及内容脚本。

这些类别的脚本在什么情况下运行,每种脚本如何与其他脚本通信?


问题答案:

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

  1. 扩展程序代码,在您的Chrome扩展程序中运行
  2. 背景 / 事件页面
  3. 浏览器动作 / 页面动作弹出
  4. 信息栏中的页面。
  5. 其顶级框架是扩展程序中的文档的选项卡,例如选项页面。
  6. 内容脚本,在选项卡的过程中运行。
  7. 选项卡流程中运行的非扩展代码(由内容脚本注入)。

请注意,<iframe src="chrome-extension://EXTENSIONID/page.htm">在非扩展页面中,页面通常被视为情况2(内容脚本),因为该框架是在非特权制表符过程中加载的。由于Chrome 56中针对扩展程序启动了进程外iframe,因此这些页面由扩展程序处理,因此它们可能使用相同的全套扩展程序API。行为上的这种改变(允许扩展框架使用特权扩展API)是有意的。

window在扩展过程中访问对象
因为所有扩展代码都在同一进程中运行,所以它们可以互相访问全局window对象。此功能并不为人所知,但是允许在同一扩展过程中直接操作JavaScript和DOM对象。通常最好不要使用此方法,而应使用消息传递 API。

// To access the `window` of a background page, use
var bgWindowObject = [chrome.extension.getBackgroundPage()](https://developer.chrome.com/extensions/extension.html#method-getBackgroundPage);
// To access the `window` of an event or background page, use:
[chrome.runtime.getBackgroundPage](https://developer.chrome.com/extensions/runtime.html#method-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]](https://developer.chrome.com/extensions/extension.html#method-getViews);

// To access the `window` of the options page (called /options.html), use
var allWindowObjects = [chrome.extension.getViews({type:'tab'})](https://developer.chrome.com/extensions/extension.html#method-getViews);
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对象。您可以使用这些方法来定义全局方法,设置全局变量,调用全局函数等。extension)弹出窗口window始终可用。这是不正确的,当关闭弹出窗口时,将丢弃全局对象!

消息通道始终具有两端:发送方和接收方。 要成为接收者,请使用chrome.runtime.onMessage.addListener方法绑定事件监听器。这可以通过扩展代码和内容脚本来完成。

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

[chrome.tabs.query](https://developer.chrome.com/extensions/tabs.html#method-query)({}, function(tabs) {
    for (var i=0; i<tabs.length; i++) {
        [chrome.tabs.sendMessage](https://developer.chrome.com/extensions/tabs.html#method-sendMessage)(tabs[i].id, "some message");
    }
});

内容脚本只能调用chrome.runtime.sendMessage以向扩展代码发送消息。如果要将消息从内容脚本发送到另一个内容脚本,则需要后台/事件页面,该页面接收消息并将其发送到所需的选项卡。

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

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 HERE

根据错误提示进行操作,return true;在您的onMessage事件监听器中添加:

chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
    setTimeout(function() { // Example: asynchronous invocation of sendResponse
        sendResponse('async response');
    }, 200);
    return true;
});

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

可以与页面进行通信。Apsillers创建了一个很好的答案,它解释了如何在(非扩展)页面和内容脚本之间建立通信通道。

apsiller的在方法的优势从文档中一个是用于自定义事件。该文档用于window.postMessage将消息发送到页面,但这可能导致与不希望发生消息事件的编码错误的页面发生冲突。



 类似资料:
  • 问题内容: 我遇到了将数据从后台脚本发送到的脚本的问题。我的内容脚本添加了一个,并且中的JavaScript 正在从我的后台脚本接收数据,但是似乎未在中检索到它。 在我的后台脚本中,我有类似以下内容: 我的后台脚本中的侦听器中的“发送者”在哪里? 在内容脚本注入的JavaScript中,我有类似以下内容: 在接收完全一样的预期消息。 我将相同的JavaScript放入了,但它没有从后台脚本接收任何

  • 问题内容: 我有一个chrome扩展程序,可以在网站上进行一些更改(编辑评论)。 在站点上进行了最近更改之后(站点不是我的站点)-使用ajax加载了注释块(之前是简单的发布请求,整个页面都重新加载了)。 现在,如果我第一次加载页面-内容脚本可以工作,但是当我转到下一页时,说页面#2-使用ajax添加注释,并且不再运行扩展脚本。所以评论并没有改变我想要的方式。 有没有简单的方法来监听页面更改DOM并

  • 问题内容: 我正在做一个插件来对界面进行一些转换。我不断收到(典型的跨网站问题) 但作为扩展程序,它应该可以访问iframe的内容 … 没有人知道如何访问它的内容以便可以被捕获吗? 问题答案: 通常,没有直接访问其他来源对象的直接方法。如果要在不同框架中的内容脚本之间 安全地 通信,则必须将消息发送到后台页面,该页面又将消息发送回选项卡。 这是一个例子: 的一部分: : : 后台脚本“ bg.js

  • 问题内容: 我正在尝试让我的Chrome扩展程序在加载新页面时运行该功能,但是在尝试了解如何执行此操作时遇到了麻烦。据我了解,我需要在background.html中执行以下操作: 使用来检查时,页面变更 使用运行的脚本。 这是我的代码: 我还想知道init()函数是否可以访问位于其他JS文件中的其他函数? 问题答案: Chrome扩展程序中的JavaScript代码可以分为以下几类: 扩展代码-

  • 我不清楚浏览器是在脚本运行时还是在执行后启动回流。因此,基本上,如果我有一个循环(100次迭代),将一个元素插入DOM,浏览器会停止脚本执行,用插入的元素重新计算布局,在每一步中重新绘制?然后下一步是什么?或者它不停地插入100个元件,然后再回流? 要将其转换为代码,这两个代码之间是否存在性能差异? 还是更好? 或者,有没有更好、更有效的解决方案,可以在DOM中插入大量元素(10000个或更多),

  • 问题内容: 方法论问题: 我有一个“主” python脚本,该脚本在系统上无限循环地运行,并且我想偶尔与其他一些python脚本一起向其发送信息(例如,json数据字符串),这些脚本稍后将由本人或另一个程序启动并且将在发送字符串后立即结束。 我不能在这里使用子流程,因为我的主脚本不知道其他脚本何时运行以及它们将执行什么代码。 我正在考虑使主脚本在本地端口上侦听,并使其他脚本在该端口上向它发送字符串