Тоже вариант. Но опять придется ловить вменяемый таймаут ожидания сообщения от проги, чтобы на медленных компах не уйти на false раньше времени. Но тут хоть нет проблемы, что кто-нибудь руками фокус уведет из браузера за время таймаута. Так, глядишь, и скоро выйдем на вполне приемлемое решение :)
Все верно. Поэтому для себя я сделал выбор — убрал все эти костыли и оставил на форме обе кнопки — маленькую серую на установку приложения и большую зеленую на запуск + краткий вступительный комментарий. В моем сценарии это лучше, чем вводить пользователей в ступор странным поведением программы, в попытках сделать их жизнь проще. В других сценариях, к сожалению, приходится извращаться.
В остальном — те же проблемы. Например, благодаря try...catch в Firefox и Opera есть возможность провести 100% проверку и все корректно обработать. А вот в Chrome всегда будут негативные срабатывания, особенно при первой проверке или перегруженной памяти. При чем, если протокол зарегистрирован, то приложение успешно стартанет в конечном итоге. Но ветка false уже пойдет на выполнение, и будет некрасиво. Ну и главная проблема — нельзя просто проверить наличие протокола (в отличие от web-handlers). Сделать можно только проверку боем, попытавшись открыть ссылку/загрузить фрейм. Мне, по крайней мере, других решений не попадалось.
Проверил isProtocolHandlerRegistered(). Функция проверяет, зарегистрирован ли конкретный URL как обработчик протокола (название функции говорит само за себя — функция проверяет именно обработчик протокола, а не сам протокол). Например, если зарегистрировать собственный протокол вот таким образом:
Так что придется пока довольствоваться костылями, предложенными в этой статье.
И еще момент, раз уж заговорили об этом. Зарегистрировать собственный протокол без префикса 'web+' тоже нельзя. Можно только повесить свой обработчик на уже зарегистрированные протоколы (так называемые whitelisted schemes, например: mailto, ssh, tel). Это значит, что зарегистрировать, скажем, протокол 'myproto' через registerProtocolHandler не получится.
Но есть и хорошая новость. Стандарт поддерживает уже не только Opera, но и последние версии Chrome и Firefox. Так что, если кому эта фича полезна, уже вполне можно пользоваться.
Я на досуге проверю в Opera, может ли isProtocolHandlerRegistered() определить схемы, зарегистрированные локальными приложениями, или же она определяет только схемы, зарегистрированные с помощью registerProtocolHandler(). Если может, внесу в статью еще один вариант для Opera, раз уж они впереди планеты всей.
Если одно из этих событий произошло, когда браузер был открыт, и пользователь висел без действия в консоли, JS получив от сервера на очередной AJAX-запрос (когда пользователь все-таки проснулся) ответ 401, перекинет пользователя на форму входа с сообщением «Your session expired».
Если эти события произошли, когда браузер/вкладку закрыли, а потом открыли, будет выведена форма логона без всяких сообщений. Да, здесь тоже можно было бы написать, что сессия истекла. Но совсем не обязательно. Пользователь закрыл вкладку и ушел. Через пару часов (или дней) открыл ее опять и получил форму логона. По-моему, логично. А когда он в консоли попадает на таймаут — вот тогда надо сказать, что время вышло.
Мое мнение, мы слишком много сегодня потратили времени на этот вопрос. По-моему, тут все понятно, и дальше каждый может развивать реализацию по логике своего приложения.
403 Forbidden
The request was a valid request, but the server is refusing to respond to it. Unlike a 401 Unauthorized response, authenticating will make no difference. On servers where authentication is required, this commonly means that the provided credentials were successfully authenticated but that the credentials still do not grant the client permission to access the resource (e.g. a recognized user attempting to access restricted content).
От вы шутник… А я уже десяток сайтов обошел в поисках 488 ошибки :)
Так я ничего и не проверяю дополнительно. Этот код возвращают два метода. Первый описан в статье — это sessionStart. Второй — метод аутентификации пользователя. Для приложения это одно и то же — в обоих случаях оно выкидывает в ответ заголовок с кодом ошибки. Но дело в том, что оно возвращает этот код в разные места — один в консоль авторизованного пользователя, второй — в форму логона. Поэтому я могу реагировать в обоих случаях по-разному, потому что для пользователя, в отличие от приложения и от нас с вами, это две разные ситуации. И вот, честно, не могу понять — что здесь плохого?
Нет, я так не считаю, конечно. Но если говорить о библиотеке, которую могут использовать другие разработчики, работающие со мной в паре, то это вполне возможно, согласитесь. Кто-то может сделать ошибку в логике и вызвать sessionStart() повторно. Библиотека должна быть к этому готова, я считаю.
488 — не знал, что этот код означает, что время сессии истекло. Нигде в стандартах такого не видел, использовал бы его, конечно. Спасибо за подсказку. Но на результат это не влияет, потому что, когда пользователь внутри приложения получает 401, это значит, что время сессии истекло (других вариантов этого кода быть не может внутри приложения), а когда он получает 401 на форме логона, это значит, что аутентификация не прошла (аналогично, других вариантов быть не может).
С точки зрения приложения действительно есть только авторизованный и не авторизованный пользователь. Но вы же не хотите сказать, что мое стремление сделать жизнь пользователя проще и понятнее заслуживает порицания? Что плохого в том, что пользователь получает немного больше информации, чем думает о нем приложение?
А зачем вызывать session_start() каждый раз при входе в функцию, если сессия уже может быть запущена? Вот для этого и стоит первой строкой проверка session_id(), а потом уже session_start(). В общем, это уже пошли мелочи, не стоящие нашего с вами времени.
А если в целом, то разница тут только в том, что вы предлагаете использовать исключения, а я обрабатываю ошибки прямо в коде. Это два разных подхода к обработке ошибок. Вам больше нравится первый подход, мне — второй. Но статья не об этом же.
А что вы имеете ввиду под «что-нибудь другое стартует сессию»? Разве может стартовать сессию что-то отличное от session.auto_start и session_start()? Если нет, то в коде все правильно. Если отключен session.auto_start, и функция session_id() вернула ненулевой результат, то значит мы уже заходили сюда раньше во время выполнения этого экземпляра скрипта, а значит мы уже сделали все проверки и повторно делать их не за чем.
Соглашусь, что не учел session.auto_start (просто он по умолчанию выключен, да и не встречал я людей, которые его включают, но согласен, что надо было упомянуть об этом, внесу правку, спасибо).
Что касается if (! session_start() ) — тут согласиться не могу, потому что не у всех пока PHP 5.3, а до 5.3 функция session_start() всегда возвращала TRUE.
www.dunnsolutions.com/content/application-development-blog/-/blogs/smart-app-banners-for-ios-and-android
jasny.github.io/jquery.smartbanner/#android
alert(getProtocol() + " supported => " + isSupported);
В остальном — те же проблемы. Например, благодаря try...catch в Firefox и Opera есть возможность провести 100% проверку и все корректно обработать. А вот в Chrome всегда будут негативные срабатывания, особенно при первой проверке или перегруженной памяти. При чем, если протокол зарегистрирован, то приложение успешно стартанет в конечном итоге. Но ветка false уже пойдет на выполнение, и будет некрасиво. Ну и главная проблема — нельзя просто проверить наличие протокола (в отличие от web-handlers). Сделать можно только проверку боем, попытавшись открыть ссылку/загрузить фрейм. Мне, по крайней мере, других решений не попадалось.
то потом можно сделать вот так:
и получить в ответ 'registered'. Но если сделать вот так:
получим 'undefined'.
Так что придется пока довольствоваться костылями, предложенными в этой статье.
И еще момент, раз уж заговорили об этом. Зарегистрировать собственный протокол без префикса 'web+' тоже нельзя. Можно только повесить свой обработчик на уже зарегистрированные протоколы (так называемые whitelisted schemes, например: mailto, ssh, tel). Это значит, что зарегистрировать, скажем, протокол 'myproto' через registerProtocolHandler не получится.
Но есть и хорошая новость. Стандарт поддерживает уже не только Opera, но и последние версии Chrome и Firefox. Так что, если кому эта фича полезна, уже вполне можно пользоваться.
Если эти события произошли, когда браузер/вкладку закрыли, а потом открыли, будет выведена форма логона без всяких сообщений. Да, здесь тоже можно было бы написать, что сессия истекла. Но совсем не обязательно. Пользователь закрыл вкладку и ушел. Через пару часов (или дней) открыл ее опять и получил форму логона. По-моему, логично. А когда он в консоли попадает на таймаут — вот тогда надо сказать, что время вышло.
Мое мнение, мы слишком много сегодня потратили времени на этот вопрос. По-моему, тут все понятно, и дальше каждый может развивать реализацию по логике своего приложения.
Так что приходится довольствоваться одним 401-ым.
Разве режим гостевого доступа не попадает под правила отсутствия активности?
Так я ничего и не проверяю дополнительно. Этот код возвращают два метода. Первый описан в статье — это sessionStart. Второй — метод аутентификации пользователя. Для приложения это одно и то же — в обоих случаях оно выкидывает в ответ заголовок с кодом ошибки. Но дело в том, что оно возвращает этот код в разные места — один в консоль авторизованного пользователя, второй — в форму логона. Поэтому я могу реагировать в обоих случаях по-разному, потому что для пользователя, в отличие от приложения и от нас с вами, это две разные ситуации. И вот, честно, не могу понять — что здесь плохого?
С точки зрения приложения действительно есть только авторизованный и не авторизованный пользователь. Но вы же не хотите сказать, что мое стремление сделать жизнь пользователя проще и понятнее заслуживает порицания? Что плохого в том, что пользователь получает немного больше информации, чем думает о нем приложение?
А если в целом, то разница тут только в том, что вы предлагаете использовать исключения, а я обрабатываю ошибки прямо в коде. Это два разных подхода к обработке ошибок. Вам больше нравится первый подход, мне — второй. Но статья не об этом же.
Думаю, разобрались :)
Что касается if (! session_start() ) — тут согласиться не могу, потому что не у всех пока PHP 5.3, а до 5.3 функция session_start() всегда возвращала TRUE.