Ещё одна причина переходить на SSL или 133 КБ не лишние
Вечерело. Мы с товарищем, сделали простенький тест (github) на проверку доступности data-uri в браузерах. Выглядит он следующим образом
В textarea javascript’ом вставляется navigator.userAgent. В этот момент я не знаю, что меня стукнуло в голову, но вместо DOMContentLoaded, я написал
. По-быстрому проверив корректную работу в десктопных браузерах и на нескольких мобильных устройствах, подключённых к интернету через wi-fi, мы успокоились и разошлись по домам.Солнце продиралось сквозь занавески. Утром, в полупустом вагоне метро, я как всегда открыл браузер на своем телефоне, на котором со вчерашнего вечера была открыта тестовая страничка. Сказать, что я удивился, когда я не увидел вывода userAgent внутри textaria — ничего не сказать.
Добравшись до компьютера, решил потратить немного времени на поиск проблемы. Запустив страничку на десктопе и в эмуляторе, я ничего не заметил. Открыл на телефоне. Чудеса! Всё работает.
Увидев включённый значок wi-fi, в мою голову начали закрадываться первые подозрения о причине проблемы. Я отключил wi-fi, подключил телефон к компьютеру и начал дебаг с помощью веб-инспектора десктопного сафари.
Горячий кофе и приятный вкус дебага
Уоу-уоу, полегче, подумал я. Откуда всё это могло взяться в 6 строка JS’а?
А вот откуда
Отличился наш любимый оператор Beeline, с которого я ещё не до конца успел слезть. На небольшую тестовую страничку внезапно прилетело ~133КБ паразитного траффика.
Anchor.js расположен по адресу http://toolbar.beeline.ru/ets/scripts/Anchor.js, который доступен только из сотовой сети Билайна. Для всех желающих посмотреть на стиль кодирования на JS в Билайне, я подготовил ссылку — gist.
Сколько вешать в граммах? Что же входит в эти 133 КБ:* 91 КБ jQuery v1.7.2;* 42 КБ самописного кода.Видно, что никто не заморачивался даже использованием CDN для jQuery. Ну ОК. Смотрим дальше на самописный код.
Первые 914 строк — один большой if:
if (document.getElementById ('toolbar') == null) { //…много кода } Дальше немного хелперов с упором на мобильные устройства от Apple:
function getIOSVersionNumber (){} function isIt (theDevice){} function isMobile (){} function isIPhone (){} function isIPad (){} function getBodyZoomLevel () {}; function isNumberPercentageBased (number) {} function getVisualViewportInfo () {}; We need to go deeper Испектируем код про тулбар: (function (jQFrm){ if (window.XDomainRequest) { // много кода } })(jQFrm); Находим здесь упоминание проприетарного XDomainRequest, который существовал только в IE8 и IE9. Не понимаю, зачем этот код нужен на мобильных устройствах.Идём дальше:
var ets_scripts = jQFrm ('[name=«ets-anchor»]');
jQFrm (window).resize (function () { resizeIframe (); });
if (ets_scripts.length == 1) { // много кода } Встречаем второй большой if и первое вмешательства в обработку событий на произвольном мобильном сайте.По этому селектору находится этот самый Anchor.js, который вставляется в момент перехвата ответа от веб-сервера мобильному браузеру.
Продолжаем чтение по диагонали:
(function () { var msgHandler = function (e) { var ets_frame = document.getElementById ('toolBarPcFrame'); if (e.origin == 'http://toolbar.beeline.ru') { // 500 строк кода } else { //alert (e.origin); throw new Error ('Origin domain is not allowed.'); } } // listen for the message event window.addEventListener ('message', msgHandler, false); })(); Находим механизм общения со встроенным iframe через window.postMessage.
Опять хелперы и…:
function GetWidth () {} function GetHeight (){} function resizeIframe (){} window.onpageshow = function (evt){}; window.onorientationchange = function (){}; window.onload = function (){ //etsAppMain functions (search application) if (InitParamForScroll) { InitParamForScroll (); } }; function isLandscape (){} function orientation_changed (actionId){} if (isMobile ()){} Oh, wait. Вот и причина изначальной проблемы — подмена window.onload
window.onload = function () { //etsAppMain functions (search application) if (InitParamForScroll) { InitParamForScroll (); } }; Режем по-живому В качестве быстрого решения, можно использовать примерно такой gist. document.addEventListener ('DOMContentLoaded', function () { var toolbar = document.getElementById ('toolbar'), iframe = toolbar && toolbar.firstElementChild; if (iframe && /beeline/.test (iframe.getAttribute ('src'))) { toolbar.parentNode.removeChild (toolbar); } }); setTimeout (function () { var script = document.querySelector ('script[name=ets-anchor]'); if (script) { script.parentNode.removeChild (script); } }, 0); Может я подумаю ещё пару минут чуть позже и придумаю более элегантное решение. Смотрите в gist:)Минутка морали. Кроме капитанского «не использовать onload», могу дать несколько полезных советов:* если вы разработчик, по возможности, используйте SSL на ваших сайтах, чтобы _никто_ не мог перехватить ваш траффик;* если вы подключили на свою страницу 90КБ jQuery кода, то используйте его, а не пишите потом document.getElementById;* если вы оператор связи, то никогда не включайте такие услуги «Мини-Кабинет»; * или такие homenet.beeline.ru/index.php? showtopic=315433.
P.S. Этот пост ни в коем случае не наезд на компанию Билайн. Я имел положительный опыт решения проблем с помощью их твиттера @Beeline_Rus. Надеюсь, чтот этот пост поможет хорошим людям внутри компании вырезать эту странную услугу на корню и сделать лично меня, и миллионы абонентов чуточку счастливей.