Як виявити обробники протоколів браузера?


82

Я створив власний обробник протоколу URL.

http://

mailto://

custom://

Я зареєстрував програму WinForms, щоб відповісти відповідним чином. Все це чудово працює.

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

Для того, щоб зробити це, мені потрібно мати можливість виявити зареєстровані обробники протоколів браузера, я б припустив з JavaScript. Але мені не вдалося знайти спосіб опитування інформації. Я сподіваюся знайти рішення цієї проблеми.

Дякуємо за будь-які ідеї, якими ви можете поділитися.


5
Я думаю, це було б можливим лише у хромованому (тобто XPCOM, ActiveX тощо) коді. В іншому випадку це може бути проблемою конфіденційності ("Ми виявили, що ви використовуєте Eudora. Перейдіть на FooMail сьогодні!"). Але, будь ласка, поясніть, який браузер (и) / ОС (и) вас цікавлять.
Метью Флашен

1
Хороший момент, але я був би радий дізнатися, що щось зареєстровано для обробки мого власного протоколу acsfs: // Windows IE, FireFox і в ідеалі Safari
Кріс Крафт

Ви вже вирішили цю проблему?
jstuardo

Відповіді:


35

Це був би дуже , дуже шалений спосіб зробити це ... але чи спрацювало б це?

  • Помістіть посилання як зазвичай ...
  • Але приєднайте до нього обробник onclick, який встановлює таймер і додає обробник onblur для вікна
  • (теоретично), якщо браузер обробляє посилання (додаток X), завантажується крадіжка фокусу з вікна ...
  • Якщо подія onblur спрацює, очистіть таймер ...
  • В іншому випадку через 3-5 секунд дайте запуск тайм-ауту ... та повідомте користувача "Хм, схоже, у вас не встановлено Mega Uber Cool Application ... ви хотіли б встановити його зараз? (Ok) (Скасувати)"

Далеко не куленепробивний ... але це може допомогти?


1
: D Це розумна ідея. Здається, був би спосіб, бо це здається загальною потребою.
Кріс Крафт

2
У Firefox на Mac (можливо, більшій кількості браузерів) вікно втрачає фокус і активується розмиття, навіть якщо програма зі спеціальним протоколом не запускається.
quano

Це гідне рішення для Chrome, оскільки він не має жодної обробки помилок для протоколів. Це було використано спільно з виявленням інших браузерів тут: rajeshsegu.com/2012/09/browser-detect-custom-protocols/…
Філіп Пейтон

Розпізнавання протоколів останнім часом є головним головним болем. ;) Вищезазначений метод, здається, працює дещо ... за допомогою реального прикладу rajesh, знайденого за адресою rajeshsegu.com/fun/code/browser/detect.html Я отримую "істину" в Chrome. Але якщо я рефакторирую так, що немає функції results () (яка, в свою чергу, використовує поле попередження - блокувальний виклик), і нехай він просто повертає логічну форму, я отримую false. Я якось відчуваю, що попередження про блокування - це також шалений спосіб якось примусити хронометраж ... будь-яке розуміння, @scunliffe?
Грег Петтіт,

Цей метод працює в Chrome, за винятком того випадку, якщо користувач вибрав запам'ятати свою відповідь, використовуючи Win8 і не маючи програми. У цьому випадку подія розмиття трапляється, хоча додаток не може запуститись
Пол Хагго,

18

Немає чудового способу зробити це у різних браузерах. У IE10 + на Win8 + новий 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


ЦЕ НЕ ПРАЦЮЄ - перевірено в браузерах Windows 7, IE

6
msLaunchUri призначений лише для Windows 8+.
EricLaw

Посилання було мертвим.
Qiulang

16

HTML5 визначає спеціальні обробники схеми та вмісту ( наскільки мені відомо, Firefox на сьогодні є єдиним реалізатором ), але, на жаль, наразі немає можливості перевірити, чи вже існує обробник - це було запропоновано , але подальших дій не було. Це здається важливою функцією для ефективного використання користувацьких обробників, і ми, як розробники, повинні звернути увагу на цю проблему, щоб забезпечити її реалізацію.


13

Здається, немає простого способу за допомогою JavaScript визначити наявність встановленої програми, яка зареєструвала обробник протоколу.

У моделі iTunes Apple надає URL-адреси своїм серверам, які надають сторінки, на яких запущено деякий javascript:

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

Отже, програма встановлення iTunes, очевидно, використовує плагіни для основних браузерів, присутність яких потім можна виявити.

Якщо ваш плагін встановлено, то ви можете бути впевнені, що переспрямування на конкретну URL-адресу вашого додатка буде успішним.


2
Це має бути найнадійнішим рішенням. Але я маю на увазі, що вам потрібно встановити, а також створити плагін для більшості браузерів, і це досить складно. Я міг би бути більш зручним, щоб замість цього перенаправити користувача на сторінку завантаження.
Natim

Чому б не використовувати FireBreath, як згадано тут? stackoverflow.com/a/14758085/427793
swdev

11

Найпростішим рішенням є перше запитання у користувача.

Використання діалогового вікна підтвердження 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/'

Печиво можна щодня видаляти чистим. Чи немає кращого способу, як створити файли cookie на основі Flash?

Добре, якщо cookie буде видалено, користувачеві буде просто запропоновано знову.
Natim

Думаю, vscode використовують цей метод, перевірте їхній сайт marketplace.visualstudio.com
Qiulang

5

