Development Tip

브라우저의 프로토콜 처리기를 감지하는 방법은 무엇입니까?

yourdevel 2020. 10. 14. 21:21
반응형

브라우저의 프로토콜 처리기를 감지하는 방법은 무엇입니까?


사용자 지정 URL 프로토콜 처리기를 만들었습니다.

http://

mailto://

custom://

이에 따라 대응할 수 있도록 WinForms 애플리케이션을 등록했습니다. 이것은 모두 훌륭하게 작동합니다.

그러나 사용자가 아직 사용자 지정 URL 프로토콜 처리기를 설치하지 않은 경우를 우아하게 처리 할 수 ​​있기를 바랍니다.

이 작업을 수행하려면 브라우저에 등록 된 프로토콜 처리기를 감지 할 수 있어야합니다. JavaScript에서 가정합니다. 하지만 정보를 조사 할 방법을 찾을 수 없었습니다. 이 문제에 대한 해결책을 찾고 싶습니다.

공유 할 수있는 아이디어에 감사드립니다.


이것은 이것을 수행하는 매우 , 매우 해키 한 방법 일 것입니다 ... 그러나 이것이 작동할까요?

  • 링크를 정상적으로 넣으십시오 ...
  • 그러나 타이머를 설정하고 창에 대한 onblur 핸들러를 추가하는 onclick 핸들러를 첨부하십시오.
  • (이론상) 브라우저가 링크 (응용 프로그램 X)를 처리하면 창에서 포커스를 훔쳐로드됩니다.
  • onblur 이벤트가 발생하면 타이머를 지 웁니다 ...
  • 그렇지 않으면 3-5 초 후에 시간 초과가 발생하도록하고 사용자에게 "음, Mega Uber Cool 애플리케이션을 설치하지 않은 것 같습니다 ... 지금 설치 하시겠습니까? (OK) (취소)"라고 알립니다.)

방탄과는 거리가 멀지 만 도움이 될까요?


이 작업을 수행하는 훌륭한 브라우저 간 방법은 없습니다. Win8 +의 IE10 +에서 새 msLaunchUriAPI를 사용하면 다음과 같이 프로토콜을 시작할 수 있습니다.

navigator.msLaunchUri('skype:123456', 
  function() 
  { 
    alert('success');
  }, 
  function()
  {
    alert('failed');
  } 
); 

프로토콜이 설치되지 않은 경우 실패 콜백이 실행됩니다. 그렇지 않으면 프로토콜이 시작되고 성공 콜백이 실행됩니다.

이 주제에 대해서는 여기에서 조금 더 논의합니다. http://blogs.msdn.com/b/ieinternals/archive/2011/07/14/url-protocols-application-protocols-and-asynchronous-pluggable-protocols-oh-my .aspx


HTML5는 사용자 정의 스키마와 콘텐츠 핸들러를 정의합니다 (내가 아는 한 Firefox가 유일한 구현 자임). 불행히도 현재 핸들러가 이미 존재하는지 확인할 방법 이 없습니다. 제안 되었지만 후속 조치는 없었습니다. 이것은 사용자 정의 핸들러를 효과적으로 사용하기위한 중요한 기능으로 보이며 우리는 개발자로서이 문제를 구현하기 위해주의를 기울여야합니다.


프로토콜 핸들러를 등록한 설치된 앱의 존재를 감지하는 자바 스크립트를 통한 직접적인 방법은없는 것 같습니다.

iTunes 모델에서 Apple은 서버에 URL을 제공 한 다음 일부 자바 스크립트를 실행하는 페이지를 제공합니다.

http://ax.itunes.apple.com/detection/itmsCheck.js

따라서 iTunes 설치 프로그램은 분명히 존재를 감지 할 수있는 주요 브라우저 용 플러그인을 배포합니다.

플러그인이 설치된 경우 앱별 URL로 리디렉션이 성공할 것이라고 합리적으로 확신 할 수 있습니다.


내장 된 iframe을 사용하여 사용자 정의 프로토콜과 알려진 프로토콜 (웹 또는 앱 스토어)간에 자동 전환 할 수 있습니다. https://gist.github.com/2662899를 참조 하십시오.


