简体   繁体   English

从注入的页面执行主机脚本

[英]Executing host script from an injected page

I'm writing a Safari Extension that adds some functionality to a web page that I don't own. 我正在编写一个Safari扩展,它为我不拥有的网页添加了一些功能。 I would like for my injected JavaScript page to be able to fire some JavaScript functions the host page uses, but it doesn't work. 我希望我注入的JavaScript页面能够激活主页使用的一些JavaScript函数,但它不起作用。 On the Console I get the message ReferenceError: Can't find variable: function_name . 在控制台上,我收到消息ReferenceError: Can't find variable: function_name

My script is specified to be an End Script, so the whole page should be loaded. 我的脚本被指定为结束脚本,因此应该加载整个页面。 The function is also called from an onclick() handler on the page, like so: 该函数也是从页面上的onclick()处理程序调用的,如下所示:

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

I can get a reference to that page element, but when I call element.onclick() I get another error: TypeError: 'undefined' is not a function (evaluating '$(this).up()') . 我可以获得对该页面元素的引用,但是当我调用element.onclick()我得到另一个错误: TypeError: 'undefined' is not a function (evaluating '$(this).up()')

Oddly, when I call the JavaScript function from an AppleScript ( do JavaScript "function_name()" in page ) it works fine. 奇怪的是,当我从AppleScript调用JavaScript函数do JavaScript "function_name()" in page )时,它工作正常。 How can I trigger these functions? 我该如何触发这些功能?

It's not working because the extension's injected script is sandboxed; 它不起作用,因为扩展的注入脚本是沙盒; it can't see the page's global objects except for the DOM (and vice versa). 除了DOM之外,它无法看到页面的全局对象(反之亦然)。 A way around this security limitation is to have the injected script create a <script> element with the statements you want and insert it into the document. 解决此安全限制的一种方法是让注入的脚本使用您需要的语句创建<script>元素并将其插入到文档中。 For example: 例如:

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

However, the inserted script will not have access to the injected script's objects either. 但是,插入的脚本也无法访问注入的脚本的对象。 So, for example, if you try to access the extension's safari object from the inserted script, you will get a reference error. 因此,例如,如果您尝试从插入的脚本访问扩展的safari对象,您将收到引用错误。

I can extend answer from canisbos. 我可以从canisbos扩展答案。 You can communicate with the inserted script with the PostMessage function. 您可以使用PostMessage函数与插入的脚本进行通信。

injected script: 注入脚本:

//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);

Test html page: 测试html页面:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM