【问题标题】:A issue when inject a javascript code that OVERRIDES the one existing in DOM?注入覆盖 DOM 中现有代码的 JavaScript 代码时出现问题?
【发布时间】:2015-06-17 04:05:39
【问题描述】:

我已阅读此问题 Is it possible to inject a javascript code that OVERRIDES the one existing in a DOM? 并且该解决方案大部分时间都运行良好,但有时页面中的 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。 有人知道如何解决吗? 谢谢!

【问题讨论】:

    标签: javascript google-chrome-extension


    【解决方案1】:

    我找到了My injected <script> runs after the target-page's javascript, despite using 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()
    

    【讨论】:

      【解决方案2】:

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

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

      这是 test.html 看到的:

      &lt;script src="my.js"&gt;&lt;/script&gt;


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

      使用Broswerify's 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>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-04-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-02-09
        相关资源
        最近更新 更多