VK Memos мой личный эксперимент. Проект был создан для себя и друзей, а позже полюбился и другими.
Друзей в социальных сетях становится все больше. Трудно запомнить кто чем занимается, какими знакомствами и навыками обладает. Хочется это записать. Помечать в блокноте или «гугл-доке» не удобно: и найти не просто, да и просто лень. Так появилась идея создать блокнот, встроенный в сам сайт социальной сети, где каждая страница — заметка, привязана к одному человеку. Если ты не сотрудник Вконтакте, то единственный способ это сделать — инжектировать свой код в на уже открытую страницу в браузере. Автоматически и незаметно для пользователя это могут делать плагины для браузера. VKMemos — блокнот личных заметок во Вконтакте, созданный как плагин для браузеров Google Chrome и Opera.
Создавая плагин, я столкнулся с рядом тупиков. Эта статья посвящена проблемам и тому как их избегать. Будет полезна разработчикам плагинов для браузеров и приложений для Вконтакте.
Плагин для браузера это архив с html, js, ccs-файлами, картинками и файлом манифеста, который описывает сам плагин и его ограничения. Архив загружается в магазин плагинов браузера, из которого устанавливается пользователями одним кликом. VKMemos следит за открытыми вкладками в браузере. Когда открывается страница с домена vk.com, он встраивает свой код в страницу, дополняя её возможности. Плагин создает текстовые поля для ввода заметок на странице списка друзей, в переписках и на личных страницах других пользователей, обеспечивает загрузку и сохранение заметок, добавляет поле поиска друзей по заметкам.
Найденная ошибка или сделанное улучшение требует повторной сборки архива, изменения файла манифеста, загрузки в магазин, а от пользователей — обновления. Пришла идея сделать плагин в виде минимального загрузчика, который загружает файл настоящего плагина с сервера и встраивает его в страницу Вконтакте. Таким образом обновление плагина сводится к замене файла на сервере, без необходимости пересобрать архив, а пользователям обновляться, ведь загрузчик не меняется. Особенно это удобно на этапе разработки и тестирования. Также подойдет, если требуется отдавать разные версии разным пользователям. Эту модель работы одобрил Google Chrome, а вот Opera запретила по политике безопасности.
В социальных сетях мы сидим с разных компьютеров. Глупо было бы иметь доступ к заметкам только с одного из них, хочется видеть заметки на каждом устройстве. Единственный способ это сделать — хранить заметки на сервере, а плагин научить узнавать пользователя. Находясь на странице Вконтакте, пользователь уже авторизован, достаточно узнать кто именно. Для этого плагин VKMemos использует библиотеку API Вконтакте. Авторизация в плагине привязана к авторизации Вконтакте.
Для использования API Вконтакте требуется создать приложение. Каждое приложение получает секретный ключ. При первом запуске плагина у пользователя возникает всплывающее окно Вконтакте запрашивающее разрешение. Пользователю достаточно дать согласие без ввода каких-либо данных. При этом в браузере библиотека Вконтакте формирует хеш-код на основе данных пользователя и секретного ключа приложения. Каждый запрос к серверу подписывается этим хеш-кодом. Сервер проверяет запросы на достоверность воссоздавая хеш-кода на своей стороне и сравнивая с полученным. Чтобы подделать код нужно знать данные пользователя и секретный ключ, известный только разработчику приложения.
Заметки хранятся на сервере и привязаны к пользователю Вконтакте. Для скорости работы плагина при запуске скачивает все заметки и позже отображает их не с сервера, а локально. Сохранение заметок всегда происходит на сервер. Если открыть несколько вкладок, то изменение заметок в одной из них приведет к сохранению их на сервере, но не приведет к обновлению заметок с сервера на других вкладках. Чтобы синхронизировать работу нескольких вкладок, заметки хранятся не в локальной переменной, а в общем для браузера локальном хранилище (localstorage). Изменение заметки в одной вкладке вызывает событие, которое получают другие вкладки, обновляя заметку.
Однако событие изменения локального хранилища не работает на страницах Вконтакте. В ходе изучения оказалось, что Вконтакте перехватывает это события для внутренней работы. Событие изменения локального хранилища согласно стандарту срабатывает во всех других вкладках за исключением той, в которой было вызвано. Видимо, Вконтакте надо было получать это событие и в исходной вкладке. Для этого они создали специальный iframe с перехватчиком события и сделали обмен данными через события Message. Было найдено два решения: подменить их подписку на копию с добавленным своим кодом, либо подписаться на событие Message. Второе безопаснее с точки зрения изменения кода Вконтактом в будущем.
Начиная с 15-й версии Opera перешла на движок Chrome. Сейчас существует две активные ветки браузеров Opera: версия 12+, основанная на собственном старом движке, и новая. Плагины для них создаются по разному, но общий принцип похож на плагины для Google. Плагины Opera имеют более строгие ограничения по безопасности и доступу к странице. Плагинам запрещается загружать какой-либо код со сторонних ресурсов. Все файлы должны быть включены в архив плагина, даже библиотека API Вконтакте. Это затрудняет разработку и обновление плагина. Обойти это не удалось. Проверка плагина на право размещения в магазине проводится модераторами в течении пары дней. Плагин утвердили с 8-й попытки, когда были перепробованы все возможные пути обхода.
Встроенные на страницу скрипты, не имеют прямого доступа к глобальным переменным и данным исходной страницы. Обращения возможны только через ссылку на объект window. Для работы библиотеки API Вконтакте потребовалось переписать обращения к переменным. Модераторы отказывались размещать плагин в магазине, так как встроенная публичная библиотека Вконтакте была изменена. Вопрос удалось решить только после недельной переписки. Ребята очень строго подходят к проверке.
Попробовать плагин вы можете установив его. Ссылка на установщик есть на сайте проекта.
Виктор Никитин