В поисках новых площадок для деятельности, я обратил внимание на "виджеты" хрома, которыми пользуюсь давно, но никогда не придавал им значения. Тут же захотелось попробовать что-нибудь реализовать.
Идеей стало создание таск-менеджера для разработчика (и не только), который был бы всегда под рукой. В нем должны были отобразиться актуальные тикеты trello и jira, реквесты в gitlab и т.п. Это те вещи, которые я обычно искал, набирая ключевые слова в адресную строку браузера, типа "jira PM-20".
Расширение для хрома
Я точно знал, что расширения в браузерах — это обычные html-странички, подпитанные js-скриптами. Но при этом не имел представления, как их создавать. Первое, что выдал мне гугл по этому вопросу — статью на medium, а не официальную документацию. Это было даже лучше, т.к. это была обзорная статья простейшего виджета от идеи до публикации.
Статья дала мне представление о том, что разработка "виджета" — дело не слишком хитрое. Я тут же приступил к созданию "hello world!".
Оказалось, что нужно создать mainfest.json в корне проекта. Он описывает расширение: название, описание, автора, иконки, разрешения и т.п. Первую версию я сделал без изучения документации.
Первый manifest.json
Расширения позволяют запускать js-скрипты в фоне, которые делают что-то даже когда пользователь ими не пользуется. Этот функционал я пощупал очень поверхностно, просто, чтобы понять, как он может работать. Он просто менял заголовок в <h1> "виджета".
Интерес для меня представляла сама страничка html, которая показывается, при нажатии на иконку в браузере, она называется popup.html в моем манифесте.
Эту страничку, кстати, можно открыть в браузере как и любой сайт, только в качестве "протокола" будет chrome-extension, например chrome-extension://id-виджета-в-webstore/popup.html. Таким образом, вы можете просмотреть исходники любого расширения, что у вас установлено.
Работает она точно так же, как и любой веб-сайт, за исключением пары возможностей, например: переходы по ссылкам работают только с target="_blank". Есть и технические ограничения, управляемые разработчиком, например Content Security Policyили permissions к функционалу браузера, которые запрашиваются у пользователя.
После создания папки с manifest.json и popup.html внутри, можно уже запустить её как виджет. На служебной страничке хрома chrome://extensions есть кнопка Загрузить распакованное расширение. С помощью нее выбираем папку
и расширение тут же отображается в списке “виджетов” рядом с адресной строкой.
С этого момента расширение уже можно тестировать: изменять popup.html, и видеть изменения, переоткрыв “виджет” нажатием на его иконку.
Начнем с того, что возможность публикации первых 20 расширений стоит 5$. Происходит она в dashboard вебстора, для этого потребуется залить zip-архив содержимого папки расширения и поработать над рекламными текстами и картинками.
Подготовка к публикации расширения
Первая часть описания расширения будет отображаться из свойства description манифеста
расширения, остальное дописывается в Detailed description в управлении расширением на webstore.
Расширение имеет гибкие настройки публикации: можно выбрать регионы мира для публикации, а также видимость расширения.
Нужно помнить, что если вы выбираете для публикации только РФ, то в остальных странах расширение не появится. Я наткнулся на это находясь в Таиланде: не мог понять почему, спустя 2 дня, расширение не ищется в сторе даже по прямому названию.
Я описал необходимые шаги для публикации простейшего расширения, чтобы процесс был понятен. Теперь хочу осветить некоторые детали для написания более сложного “виджета“.
Суть моего расширения в использовании чужих API для получения информации. Для этого мне нужен как минимум localStorage, чтобы запоминать токены авторизации.
Я воспользовался "permissions": ["storage"] в своем манифесте.
OAuth2
В большинстве случаев разработчики API предлагают OAuth2 протокол для авторизации.
Если вы не знакомы с этим протоколом: он предлагает безопасный процесс аутентификации и авторизации приложения от лица пользователя без доступа к логину/паролю со стороны этого приложения.
Протокол описывает несколько способов для авторизации. В идеале нужно использовать Authorization Code Flow, которое предполагает наличие бэкенда у приложения; API редиректит пользователя с Auth-кодом на приложение, а приложение на бэкенде обменивает его на токен.
Есть также упрощенный Implicit Flow, позволяющий авторизовываться без бэкенда: API после авторизации редиректит пользователя на приложение с токеном в URL.
Как же пользоваться этой “редиректной” авторизацией в расширении хрома? Заводить веб-сайт? Оказывается, что не обязательно.
Мои костыли
Изначально я взялся интегрироваться с Gitlalb и Trello. С Gitlab все оказалось “просто”: отправляешь пользователя в админку к его Gitlab, чтобы он сделал токен и передал его тебе. С таким подходом долго возиться не пришлось, я просто сделал поле для ввода токена и описал как его получить.
Trello же предоставил OAuth2, я сразу же заметил, что в нем есть implicit flow, но немного странный: токен отображается на их странице /approve в таком виде
Не став углубляться, я так же сделал поле для ввода токена в своем расширении и описал пользователю, как это сделать.
Правильный способ
Как обычно, хорошее решение приходит не сразу. Я на него наткнулся, когда начал интеграцию с Jira, которая имеет только Authorization Code Flow.
Как-то случайно я наткнулся на chrome.identity: функционал браузера, уже реализовавший все “костыли” для авторизации. Этот функционал требует включения identityв разрешениях манифеста. Я дополнил свой манифест: "permissions": ["storage", "identity"].
Как я уже и говорил: у каждого расширения есть URL типа chrome-extension://<id>/. Такой адрес ни для чего не годится, но chrome.identity предоставляет настоящий URL https://<app-id>.chromiumapp.org/*, который можно передать в API с OAuth2 в качестве redirectUrl. API, после авторизации, отправит пользователя на него с дополнительными параметрами, будь то authCode или token, а хром их подхватит и передаст в ваш js-callback расширения.
Для этого нужно воспользоваться chrome.identity.launchWebAuthFlow(), которое открывает страницу авторизации API в новом окне:
chrome.identity.launchWebAuthFlow(
{
'url': JiraApi.url(),
'interactive': true
},
jira.callback()
);
Сразу же скажу: это окно выглядит не совсем как окно основного браузера, что у меня вызвало бы вопросы, будь я обычным пользователем, т.к. оно похоже на какой-то фишинговый блок, а не окно. Может быть это только мое восприятие, может быть так только в моей операционке.
Окно авторизации chrome.identity.launchWebAuthFlow
Другие опции
Когда появляется идея реализовать какой-либо функционал, рекомендую гуглить chrome API, т.к. в нем уже достаточно много подобных фич, которые облегчат вам работу. Например полный manifest.json впечатляет:
{
// Required
"app": {
"background": {
// Optional
"scripts": ["background.js"]
}
},
"manifest_version": 2,
"name": "My App",
"version": "versionString",
// Recommended
"default_locale": "en",
"description": "A plain text description",
"icons": {...},
// Optional
"action_handlers": ["new_note"],
"author": ...,
"automation": ...,
"bluetooth": {
"uuids": ["1105", "1006"]
},
"commands": {...},
"current_locale": ...,
"event_rules": [{...}],
"externally_connectable": {
"matches": ["*://*.example.com/*"]
},
"file_handlers": {...},
"file_system_provider_capabilities": {
"configurable": true,
"multiple_mounts": true,
"source": "network"
},
"import": [{"id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}],
"key": "publicKey",
"kiosk": {
"always_update": ...,
"required_platform_version": ...
},
"kiosk_enabled": true,
"kiosk_only": true,
"kiosk_secondary_apps": ...,
"minimum_chrome_version": "versionString",
"nacl_modules": [...],
"oauth2": ...,
"offline_enabled": true,
"optional_permissions": ["tabs"],
"permissions": ["tabs"],
"platforms": ...,
"requirements": {...},
"sandbox": [...],
"short_name": "Short Name",
"signature": ...,
"sockets": {
"tcp": {
"connect": "*"
},
"udp": {
"send": "*"
}
},
"storage": {
"managed_schema": "schema.json"
},
"system_indicator": ...,
"update_url": "http://path/to/updateInfo.xml",
"url_handlers": {...},
"usb_printers": {
"filters": [...]
},
"version_name": "aString",
"webview": {...}
}
Предварительно разбираться со всеми возможностями может оказаться слишком расточительным, т.к. их огромное количество.
К тому же только js-сторона расширения сама по себе может увеличиться до больших размеров.
Моя текущая схема
Немного стоит упомянуть продвижение своего расширения. Особенностью “виджетов” является то, что они направлены на пользователей десктопов, которые в последние годы успели стать меньшинством.
Я попробовал контекстную рекламу и рекламу в социальных сетях. Получил небольшой опыт и нулевую конверсию.
Контекстная реклама
Мой опыт пока ограничился одной площадкой, не могу говорить за остальные, но думаю, там то же самое.
Оказывается, что в контекстной рекламе яндекса нельзя настраивать таргетинг по устройствам и браузерам. Так что если ваше расширение только для хрома, показывать рекламу придется и людям, сидящим на других браузерах, переходы которых принесут только лишние убытки.
Я не хотел делать отдельный сайт для своего расширения, поэтому рекламировал его страницу в webstore. Минус этого подхода в том, что ты можешь доверять только статистике рекламного кабинета и не можешь увидеть как пользователи ведут себя на рекламируемой странице.
Социальные сети
Они как раз и относятся к категории сайтов, на которых десктоп это умирающее меньшинство.
Вконтакте предоставляет таргетинг на мобильную и полную версию своего сайта. Но эта галочка скрыта в самом конце настроек, лично я ее не заметил до того, как слил бюджет и увидел в статистике печальный охват
На самом деле в тот день мобильные просмотры были сильно больше
Я считаю, что расширения это мощный инструмент для людей, работающих в интернете, т.к. в браузере мы проводим много времени, которое иногда хочется оптимизировать. Например виджет гугл-переводчика, переводящий текст при выделении, хороший пример оптимизации. Решение проблемы огромного количества открытых вкладок “на попозже” я тоже решил с помощью виджета.
Написание расширений дает опыт в изучении подводной части айсберга “Chrome” и написании “фронтенда” (особенно если вы бэкенд-разработчик). Расширения можно писать на том же React JS с которого можно перекинуться на написание приложений под мобильные устройства. Процесс написания и того и того очень похожий.
Комментариев нет:
Отправить комментарий