2009-05-07 2 views
70

Я создал собственный обработчик протокола URL.Как обнаружить обработчики протокола браузера?

http://

mailto://

custom://

Я зарегистрировал заявку WinForms реагировать соответствующим образом. Все это прекрасно работает.

Но я хотел бы иметь возможность изящно обрабатывать случай, когда пользователь не имеет настраиваемого обработчика протокола URL.

Для того, чтобы это сделать, мне нужно иметь возможность обнаруживать зарегистрированные обработчики протокола браузера, которые я бы предположил из JavaScript. Но я не смог найти способ опроса информации. Я надеюсь найти решение этой проблемы.

Спасибо за любые идеи, которые вы могли бы поделиться.

+4

Я думаю, что это было бы возможно в хроме только (то есть XPCOM, ActiveX и т.д.) код. В противном случае это будет проблема конфиденциальности («Мы обнаружили, что вы используете Eudora. Переключитесь на FooMail сегодня!»). Но, пожалуйста, уточните, какие браузеры/ОС (ы) вас интересуют. –

+0

Хорошо, но я был бы рад узнать, что что-то зарегистрировано для обработки моего проприетарного протокола acsfs: // Windows IE, FireFox , и в идеале Safari –

ответ

29

Это было бы очень , оченьHacky способ сделать это ... но это будет работать?

  • Поместить ссылку в как обычно ...
  • Но присоединить обработчик OnClick к нему, который устанавливает таймер и добавляет обработчик ONBLUR для окна
  • (в теории), если браузер обрабатывает link (приложение X) будет загружать кражу фокуса из окна ...
  • Если событие onbler срабатывает, очистите таймер ...
  • В противном случае через 3-5 секунд пусть ваш тайм-аут ... и уведомит пользователя «Хм, похоже, что у вас нет приложения Mega Uber Cool Application ... вы хотели бы установить его сейчас? (Ok) (Отмена)«

Далеко не пуленепробиваемый ... но это может помочь?

+1

: D Это умная идея. Похоже, что это будет так, потому что это кажется общей потребностью. –

+1

В Firefox на Mac (возможно, больше браузеров) окно теряет фокус и onblur, даже если приложение с настраиваемым протоколом не запускается. – quano

+0

Это достойное решение для Chrome, поскольку в нем нет какой-либо обработки ошибок для протоколов. Это было использовано в сочетании с обнаружением других браузеров здесь: http://www.rajeshsegu.com/2012/09/browser-detect-custom-protocols/comment-page-1/ –

0

Это не тривиальная задача; одним из вариантов может быть использование подписанного кода, который вы могли бы использовать для доступа к реестру и/или файловой системе (обратите внимание, что это опция very expensive). Также нет единого API или спецификации для подписи кода, поэтому вам потребуется генерировать конкретный код для каждого целевого браузера. Кошмар поддержки.

Кроме того, я знаю, что система доставки игрового контента Steam, похоже, не решена.

+2

. Подписанный код должен быть подписан сертификатом, который устанавливается вместе с приложением, которое обрабатывает пользовательский интерфейс: // поэтому не было бы необходимости в очень дорогостоящем сертификат приложения, подписанный кем-то вроде verisign. – WhyNotHugo

+0

Очень проницательный, спасибо! – ken

3

Вы говорите, что вам нужно обнаружить обработчики протокола браузера - неужели?

Что делать, если вы сделали что-то вроде того, что происходит при загрузке файла из sourceforge? Предположим, вы хотите открыть myapp: // что-то. Вместо того, чтобы просто создать ссылку на него, создайте ссылку на другую страницу HTML, доступную через HTTP. Затем, на этой странице, скажите, что вы пытаетесь открыть приложение для них. Если это не сработает, им необходимо установить приложение, которое они могут сделать, щелкнув ссылку, которую вы предоставите. Если это сработает, тогда вы все настроены.

+0

Невозможно предположить, что это было бы бесполезно. Мне кажется очевидным, что возможность условно показать ссылку на запуск или загрузку - или даже условно запускать или загружать, когда щелчок по ссылке будет превосходным UX, чтобы сообщить пользователю, что им нужно установить в первую очередь. – StuartQ

13

С помощью javascript не существует простого способа обнаружить присутствие установленного приложения, зарегистрировавшего обработчик протокола.

В модели Itunes, Apple обеспечивает URLs к серверам, которые затем предоставляют страницы, которые работают некоторые JavaScript:

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

Так инсталлятор Itunes, по-видимому развертывает плагин для основных браузеров, присутствие которых может затем быть обнаружен.

Если ваш плагин установлен, вы можете быть уверены, что перенаправление на ваш URL-адрес приложения будет успешным.

+2

Это должно быть самым надежным решением. Но я имею в виду, что вам нужно установить и создать плагин для большей части браузера, и это довольно сложно. Я мог бы быть более дружелюбным, чтобы иметь возможность перенаправлять пользователя на страницу загрузки. – Natim

+0

Почему бы не использовать FireBreath, как упоминалось здесь? http://stackoverflow.com/a/14758085/427793 – swdev

9

Какие швы наиболее простое решение - спросить пользователя в первый раз.

Использование 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/' 
+0

Печенье можно удалять ежедневно. Нет лучшего способа сделать флеш-файл cookie? – YumYumYum

+0

Ну, если cookie будет удален, пользователь снова будет запрошен. – Natim

1

Я пытаюсь сделать что-то подобное, и я только что обнаружил трюк, который работает с Firefox. Если объединить его с трюком для IE вы можете иметь один, который работает на обоих основных браузерах (я не уверен, если он работает в Safari, и я знаю, что это не работает в 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"); 
     } 
    } 
} 

Для того, для этой работы вы также должны иметь скрытую ссылку где-то на странице, как это:

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

это немного Hacky, но это работает. В версии Firefox, к сожалению, по-прежнему появляется предупреждение по умолчанию, которое появляется при попытке посетить ссылку с неизвестным протоколом, но она запустит ваш код после отклонения предупреждения.

+1

Я нашел, что у меня все еще есть «Firefox не знает, как открыть этот адрес, потому что протокол (tel) не связан ни с одной программой». сообщение перед блоком catch – Deebster

+5

protocolLong возвращает результаты только для «известных» протоколов (файл:, mailto:, gopher:, ftp:, http:, https:, news :), а не для других протоколов приложений. – EricLaw

5

Вы можете попробовать что-то вроде этого:

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 
     } 
    } 
} 
+2

Является ли этот браузер-агностик? – Reuven

+0

Нет, не работает в Firefox 27. (Не тестировался в других браузерах) – Blaise

+0

НЕ РАБОТАЕТ - протестирован в Windows 7, IE, Firefox, Opera, Chrome – YumYumYum

1

Это рекомендуемый подход для IE при поддержке Microsoft

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

«Если у вас есть некоторый контроль над двоичными файлами устанавливается на пользовательский компьютер, проверка подлинности UA в сценарии кажется подходящим подходом: HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Internet Settings \ 5.0 \ Пользовательский агент \ Почтовая платформа »- по поддержке M $

Каждая веб-страница имеет доступ к строке userAgent, и если вы отбрасываете значение пользовательской платформы, обнаружение этого в javascript с помощью navigator.userAgent довольно просто.

