2010-05-20 103 views
48

我們正在使用註冊自己的協議的軟件。我們可以通過再像鏈接運行從瀏覽器應用程序:如何檢查是否支持自定義協議

customprotocol://do_this. 

但有沒有辦法來檢查是這樣的定製協議由user`s系統支持?如果沒有,我們想要求用戶先安裝軟件。

E.g:

if (canHandle ('customprotocol')) { 
    // run software 
} 
else { 
    // ask to install 
} 

編輯 我知道protocolLong屬性,但它只能在IE瀏覽器。

+4

您可能想要閱讀http://stackoverflow.com/questions/836777/how-to-detect-browsers-protocol-handlers – 2010-05-20 08:39:42

+1

Thx,已經嘗試過大部分描述的方法。似乎沒有好的方法可以在所有流行的瀏覽器中實現此功能,而無需警報或其他問題。 – 2010-05-20 08:50:07

回答

44

不幸的是,有沒有簡單的方法來實現這一點。當然沒有預先確定協議處理程序是否安裝的方法。

的Internet Explorer,正如你所說,有protocolLong屬性,但我無法得到它的收益高於「未知協議」以外的其他所有自定義協議處理程序 - 如果有誰知道如何讓IE瀏覽器返回正確的值請讓我知道,所以我可以更新此部分。我在IE中找到的最佳解決方案是append to the user agent string,或者安裝一個瀏覽器擴展程序以及暴露Javascript可訪問屬性的應用程序。

Firefox是迄今爲止最簡單的主流瀏覽器,因爲它將允許您嘗試並捕獲失敗的導航嘗試。返回的錯誤對象包含name屬性,其值是NS_ERROR_UNKNOWN_PROTOCOL

try { 
    iframe.contentWindow.location.href = "randomprotocolstring://test/"; 
} catch(e) { 
    if (e.name == "NS_ERROR_UNKNOWN_PROTOCOL") 
     window.location = "/download/"; 
} 

Firefox會彈出有自己的警告框:

Firefox不知道如何打開此地址,因爲協議(randomprotocolstring)不與任何程序關聯。

關閉此框後,將會執行catch塊,並且您有一個工作回退。

其次是Opera,它允許您使用可預測性法則來檢測點擊自定義協議鏈接的成功。如果自定義協議點擊有效,該頁面將保持相同的位置。如果沒有安裝處理程序,Opera將導航到錯誤頁面。這使得它比較容易用一個iframe檢測:

iframe.contentWindow.location = "randomprotocolstring://test/"; 
    window.setTimeout(function() { 
     try { 
      alert(ifr.contentWindow.location); 
     } catch (e) { window.location = "/download/"; } 
    }, 0); 

這裏的setTimeout是確保我們檢查位置導航。請注意,如果您嘗試訪問該頁面,則Opera會引發ReferenceException(跨域安全錯誤)。這並不重要,因爲我們需要知道的是,位置從about:blank更改,所以try...catch工作得很好。

Chrome正式吸引了這方面。如果自定義協議處理程序失敗,它會絕對壓縮。如果處理程序工作...你猜對了......它絕對壓縮。恐怕沒有辦法區分兩者。

我還沒有測試Safari但我擔心它會和Chrome一樣。

歡迎您在調查此事時嘗試test code I wrote(我自己有一個既得利益)。它與Opera和Firefox交叉兼容,但目前在IE和Chrome中沒有任何作用。

+1

你可能想檢查一下。 http://www.rajeshsegu.com/2012/09/browser-detect-custom-protocols/comment-page-1/這是一個腳本,應該適用於所有瀏覽器(但不適用於IE)。它有一個hacky,但功能正常,適用於Chrome。 – d512 2014-01-07 20:19:22

+2

因爲這個答案是在2010年編寫的,所以我應該提到Google員工,在更新版本的Firefox中,try/catch方法不再有任何效果。 (iframe仍然避免錯誤頁面) – Katana314 2014-05-02 14:55:48

+0

如果處理程序打開,則Chrome和Safare失去焦點(可以使用window.onblur)。 – 2017-02-20 22:59:39

4

對於Internet Explorer,我發現的最佳解決方案是使用Conditionl註釋&版本向量(應用程序必須在安裝協議時向註冊表寫入內容,請參閱http://msdn.microsoft.com/en-us/library/ms537512.aspx#Version_Vectors)。 protocolLong不適用於自定義協議。

+1

對於Chrome,也許可以在安裝過程中註冊MIME時間,並使用'window.navigator.mimeTypes [i]'進行檢查。我找不到一個簡單的方法來做到這一點。 – 2012-02-08 14:57:15

+1

+1,對於IE 9及更低版本,這是一個很好的解決方法,Mark。不幸的是,IE 10不再支持條件註釋,但也許他們修正了'protocolLong'問題。 – 2013-04-02 19:36:04

3

在移動設備上,你可以使用嵌入式iframe來定製協議和已知的一個(網絡或應用程序商店)之間自動切換,見https://gist.github.com/2662899

11

只是爲了我們自己的經驗幫腔,我們使用FireBreath創建一個簡單的跨平臺插件。一旦安裝這個插件註冊一個MIME類型,可以在頁面刷新後從瀏覽器javascript中檢測到。檢測MIME類型表示協議處理程序已安裝。

if(IE) { //This bastard always needs special treatment 
    try { 
     var flash = new ActiveXObject("Plugin.Name"); 
    } catch (e) { 
     //not installed 
    } 
else { //firefox,chrome,opera 
    navigator.plugins.refresh(true); 
    var mimeTypes = navigator.mimeTypes; 
    var mime = navigator.mimeTypes['application/x-plugin-name']; 
    if(mime) { 
     //installed 
    } else { 
     //not installed 
    } 
} 
+1

+ 1 - 雖然不是「隱形」檢測方法(IE會要求用戶允許運行ActiveXObjects),但這仍然是一個聰明的方法。特別是對於沒有其他解決方法的Chrome,瀏覽器插件可能是某些人的唯一選擇。 – 2013-04-02 19:33:11

+0

FireBreath是解決這個問題的一個非常好的方法,如果這是您所需要的,非常簡單。我已經使用它(嘗試找到同樣問題的解決方案之後)。 – 2014-04-19 23:32:41

+1

爲了讓人們意識到,Mozilla和Google認爲插件是一項傳統技術,Chrome開始逐步淘汰NPAPI,https://developer.chrome.com/extensions/npapi – Burjua 2015-03-23 16:07:33

7

在Windows 8的Internet Explorer 10中引入用於啓動自定義協議的URL和檢測的成功或失敗的非常有益的方法navigator.msLaunchUri。例如:

 if (typeof (navigator.msLaunchUri) == typeof (Function)) { 
      navigator.msLaunchUri(witchUrl, 
       function() { /* Success */ }, 
       function() { /* Failure */ showError(); }); 

      return; 
     } 

Windows 7/IE 9及以下版本支持條件註釋,如@ mark-kahn所示。

+1

請注意,'msLaunchUri'方法僅在Windows 8 **的IE> = 10 **中存在。 – aaronk6 2015-01-05 13:46:07

+0

@ aaronk6。我不確定這是否正確,因爲我在Windows 7上使用此方法。 – antmeehan 2015-01-20 06:53:47

+1

我在Windows 7上檢查了IE 10和IE 11。在這兩種情況下,'typeof navigator.msLaunchUri'都返回'「undefined」'。此外,Microsoft已確認此API尚未添加到Windows 7中:[Windows 7中不存在有文檔記錄的API函數'navigator.msLaunchUri'](https://connect.microsoft.com/IE/feedback/details/864863 /文檔化的api-function-navigator-mslaunchuri-not-present-in-windows-7)(請參閱2014年5月5日下午12:27評論) – aaronk6 2015-01-20 08:50:25

1

下面是一個非常流行的答案:在註冊自定義協議時安裝不尋常的字體。然後使用javascript檢查該字體是否存在,使用like this

確定這是一個黑客攻擊,但與其他答案不同,它可以跨瀏覽器和操作系統使用。

+0

非常好的答案! +1 – 2017-01-23 23:43:19

+0

我不承認 – 2017-05-03 18:12:48

1

我只是想解釋更多以前的馬克的答案(有些人不明白,例如user7892745)。

1)當你啓動你的網頁或網頁應用程序時,它會檢查一個不尋常的字體(如中文Konfuciuz字體http://www.fontspace.com/apostrophic-lab/konfuciuz)。

下面是樣本網頁與功能的代碼檢查字體(稱爲isFontAvailable):

<!DOCTYPE html> 
<html> 
<head> 

</head> 
<body> 

<script> 
/** 
* Checks if a font is available to be used on a web page. 
* 
* @param {String} fontName The name of the font to check 
* @return {Boolean} 
* @license MIT 
* @copyright Sam Clarke 2013 
* @author Sam Clarke <[email protected]> 
*/ 
(function (document) { 
    var width; 
    var body = document.body; 

        var container = document.createElement('span'); 
        container.innerHTML = Array(100).join('wi'); 
        container.style.cssText = [ 
     'position:absolute', 
     'width:auto', 
     'font-size:128px', 
     'left:-99999px' 
    ].join(' !important;'); 

    var getWidth = function (fontFamily) { 
     container.style.fontFamily = fontFamily; 

     body.appendChild(container); 
     width = container.clientWidth; 
     body.removeChild(container); 

     return width; 
    }; 

    // Pre compute the widths of monospace, serif & sans-serif 
    // to improve performance. 
    var monoWidth = getWidth('monospace'); 
    var serifWidth = getWidth('serif'); 
    var sansWidth = getWidth('sans-serif'); 

    window.isFontAvailable = function (font) { 
     return monoWidth !== getWidth(font + ',monospace') || 
      sansWidth !== getWidth(font + ',sans-serif') || 
      serifWidth !== getWidth(font + ',serif'); 
    }; 
})(document); 



function isProtocolAvailable() 
{ 
    if (isFontAvailable('Konfuciuz')) 
    { 
     return true; 
    } 
    else 
    { 
     return false; 
    } 
} 

function checkProtocolAvail() 
{ 
    if (isProtocolAvailable()) 
    { 
     alert('Custom protocol is available!'); 
    } 
    else 
    { 
     alert('Please run executable to install protocol!'); 
    } 
} 
</script> 

<h3>Check if custom protocol was installed or not</h3> 

<pre> 


<input type="button" value="Check if custom protocol was installed!" onclick="checkProtocolAvail()"> 

</body> 
</html> 

2)當用戶打開該網頁第一次,字體將不會被安裝,所以他會得到一條消息說「請運行可執行文件以安裝自定義協議...」。

3)他將運行將安裝字體的可執行文件。你的EXE可以直接將字體文件複製(在我的情況下,它是KONFUC __ TTF)到C:\ Windows目錄或使用這樣的代碼(Delphi的例子):

// Adding the font .. 

AddFontResource(PChar('XXXFont.TTF')); 
SendMessage(HWND_BROADCAST, WM_FONTCHANGE, 0, 0); 

4)之後,當用戶再次運行Web應用程序,他得到「自定義協議可用!」消息,因爲這次是安裝字體。

在Google Chrome,Internet Explorer和Firefox上測試 - 效果很好!