有没有一种方法可以使用javascript阻止javascript?

时间:2019-11-22 23:04:26

标签: javascript safari safari-extension

我正在尝试对Safari进行扩展,使用户可以使用新的API在每个站点上阻止javascript。该API可让您注入一个javascript文件,该文件将在任何内容之前加载到网站上,其功能不如常规javascript,就好像它在HTML页面上运行一样。有没有一种方法可以使用javascript阻止所有javascript?

API含糊地告诉我,“注入的脚本是在网页完全加载之前执行的,因此可以在将资源添加到网页时采取措施。”我是否可以挂入一些事件来捕获正在加载的资源并阻止它们?

1 个答案:

答案 0 :(得分:2)

有一种方法可以阻止 most Javascript:在页面加载的最开始处附加一个MutationObserver,并且只要文档发生更改,如果找到<script>标签,请将其删除:

<script>
new MutationObserver(() => {
  console.log('Mutation observer running...');
  document.body.querySelectorAll('script').forEach(scr => scr.remove());
})
.observe(document.documentElement, { childList: true, subtree: true });
</script>
<script>
console.log('hi');
</script>

内联处理程序中的Javascript仍然可以运行,但是幸运的是,与<script>标记(由于这是一种不好的做法),相比,内联Java并不是那么普遍无论如何,实质性Javascript都将放在<script>标记中,因此内联Javascript可能可能由于引用未定义的函数而经常引发错误。

尽管subtree: true在动态添加元素时比其他MutationObserver昂贵得多,但由于(几乎可以肯定)页面上没有运行Javascript,这应该不是问题,尤其是在页面完全加载后

要同时删除内联处理程序,请检查添加的元素是否具有on属性,并删除它们:

<script>
const cleanNode = (node) => {
  if (node.nodeType !== 1) {
    // Not an element node:
    return;
  }
  if (node.matches('script')) {
    node.remove();
  }
  [...node.attributes].forEach((attr) => {
    if (attr.name.startsWith('on')) {
      node.removeAttribute(attr.name);
    }
  });
};
new MutationObserver((mutations) => {
  mutations.forEach((mutation) => {
    [...mutation.addedNodes].forEach(cleanNode);
  });
})
.observe(document.documentElement, { childList: true, subtree: true });
</script>
<script>
console.log('hi');
</script>
<img onerror="alert('JS running')" src>