Помни о расширениях или история одного бага

в 21:49, , рубрики: javascript, расширения, метки: ,
Предыстория

Пришло однажды нам на почту письмо пользователя недовольного. «Не загружаются у меня на сайт ваш фотографии», говорил пользователь и прикладывал к письму скриншот. На скриншоте был слой с картинкой, а вместо картинки — обрезки от тега <img />.
Помни о расширениях или история одного бага
(слева — у обычных пользователей, справа — у гневного)

В те времена загрузка была сделана просто — через форму, которая сабмитится в iframe и потом оттуда из ответа в plain-text забирает часть имени файла, с помощью которого можно получить ссылку на файл уже на нашем сервере. «Модная» загрузка через XMLHttpRequest и FormData была только в планах.

Поломав некоторое время голову, переделал создание картинки вручную, а атрибутов ее — через setAttribute, вместо создания элемента прямо через plain-html. Как оказалось уже гораздо позже, бестолку, но не суть важно — пользователю надоело с нами общаться, мы сами не смогли воспроизвести (хотя очень старались) и отложили проблему в долгий ящик, благо никто больше не жаловался.

Внезапно

Спустя более чем полгода, когда уже и загрузку картинок переделали на новый способ, с прогресс-баром и модными фишками, меня позвал тестировщик, который решил написать тест загрузки старым способом, через iframe, на браузерах, которые не поддерживают XMLHttpRequest или FormData. Подхожу к нему и вижу то же самое, что когда-то присылал нам на скриншоте гневный пользователь. Прямо здесь, в браузере, можно подебажить, даже воспроизводилось постоянно!

Открываю FireBug, смотрю результат, вернувшийся в iframe и вижу что все ок, смотрю в javascript и вижу, что на самом деле внутри iframe кроме имени файла лежит и какой-то вражеский <div>. Наверное, поздно, но тут меня осенило и я пошел отключать расширения и, один за одним, проверять. Действительно, дело оказалось в одном из расширений. И такой вариант изначально как-то даже не пришел мне в голову, хотя на тот момент у меня было несколько своих расширений, у одного из которых аж несколько тысяч пользователей. В расширении (понятия не имею зачем) автор решил вставлять вообще во все возможные документы, свой какой-то специальный <div>.

Как-то так (форматирование сохранено, идентификатор — заменен, дабы не идентифицировать расширение):

if(!doc.body)return;
if(doc.getElementById('xxx'))
        return;
var tmp = doc.createElement("div");
tmp.setAttribute("style", "display:none");
tmp.setAttribute("id",'xxx');
(doc.body||doc.head[0]).appendChild(tmp);

Даже не матерился на огромную простыню страшного кода расширения, а просто улыбался — настолько простой оказалась проблема.

Костыль для починки

Не писать же разработчику расширения, тем более что оно — далеко не единственное, которое вражески вставляет во все, что только можно, свои побрякушки. Старый способ загрузки файлов пользуется у нас хоть и редко, но пользуется, поэтому починили все это дело на своей стороне вот таким быстрым способом:

var 
    $source = $('<div />').html(iframeBodyContent),
    filename;
  
$source.children().remove();
filename = $.trim($source.text());

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

Зачем я вообще это все сюда написал?

Расширений к браузерам, как качественных, так и не очень (таких, увы, большинство), становится все больше и больше. Большинство расширений нагло врезается в ваш код и как-то его модифицирует. И не все они одинаково полезны. Мне очень повезло, что у тестера был тот злосчастный плагин.

Будьте бдительны (тут должен быть смайлик, но суровый НЛО предупредил, что вставлять его сюда не стоит).

Автор: return

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js