Оранжевый - новый синий
Как портировать Chrome Extension в Firefox Extension
или написать кросс-браузерное расширение с нуля
Борис Мосунов
facebook.com/mossounov
linkedin.com/in/borismossounov
anotherguru.me
Основные отличия архитектуры:
Chrome Extension v.s. Firefox Addon
Документация для разработчика
https://developer.chrome.com/extensions https://developer.mozilla.org/en-US/Add-ons
Изучая документацию Mozilla можно наткнуться на:
Legacy Extensions Overlay extensions
Restartless Extensions Bootstrapped Extensions
Add-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 project
2009.09
Краткая история Firefox Addon:
Legacy Extensions / Overlay Extensions
(XUL, JSM, XPCOM)
2004.06 - Firefox 0.9
Mozilla starts Jetpack SDK project
2009.09
Restartless Extensions / Bootstrapped Extensions
2011.03 - Firefox 4+
Jetpack SDK 0.1 release
Addon SDK extensions
cfx 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 release
Addon SDK extensions
cfx tool (python powered)
jpm tool (node.js powered)
Запущен Google Chrome Store с блэкджеком и расширениями
Изучая документацию Mozilla нужно читать про:
Legacy Extensions Overlay extensions
Restartless Extensions Bootstrapped Extensions
Add-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?
eloper.mozilla.org/en-US/Add-ons/SDK/Guides/Content_Scripts/u
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 yo
npm install -g generator-chrome-extension
npm install -g generator-firefox-extension
npm 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-chrome
app-firefox
2. grunt copy:
app-chrome/scripts/bg-* -> app-firefox/lib
все остальное -> app-firefox/data
3. добавляем в .gitignore
app-firefox/lib
app-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 script
content scripts,
styles, assets
toolbar button
popup
все вместе
А стоит ли оно того?
Использование браузеров в РФ
Использование браузеров в МИРЕ
Чтобы реализовать экстеншен, подобный по
функционалу на Chrome Extension или Firefox Extension,
необходимо писать на C#, так что про кросс-
браузерность здесь можно забыть.
Google Chrome = Webkit = Opera = Yandex Browser, и т.д.
Apple Safari - это почти Webkit.
К слову сказать:
А что там у Safari?
Таким образом, если следовать описанным здесь
рекомендациям, вы получите расширение
совместимое со всеми основными браузерами,
не считая IE
Вопросы?

