Orange is the new blue: How to port Chrome Extension to Firefox Extension

Post on 18-Jan-2017

647 views 1 download

transcript

Orange is the new blueHow to port Chrome Extension to Firefox Extensionor develop cross-browser extension from scratch

Boris Mossounovfacebook.com/mossounov

linkedin.com/in/borismossounovanotherguru.me

Major architectural differences:Chrome Extension v.s. Firefox Addon

Developer documentation

https://developer.chrome.com/extensionshttps://developer.mozilla.org/en-US/Add-ons

While digging Mozilla docs you can come across:Legacy Extensions Overlay extensions

Restartless Extensions Bootstrapped ExtensionsAdd-on SDK Extensions

Jetpack SDK Add-on SDK

==

=

Firefox Addon history digest:

Legacy Extensions / Overlay Extensions (XUL, JSM, XPCOM)

2004.06 - Firefox 0.9

Legacy Extensions / Overlay Extensions (XUL, JSM, XPCOM)

2004.06 - Firefox 0.9

Firefox Addon history digest:

Legacy Extensions / Overlay Extensions (XUL, JSM, XPCOM)

2004.06 - Firefox 0.9

browser.xul:

overlay.xul:

Firefox Addon history digest:

Legacy Extensions / Overlay Extensions (XUL, JSM, XPCOM)

2004.06 - Firefox 0.9

Mozilla starts Jetpack SDK project2009.09

Firefox Addon history digest:

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

Firefox Addon history digest:

Google announces Chrome Extensions support2009.09

Google Chrome Store launches(with blackjack and extensions)

2010.12

Chrome Extension history digest:

Краткая история:2004.06 - Firefox 0.9

2009.09

2011.03 - Firefox 4+

2011.06

2015.05 - Firefox 38

2010.12

Google announces Chrome Extensions support

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 launches (with blackjack and extensions)

While digging Mozilla docs you should read about:Legacy Extensions Overlay extensions

Restartless Extensions Bootstrapped ExtensionsAdd-on SDK Extensions

Jetpack SDK Add-on SDK

==

=

An average browser extensionconsists of the following blocks:

manifest

background script

content scripts, styles, assets

toolbar button popup

locales

embedded pages(options / help)

The major difference between Chrome Extension and Firefox Addon

is the way the following 3 blocks interact:

background.js

contentscript.js popup.js

Google Chrome possesses two APIs for message passing:

• 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 can:

Is cross-browser support on the table?

If it is, then don’t.If not, go on.

background.js

contentscript.js popup.js

• two message passing APIs• contentscript.js & popup.js can get

background window object and store some objects and methods there.

• all blocks can interact using untitled messages and setting response callbacks.

• background.js knows nothing about other scripts till they connect to it

What about 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

• all blocks are run in isolated runtimes and can interact using named messages without response callbacks

• background.js creates contentscript.js & popup.js and can control them

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: {}}

Let’s compare Mozilla Extension & Chrome Extensionby blocks:

manifest

background script

content scripts, styles, assets

toolbar button popup

locales

embedded pages(options / help)

manifest

manifest.jsondescribes:• title, description,

version, license,• location of all

scripts, styles, html,• permissions

package.jsondescribes:• title, description,

version, license,• location of background

script

and background scriptloads all the content & popup scripts, styles, html

manifest

How to develop cross-browser way:

Setup grunt task, that will synchronize manifest.json & package.json (version, title, description…)

• Invisible html page with it’s window js-object,

• this window js-object shares the same runtime context with content scripts and popup script

• Separate javascript without window object.

• this javascript is run in an isolated runtime

• Background script initializes content scripts and popup and can control them.

• EcmaScript 6

background script

How to develop cross-browser way:

1. Avoid chrome.extension.getBackgroundPage() at all costs

2. For Firefox - create separate background script since firefox addon sdk is implemented on ES6.

3. Develop a cross-browser middle layer to call browser specific API that above all implements message passing with named messages and response callbacks

4. Store background script and content script / popup script logic in separate files. Even if some mechanisms require both background and content scripts. Use message passing, Luke.

background script

• content scripts are run in a web-page isolated world

• can access background window

• cross-domain request are manifest permission dependent

• content scripts are run in a web-page isolated world

• are run in context isolated from background script

• cross-domain requests are forbidden

content scripts, styles, assets

How to develop cross-browser way:

1. Avoid chrome.extension.getBackgroundPage() at all costs2. Develop a cross-browser middle layer to call browser

specific API that above all implements message passing with named messages and response callbacks

