2

我目前正在使用 Chrome 扩展程序,找不到一个方便的解决方案来将消息从后台上下文(我们称之为BG)发送到注入脚本的上下文(我们称之为INJ)。从INJBG发送消息就像一个魅力。但我希望BG做一个XMLHttpRequest可能需要一些时间的事情,所以我想将此请求的评估发送给INJ

不幸的是,我不允许在INJ的上下文中注册侦听器。所以我能想到的最佳解决方案包括:

  • INJBG发消息,触发XMLHttpRequest
  • 只要请求返回BG就在本地存储请求的结果
  • INJ反复向BG发送进一步的消息询问结果,除非BG以结果回答。

也许是这样的:

输入

function whaitForResult ()
{
  chrome.runtime.sendMessage ({method: "getResult"}, function (response)
  {
    if (response.finished === "true")
      // request finished, lets go on
    else
      setTimeout(whaitForResult, 100);
  }
}
chrome.runtime.sendMessage({method : "triggerRequest"}, function(response) {});
whaitForResult ();

背景

chrome.runtime.onMessage.addListener (function(request, sender, sendResponse)
{
  if (request.method == "triggerRequest")
  {
    // startXMLHttpRequest ();
    sendResponse ({});
    return true;
  }
  else if (request.method == "getResult")
  {
    if (finishedXMLHttpRequest ())
      sendResponse ({finished:"true", result: resultFromXMLHttpRequest ()});
    else
      sendResponse ({finished:"false"});
    return true;
  }
});

我想这应该可行,但在我看来这很混乱。所以我的问题是:有没有一种方便的方法可以向注入的脚本发送消息?

如果我的扩展概念是废话,请提出替代方案。但要做到这一点,XMLHttpRequest我需要一些变量localStorage,因为这些数据非常敏感,我不想将这些变量传递给INJ的上下文。因此,XMLHttpRequestINJ中进行不是一种选择。

4

1 回答 1

4

在继续之前,我想指出您只是在处理普通的内容脚本,而不是“注入脚本”(根据我的定义)。

不要在第一个请求 ( sendResponse({})) 时发送响应。相反,sendResponse在响应完成时调用:

// Content script
chrome.runtime.sendMessage({method: "getResultForRequest"}, function(response) {

});
// Background page
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
    if (request.method == "getResultForRequest") {
        $.ajax({success: sendResponse}); // Example
        return true;
    }
});

如本答案顶部所述,您要处理的不是注入脚本,而是内容脚本。内容脚本和页面的脚本执行环境是严格分离的,页面无法读取变量。换句话说,你的前提是有缺陷的;可以将凭据从后台页面传递到内容脚本。

我建议不要使用 localStorage,而是使用chrome.storageAPI。此异步 API 允许内容脚本直接读取扩展存储的持久变量。因此,您不再需要背景或事件页面。有关更详细的比较和示例,请参阅此答案

注意:有两种情况让后台页面处理 XHR 是有意义的:

  • 页面的内容安全策略阻止目标 URL(这会影响 Chrome 扩展
  • 当前页面通过 https 提供,而请求的资源通过 http 提供。混合使用 http 和 https 会改变挂锁的外观,应尽可能避免。

但除此之外,我建议使用chrome.storageAPI 并在您的内容脚本中执行跨域 http 请求。

于 2013-06-29T12:57:43.773 回答