【问题标题】:Executing host script from an injected page从注入的页面执行主机脚本
【发布时间】:2012-02-14 05:17:12
【问题描述】:

我正在编写一个 Safari 扩展程序,为我不拥有的网页添加一些功能。我希望我注入的 JavaScript 页面能够触发主机页面使用的一些 JavaScript 函数,但它不起作用。在控制台上,我收到消息 ReferenceError: Can't find variable: function_name

我的脚本被指定为结束脚本,因此应该加载整个页面。该函数也从页面上的 onclick() 处理程序调用,如下所示:

onclick="function_name($(this).up());"

我可以获得对该页面元素的引用,但是当我调用 element.onclick() 时,我收到另一个错误:TypeError: 'undefined' is not a function (evaluating '$(this).up()')

奇怪的是,当我从 AppleScript (do JavaScript "function_name()" in page) 调用 JavaScript 函数时,它工作正常。如何触发这些函数?

【问题讨论】:

    标签: javascript automation obfuscation safari-extension


    【解决方案1】:

    我可以从 canisbos 扩展答案。您可以使用 PostMessage 函数与插入的脚本进行通信。

    注入脚本:

    //insert script to page
    var myScriptElement = document.createElement('script'); 
    myScriptElement.innerHTML =
      'window.addEventListener("message", function(e) {' +
      '  if (e.data.msg == "do") {' +
      '    foo(e.data.info);' +
      '    postMessage({msg: "done", info: "answer"}, "*");' +
      '  };' +
      '}, false);'
    document.querySelector('head').appendChild(myScriptElement);
    
    //add answers listener
    window.addEventListener('message', function(e) {
      if (e.data.msg == 'done') {
        console.log(e.data.info);
      };
    }, false);
    
    //add the testing function on the body click
    document.addEventListener('click', function (e) {
      //call inserted script
      postMessage({msg: 'do', info: 'from inject'}, '*');
    }, false);
    

    测试html页面:

    <html>
    <script>
      function foo(text) {
        console.log(text);
      };
    </script>
    <body>
      <button id='button' onclick='foo("from page")'>test</button>
    </body>
    </html>
    

    【讨论】:

      【解决方案2】:

      因为插件注入的脚本是沙盒的,所以它不起作用;除了 DOM 之外,它看不到页面的全局对象(反之亦然)。解决此安全限制的一种方法是让注入的脚本使用您想要的语句创建一个&lt;script&gt; 元素并将其插入到文档中。例如:

      var myScriptElement = document.createElement('script');
      myScriptElement.innerHTML = 'alert("Page is using jQuery " + $.fn.jquery)';
      document.querySelector('head').appendChild(myScriptElement);
      

      但是,插入的脚本也无法访问注入脚本的对象。因此,例如,如果您尝试从插入的脚本中访问扩展程序的 safari 对象,则会收到引用错误。

      【讨论】:

      • 我有什么方法可以与插入的脚本通信吗?这是有用的信息,可以解释正在发生的事情,但我真的很想绕过它。
      • 您可以使用 DOM 在注入的脚本(扩展)和插入的脚本之间进行某种通信。如果您想将插入脚本中的值传递给注入脚本,反之亦然,第一个脚本可以使用 element.setAttribute() 在文档中的元素上设置一个属性,稍后第二个脚本可以读取它使用 element.getAttribute()。例如,您可以使用:document.documentElement.setAttribute('my_attr', '999') 然后检索值:document.documentElement.getAttribute('my_attr')
      • 但它必须每隔一段时间轮询一次?
      • 根据您的目标,这将是一种方式。可能还有其他人。
      猜你喜欢
      • 2012-03-29
      • 2013-04-26
      • 1970-01-01
      • 2015-09-30
      • 2021-12-06
      • 1970-01-01
      • 1970-01-01
      • 2018-02-22
      • 2011-01-19
      相关资源
      最近更新 更多