3

我希望将 Safari 中的新标签重定向到某个 URL,实质上是更改默认的新标签页。但是,我不想重定向通过以下链接打开的新选项卡。

Windows 和选项卡API描述选项卡“打开”事件,但这些事件会在任何新选项卡打开(包括从链接打开的新选项卡)时触发。

有没有办法只为那些通过单击新选项卡按钮创建的选项卡捕获新选项卡事件?

4

1 回答 1

8

在您的open事件处理程序中,首先检查事件目标是否是选项卡。如果是,请beforeNavigate在该选项卡上为该事件注册一个事件处理程序。beforeNavigate如果事件在 50 毫秒内未触发,还设置一个超时以取消注册处理程序。例如:

function handleOpen(e) {
    if (e.target instanceof SafariBrowserTab) {
        e.target.addEventListener('beforeNavigate', handleBeforeNavigate, false);
        setTimeout(function () {
            e.target.removeEventListener('beforeNavigate', handleBeforeNavigate, false);
        }, 50);
    }
}

beforeNavigate现在,标签打开事件之后的事件有三个相关的可能结果。

情况 1beforeNavigate事件不会在超时内触发。这通常意味着选项卡是空的。空标签不能是链接点击的结果,所以我们可以在 timeout 函数中添加一些代码来做任何我们喜欢的事情:

function handleOpen(e) {
    if (e.target instanceof SafariBrowserTab) {
        e.target.addEventListener('beforeNavigate', handleBeforeNavigate, false);
        setTimeout(function () {
            e.target.removeEventListener('beforeNavigate', handleBeforeNavigate, false);
            takeOverTab();
        }, 50);
    }
}

情况 2beforeNavigate事件将触发,其url属性值为null. 这意味着该选项卡将加载“热门站点”页面或“书签”页面(两个特殊的 Safari 页面,它们是新选项卡的选项之一)。就像一个空标签一样,这样的标签不可能是链接点击的结果,所以我们可以对标签做我们喜欢的事情。例如:

function handleBeforeNavigate(e) {
    e.target.removeEventListener('beforeNavigate', handleBeforeNavigate, false);
    if (e.url === null) {
        takeOverTab();
    }
}

情况 3beforeNavigate将触发,其url值将是一个非空字符串:即一个实际的 URL。这是一个棘手的情况,因为选项卡可能来自链接单击、new-tab 命令(如果用户已将 Safari 配置为在其主页上打开新选项卡)或其他应用程序或扩展程序的操作。让我们将选项卡是链接单击结果的情况称为案例 3A;它是 new-tab 命令结果的情况,案例 3B;和其他应用案例,案例 3C。

我想不出区分3B和3C的方法。如果真的没有办法区分这两种情况,那可能对您的应用程序非常不利,因为您可能不想重定向其他应用程序打开的选项卡。

如果您不在乎您的应用程序是否会干扰 3C 选项卡,那么至少有一种方法可以区分 3A 选项卡和 3B/3C 选项卡。这是我想到的方式:

  • 在每个页面中使用注入脚本来监听链接点击。单击链接时,将 URL 和单击时间转发到全局页面,全局页面将记住它们以供将来参考。例如:

    function handleMessage(e) {
        if (e.name === 'linkClicked') {
            lastClickedLinkUrl = e.message.url;
            lastLinkClickTime = e.message.clickTime;
        }
    }
    
  • 在您的beforeNavigate处理程序中,测试事件的url值是否与最后单击链接的 URL 不同。如果是,则新选项卡不是由该链接单击产生的,因此它可能不是由任何链接单击产生的。如果这两个 URL 相同,请检查自上次链接单击后是否已超过 100 毫秒。如果是这种情况,那么 URL 相同可能只是巧合,因此您可以再次推断新选项卡不是由链接点击产生的。例如:

    function handleBeforeNavigate(e) {
        e.target.removeEventListener('beforeNavigate', handleBeforeNavigate, false);
        if (e.url === null) {
            takeOverTab();
        } else if (e.url !== lastClickedLinkUrl || (new Date) - lastLinkClickTime > 100) {
            takeOverTab();
        }
    }
    

请注意,这种检测方法并非万无一失。可能有很多方法可能出错。不过,我希望这会有所帮助。

于 2012-04-14T23:57:09.403 回答