К счастью, другие крупные браузеры, такие как Firefox и Chrome (запрет Safari :(), не бросают ошибки «страницы не найдены» при нажатии ссылки с пользовательским протоколом, а протокол не установлен на компьютере пользователя. здесь очень непростительно, любой трюк, который нужно щелкнуть в невидимом фрейме или ошибки ловушки javascript, не работает и заканчивается ошибкой «ошибки веб-страницы». на ссылке пользовательского протокола откроется приложение. И если они не обнаружат приложение, оно может щелкнуть по странице «Установка». Что касается XD, это будет лучше, чем подход ActiveX для IE. Для FF и Chrome, просто продолжайте и запускайте собственный протокол без какого-либо обнаружения. Позвольте пользователю рассказать вам, что он видит. Для Safari, :(нет ответов пока

+0

Расширение User-Agent - общий, но проблематичный подход. http://blogs.msdn.com/b/ieinternals/archive/2009/10/08/extending-the-user-agent-string-problems-and-alternatives.aspx – EricLaw

14

HTML5 не определяет Custom scheme and content handlers (к моему знанию Firefox является единственным implementor до сих пор), но, к сожалению, в настоящее время нет способа проверить, если обработчик уже существует, он был proposed, но не было никаких последующих действий. Это похоже на критическую особенность эффективного использования пользовательских обработчиков, и мы, как разработчики, должны обратить внимание на эту проблему, чтобы ее реализовать.

4

Если у вас есть контроль над программой, которую вы пытаетесь для запуска (код), один из способов проверить, был ли пользователь успешным при запуске приложения, был бы:

  1. Прежде чем пытаться открыть настраиваемый протокол, сделайте запрос AJAX к серверному скрипту, который сохраняет намерение пользователя в базе данных (например, сохраните идентификатор пользователя и что он хочет делать).

  2. Попробуйте открыть программу и передать данные о намерениях.

  3. Попросите программу сделать запрос на сервер, чтобы удалить запись базы данных (используя данные о намерениях, чтобы найти правильную строку).

  4. Проведите опрос javascript на сервере некоторое время, чтобы узнать, исчезла ли запись в базе данных. Если запись не удалась, вы узнаете, что пользователь успешно открыл приложение, иначе запись останется (вы можете удалить ее позже с помощью cronjob).

Я не пробовал этот метод, просто подумал.

13

Вы можете использовать встроенный IFRAME для автоматического переключения между пользовательским протоколом и известным один (или веб-приложением магазина), см https://gist.github.com/2662899

+0

Этот ответ должен быть увеличен, он работает просто отлично подходит для iOS и Android, благодаря этому умному рубить! – vdaubry

+2

Вопрос был не в iOS или Android. – Burjua

17

Там нет отличного способа кросса-браузера, чтобы сделать это. В IE10 + на Win8 +, новый msLaunchUri апи позволяет запускать протокол, например, так:

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

+0

ЭТО НЕ РАБОТАЕТ - протестировано в Windows 7, браузерах IE – YumYumYum

+4

msLaunchUri - только для Windows 8+. – EricLaw

4

я смог, наконец, получить кросс-браузер (Chrome 32, Firefox 27, IE 11, Safari 6) решение работает с комбинацией this и супер-простое расширение Safari. Большая часть этого решения была упомянута так или иначе в этом и этом other question.

Вот сценарий:

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.ЯШ:

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

Затем на веб-странице JavaScript, вам необходимо сначала зарегистрировать сообщение о событии и установить флаг, если сообщение получено:

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

Это предполагает приложение, которое связано с пользовательский протокол будет управлять установкой расширения Safari.

Во всех случаях, если обратный вызов возвращает false, вы знаете, чтобы информировать пользователя о том, что приложение (т. Е. Пользовательский протокол) не установлено.

+0

Это не работает для IE. Как это должно работать? Какая связь между 'myWindow.location.href;' и iframe 'src' определена внутри этого окна? Предполагается ли исключение? Это не зависит от того, поддерживается ли пользовательский протокол или нет. – Burjua

0

Вот еще один хакерский ответ, который потребует (надеюсь, световой) модификации вашего приложения на «телефон дома» при запуске.

  1. Пользователь щелкает ссылку, которая пытается запустить приложение. Уникальный идентификатор помещается в ссылку, так что он передается приложению при его запуске. Веб-приложение показывает прядильщик или что-то в этом роде.
  2. Веб-страница затем начинает проверку на событие 'phone phone' из приложения с этим же уникальным идентификатором.
  3. При запуске ваше приложение отправляет сообщение HTTP вашему веб-приложению с уникальным идентификатором, чтобы указать наличие.
  4. Либо веб-страница видит, что приложение запущено, в конце концов, либо переходит на страницу «загрузите».
4

Я создал общую библиотеку для этой проблемы, исходя из предположения, что обработчик пользовательского протокола вызовет новое окно, чтобы вывести фокус из браузера.

Смежные вопросы