如何将数据从内容脚本传递到页面级?

时间:2015-11-30 04:41:53

标签: javascript jquery google-chrome-extension content-script

我将所有js代码注入首页,但它需要ui和stuff的图片,只能在chrome.extension.getUrl的帮助下导入,并且只能从content-script调用,所以我发现了很多关于如何将数据传递到内容页面的建议,没有关于如何传回数据的信息,是否有可能呢?

我的代码现在看起来像这样:

我的js代码,将注入其他代码:

var Content = {};
$(document).contentReady = function(content) {
    Content = content;
    $(document).ready(function () {/*cool stuff here, that require content*/});
}
var event = new CustomEvent('LoadContent');
window.dispatchEvent(event);

内容的脚本:

document.querySelector('head').appendChild(jsCode);
window.addEventListener("LoadContent", function(evt) {
    var content =
    {
        data:   "url(" + chrome.extension.getURL('content.smth') + ")"
    };
    document.contentReady(content);
}, false);

显然,我得到document.contentReady is not a function 但是在文档中声明函数是关于如何在大约2小时的谷歌搜索后从内容脚本传回数据的唯一(!)建议。

3 个答案:

答案 0 :(得分:3)

没有什么可以阻止您进行基于CustomEvent的双向通信,并且可以使用detail属性传递数据:

// Page script
window.addEventListener('RecieveContent', function(evt) {
  // do something cool with evt.detail
});
var event = new CustomEvent('LoadContent');
window.dispatchEvent(event);

// Content script
window.addEventListener('LoadContent', function(evt) {
  content = /* ... */
  var event = new CustomEvent('RecieveContent', {detail: content});
  window.dispatchEvent(event);
});    

可以找到更深入的答案here

但是,您应该问自己是否需要页面级脚本来查询数据,因为您可以完全控制何时注入数据。确保代码执行后,您可以使用单向方法:

// Page script
window.addEventListener('RecieveContent', function(evt) {
  // do something cool with evt.detail
});    

// Content script
jsCode.onload = function() {
  // This fires after the page script finishes executing
  content = /* ... */
  var event = new CustomEvent('RecieveContent', {detail: content});
  window.dispatchEvent(event);
}
document.querySelector('head').appendChild(jsCode);

答案 1 :(得分:1)

您可以通过创建新的脚本标记将JS数据传递到页面。例如:

function injectScript(code) {
    var body = document.getElementsByTagName('body')[0];
    var s = document.createElement('script');
    s.innerHTML = code;
    body.appendChild(s);
}
injectScript('var foo = 2;');

因此,对于您的特定示例,您应该能够:

injectScript('document.contentReady({data: url(' + blahblah + '})');

不漂亮(当你正在使用覆盖内容脚本时是什么时候?)但是它有效。

答案 2 :(得分:1)

Content Scripts不与页面上的普通脚本共享窗口对象。它们都在不同的背景下工作。

在您的情况下,您正在窗口上注册事件侦听器并在其他上下文(窗口)上侦听事件。因此,永远不会调用您的事件监听器。

但是,我可以看到在内容脚本和普通脚本之间进行通信的另一种方法是使用MutationObserver

  1. 使用某个Id定义一个节点,您可以在该节点下创建与事件对应的子节点。
  2. 在脚本中注册Mustation Observer。
  3. 从内容脚本中添加数据为data-* api。
  4. 的节点

    实施例

    内容脚本
    var submitEvent = function(category, action, label) {
      var eventObserverPlaceholder = document.getElementById('events-observer-placeholder'),
        $eventEl = $('<span></span>').attr({
          'data-category': category,
          'data-action': action,
          'data-label': label
        });
    
      eventObserverPlaceholder.appendChild($eventEl.get(0));
    };
    

    注册变异观察者的正常脚本:

    RQ.Methods.addObserverForEvents = function(targetNode) {
      var observer = new MutationObserver(RQ.Methods.handleMutationList);
    
      // Notify me when a new child is added
      var observerConfig = {
        attributes: false, 
        childList: true, 
        characterData: false 
      };
    
      observer.observe(targetNode, observerConfig);
      return observer;
    };
    
    RQ.mutationObserver = RQ.Methods.addObserverForEvents(document.getElementById('events-observer-placeholder'));
    

    链接

    1. https://davidwalsh.name/mutationobserver-api
    2. https://developer.mozilla.org/en/docs/Web/API/MutationObserver
    3. 工作示例:

      我在Requestly Chrome扩展程序中使用了相同的方法向Google Analytics提交活动。

      1. 内容脚本:https://github.com/requestly/chrome-extension/blob/master/src/Shared/utils.js#L26
      2. 普通脚本:https://github.com/requestly/web/blob/gh-pages/js/scripts/tracker.js#L35