启动应用程序(如果已安装)或重定向下载

Sta*_*own 7 javascript macos github href url-scheme

在每个repo上,GitHub都有一个标记为"Clone in Desktop"的按钮(例如:https://github.com/github/developer.github.com).如果您安装了GitHub for Mac,href则类似于:

github-mac://openRepo/https://github.com/github/developer.github.com
Run Code Online (Sandbox Code Playgroud)

这将打开GitHub for Mac并提供克隆回购.如果你不这样做,那href就是:

http://mac.github.io`
Run Code Online (Sandbox Code Playgroud)

这是GitHub for Mac的下载页面.我想在我的网站上做类似的事情:如果已安装,请打开我的应用程序,如果没有则重定向下载.如何才能最好地完成?

Ale*_*ara 7

GitHub是如何做到的?

在GitHub上的Mac客户端包括称为本地服务GitHub的管道,在后台运行.GitHub页面通过URL与此服务进行通信https://ghconduit.com:25035/status.

摘自GitHub Conduit帮助页面:

例如,Conduit位于Clone in Desktop存储库页面上的Open按钮和文件页面上的按钮之后.Conduit从浏览器中侦听有关GitHub for Mac操作的查询.要查看此操作,请访问https://ghconduit.com:25035/status.它应该看起来像这样:

{"capabilities":["status","unique_id","url-parameter-filepath"],"running":true,"server_version":"5"}
Run Code Online (Sandbox Code Playgroud)

如果您正在运行GitHub Conduit服务,则页面上的JavaScript将从此URL获取数据,并为"在桌面克隆"按钮提供github-mac://URL.否则,URL返回404响应,并假设您没有安装GitHub for Mac,并为您提供下载它的链接.


如何实现这样的功能?

不幸的是,在浏览器中没有JavaScript API可以做到这一点.浏览器无法识别的协议由操作系统本身处理.我尽了最大努力,但我只能在Mac上为Firefox提供一个体面的JavaScript解决方案,并为Safari提供了一个丑陋的半生不熟的解决方案.两种黑客都依赖于未定义的行为,并且都不适用于Chrome.您可以在下面看到我的研究代码.

如果您想以GitHub方式执行此操作,则必须创建一个本地HTTP服务器,该服务器作为服务在用户计算机上的已知端口上运行.然后,您可以使用JavaScript连接到它并检索有关已安装应用程序的信息.这样做不是微不足道的,除非它提供了一些惊人的功能,否则我建议不要这样做.

但是,执行此操作的JavaScript代码相当简单.假设您返回相应的CORS标头,您可以只生成一个简单的AJAX请求.这是一个基于jQuery的例子.

$.ajax({
    url: 'http://127.0.0.1:1337',
    dataType: 'json',
    success: function(jqXHR) {
        //Replace links to app protocol URLs.
    }
});
Run Code Online (Sandbox Code Playgroud)


研究代码:

以下代码是我的超级hacky和相当脆弱的Firefox和Safari代码.虽然它正在我的工作,我绝对不能保证它将按预期工作,或将继续在未来工作.它依赖于特定于浏览器的未定义行为,应该被视为不稳定.我也不知道这个代码在非OS X系统上会做什么.

火狐:

此代码依赖于在iframe中打开链接,当协议无法识别时将触发错误(成功时它将正常打开URL).

function openAppFirefox(url, failure) {
    var iframe = document.createElement('iframe');
    //Firefox will fire an error if protocol fails to open.
    iframe.onerror = function() {
        failure();
    };
    //Hide the iframe.
    iframe.style.width = 0;
    iframe.style.height = 0;
    iframe.style.visibility = "hidden";
    iframe.style.position = "fixed";
    //Load the URL.
    iframe.src = url;
    document.body.appendChild(iframe);
    //Clean up the iframe.
    setTimeout(function() {
        document.body.removeChild(iframe);
    }, 1000);
}
Run Code Online (Sandbox Code Playgroud)

用法示例:

//Will work.
//var url = 'itmss://itunes.apple.com/us/app/stack-exchange/id871299723';
//Will fail.
var url = 'wat://bummer';
someElment.addEventListener('click', function() {
    openAppFirefox(url, function() {
        alert('Download my app!');
    });
});
Run Code Online (Sandbox Code Playgroud)

苹果浏览器:

此代码依赖于在新选项卡中打开URL,如果无法识别URL,该选项卡win.location.href将undefined在一秒钟之内(但可能更短的时间).不幸的是,如果无法打开协议,"没有应用程序设置打开URL"对话框仍将打开.

function openAppSafari(url, failure) {
    var win = window.open(url);
        var done = function(failed) {
            win.close();
            clearInterval(checkFail);
            clearTimeout(giveup);
            if (failed) {
                failure();
            }
        };
        //Chck for failure.
        var checkFail = setInterval(function() {
        //In Safari, location.href becomes undefined on failure.
        if (!win.location.href) {
            done(true);
        }
    });
    //After a second, assume success.
    var giveup = setTimeout(function() {
        done(false);
    }, 1000);
}
Run Code Online (Sandbox Code Playgroud)

用法示例:

//Will work.
//var url = 'itmss://itunes.apple.com/us/app/stack-exchange/id871299723';
//Will fail.
var url = 'wat://bummer';
someElment.addEventListener('click', function() {
    openAppSafari(url, function() {
        alert('Download my app!');
    });
});
Run Code Online (Sandbox Code Playgroud)

  • @StackOverflown当然可以!GitHub的代码没有什么特别之处,但我添加了一个基本的例子.我还添加了我的Firefox和Safari研究代码. (3认同)
  • 这似乎是答案.如果您将JavaScript GitHub用于此和/或您的Firefox代码,即使只是为了学习,我也将不胜感激.谢谢! (2认同)