1

我已经阅读了这个问题是否可以注入一个覆盖 DOM 中存在的 JavaScript 代码?并且该解决方案大部分时间都运行良好,但有时,页面中的 JavaScript 代码似乎会先运行,然后是 content_scripts。

这有时会使“OVVERRIDES”失败。

我的测试代码如下:

//manifest.json
"content_scripts": [
{
    "matches": ["http://*/*"],
    "js": ["js_injector.js"],
    "run_at": "document_start"
}

//js_injector.js
function injectJs(link) {
var scr = document.createElement('script');
scr.type="text/javascript";
scr.src=link;

document.documentElement.appendChild(scr);
}
injectJs(chrome.extension.getURL('my.js'));

//my.js
console.log("in my.js");
function foo() {
    console.log("in my.js foo");
}

//test.html (view this page in chrome)
<html>
<script type="text/javascript">
    console.log("I am here 1110");
    foo()
    console.log("I am here 1111");
</script>
</html>

通常,我会得到以下日志:

in my.js my.js:114
I am here 1110 test.html:4
in my.js foo my.js:116
I am here 1111 test.html:6

但有时,会得到以下日志:

I am here 1110 test.html:4
Uncaught ReferenceError: foo is not defined test.html:5
in my.js test.js:114

似乎在页面和内容脚本中运行代码的顺序是随机的?我的目的是让目标页面运行在内容脚本中定义的 js api。有人知道如何解决吗?谢谢!

4

2 回答 2

0

我发现我注入的 <script> 在目标页面的 javascript 之后运行,尽管使用了 run_at: document_start? 这已经指出了原因并给出了解决方案。

但是像这样把js代码写成字符串真的很难。所以我写了一个python代码来读取和生成它们。

import sys

s_injector_header = """
function injectJs(text) {
    var scr = document.createElement('script');
    scr.type="text/javascript";
    scr.textContent=text;
    document.documentElement.appendChild(scr);
}

"""

def openInjector():
    fd = open(sys.path[0]+"/js_injector.js","w")
    fd.write(s_injector_header)
    return fd

def closeInjector(fd):
    fd.close()

def injectJs(fd,filename):
    jsfd = open(sys.path[0]+"/"+filename,"r")
    text = jsfd.read()
    text = text.replace("\\","\\\\")
    text = text.replace("'","\\'")
    text = text.replace('"','\\"')
    text = text.replace('\n','\\n')
    fd.write("injectJs('"+text+"');\n\n")

def main():
    fd = openInjector()
    injectJs(fd,"md5.js")
    injectJs(fd,"dessrc.js")
    injectJs(fd,"my_code.js")
    closeInjector(fd)

if __name__ == '__main__':
    main()
于 2013-05-29T09:10:43.390 回答
0

执行顺序当然不是随机的。

你的函数 injectJS 正在做的是创建一个带有“src”字段的标签my.js。然后将其注入您的 HTML。这意味着my.js异步包含。

这是 test.html 看到的:

<script src="my.js"></script>


因为它是异步的,所以 my.js 的内容并不总是在你想要的时候加载。为了缓解这个问题,您不想包含my.js,您想包含 的内容my.js

使用Broswerify 的 brfs,您可以将require()语句放入浏览器端代码并​​让它注入实际的文件内容。正确安装后,您js_injector.js将需要以下内容:

//js_injector.js

var fs = require('fs');

function injectJs(link) {
    //Create script tag with full file content as the content
    var scr = document.createElement('script');
    link = fs.readFileSync(__dirname + '/inject.js', 'utf-8');
    scr.textContent = link;

    (document.head || document.documentElement).appendChild(src);
}

injectJs('my.js');

这将为您提供以下内容和您期望的行为:

//test.html

<script> 
    console.log("in my.js");
    function foo() {
        console.log("in my.js foo");
    }
</script>
于 2015-06-16T17:28:15.643 回答