가장 쉬운 해결책은 사용자에게 처음으로 묻는 것입니다.

Javascript 확인 ​​대화 상자를 사용하여 예제별로 :

You need this software to be able to read this link. Did you install it ?

if yes: create a cookie to not ask next time; return false and the link applies
if false: window.location.href = '/downloadpage/'

사용자 지정 프로토콜 처리기가 브라우저에서 포커스를 가져 오기 위해 새 창을 트리거한다는 가정을 기반으로이 문제에 대한 일반 라이브러리를 만들었습니다.

https://github.com/ismailhabib/custom-protocol-detection


실행하려는 프로그램 (코드)을 제어 할 수있는 경우 사용자가 응용 프로그램을 성공적으로 실행했는지 확인하는 한 가지 방법은 다음과 같습니다.

  1. 사용자 정의 프로토콜을 열기 전에 사용자의 의도를 데이터베이스에 저장하는 서버 스크립트에 AJAX 요청을 작성하십시오 (예 : 사용자 ID 및 원하는 작업 저장).

  2. 프로그램을 열고 의도 데이터를 전달하십시오.

  3. 프로그램이 데이터베이스 항목을 제거하도록 서버에 요청하도록하십시오 (정확한 행을 찾기 위해 의도 데이터 사용).

  4. 데이터베이스 항목이 사라 졌는지 확인하기 위해 잠시 동안 자바 스크립트가 서버를 폴링하도록합니다. 항목이 사라지면 사용자가 응용 프로그램을 성공적으로 열었 음을 알 수 있습니다. 그렇지 않으면 항목이 유지됩니다 (나중에 cronjob을 사용하여 제거 할 수 있음).

나는이 방법을 시도하지 않고 단지 생각했다.


드디어 크로스 브라우저 (Chrome 32, Firefox 27, IE 11, Safari 6) 솔루션 이이 솔루션 과 매우 간단한 Safari 확장 기능을 함께 사용할 수있게되었습니다. 이 솔루션의 대부분은이 질문다른 질문 에서 어떤 식 으로든 언급되었습니다 .

다음은 스크립트입니다.

function launchCustomProtocol(elem, url, callback) {
    var iframe, myWindow, success = false;

    if (Browser.name === "Internet Explorer") {
        myWindow = window.open('', '', 'width=0,height=0');
        myWindow.document.write("<iframe src='" + url + "'></iframe>");

        setTimeout(function () {
            try {
                myWindow.location.href;
                success = true;
            } catch (ex) {
                console.log(ex);
            }

            if (success) {
                myWindow.setTimeout('window.close()', 100);
            } else {
                myWindow.close();
            }

            callback(success);
        }, 100);
    } else if (Browser.name === "Firefox") {
        try {
            iframe = $("<iframe />");
            iframe.css({"display": "none"});
            iframe.appendTo("body");
            iframe[0].contentWindow.location.href = url;

            success = true;
        } catch (ex) {
            success = false;
        }

        iframe.remove();

        callback(success);
    } else if (Browser.name === "Chrome") {
        elem.css({"outline": 0});
        elem.attr("tabindex", "1");
        elem.focus();

        elem.blur(function () {
            success = true;
            callback(true);  // true
        });

        location.href = url;

        setTimeout(function () {
            elem.off('blur');
            elem.removeAttr("tabindex");

            if (!success) {
                callback(false);  // false
            }
        }, 1000);
    } else if (Browser.name === "Safari") {
        if (myappinstalledflag) {
            location.href = url;
            success = true;
        } else {
            success = false;
        }

        callback(success);
    }
}

Safari 확장은 구현하기 쉬웠습니다. 한 줄의 주입 스크립트로 구성되었습니다.

myinject.js :

window.postMessage("myappinstalled", window.location.origin);

그런 다음 웹 페이지 JavaScript에서 먼저 메시지 이벤트를 등록하고 메시지가 수신되면 플래그를 설정해야합니다.

window.addEventListener('message', function (msg) {
    if (msg.data === "myappinstalled") {
        myappinstalledflag = true;
    }
}, false);