Оранжевый - новый синий: Как портировать Chrome Extension в Firefox Extension

  • 1.
    Оранжевый - новыйсиний Как портировать Chrome Extension в Firefox Extension или написать кросс-браузерное расширение с нуля Борис Мосунов facebook.com/mossounov linkedin.com/in/borismossounov anotherguru.me
  • 2.
  • 3.
  • 4.
    Изучая документацию Mozillaможно наткнуться на: Legacy Extensions Overlay extensions Restartless Extensions Bootstrapped Extensions Add-on SDK Extensions Jetpack SDK Add-on SDK = = =
  • 5.
    Краткая история FirefoxAddon: Legacy Extensions / Overlay Extensions (XUL, JSM, XPCOM) 2004.06 - Firefox 0.9
  • 6.
    Краткая история FirefoxAddon: Legacy Extensions / Overlay Extensions (XUL, JSM, XPCOM) 2004.06 - Firefox 0.9
  • 7.
    Краткая история FirefoxAddon: Legacy Extensions / Overlay Extensions (XUL, JSM, XPCOM) 2004.06 - Firefox 0.9 browser.xul: overlay.xul:
  • 8.
    Краткая история FirefoxAddon: Legacy Extensions / Overlay Extensions (XUL, JSM, XPCOM) 2004.06 - Firefox 0.9 Mozilla starts Jetpack SDK project 2009.09
  • 10.
    Краткая история FirefoxAddon: Legacy Extensions / Overlay Extensions (XUL, JSM, XPCOM) 2004.06 - Firefox 0.9 Mozilla starts Jetpack SDK project 2009.09 Restartless Extensions / Bootstrapped Extensions 2011.03 - Firefox 4+ Jetpack SDK 0.1 release Addon SDK extensions cfx tool (python powered) 2011.06 jpm tool (node.js powered) 2015.05 - Firefox 38
  • 11.
    Краткая история ChromeExtension: Chrome стал поддерживать расширения 2009.09 Запущен Google Chrome Store с блэкджеком и расширениями 2010.12
  • 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 release Addon SDK extensions cfx tool (python powered) jpm tool (node.js powered) Запущен Google Chrome Store с блэкджеком и расширениями
  • 13.
    Изучая документацию Mozillaнужно читать про: Legacy Extensions Overlay extensions Restartless Extensions Bootstrapped Extensions Add-on SDK Extensions Jetpack SDK Add-on SDK = = =
  • 14.
    Из чего состоитсреднестатистическое браузерное расширение? manifest background script content scripts, styles, assets toolbar button popup locales embedded pages (options / help)
  • 15.
    Основное и самоеглавное отличие Chrome Extension и Firefox Addon состоит в способах взаимодействия javascript сценариев из 3 блоков: background.js contentscript.js popup.js
  • 16.
    В Google Chromeцелых два API обмена сообщениями: • Simple one-time requests • Long-lived connections https://developer.chrome.com/extensions/messaging
  • 17.
  • 18.
    chrome.runtime.sendMessage({ greeting: «hello» }, function(response){ console.log(response.farewell); }); background.js contentscript.js popup.js
  • 19.
    chrome.tabs.sendMessage(tabs[0].id, { greeting: «hello» },function(response) { console.log(response.farewell); }); background.js contentscript.js
  • 20.
    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 ?
  • 21.
  • 22.
    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
  • 23.
    Window chrome.extension.getBackgroundPage() background.js contentscript.js popup.js contentscript.jsи popup.js могут: Нужна кросс-браузерность? Если да, то не стоит. Если нет, то можно.
  • 24.
    background.js contentscript.js popup.js • естьдва разных API обмена сообщениями • contentscript.js и popup.js могут получить background window и сохранить там объект с методами • все могут обмениваться безымянными сообщениями, задавая колбек для ответа. • background.js ничего не знает об остальных, пока они к нему не подключатся
  • 25.
    А что таму Firefox? eloper.mozilla.org/en-US/Add-ons/SDK/Guides/Content_Scripts/u
  • 26.
    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
  • 28.
    background.js contentscript.js popup.js • всемогут обмениваться именованными сообщениями без колбэков • background.js создает contentscript.js и popup.js и может ими управлять.
  • 29.
    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: {} }
  • 30.
    Разберем отличия MozillaExtension и Chrome Extension по составляющим manifest background script content scripts, styles, assets toolbar button popup locales embedded pages (options / help)
  • 31.
    manifest manifest.json описывает: • название, описание, версия,лицензия, • расположение всех компонентов, • права доступа расширения package.json описывает: • название, описание, версия, лицензия, • расположение background script а background script подгружает все компоненты
  • 32.
    manifest Как сделать кросс-браузерно: Настроитьgrunt task, который будет синхронизировать общие поля в manifest.json и package.json (версию, название, описание…)
  • 33.
    • Виртуальная html страницасо своим window js-объектом, • этот window выполняется в одном контексте content script и popup script, примерно как iframe • Отдельный JavaScript, без window. • выполняется в отдельном от остальных контексте • Из него подгружаются content scripts, styles, popup, etc. • EcmaScript 6 background script
  • 34.
    Как сделать кросс-браузерно: 1.Вообще не пользоваться chrome.extension.getBackgroundPage() 2. Для firefox - отдельный background script поскольку все firefox addon sdk на ES6. 3. Написать прослойку - систему обмена с content-script и popup script именованными сообщениями c колбеками который использовать и там и там 4. Заранее разделять скрипты для background и content scripts, вплоть до клиент-серверной архитектуры. background script
  • 35.
    • выполняются в изолированноммире веб-страницы • можно получить доступ к background window • кросс-доменные запросы в рамках прав доступа • выполняются в изолированном мире веб-страницы • выполняются в контексте изолированном от background script • кросс-доменные запросы запрещены content scripts, styles, assets
  • 36.
    Как сделать кросс-браузерно: 1.Вообще не пользоваться chrome.extension.getBackgroundPage() 2. Написать прослойку - систему обмена с content-script и popup script именованными сообщениями c колбеками который использовать и там и там 3. Заранее разделять скрипты для background и content scripts, вплоть до клиент-серверной архитектуры. 4. Для ajax запросов в firefox использовать Request на стороне background и вышеупомянутую систему обмена сообщениями с колбеками content scripts, styles, assets
  • 37.
    • кнопка можетбыть только одна • можно получить доступ к background window • попап загружается по клику на кнопку и выгружается после закрытия • javascript подгружается через тег <script> • размер попапа вычисляется автоматически • кнопок может быть несколько • контекст изолирован от background script • попап загружается при старте экстеншена и остается в памяти • скрипты надо подгружать как контент скрипты • размер попапа задается вручную toolbar button popup
  • 38.
    Как сделать кросс-браузерно: 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
  • 39.
    Формат: .json доступны из: •background script • content script • popup script Формат: .properties доступны из: • только background script, который может передать остальным • в popup.html можно использовать идентификаторы locales
  • 40.
    Как сделать кросс-браузерно: 1.Выбрать один из форматов как основной (json). 2. Использовать в firefox файлы .properties только для хранения идентификатора языка. 3. В Firefox Запрашивать из content script и popup script весь словарь сразу, который background считывает из json. Или передавать словарь при инициализации контент и попап скриптов в конфиге. locales
  • 41.
    Как собрать экстеншен npminstall -g yo npm install -g generator-chrome-extension npm install -g generator-firefox-extension npm install -g jpm
  • 42.
    Как собрать? yo chrome-extensionyo firefox-extension Основное отличие: background scripts - в /lib все остальное - в /data
  • 43.
  • 44.
    Сводим воедино yo chrome-extensionyo firefox-extension .gitignore .gitignore 1. Объединяем в проект app-chrome app-firefox 2. grunt copy: app-chrome/scripts/bg-* -> app-firefox/lib все остальное -> app-firefox/data 3. добавляем в .gitignore app-firefox/lib app-firefox/data
  • 45.
    Сводим воедино yo chrome-extensionyo firefox-extension или… просто все сводим все к структуре папок firefox и обновляем manifest.json.
  • 46.
    en-US.properties содержит однустроку: lng= en это служит только для определения локали, а национализированные строки подгружаются из .json в bg-main-firefox locales
  • 47.
    и последнее… generator-firefox-extension используетдля сборки утилиту cfx, запуская ее через shell утилита cfx устарела и ее надо заменить на утилиту jpm но это не сложно
  • 48.
  • 49.
    jpm syntax не забытьдобавить: cd app-firefox
  • 50.
    Как сделать кросс-браузерно: •Для генерации пустого проекта использовать 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 script content scripts, styles, assets toolbar button popup все вместе
  • 51.
    А стоит лионо того?
  • 52.
  • 53.
  • 54.
    Чтобы реализовать экстеншен,подобный по функционалу на Chrome Extension или Firefox Extension, необходимо писать на C#, так что про кросс- браузерность здесь можно забыть. Google Chrome = Webkit = Opera = Yandex Browser, и т.д. Apple Safari - это почти Webkit. К слову сказать:
  • 55.
    А что таму Safari?
  • 56.
    Таким образом, еслиследовать описанным здесь рекомендациям, вы получите расширение совместимое со всеми основными браузерами, не считая IE
  • 57.