Якщо у вас є контроль над програмою, яку ви намагаєтеся запустити (код), одним із способів перевірити, чи успішно користувач запускав програму, є:

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

  2. Спробуйте відкрити програму та передайте дані про наміри.

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

  4. Зробіть опитування javascript на сервері на деякий час, щоб перевірити, чи немає в базі даних. Якщо запис зникне, ви дізнаєтесь, що користувач успішно відкрив програму, інакше запис залишиться (ви можете видалити її пізніше за допомогою cronjob).

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


4

Нарешті я зміг отримати крос-браузерне рішення (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.

У всіх випадках, якщо зворотний виклик повертає значення false, ви знаєте, як повідомити користувача, що додаток (тобто його власний протокол) не встановлено.


Це не працює для IE. Як це має працювати? який зв’язок між myWindow.location.href;і iframe srcвизначено всередині цього вікна? Чи слід кидати виняток? Це не залежить від того, підтримується користувацький протокол чи ні.
Бурджуа,

3

Ви кажете, що вам потрібно виявити обробники протоколів браузера - ви справді?

Що робити, якщо ви зробили щось на зразок того, що відбувається, коли ви завантажуєте файл із sourceforge? Скажімо, ви хочете відкрити myapp: // something. Замість того, щоб просто створювати посилання на нього, створіть посилання на іншу сторінку HTML, доступ до якої здійснюється через HTTP. Потім на цій сторінці скажіть, що ви намагаєтесь відкрити для них програму. Якщо це не спрацює, їм потрібно встановити вашу програму, що вони можуть зробити, натиснувши посилання, яке ви надасте. Якщо це все працює, то все готово.


4
Неприпустимо припускати, що це не буде корисним. Мені здається очевидним, що можливість умовно показати посилання на запуск або завантаження - або навіть умовно запустити або завантажити при натисканні на посилання було б чудовим UX, ніж сказати користувачеві, що потрібно встановити його спочатку.
StuartQ

3

Ви можете спробувати щось подібне:

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

Ні, не працює у Firefox 27. (Не тестував в інших браузерах)
Blaise

1
НЕ ПРАЦЮЄ - перевірено в Windows 7, IE, Firefox, Opera, Chrome

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>

Це трохи хакі, але це працює. На жаль, версія Firefox, як і раніше, видає попередження за замовчуванням, яке з’являється під час спроби відвідати посилання з невідомим протоколом, але він буде запускати ваш код після відхилення попередження.


1
Я виявив, що я все-таки отримав "Firefox не знає, як відкрити цю адресу, оскільки протокол (tel) не пов'язаний з жодною програмою". повідомлення перед блоком лову
Дібстер

6
protocolLong повертає результати лише для "відомих" протоколів (файл:, mailto:, gopher:, ftp:, http:, https:, news :), а не для інших Протоколів додатків.
EricLaw

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 \ User Agent \ Post Platform" - Підтримка M $

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

На щастя, інші основні браузери, такі як Firefox та Chrome (забороняючи Safari :(), не видавати помилки "сторінку не знайдено", коли клацається посилання із користувацьким протоколом і протокол не встановлюється на комп'ютері користувачів. IE тут дуже невблаганний , будь-який трюк, щоб натиснути в невидимому кадрі або зафіксувати помилки JavaScript, не працює, і закінчується потворною помилкою "Веб-сторінка не відображається". Фокус, який ми використовуємо в нашому випадку, полягає в тому, щоб повідомити користувачів із зображеннями певного браузера, що натискання на користувацький протокол посилання відкриє програму. І якщо вони не знаходять, що програма відкривається, вони можуть натиснути на сторінку "встановити". Що стосується XD, це wprks набагато краще, ніж підхід ActiveX для IE. Для FF та Chrome, просто продовжуйте і запустити власний протокол без будь-якого виявлення. Нехай користувач розповість вам, що він бачить. Для Safari:(відповідей поки немає


Розширення User-Agent - це поширений, але проблематичний підхід. blogs.msdn.com/b/ieinternals/archive/2009/10/08/…
EricLaw

0

Це не тривіальне завдання; одним із варіантів може бути використання підписаного коду, який ви можете використати для доступу до реєстру та / або файлової системи (зверніть увагу, що це дуже дорогий варіант). Також не існує уніфікованого API або специфікації для підписання коду, тому вам потрібно буде згенерувати певний код для кожного цільового браузера. Кошмар підтримки.

Крім того, я знаю, що Steam , система доставки ігрового вмісту, схоже, теж не вирішила цю проблему.


2
Підписаний код повинен бути підписаний сертифікатом, який встановлено разом із додатком, який обробляє спеціальний: //, тому не буде потреби в справді дорогому сертифікаті програми, підписаному кимось, як verisign.
WhyNotHugo

0

Ось ще одна шалена відповідь, яка вимагатиме (сподіваємось, легкої) модифікації вашого додатка, щоб “зателефонувати додому” при запуску.

  1. Користувач натискає посилання, яке намагається запустити програму. У посилання розміщується унікальний ідентифікатор, який передається додатку під час його запуску. Веб-програма показує блешню або щось подібне.
  2. Потім веб-сторінка починає перевіряти наявність події «домашній телефон телефону» із програми з цим самим унікальним ідентифікатором.
  3. Після запуску ваша програма робить повідомлення HTTP у вашому веб-додатку з унікальним ідентифікатором, щоб вказати присутність.
  4. Або веб-сторінка бачить, що програма запущена, або врешті-решт, або переходить на сторінку "будь ласка, завантажте".
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.