从扩展程序中看不到自定义DOM属性?

时间:2015-07-20 00:45:04

标签: javascript google-chrome-extension

我有一个包含单个元素的简单页面,id="test"。我使用以下内容脚本进行了简单的扩展:

chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse) {
  var elem = document.getElementById("test");
  console.log(test.value);
  test.value = 3;
});

现在,如果我单击扩展按钮,它会打印undefined,然后继续打印3.但是,如果我尝试从控制台访问此值,它仍然是未定义的,并且更改它不会影响扩展名打印的内容。有没有办法从扩展名中实际访问此值?

更新:好的,我发现扩展程序在一个不共享“扩展程序”的单独环境中运行。使用主脚本,所以我需要在实际页面中注入一个脚本来执行此操作。

2 个答案:

答案 0 :(得分:0)

Content scripts在名为隔离世界的特殊环境中执行。他们可以访问注入页面的DOM,但不能访问页面创建的任何JavaScript变量或函数。它将每个内容脚本视为在其运行的页面上没有执行其他JavaScript。反过来也是如此:页面上运行的JavaScript无法调用任何函数或访问由content scripts定义的任何变量。

虽然content scripts的执行环境和托管它们的页面彼此隔离,但它们共享对页面DOM的访问权限。如果页面希望与内容脚本(或通过内容脚本扩展)进行通信,则必须通过共享DOM进行通信。

  1. 使用window.postMessage
  2. 在内容脚本中 -

    var port = chrome.runtime.connect();
    
        window.addEventListener("message", function(event) {
          // We only accept messages from ourselves
          if (event.source != window)
            return;
    
          if (event.data.type && (event.data.type == "FROM_PAGE")) {
            console.log("Content script received: " + event.data.text);
            port.postMessage(event.data.text);
          }
        }, false);
    

    在您的页面脚本中 -

    document.getElementById("theButton").addEventListener("click",
        function() {
      window.postMessage({ type: "FROM_PAGE", text: "Hello from the webpage!" }, "*");
    }, false);
    
    1. 在您的页面中注入脚本:
    2. 在内容脚本中 -

        function main() {
            var elem = document.getElementById("test");
            console.log(test.value);
            test.value = 3;
        }
       var script = document.createElement('script');
       script.appendChild(document.createTextNode('('+ main +')();'));
       (document.body || document.head).appendChild(script);
      
      1. 创建自定义事件
      2. 在注入或您的内容脚本中添加一个事件监听器:

        document.addEventListener('yourCustomEvent', function (e)
        {
          var data=e.detail;
          console.log("received "+data);
        });
        

        另一方面(内容或注入脚本)调用事件:

        var data="anything";
        var evt=document.createEvent("CustomEvent");
        evt.initCustomEvent("yourCustomEvent", true, true, data);
        document.dispatchEvent(evt);
        

答案 1 :(得分:0)

元素在页面和扩展上下文之间共享的一件事是data-*属性。

您可以通过.dataset界面操作它们:

chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse) {
  var elem = document.getElementById("test");
  console.log(test.dataset.value);
  test.dataset.value = 3; // will become "3"
});

这将对应于DOM中元素的data-value="3"属性。

更一般地说,

function storeValue(id, key, value) {
  var element = document.getElementById(id);
  if(!element) throw Error("Element #" + id = " not found");
  element.dataset[key] = JSON.stringify(value);
}

function readValue(id, key) {
  var element = document.getElementById(id);
  if(!element) throw Error("Element #" + id = " not found");
  var value = element.dataset[key];
  if(typeof value == "undefined") return undefined;
  else return JSON.parse(value);
}

storeValue("test", "value", 3);
console.log(readValue("test", "value"));

我添加了序列化/反序列化,因为属性只能是字符串。