[Из песочницы] Расширение для хрома: создание, публикация, опыт

В поисках новых площадок для деятельности, я обратил внимание на «виджеты» хрома, которыми пользуюсь давно, но никогда не придавал им значения. Тут же захотелось попробовать что-нибудь реализовать.

Идеей стало создание таск-менеджера для разработчика (и не только), который был бы всегда под рукой. В нем должны были отобразиться актуальные тикеты trello и jira, реквесты в gitlab и т.п. Это те вещи, которые я обычно искал, набирая ключевые слова в адресную строку браузера, типа «jira PM-20».

uk1yqzybao8vdhc0styudgtb9r0.png
Расширение для хрома

Я точно знал, что расширения в браузерах — это обычные html-странички, подпитанные js-скриптами. Но при этом не имел представления, как их создавать. Первое, что выдал мне гугл по этому вопросу — статью на medium, а не официальную документацию. Это было даже лучше, т.к. это была обзорная статья простейшего виджета от идеи до публикации.

Статья дала мне представление о том, что разработка «виджета» — дело не слишком хитрое. Я тут же приступил к созданию «hello world!».

qyur1knwe_yms0xfwkfgshzy63a.png

Оказалось, что нужно создать mainfest.json в корне проекта. Он описывает расширение: название, описание, автора, иконки, разрешения и т.п. Первую версию я сделал без изучения документации.

uiyfq5fyk9jngrs9wct5qfyf7sg.png


Первый manifest.json

Расширения позволяют запускать js-скрипты в фоне, которые делают что-то даже когда пользователь ими не пользуется. Этот функционал я пощупал очень поверхностно, просто, чтобы понять, как он может работать. Он просто менял заголовок в 

 «виджета».

Интерес для меня представляла сама страничка html, которая показывается, при нажатии на иконку в браузере, она называется popup.html в моем манифесте.

Эту страничку, кстати, можно открыть в браузере как и любой сайт, только в качестве «протокола» будет chrome-extension, например chrome-extension://id-виджета-в-webstore/popup.html. Таким образом, вы можете просмотреть исходники любого расширения, что у вас установлено.

Работает она точно так же, как и любой веб-сайт, за исключением пары возможностей, например: переходы по ссылкам работают только с target=»_blank». Есть и технические ограничения, управляемые разработчиком, например Content Security Policyили permissions к функционалу браузера, которые запрашиваются у пользователя.

После создания папки с manifest.json и popup.html внутри, можно уже запустить её как виджет. На служебной страничке хрома chrome://extensions есть кнопка Загрузить распакованное расширение. С помощью нее выбираем папку

jgnchavdydr1i6hp1ymjeawu3w4.png

и расширение тут же отображается в списке «виджетов» рядом с адресной строкой.

С этого момента расширение уже можно тестировать: изменять popup.html, и видеть изменения, переоткрыв «виджет» нажатием на его иконку.

Начнем с того, что возможность публикации первых 20 расширений стоит 5$. Происходит она в dashboard вебстора, для этого потребуется залить zip-архив содержимого папки расширения и поработать над рекламными текстами и картинками.

hiwimxrg4wexfpgqrokedvq3qnm.png

Подготовка к публикации расширения

Первая часть описания расширения будет отображаться из свойства description манифеста
расширения, остальное дописывается в Detailed description в управлении расширением на webstore.

Расширение имеет гибкие настройки публикации: можно выбрать регионы мира для публикации, а также видимость расширения.

tmuqlyxnqnmgrpm0znpaatcubru.png

Нужно помнить, что если вы выбираете для публикации только РФ, то в остальных странах расширение не появится. Я наткнулся на это находясь в Таиланде: не мог понять почему, спустя 2 дня, расширение не ищется в сторе даже по прямому названию.

Я описал необходимые шаги для публикации простейшего расширения, чтобы процесс был понятен. Теперь хочу осветить некоторые детали для написания более сложного «виджета».

qqgw_jneinomo-x5se1kxul67qk.png

Суть моего расширения в использовании чужих 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 в таком виде

obkms3gmcyih9glliorcwlcyk6y.png

Не став углубляться, я так же сделал поле для ввода токена в своем расширении и описал пользователю, как это сделать.

Правильный способ

Как обычно, хорошее решение приходит не сразу. Я на него наткнулся, когда начал интеграцию с Jira, которая имеет только Authorization Code Flow.

Как-то случайно я наткнулся на chrome.identity: функционал браузера, уже реализовавший все «костыли» для авторизации. Этот функционал требует включения identityв разрешениях манифеста. Я дополнил свой манифест: «permissions»: [«storage»,  «identity»].

Как я уже и говорил: у каждого расширения есть URL типа chrome-extension:///. Такой адрес ни для чего не годится, но chrome.identity предоставляет настоящий URL https://.chromiumapp.org/*, который можно передать в API с OAuth2 в качестве redirectUrl. API, после авторизации, отправит пользователя на него с дополнительными параметрами, будь то authCode или token, а хром их подхватит и передаст в ваш js-callback расширения.

Для этого нужно воспользоваться chrome.identity.launchWebAuthFlow (), которое открывает страницу авторизации API в новом окне:

chrome.identity.launchWebAuthFlow(
    {
        'url': JiraApi.url(),
        'interactive': true
    },
    jira.callback()
);

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

4in5ldmxa9aanys9f9oq2bwdo2u.png


Окно авторизации 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-сторона расширения сама по себе может увеличиться до больших размеров.

eik19yftcv2f-rm1uodd98dpblo.png

Моя текущая схема

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

Я попробовал контекстную рекламу и рекламу в социальных сетях. Получил небольшой опыт и нулевую конверсию. 

Контекстная реклама

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

Оказывается, что в контекстной рекламе яндекса нельзя настраивать таргетинг по устройствам и браузерам. Так что если ваше расширение только для хрома, показывать рекламу придется и людям, сидящим на других браузерах, переходы которых принесут только лишние убытки.

Я не хотел делать отдельный сайт для своего расширения, поэтому рекламировал его страницу в webstore. Минус этого подхода в том, что ты можешь доверять только статистике рекламного кабинета и не можешь увидеть как пользователи ведут себя на рекламируемой странице.

Социальные сети

Они как раз и относятся к категории сайтов, на которых десктоп это умирающее меньшинство.

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

uv8-ckxr9iw4i_znpploac-1cyy.png

На самом деле в тот день мобильные просмотры были сильно больше

Я считаю, что расширения это мощный инструмент для людей, работающих в интернете, т.к. в браузере мы проводим много времени, которое иногда хочется оптимизировать. Например виджет гугл-переводчика, переводящий текст при выделении, хороший пример оптимизации. Решение проблемы огромного количества открытых вкладок «на попозже» я тоже решил с помощью виджета.

Написание расширений дает опыт в изучении подводной части айсберга «Chrome» и написании «фронтенда» (особенно если вы бэкенд-разработчик). Расширения можно писать на том же React JS с которого можно перекинуться на написание приложений под мобильные устройства. Процесс написания и того и того очень похожий.

© Habrahabr.ru