无法访问Firefox加载项内容脚本中的DOM元素

无法访问Firefox加载项内容脚本中的DOM元素,firefox,firefox-addon-sdk,content-script,Firefox,Firefox Addon Sdk,Content Script,使用Firefox 34和addon SDK 1.17 我正在使用SDK的页面模块来附加内容脚本。在内容脚本中,当尝试访问DOM元素时,我看到了非常奇怪的行为 main.js pageMod.PageMod({ include: "somewebsite", contentScriptWhen: 'end', contentScriptFile: [data.url("stuff.js")] }); stuff.js log(document.getElementsBy

使用Firefox 34和addon SDK 1.17

我正在使用SDK的页面模块来附加内容脚本。在内容脚本中,当尝试访问DOM元素时,我看到了非常奇怪的行为

main.js

pageMod.PageMod({
    include: "somewebsite",
    contentScriptWhen: 'end',
    contentScriptFile: [data.url("stuff.js")]
});
stuff.js

log(document.getElementsByTagName("body")); // empty object
log(document.getElementById("SomeIdThatShouldBeThere")); // empty object
log(document.getElementsByTagName("li")); // x amount of empty objects...
但是,这将按预期工作:

document.body.style.border = "5px solid red";
对于我得到的空对象,我也可以这样做

obj.style.border = ...
它会工作,html元素会改变边框颜色等。但是我不能读取元素的属性,所以我是盲目工作的

我读到有人说从内容脚本修改DOM有一些限制,但我甚至不能做最基本的事情。这是否应该得到支持呢

编辑:最后我注意到元素位于正确的位置,我可以读取它们的属性,但是记录元素仍然只能打印空对象。。。这意味着元素的每个所需属性都必须单独打印。至少它起作用了,但可能更好。

改变:

log(document.getElementsByTagName("body")); // empty object
log(document.getElementById("SomeIdThatShouldBeThere")); // empty object
log(document.getElementsByTagName("li")); // x amount of empty objects...
为此:

console.log(document.getElementsByTagName("body")); // empty object
console.log(document.getElementById("SomeIdThatShouldBeThere")); // empty object
console.log(document.getElementsByTagName("li")); // x amount of empty objects...

我也有同样的问题。这使得基本脚本编写更加繁琐

试试这个(从)

内联脚本注入

正确的方法是在页面中插入内联脚本和/或使用customEvents。内联脚本是第三级脚本,可用于在全局范围内创建变量或函数:

// Quotes nesting would be a real mess now,
// let's use a separate file loaded as a contentScriptFile
var script = document.createElement( "script" );
script.innerHTML = "var test =" + JSON.stringify( anyValue )+";";
document.body.appendChild( script );
此代码的验证将输出警告,因为加载项不应创建脚本标记。但这仍然是unsafeWindow最安全的替代方法

customEvents

customEvents与鼠标事件非常相似,不同之处在于它们是通过编程触发的,并且它们可以在内容脚本和页面之间双向传输任意(JSO)数据:

// inline script in example.com/index.html
var evt = document.createEvent("CustomEvent");
evt.initCustomEvent( "transData", true, false, jsonableValue );
window.dispatchEvent(evt);
// in contentScript.js
window.addEventListener( "transData", function( event ) {
  // the data is available in the detail property of the event
  self.port.emit( "transData", event.detail );
});"

我在加载项的内容脚本中遇到了同样的问题。由于未知原因,如果将
对象的值复制到新对象,则可以将其打印到控制台。您可以创建一个简单的函数作为解决方法:

function getLoggableObject(obj){
    var loggable={};
    for(var key in obj){
        loggable[key]=obj[key];
    }
    return loggable;
}
下面是调用此函数的示例:

 console.log("default  : ", $("table")[0]);
 console.log("loggable : ", getLoggableObject($("table")[0]));
以及这些日志语句的输出:

"default  : " Object {  }
"loggable : " Object { createCaption: "function createCaption() {
    [native code]
}", deleteCaption: "function deleteCaption() {
    [native code]
}", createTHead: "function createTHead() {
    [native code]
}", deleteTHead: "function deleteTHead() {
    [native code]
}", createTFoot: "function createTFoot() {
    [native code]
}", deleteTFoot: "function deleteTFoot() {
    [native code]
}", createTBody: "function createTBody() {
    [native code]
}", insertRow: "function insertRow() {
    [native code]
}", deleteRow: "function deleteRow() {
    [native code]
}", caption: null, 210 more… }

如果要将对象从dom输出到控制台,请使用:

unsafeWindow.console.log(document.getElementById("SomeIdThatShouldBeThere"));
// Or map it in your contentscript file for less typing
var log = unsafeWindow.console.log;
log(document.getElementById("SomeIdThatShouldBeThere"));
这也可以在无需进入about:config并添加值为“all”的首选项“extensions.sdk.console.logLevel”的情况下工作,因此您可以记录任何需要的消息

但是,如果您同时运行sdkcmd控制台,这将输出一个错误,但我不认为这有什么好担心的,所有代码执行都没有问题

编辑:
当我将它映射到var日志时才发现,如果firebug控制台未打开,它将导致加载项停止工作,并且在firefox控制台打开时仍然无法工作。但是,执行Windows.console.log(foo)工作正常。

您是否尝试过使用
unsafeWindow.document
而不是
document
?这似乎没有什么区别。顺便说一句,您的代码中有一个输入错误。它应该是
getElementById
,而不是
getElementsById
(注意
s
)。但是我不明白为什么
getElementsByTagName
返回空对象。你在控制台中看到这些空对象了吗?斜视:我得到了页面上应该存在的元素的实际数量。仅当我打印单个元素时,它看起来像一个没有任何属性的空对象。属性仍然可以是空的正常访问,但如果你最终在这方面有所进展,我不知道,但我也遇到了同样的问题,并且做了更多的研究,我怀疑这与内容脚本如何与DOM隔离有关。我在一开始做了var log=console.log;但我到家后还是会尝试,永远不知道。很抱歉,耽搁了。它没有与众不同