Pull to refresh

Пользовательский JavaScript и CSS на мобильных устройствах

Website development *CSS *JavaScript *


Хочется странного


Если вы регулярно посещаете с мобильного устройства (телефона, планшета) какие-нибудь сайты, и если у вас регулярно возникает желание изменить на них JS/CSS (но разработчикам сайтов вы по какой-то причине не сообщаете об этих желаниях), то статья вам может быть интересна.



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

Давай покрасим холодильник…


В целом, спектр возможностей видится широкий: изменение «темы» сайты, размеров отдельных элементов, исправление ошибок JS/CSS, включение спрятанных возможностей (к примеру, на VK есть HTML5 плеер, который не активен), или отключение имеющихся, вроде заботливо расставленных на сайте «ховеров», из-за которых на мобильных устройствах по ссылкам приходится тыкать два раза, и т.д. Но увы, в стандартных браузерах большей части устройств нет механизмов для реализации UserCSS или UserScript. Где-то работают букмарклеты (и я даже написал для себя около десятка), но процесс их «приготовления» нельзя назвать быстрым. В случае, если количество правок растёт (или уменьшается), постоянно править «закладурки» становится неудобно.

В общем, как это можно решить:
  • находим хостинг с Apache или nginx
  • включаем там 2 расширения: прокси и что-то, что позволит менять проходящие через прокси файлы
  • настраиваем заменялку так, чтобы она подключала к страницам нужные вам JS/CSS
  • прописываем прокси на устройстве
  • профит

У меня «хостинг» нашелся с Apache, его я и мучил.

Injection


Включить прокси на Apache несложно, сложнее оказалось с подменой контента на лету. Расширений «на рынке» несколько: mod_substitute, mod_filter, mod_sar. mod_sar я тупо не смог собрать, у mod_substitute были проблемы сначала со сжатыми страницами (пришлось собирать цепочку из фильтров распаковки-замены-упаковки, чтобы работало), потом обнаружилось что некоторые страницы он портил, причину «быстро» установить не удалось. Обновить Apache и все фильтры до последних версий (нового mod_sed, к примеру) мне не светило (ядро и либы старые в системе). В общем, остался я с mod_filter, в конфиг виртуального хоста вставил что-то вроде

ExtFilterDefine fixtext mode=output intype=text/html \
    cmd="/opt/bin/sed 's|</body>|<script src=\"/injector.js\" type=\"text/javascript\"></script></body>|i'"

ProxyRequests On
ProxyVia On

<Proxy *>
SetOutputFilter fixtext
</Proxy>

и пользовался. Файлы правил «как обычно», через SSH/mc, или в Textastic через SFTP (у меня iPad).

Содержание injector.js, пример:

function injectJS(file) {
    var head = document.getElementsByTagName('head')[0];
    var script = document.createElement('script');
    script.src = 'file';
    script.type = 'text/javascript';
    head.appendChild(script);
}

if (window.location.hostname == 'habrahabr.ru') {
    injectJS('filepath/mod-habrahabr.ru.js');
}

Вместе веселее


А потом одному стало скучно. Предлагаю желающим присоединиться к тестированию и использованию.

Сделана страница регистрации, где вы вводите свой email. От него откусывается часть до @, с этим именем создается пользователь для openssh, домашняя папка под chroot, и UserDir для Apache. На почту высылается сгенерированный пароль. В выданный shell можной зайти через SSH или SFTP, в папке htdocs лежит пример «инжектора» на JS, доступен редактор vim.

Хост для SSH/SFTP и прокси один и тот-же.

После успешной авторизации, прокси подключает ко всем страницам (к которым сможет) ваш собственный injector.js из htdocs, в чём собственно и смысл создания учёток. Ссылка на корень сайта, где якобы лежит injector.js, подменяется сервером на путь вида /~username/, откуда на самом деле и берутся файлы для подмены (JS/CSS).

Адрес страницы регистрации: http:/injector.slcontent.ru/reg/.

Хотелось бы услышать мнения относящиеся к идее как таковой, советы, отзывы по использованию.

upd1: Чтобы проверить правильность присланной вам пары логин/пароль, проще всего зайти на страницу вида
http://injector.slcontent.ru/~username/

upd2: Внутри injector.js, если кто видел, есть обращение к скрипту getlink.php. У него есть параметр ts. Если ts=1, к имени файла добавляется таймштамп, что поможет избежать «залипания», к примеру, файлов стилей в кеше при частых правках.

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

upd4: После 14 часов 29.01.2012 была недоступна страница регистрации, глупая ошибка, починил.

upd5: Примеры того, что можно «внедрить» через этот прокси (для хабра): улучшенный навигатор по комментариям, изменения в дизайне, смена favicon, если пост перенесен в черновики или даже HabrAjax.

upd6: При желании, можно настроить устройство ходить через прокси не на все сайты, а всего на пару, скажем. Используем для этого Web Proxy Auto Discovery Protocol. Собственно как уже писалось (возможно, не раз), цель этого протокола — рассказать, где искать файл с типом «application/x-ns-proxy-autoconfig», по-умолчанию — wpad.dat. Рассказывается это через DNS/DHCP или, что нужно в нашем случае, можно указать местоположение файла явно. В настройках прокси большинства устройств это пункт Auto c полем для URL. В поле нужно вписать
http://injector.slcontent.ru/wpad.dat?
со знаком вопроса в конце.

Принцип тут такой же, как с injector.js — после авторизации выполняется редирект на версию файла в папке пользователя, т.е. всеми правилами использовать/не использовать прокси рулит сам пользователь. Пример wpad.dat (собственно, это JS с зарезервированным именем функции FindProxyForURL):

function FindProxyForURL(url, host) {
    var proxy = "PROXY injector.slcontent.ru";
    var viaproxy = new Array(
			    /\.ya\.ru$/,
			    /\.yandex\.ru$/);
    for (i = 0; i < viaproxy.length; i++) {
	if (viaproxy[i].test(host)) {
	    return proxy;
        }
    }
    return "DIRECT";
}

Может даже получится использовать как блокер нежелательного контента (баннеров?), если сделать список с нужными хостами и указывать для них несуществующий прокси, 127.0.0.1, как часто в hosts прописывают.
upd7: Прошли годы, и на iOS появились Content Blockers…
Tags:
Hubs:
Total votes 22: ↑20 and ↓2 +18
Views 17K
Comments 27
Comments Comments 27

Posts