3. Store background script and content script / popup script logic in separate files. Even if some mechanisms require both background and content scripts. Use message passing, Luke.

4. For ajax requests in Firefox use Request API in background and message passing.

content scripts, styles, assets

• only one toolbar button• can access background

window • popup load on toolbar

button click and unload on hide

• javascript is loaded using <script>

• popup size is calculated automatically

• several toolbar buttons allowed

• popup javascript context is isolated from background js

• popup is loaded when extension is initialized and unloaded with extension itself

• scripts should be loaded like content scripts

• popup size is set manually

toolbar button popup

How to develop cross-browser way:

1. Avoid chrome.extension.getBackgroundPage() at all costs2. Consider that only one toolbar button allowed3. Develop popup script assuming it is loaded once and should

react to all events that occur in content scripts and background script.

4. Keep in mind that Chrome and Firefox load popup differently though.

5. In Firefox load popup scripts using content script mechanism and block those loaded using <script>. (https://developer.mozilla.org/en-US/Add-ons/SDK/Tutorials/Display_a_Popup)

toolbar button popup

Format: .json

locale API available in:• background script• content script• popup script

Format: .properties

locale API available in:• background script only

that can pass dictionary to rest of scripts

• in popup.html you can use nls ids that will be replaced by localized strings

locales

How to develop cross-browser way:

1. Chose one of the formats as the base one (json).2. Use firefox properties to store language identifier only.3. In Firefox content scripts and popup scripts should request whole localized dictionary that background should read from json. Or you can provide dictionary on initialization of content and popup scripts as config.

locales

How to assemble cross-browser extension:

npm install -g yonpm install -g generator-chrome-extensionnpm install -g generator-firefox-extensionnpm install -g jpm

How to assemble?yo chrome-extension yo firefox-extension

Main difference:background scripts - /liball the rest - /data

Lets make it look more consistent

yo chrome-extension yo firefox-extension

Let’s move both to the single project

yo chrome-extension yo firefox-extension

.gitignore

.gitignore

1. In the single project:app-chromeapp-firefox

2. grunt copy:app-chrome/scripts/bg-* ->

app-firefox/libвсе остальное ->

app-firefox/data

3. add to .gitignoreapp-firefox/libapp-firefox/data

yo chrome-extension yo firefox-extension

or…

adjust folder structure to the Firefox standards and update manifest.json

Let’s move both to the single project

en-US.properties contains only one string:

lng= en

it is used to detect language and load appropriate .jsondictionary in bg-main-firefox

locales

and one last thing…

generator-firefox-extension uses cfx utility for building and runs it using shell

cfx is deprecated by Mozillayou should use jpm instead

but that’s easy

cfx syntax

jpm syntax

don’t forget:cd app-firefox

How to develop cross-browser way:• To generate prject use yeoman generators: generator-chrome-extension & generator-firefox-

extension. Replace cfx with jpm.• Merge code base to the single project and setup grunt build.• Setup grunt task that will synchronize manifest.json & package.json (version, title,

description…).• Develop a cross-browser middle layer to call browser specific API that above all implements

message passing with named messages and response callbacks• Avoid chrome.extension.getBackgroundPage() at all costs• Create two separate background scripts for Chrome & Firefox.• Store background script and content script / popup script logic in separate files. Even if some

mechanisms require both background and content scripts. Use message passing, Luke.• For ajax requests in Firefox use Request API in background and message passing, in Chrome -

jQuery.ajax will do.• Consider that only one toolbar button allowed.• Develop popup script assuming it is loaded once and should react to all events that occur in

content scripts and background script. Keep in mind that Chrome and Firefox load popup differently though.

• In Firefox load popup scripts using content script mechanism and block those loaded using <script>. (https://developer.mozilla.org/en-US/Add-ons/SDK/Tutorials/Display_a_Popup).

• Chose one of the formats as the base one (json). Use firefox properties to store language identifier only. In Firefox content scripts and popup scripts should request whole localized dictionary that background should read from json. Or you can provide dictionary on initialization of content and popup scripts as config.

manifestbackground scriptcontent scripts, styles, assets

toolbar button popupall together

Is it worth it?

Browsers market share in Russian Federation

Overall browsers market share

To create IE extension with the same functionality like Chrome or Firefox extension you need to

implement it on C#, so no cross-browser support here.

Google Chrome = Webkit = Opera = Yandex Browser, etc

Apple Safari is almost Webkit.

Keep in mind:

What about Safari?

So implementing browser extension the way it was described here covers support of all the

major browsers except IE.

Questions?