在Chrome 86中检测自定义协议处理程序

6

我已根据https://gist.github.com/aaronk6/d801d750f14ac31845e8实现了一个解决方案,它在Chrome 85版本之前运行良好。但是,在最新的Chrome更新中,Onblur无法检测到打开协议处理程序弹出窗口。有没有一种方法可以使用Chrome 86新版本识别在Windows中注册的自定义协议?我实现的代码如下,并且在Firefox上运行良好。

function LinkClicked() {
        launchUri($(this).attr("href"), function () {
            // SUCCESS APPLICATION INSTALLED
        }, function () {
            // PROTOCOL NOT REGISTERD IN REGISTRY
            setTimeout(showAppInstallWarningMessage, 4000);
        }, function () {
            // STATUS CANNOT IDENTIFY
            setTimeout(showAppInstallWarningMessage, 4000);
        });
    }





function launchUri(uri, successCallback, noHandlerCallback, unknownCallback) {
    var res, parent, popup, iframe, timer, timeout, blurHandler, timeoutHandler, browser;

    function callback(cb) {
        if (typeof cb === 'function') cb();
    }

    function createHiddenIframe(parent) {
        var iframe;
        if (!parent) parent = document.body;
        iframe = document.createElement('iframe');
        iframe.style.display = 'none';
        parent.appendChild(iframe);
        return iframe;
    }

    function removeHiddenIframe(parent) {
        if (!iframe) return;
        if (!parent) parent = document.body;
        parent.removeChild(iframe);
        iframe = null;
    }

    browser = { isChrome: false, isFirefox: false, isIE: false };

    if (window.chrome && !navigator.userAgent.match(/Opera|OPR\//)) {
        browser.isChrome = true;
    } else if (typeof InstallTrigger !== 'undefined') {
        browser.isFirefox = true;
    } else if ('ActiveXObject' in window) {
        browser.isIE = true;
    }

    // EVALUATE msLaunchUri for IE 10+ browser in  Windows 8+
    if (navigator.msLaunchUri) {
        navigator.msLaunchUri(uri, successCallback, noHandlerCallback);
    }
    // Evaluating Blur-hack Chrome and FireFox
    else if (browser.isChrome || browser.isFirefox) {
        blurHandler = function () {
            window.clearTimeout(timeout);
            window.removeEventListener('blur', blurHandler);
            callback(successCallback);
        };
        timeoutHandler = function () {
            window.removeEventListener('blur', blurHandler);
            callback(noHandlerCallback);
        };
        window.addEventListener('blur', blurHandler);
        timeout = window.setTimeout(timeoutHandler, 500);
        window.location.href = uri;
    }
    else if (browser.isIE) {
        popup = window.open('', 'launcher', 'width=0,height=0');
        popup.location.href = uri;
        try {
            popup.location.href = 'about:blank';
            callback(successCallback);
            timer = window.setInterval(function () {
                popup.close();
                if (popup.closed) window.clearInterval(timer);
            }, 500);
        } catch (e) {
            popup = window.open('about:blank', 'launcher');
            popup.close();
            callback(noHandlerCallback);
        }
    }
    else {
        iframe = createHiddenIframe();
        iframe.contentWindow.location.href = uri;
        window.setTimeout(function () {
            removeHiddenIframe(parent);
            callback(unknownCallback);
        }, 500);
    }
}

使用 pagehide 事件。 - wOxxOm
@wOxxOm 我尝试了pagehide,但它也没有起作用。 - Qiulang
1
自Chrome 89+版本以来,它再次可以工作了!我还更新了我的答案。 - Qiulang
2个回答

3

我尝试了pagehideblur,但它们都没有起作用。我认为这是因为从Chrome 86+开始,外部协议处理程序不再模糊当前页面。

使用Chrome检测Windows 8+中的自定义协议处理程序提到了使用HTML5可见性API,我也尝试了它,但它在Chrome 86+中也无法正常工作。

我觉得我们可能没有Chrome 86+的解决方案。vscode处理方式可以给我们一些提示。当你第一次访问https://marketplace.visualstudio.com/时,无论你是否安装了vscode,它都会弹出此对话框。

如果您没有安装vscode,并且您点击了外部协议处理程序中的打开按钮,则不会收到任何错误。这可能表明他们也无法获取外部协议处理程序的结果。

vscode

我发现如果我没有注册自定义协议,则Chrome会在控制台日志中打印“因为该方案没有注册处理程序。”,如此处所示

https://chromium.googlesource.com/chromium/src/+/master/chrome/browser/external_protocol/external_protocol_handler.cc#119

  if (shell_integration::GetApplicationNameForProtocol(url).empty()) {
    web_contents->GetMainFrame()->AddMessageToConsole(
        blink::mojom::ConsoleMessageLevel::kError,
        "Failed to launch '" + url.possibly_invalid_spec() +
            "' because the scheme does not have a registered handler.");
    return;
  }

但是我们怎么可以从JavaScript代码中获得shell_integration::GetApplicationNameForProtocol(url).empty()呢?

还可以在此处检查https://support.google.com/chrome/thread/78279651?hl=en,也没有答案。

---Chrome 89+更新---

我发现onBlur再次起作用了! 我找不到一个明确的文档,但是从问题1137801: 回归:“onBlur”事件不会为内置对话框触发中可以看出。

评论30由ericlaw@microsoft.com于2021年3月24日上午6:43发布GMT+8

自版本v89以后,这里的原始抱怨不再重复出现,这意味着我们现在引入了一个允许协议检测的隐私漏洞。 二分法显示 协议检测黑客正在重新开始运作

我测试了Chrome 90+,它确实有效!


有没有办法捕获当协议未注册时出现的错误? - Ankit Wadhwana
你有关于@Qiulang那件事的任何消息吗? - user3659739
检查我的更新,5个月后它再次正常工作。 - Qiulang

2
为了保护隐私和安全,JavaScript 意图上无法检测本地协议处理程序;请参见 this post
这个停止工作的具体原因是 https://crbug.com/1137801

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