이것은 사용자 정의 프로토콜과 관련된 응용 프로그램이 Safari 확장 설치를 관리한다고 가정합니다.

In all cases, if the callback returns false, you know to inform the user that the application (i.e., it's custom protocol) is not installed.


You say you need to detect the browser's protocol handlers - do you really?

What if you did something like what happens when you download a file from sourceforge? Let's say you want to open myapp://something. Instead of simply creating a link to it, create a link to another HTML page accessed via HTTP. Then, on that page, say that you're attempting to open the application for them. If it doesn't work, they need to install your application, which they can do by clicking on the link you'll provide. If it does work, then you're all set.


You can try something like this:

function OpenCustomLink(link) {

    var w = window.open(link, 'xyz', 'status=0,toolbar=0,menubar=0,height=0,width=0,top=-10,left=-10');
    if(w == null) {            
        //Work Fine
    }
    else {
        w.close();
        if (confirm('You Need a Custom Program. Do you want to install?')) {
            window.location = 'SetupCustomProtocol.exe'; //URL for installer
        }
    }
}

I'm trying to do something similar and I just discovered a trick that works with Firefox. If you combine it with the trick for IE you can have one that works on both main browsers (I'm not sure if it works in Safari and I know it doesn't work in Chrome)

if (navigator.appName=="Microsoft Internet Explorer" && document.getElementById("testprotocollink").protocolLong=="Unknown Protocol") {
    alert("No handler registered");
} else {
    try {
        window.location = "custom://stuff";
    } catch(err) {
        if (err.toString().search("NS_ERROR_UNKNOWN_PROTOCOL") != -1) {
            alert("No handler registered");
        }
    }
}

In order for this to work you also need to have a hidden link somewhere on the page, like this:

<a id="testprotocollink" href="custom://testprotocol" style="display: none;">testprotocollink</a>

It's a bit hacky but it works. The Firefox version unfortunately still pops up the default alert that comes up when you try to visit a link with an unknown protocol, but it will run your code after the alert is dismissed.


This was a recommended approach for IE by Microsoft support

http://msdn.microsoft.com/en-us/library/ms537503%28VS.85%29.aspx#related_topics

"If you have some control over the binaries being installed on a user’s machine, checking the UA in script seems like a relevant approach: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\5.0\User Agent\Post Platform " -- By M$ support

Every web page has access to the userAgent string and if you drop a custom post platform value, detecting this in javascript using navigator.userAgent is quite simple.

Fortunately, other major browsers like Firefox and Chrome (barring Safari :( ), do not throw "page not found" errors when a link with a custom protocol is clicked and the protocol is not installed on the users machine. IE is very unforgiving here, any trick to click in a invisible frame or trap javascript errors does not work and ends up with ugly "webpage cannot be displayed" error. The trick we use in our case is to inform users with browser specific images that clicking on the custom protocol link will open an application. And if they do not find the app opening up, they can click on an "install" page. In terms of XD this wprks way better than the ActiveX approach for IE. For FF and Chrome, just go ahead and launch the custom protocol without any detection. Let the user tell you what he sees. For Safari, :( no answers yet


This is not a trivial task; one option might be to use signed code, which you could leverage to access the registry and/or filesystem (please note that this is a very expensive option). There is also no unified API or specification for code signing, so you would be required to generate specific code for each target browser. A support nightmare.

Also, I know that Steam, the gaming content delivery system, doesn't seem to have this problem solved either.


Here's another hacky answer that would require (hopefully light) modification to your application to 'phone home' on launch.

  1. User clicks link, which attempts to launch the application. A unique identifier is put in the link, so that it's passed to the application when it launches. Web app shows a spinner or something of that nature.
  2. Web page then starts checking for a 'application phone home' event from an app with this same unique ID.
  3. When launched, your application does an HTTP post to your web app with the unique identifier, to indicate presence.
  4. Either the web page sees that the application launched, eventually, or moves on with a 'please download' page.

참고URL : https://stackoverflow.com/questions/836777/how-to-detect-browsers-protocol-handlers

반응형