那些被浏览器阻止的模拟事件...

浏览器里面我们并不能愉快的用js模拟鼠标和键盘事件, 连最常用的click方法都收到许多限制, 比如在init函数中执行file_input.click()之类的. 我们可以快速查看使用HTML和JavaScript的文件上传。如今,许多网站不再显示原始<input type="file">元素。以Facebook为例:

Facebook发布表格

当您单击上面突出显示的照片按钮时,将打开本机文件对话框:

Mac OS X上的文件选择对话框

在现代浏览器中使这些功能发挥作用并不难。从本质上讲,<input type="file">只要点击照片按钮,它就可以在隐藏时触发点击事件。这是一个很小但却有效的HTML示例,可以重现该功能:

<html>
  <body>
    <input type="file" style="display: none" />
    <button>Open File Dialog</button>

    <script src="https://code.jquery.com/jquery-2.2.4.js"></script>
    <script>
      $("button").on("click", function() {
        $("input").trigger("click");
      });
    </script>
  </body>
</html>

事实上,如果我们尝试一下,单击“打开文件对话框”按钮将打开文件对话框,正如我们所期望的那样。现在让我们尝试在页面加载后立即自动打开文件对话框:

<script>
  $("input").trigger("click");
</script>

这似乎不起作用。会不会是页面构建过程一些api没有准备好呢, 于是我settimeout之后再调用:

<script>
  setTimeout(function() {
    $("input").trigger("click");
  }, 1000);
</script>

这似乎也不起作用。为什么在第一个例子中,文件对话框已成功打开?第一个示例有效的原因是click事件是在代码块中触发的,该代码块是用户启动的事件处理程序

当我们单击按钮时,已执行已注册的处理程序功能,并且浏览器会跟踪启动该按钮单击事件的用户的事实,而不是某些代码。在此类用户启动的事件之外,无法以编程方式打开文件对话框。

类似地,当window.open()未在用户启动的事件的处理程序内调用时,现代浏览器通常不会打开新窗口。相反,他们会显示如下警告:

谷歌浏览器:“弹出窗口被阻止”警告

讽刺的是, 在console接口中是可以愉快的模拟的, 因为此时的你是用户, 不过话又说回来了, 就算在初始化总共模拟了打开文件对画框或者弹出一个新的页面并不会造成什么安全问题, 我们甚至可以给body监听一个mouseenter事件(发生概率99%)然后让浏览器以为是用户触发了我们想要执行的代码, 或者通过其他欺骗用户的无聊手段, 但仔细想想也没什么意义....

总之这是一个坑把, 在以后的chromium中应该会改善, 至少目前是不能在网页打开的时候立刻启动文件对话框的..

posted @ 2018-12-19 15:32  xosg  阅读(552)  评论(0编辑  收藏  举报