- PVSM.RU - https://www.pvsm.ru -
Доброго времени суток.
Изначально этот пост планировался как очередной tutorial для начинающих. Но поверхностный поиск показал, что в этом смысла нет. Потому решил просто поделиться с начинающими и не очень опытом в некоторых вопросах. Это будет некий псевдо-tutorial с решениями ответами на не очевидные (для некоторых) вопросы.
Идеи в посте не претендуют на особую уникальность или новизну, но многие вопросы мне вначале самому было решить непросто. Надеюсь, кому-то мои знания принесут пользу. Всех заинтересовавшихся прошу под кат.
Я, будучи web-разработчиком, уже давно в качестве хобби увлекся расширениями. Чисто из интереса, и для решения некоторых задач. Тем более, под Chrome, наверное, их разрабатывать проще всего. Уже «заимел» достаточно опыта, потому частью его решил поделиться с вами в этом посте.
Расширения Chrome представляют собой набор обычных HTML-страниц и некоторых дополнительных файлов. Даже в popup-окне предоставляется полноценная среда HTML. Потому вопрос о возможности использования CSS и каких либо JS-фреймворков отпадает сам собой. Можно. Главное не переусердствовать, ибо на производительность это повлияет аналогичным образом (особенно, на загрузку popup).
В конфигурационных файлах используется полноценный валидный JSON. Будьте внимательны, например, с trailing commas. Ибо на эти самые запятые браузер ругается ещё на этапе сборки расширения, и отладочная информация дается криво. Я люблю писать в свободном стиле, особенно люблю эти самые запятые в конце конструкций, потому не раз уже мучился с устранением подобных ошибок.
AJAX-запросы из-под расширения кросс-доменны сами по себе без никаких танцев с бубном (да, многие знакомые разработчики, далекие от расширений, реально удивлялись и спрашивали по поводу кросс-доменности). Достаточно только прописать соответствующие разрешения в манифесте.
Кстати, что касается этих же разрешений. Как показывает практика, в зависимости от сложности расширения достаточно либо одного-двух адресов, либо лучше сразу давать доступ ко всем адресам. Особенно в расчете на последующее развитие.
Также я лично много сталкивался с вопросами работоспособности расширений под разными браузерами на движке Chromium. После перехода на манифест версии 2 сразу отпадают все браузеры ниже 18-й версии. Начиная с 18 и дальше, если не использовать какие-то особые API или HTML5, работоспособность можно почти гарантировать в любом варианте. Требования к брендовым выпускам (например, Yandex Интернет) такие же. Тот же Mail.ru не работает (до сих пор толкают 17-ю версию).
Не знаю, как обстоят дела в других браузерах, но в Chrome возможность поддержки нескольких языков заложена в сами расширения, без необходимости как-то явно указывать и обрабатывать текущую локаль. С одной стороны это удобно, с другой – для организации ручного переключения языка нужно изобретать свой велосипед.
Предложенное Google решение пусть не идеальное и не совсем удобное, но вполне работоспособное.
Для поддержки мультиязычности в папке с исходниками расширения необходимо создать папку _locales (да, именно в таком виде, с символом подчёркивания). Внутри на каждый язык создается папка, в которую добавляется единственный файл messages.json.
Содержимое файла имеет следующий вид:
"title": {
"message":"blah-blah-blah"
},
...
Заголовки выбираются свободно, главное не повторяться. Плюс, существуют пару зарезервированных заголовков. Можно объявить сообщения «appName» и «appDesc», которые потом будут так же автоматически подставляться в зависимости от локали в название и описание расширения в браузере. Для этого в манифесте нужно указать следующие параметры:
"name": "__MSG_appName__",
"description": "__MSG_appDesc__",
Также, в случае введения в расширение мультиязычности, в манифесте должен быть объявлен параметр «default_locale».
Для получения значения конкретной строки используется функция chrome.i18n.getMessage('<title>');. Для удобства её можно обернуть в две следующие функции.
function _writeMessage(a) {
document.write(_getMessage(a))
}
function _getMessage(a) {
return (chrome.i18n.getMessage(a))
}
Думаю, нет необходимости как-то подробно их объяснять. В теле HTML в нужных местах ставить, например, такие вызовы: <script>_writeMessage('title');</script>
Правда, после недавних изменений в политике безопасности расширений использование этих функций, особенно первой, стало невозможным. В процессе переделки старых расширений был изобретен следующий велосипед. Во всех местах, где надо было поставить мультиязычную строку, нужным элементам был добавлен некий класс и дополнительный атрибут, указывающий ID нужной строки. При инициализации страницы достаточно получить все такие элементы и для каждого проставить нужное содержимое. Например, так:
var m = document.getElementsByClassName('mopts');
for (var i = 0, l = m.length; i < l; i++){
m[i].innerHTML = _getMessage(m[i].getAttribute('mid'));
}
Конечно, такой вариант можно оптимизировать, расширить на проставку innerHTML и title, использовав, например, querySelector (либо тот же jQuery), но в моем случае этого предложенного варианта было достаточно.
Они же user-scripts. Для тех, кто впервые слышит (да ну?) – это пользовательские CSS-стили или JS-скрипты, которые после загрузки вставляются в тело документа для улучшений или предоставления каких-то функций. Расширения тоже могут добавлять на страницы свои скрипты.
Расширения также могут добавлять в открываемые страницы свои скрипты. При этом есть возможности по выбору момента внедрения(перед загрузкой документа, после) и выборочного внедрения в страницы (фильтр по URL).
Для добавления своих скриптов необходимо в манифесте объявить секцию «content_scripts», и для каждого скрипта добавить параметры внедрения в страницы. Детальнее об этом можно узнать в документации [1].
Есть некоторые нюансы выполнения JS-контент-скриптов. Они выполняются в окне документа, но в своем изолированном контексте. При этом есть полный доступ к DOM и к объекту window (но не к переменным и функциям страницы). Также в контексте скриптов доступна часть API chrome.extension, что позволяет полностью взаимодействовать с фоновой страницей расширения.
Что касается выполнения скриптов непосредственно в контексте страницы – никто не запрещает контент-скрипту создать объект script, вписать туда нужное содержимое и прицепить его к DOM. На базе этого даже можно реализовать взаимодействие между контент-скриптом и скриптами страницы (например, для случая, когда контент-скрипт внедряет конечный скрипт на страницу, но тот в процессе выполнения должен как-то общаться с самим расширением).
Для этого в тело документа необходимо добавить скрытый элемент (теми же методами DOM, или использовать существующий), и добавить JS-код следующего содержания:
var customEvent=document.createEvent('Event');
customEvent.initEvent('myevent',true,true);
//...
//вдруг понадобилось что-то передать или просто сделать запрос к расширению
document.getElementById('my_gateway').innerHTML = 'какие-то нужные данные';
document.getElementById('my_gateway').dispatchEvent(customEvent);
В этом коде на странице создается произвольное событие. Когда скрипту нужно как-то обратиться к расширению, в этот DIV можно записать необходимые данные и вызвать это событие.
Контент-скрипт должен подписаться на прослушку этого события на соответствующем элементе DOM.
document.getElementById('my_gateway').addEventListener('myevent', function() {
//получаем данные
var data = document.getElementById('my_gateway').innerHTML;
//выполняются необходимые действия и запросы к расширению
},false);
Решение приблизительно такого содержания предложено в официальных мануалах по разработке расширений от Google.
По монетизации расширений есть предложения [2] в официальной документации, и даже соответствующее API в Chrome Webstore. Но лично я не увидел в этом никакого смысла, исходя из того, что расширения браузер хранит в исходных кодах в своих папках. В итоге, рассматривая какую-то грань полезности расширения, либо монетизация не принесет ощутимых результатов, либо всегда найдется знающий программист, который спокойно сможет взять исходники из папок браузера и получить работающий бесплатный аналог. Да, может помочь обфускация кода, но и она не настолько эффективна. Либо её будет просто разобрать, либо потраченные силы на запутывание не будут того стоить. Более того, когда я смотрел возможность размещения платных расширений в магазине, платежи можно было принимать только в ограниченных странах (ясное дело, Россия и смежные туда не входили). Как сейчас обстоят дела – честно, не знаю.
Исходя из всего этого, я для себя решил, что лучше всего добавить кнопку добровольных пожертвований. Вариантов реализации тут масса. Взглянуть на тот же AdBlock. Решение автора мне нравится.
На этом всё. Большинство из этой информации и более того можно почерпнуть в документации (хоть, может, не так прозрачно и доходчиво). Есть ещё одна тема по поводу работы с cookies, вкладками и обработки HTTP-запросов, но этому я решил посвятить отдельный пост.
Chrome extensions: Getting strarted [3]
Описание методов API [4]
Панель разработчика [5] (именно здесь можно добавлять и публиковать свои расширения)
Справка Chrome Web Store [6]
Автор: UZER2006
Источник [7]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/javascript/28546
Ссылки в тексте:
[1] документации: http://developer.chrome.com/extensions/content_scripts.html
[2] предложения: https://developers.google.com/chrome/web-store/docs/money?hl=ru
[3] Chrome extensions: Getting strarted: http://developer.chrome.com/extensions/getstarted.html
[4] Описание методов API: http://developer.chrome.com/extensions/api_index.html
[5] Панель разработчика: https://chrome.google.com/webstore/developer/dashboard
[6] Справка Chrome Web Store: https://developers.google.com/chrome/web-store/docs/
[7] Источник: http://habrahabr.ru/post/171491/
Нажмите здесь для печати.