使用JavaScript特征检测新窗口/标签页(target=_blank)的打开方式

15

根据我的研究:

  • “WebView”可以禁用“在新窗口/选项卡中打开链接”。
  • 本机应用程序开发人员使用WebView在其应用程序中显示网页(请参见Twitter的应用程序)。
  • 通过用户代理检测WebView不一致,并且也不是最佳实践。
  • 仅尝试使用JS打开新窗口会触发弹出窗口拦截器,使其成为一种不可靠的测试新窗口是否可以打开的方法。

我需要检测此功能不可用的情况。不可能吗?

补充说明

我正在尝试检测是否可以通过target=_blank打开新窗口。例如,在应用程序浏览器中,UIWebView可以防止target=_blank按预期工作(它只是在同一窗口中打开而不是在新窗口中)。我需要一种解决方案来指示由于浏览器限制(例如,在UIWebView情况下)无法打开新窗口。不幸的是,弹出窗口阻止器防止检查此类功能,因为它们永远不允许打开新窗口而不需要用户输入(即点击)来绕过。


2
所以,你是想检测WebView,还是试图弄清楚是否可以打开一个新窗口?或者你是在假设WebView永远无法打开新窗口的情况下检测WebView(这是不正确的)? - Mikhail Naganov
2
事件监听器在事件发生后处理安全性。因此,您可以检测Web视图,检测用户代理,甚至可以检查侦听器或查询Web视图的安全设置,但您无法直接查询将被阻止还是不会被阻止。这并不像库或API是否存在那么简单。 - Dave Alperovich
1
@DaveAlperovich 你能不能检查一下 <uses-permission android:name="android.permission.INTERNET" /> 这个权限? - maioman
3
@maioman,是的,这是一种合法的检查方式。我不确定它是否绝对有效,但像这样的方法是正确的。OP似乎想要更决定性的东西,比如 if (window.allownew) -- 这是一个“特性检查”,并且没有类似这样确定性的方式。 - Dave Alperovich
2
根据你的要求,我进行了测试。由于它可以正常运行,所以我将其发布为答案。如果你需要其他帮助,请告诉我。 - Francisco Félix
显示剩余3条评论
2个回答

10

您不会拥有100%可靠的东西。

仅仅尝试使用JS打开一个新窗口就会触发弹出窗口拦截器;这使得测试是否可以打开新窗口成为一种不可靠的方法。

您说得对,这绝对是不可靠的... window.open()被阻止了(即使使用诸如 window.open(url, '_blank');window.focus(); 的技巧),click()也被阻止了(在包含target="_blank"的链接上),就像evt = document.createEvent("MouseEvents");evt.initEvent("click", true, true);...

但无论如何:如果WebView不允许在新选项卡中打开链接,则它将正常工作。但是,正如您所暗示的那样,Webview可能会授权它。在这种情况下,您将不知道自己是否在Webview中。可以轻松检测打开链接的新标签页最终是否在相同位置打开(可以在非显示的iframe中使用javascript进行测试),但是如果链接在浏览器中打开,则无法知道(想象一下从应用程序向浏览器中打开新标签页的Javascript代码带来的用户体验......)。正如Dave Alperovich所说,没有办法预先知道什么会被阻止,而不进行尝试。因此,您不应该从这个方向考虑。

没有可靠的功能或行为可以区分Webview和Web浏览器。在Webview中,您拥有所有在浏览器中获取的内容(cookie、WebStorage等)。用户代理存在其不完美之处,但在许多情况下它是有效的。可以在这里这里找到建立它的说明。


1
已编辑以包括我能想到的最佳UA检测正则表达式。/(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)|(Android).*(wv|AppleWebKit.*Version)/i - Brian Petro

5
根据OP的要求,我已经测试并且它有效。如果弹出窗口阻止程序被启用,我将捕获它,从而得到一种可靠的方式来知道它是否启用。在这种情况下,我只是发送了一个警报,但你可以根据自己的需要进行任何操作。
以下是代码:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Testing Pop-up Blocker</title>
<script>
function openPopUp(urlToOpen) {
  var popup_window=window.open(urlToOpen,"myWindow","toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=yes, resizable=yes, copyhistory=yes, width=400, height=400");            
  try {
    popup_window.focus();   
  }
  catch (e) {
    alert("Pop-up Blocker is enabled! Please add this site to your exception list.");
  }
}
</script>
</head>
<body onload="openPopUp('http://www.google.com'); return false;">
<p>Testing Pop-up Blocker</p>
</body>
</html>

这是我得到的内容,因为弹出窗口拦截器被启用了。 输入图片说明

1
我正在尝试检测是否可以在没有弹出拦截器的情况下打开新窗口。例如,UIWebView [应用内浏览器] 可以防止 target=_blank 正常工作 [它只是在同一窗口中打开而不是新窗口]。我需要这个解决方案来指示由于浏览器限制(如在 UIWebView 中)无法打开新窗口的情况。不幸的是,弹出拦截器会阻止检查此类功能,因为它们从不允许在没有用户输入(即点击)的情况下打开新窗口。 - Brian Petro

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接