Оранжевый - новый синий: Как портировать chrome extension в...
TRANSCRIPT
Оранжевый - новый синий
Как портировать Chrome Extension в Firefox Extension
или написать кросс-браузерное расширение с нуля
Борис Мосуновfacebook.com/mossounov
linkedin.com/in/borismossounovanotherguru.me
Основные отличия архитектуры:Chrome Extension v.s. Firefox Addon
Документация для разработчика
https://developer.chrome.com/extensionshttps://developer.mozilla.org/en-US/Add-ons
Изучая документацию Mozilla можно наткнуться на:Legacy Extensions Overlay extensions
Restartless Extensions Bootstrapped ExtensionsAdd-on SDK Extensions
Jetpack SDK Add-on SDK
==
=
Краткая история Firefox Addon:
Legacy Extensions / Overlay Extensions (XUL, JSM, XPCOM)
2004.06 - Firefox 0.9
Краткая история Firefox Addon:
Legacy Extensions / Overlay Extensions (XUL, JSM, XPCOM)
2004.06 - Firefox 0.9
Краткая история Firefox Addon:
Legacy Extensions / Overlay Extensions (XUL, JSM, XPCOM)
2004.06 - Firefox 0.9
browser.xul:
overlay.xul:
Краткая история Firefox Addon:
Legacy Extensions / Overlay Extensions (XUL, JSM, XPCOM)
2004.06 - Firefox 0.9
Mozilla starts Jetpack SDK project2009.09
Краткая история Firefox Addon:
Legacy Extensions / Overlay Extensions (XUL, JSM, XPCOM)
2004.06 - Firefox 0.9
Mozilla starts Jetpack SDK project2009.09
Restartless Extensions / Bootstrapped Extensions2011.03 - Firefox 4+
Jetpack SDK 0.1 releaseAddon SDK extensionscfx tool (python powered)
2011.06
jpm tool (node.js powered)2015.05 - Firefox 38
Краткая история Chrome Extension:
Chrome стал поддерживать расширения2009.09
Запущен Google Chrome Store с блэкджеком и расширениями
2010.12
Краткая история:2004.06 - Firefox 0.9
2009.09
2011.03 - Firefox 4+
2011.06
2015.05 - Firefox 38
2010.12
Chrome стал поддерживать расширения
Legacy Extensions / Overlay Extensions (XUL, JSM, XPCOM)addons.mozilla.org
Mozilla starts Jetpack SDK project
Restartless Extensions / Bootstrapped Extensions
Jetpack SDK 0.1 releaseAddon SDK extensionscfx tool (python powered)
jpm tool (node.js powered)
Запущен Google Chrome Store с блэкджеком и расширениями
Изучая документацию Mozilla нужно читать про:Legacy Extensions Overlay extensions
Restartless Extensions Bootstrapped ExtensionsAdd-on SDK Extensions
Jetpack SDK Add-on SDK
==
=
Из чего состоит среднестатистическое браузерное расширение?
manifest
background script
content scripts, styles, assets
toolbar button popup
locales
embedded pages(options / help)
Основное и самое главное отличие Chrome Extension и Firefox Addon
состоит в способах взаимодействия javascript сценариев из 3 блоков:
background.js
contentscript.js popup.js
В Google Chrome целых два API обмена сообщениями:
• Simple one-time requests• Long-lived connections
https://developer.chrome.com/extensions/messaging
Simple one-time requests
chrome.runtime.sendMessage({greeting: «hello»}, function(response) {
console.log(response.farewell);});
background.js
contentscript.js popup.js
chrome.tabs.sendMessage(tabs[0].id, {greeting: «hello»}, function(response) {console.log(response.farewell);});
background.js
contentscript.js
chrome.runtime.onMessage.addListener( function(request, sender, callback) { console.log(sender.tab ? "from a content script:" +
sender.tab.url : "from the extension"); if (request.greeting ==
"hello") callback({farewell:
"goodbye"}); });
background.js
contentscript.js popup.js
?
Long-lived connections
port.postMessage({joke: "Knock knock»});
port.onMessage.addListener(function(msg) { if (msg.question == "Who's there?"){ port.postMessage({answer: "#4front"}); }});
background.js
contentscript.js popup.js
Window chrome.extension.getBackgroundPage()
background.js
contentscript.js popup.js
contentscript.js и popup.js могут:
Нужна кросс-браузерность?
Если да, то не стоит.Если нет, то можно.
background.js
contentscript.js popup.js
• есть два разных API обмена сообщениями
• contentscript.js и popup.js могут получить background window и сохранить там объект с методами
• все могут обмениваться безымянными сообщениями, задавая колбек для ответа.
• background.js ничего не знает об остальных, пока они к нему не подключатся
А что там у Firefox?
https://developer.mozilla.org/en-US/Add-ons/SDK/Guides/Content_Scripts/using_port
port.emit("myMessage", msg);
port.on("myMessage",function(msg) { if (msg.question == "Who's there?") port.emit("myMessage.reply", {
answer: "#4front"});});
background.js
contentscript.js popup.js
background.js
contentscript.js popup.js
• все могут обмениваться именованными сообщениями без колбэков
• background.js создает contentscript.js и popup.js и может ими управлять.
callbacks = {«1234»:
function(payload){},«1235»:
function(payload){}
}
message = {action:
«myMessage.reply»,uid: 1234,paylaod: {}}
message = {}
message = {action:
«myMessage»,paylaod: {}}
message = {action:
«myMessage»,uid: 1234,paylaod: {}}
Разберем отличия Mozilla Extension и Chrome Extensionпо составляющим
manifest
background script
content scripts, styles, assets
toolbar button popup
locales
embedded pages(options / help)
manifest
manifest.jsonописывает:• название,
описание, версия, лицензия,
• расположение всех компонентов,
• права доступа расширения
package.jsonописывает:• название, описание,
версия, лицензия,• расположение
background script
а background scriptподгружает все компоненты
manifest
Как сделать кросс-браузерно:
Настроить grunt task, который будет синхронизировать общие поля в manifest.json и package.json (версию, название, описание…)
• Виртуальная html страница со своим window js-объектом,
• этот window выполняется в одном контексте content script и popup script, примерно как iframe
• Отдельный JavaScript, без window.
• выполняется в отдельном от остальных контексте
• Из него подгружаются content scripts, styles, popup, etc.
• EcmaScript 6
background script
Как сделать кросс-браузерно:
1. Вообще не пользоваться chrome.extension.getBackgroundPage()
2. Для firefox - отдельный background script поскольку все firefox addon sdk на ES6.
3. Написать прослойку - систему обмена с content-script и popup script именованными сообщениями c колбеками который использовать и там и там
4. Заранее разделять скрипты для background и content scripts, вплоть до клиент-серверной архитектуры.
background script
• выполняются в изолированном мире веб-страницы
• можно получить доступ к background window
• кросс-доменные запросы в рамках прав доступа
• выполняются в изолированном мире веб-страницы
• выполняются в контексте изолированном от background script
• кросс-доменные запросы запрещены
content scripts, styles, assets
Как сделать кросс-браузерно:
1. Вообще не пользоваться chrome.extension.getBackgroundPage()
2. Написать прослойку - систему обмена с content-script и popup script именованными сообщениями c колбеками который использовать и там и там
3. Заранее разделять скрипты для background и content scripts, вплоть до клиент-серверной архитектуры.
4. Для ajax запросов в firefox использовать Request на стороне background и вышеупомянутую систему обмена сообщениями с колбеками
content scripts, styles, assets
• кнопка может быть только одна
• можно получить доступ к background window
• попап загружается по клику на кнопку и выгружается после закрытия
• javascript подгружается через тег <script>
• размер попапа вычисляется автоматически
• кнопок может быть несколько
• контекст изолирован от background script
• попап загружается при старте экстеншена и остается в памяти
• скрипты надо подгружать как контент скрипты
• размер попапа задается вручную
toolbar button popup
Как сделать кросс-браузерно:
1. Вообще не пользоваться chrome.extension.getBackgroundPage()2. Считать, что кнопка на тулбаре может быть только одна.3. Писать popup script так, словно он загружается один раз и
выгружается при закрытии браузера (отключении экстеншена), при этом popup должен реагировать на события экстеншена и, а не рендериться один раз.
4. При этом помнить, что все же в разных браузерах он загружается в разное время.
5. В firefox скрипты подгружать через content scripts, а <script> блокировать (https://developer.mozilla.org/en-US/Add-ons/SDK/Tutorials/Display_a_Popup).
toolbar button popup
Формат: .json
доступны из:• background script• content script• popup script
Формат: .properties
доступны из:• только background
script, который может передать остальным
• в popup.html можно использовать идентификаторы
locales
Как сделать кросс-браузерно:
1. Выбрать один из форматов как основной (json).2. Использовать в firefox файлы .properties только для хранения идентификатора языка.3. В Firefox Запрашивать из content script и popup script весь словарь сразу, который background считывает из json. Или передавать словарь при инициализации контент и попап скриптов в конфиге.
locales
Как собрать экстеншен
npm install -g yonpm install -g generator-chrome-extensionnpm install -g generator-firefox-extensionnpm install -g jpm
Как собрать?yo chrome-extension yo firefox-extension
Основное отличие:background scripts - в /libвсе остальное - в /data
Cделаем единообразноyo chrome-extension yo firefox-extension
Сводим воединоyo chrome-extension yo firefox-extension
.gitignore
.gitignore
1. Объединяем в проект
app-chromeapp-firefox
2. grunt copy:app-chrome/scripts/bg-* ->
app-firefox/libвсе остальное ->
app-firefox/data
3. добавляем в .gitignore
app-firefox/libapp-firefox/data
Сводим воединоyo chrome-extension yo firefox-extension
или…
просто все сводим все к структуре папок firefox и обновляем manifest.json.
en-US.properties содержит одну строку:
lng= en
это служит только для определения локали,а национализированные строки подгружаются из .json
в bg-main-firefox
locales
и последнее…
generator-firefox-extension использует для сборки утилиту cfx, запуская ее через shell
утилита cfx устарела и ее надо заменить на утилиту jpm
но это не сложно
cfx syntax
jpm syntax
не забыть добавить:cd app-firefox
Как сделать кросс-браузерно:• Для генерации пустого проекта использовать yeoman генераторы: generator-chrome-
extension и generator-firefox-extension. Заменить cfx на jpm.• Свести всю базу кода в один проект и настроить grunt build.• Настроить grunt task, который будет синхронизировать общие поля в manifest.json и
package.json (версию, название, описание…).• Сделать прослойку адаптер, которая будет использовать api того браузера, в котором
запущено расширение.• Реализовать кросс-браузерный механизм обмена именованных сообщений с колбеками.• Вообще не пользоваться chrome.extension.getBackgroundPage()• Сделать два отдельных background script для Chrome и Firefox.• Заранее разделять скрипты для background и content scripts, вплоть до клиент-серверной
архитектуры.• Для ajax запросов в firefox использовать Request на стороне background и
вышеупомянутую систему обмена сообщениями с колбеками, для Chrome - jQuery.ajax отлично подойдет.
• Считать, что кнопка на тулбаре может быть только одна.• Писать popup script так, словно он загружается один раз и выгружается при закрытии
браузера (отключении экстеншена). Другими словами popup должен подписываться на события экстеншена и реагировать на них, а не рендериться один раз. При этом помнить, что все же в разных браузерах он загружается в разное время.
• В firefox popup скрипты подгружать через content scripts, а <script> блокировать.• Локали хранить в формате Chrome - json. В firefox использовать файлы .properties только
для хранения идентификатора языка и запрашивать из content script и popup script весь словарь сразу, который background считывает из json.
manifestbackground scriptcontent scripts, styles, assets
toolbar button popupвсе вместе
А стоит ли оно того?
Использование браузеров в РФ
Использование браузеров в МИРЕ
Чтобы реализовать экстеншен, подобный по функционалу на Chrome Extension или Firefox
Extension, необходимо писать на C#, так что про кросс-браузерность здесь можно забыть.
Google Chrome = Webkit = Opera = Yandex Browser, и т.д.
Apple Safari - это почти Webkit.
К слову сказать:
А что там у Safari?
Таким образом, если следовать описанным здесь рекомендациям, вы получите
расширение совместимое со всеми основными браузерами, не считая IE
Вопросы?