Mozilla Firefox Extension Development, Course 1: Basic
1. Mozilla Firefox
Extension Development
Course 1: Basic
Littlebtc
OSSF Workshop / MozTW Acitivity
The text of the slide is under CC-BY-SA-3.0.
Most photos are under CC-BY-SA compatible license,
while screenshots / logos are under Fair Use.
Code is under MIT license.
2. Note
• This slide is partialy based on Firefox addons
developer guide (CC-BY-SA-2.1JP)
https://developer.mozilla.org/En/Firefox_addons
_developer_guide/
Original authors:
– Hideyuki Emura
– Hiroshi quot;Piroquot; Shimoda
– Taiga Gomibuchi
– Taro Matsuzawa
– Yutaka Kachi
9. Extensions
• One of the “Add-ons”:
– Extensions, Themes, Plugin
• “Extend” your browser
– Provide more features
– Fix some problem
– Integrate with sites or applications
10. Extensions with Single Feature…
• Locationbar2
• Hide Menubar (Made in Taiwan!)
After Press Alt
23. • Rendered by Gecko Engine
XUL • “Write” Interface in an XML
text format
XML User
– Just Like write web pages in
Interface
HTML
Language
• Cross-platform interface
elements
• The idea may be similar to
Adobe’s MXML (Flex) and
THERE IS NO DATA. Microsoft’s XAML (WPF)
THERE IS ONLY XUL.
25. CSS
• It’s true!
• CSS can also modify user interface’s style
• For example: Toolbar icon
26. JavaScript
• It’s true… again!
• Handle the command in the interface
• Almost like what it is on AJAX websites
– XMLHTTPRequest, DOM, …
• But able to access some core API
• ... So it is more dangerous
<script type=“application/x-javascript”>
alert(„Hello World!‟);
</script>
27. XPCOM
• Cross Platform Component Object Model
• The core, or the “black box” of Firefox
• Very similar to Microsoft’s COM
• A cross-platform API that can be extended
• Some API may allow access from JavaScript
28. Above all…
• XPCOM is the “brain”
• XUL is the “skeleton”
• JavaScript is the “muscle”
• CSS is the “skin”
29. Break #1
• Try to Install some extensions on your Firefox!
• And remember to install our tutorial
extensions set
34. Some common attribute
• Identifier: id
• Classes: class
• Style: style, width, height, flex
– We will explain flex later
• disabled=quot;truequot;
– In .NET, it is Enabled=“False” ;p
35. <label>
• <label>
– Attributes
• value
• control (explain later)
• accesskey: Used for Alt+…
<label value=quot;好玩!quot; accesskey=quot;Fquot; />
37. <label>, again
• controls element in <label>:
• When clicking on the specific label,
• will focus on the control with specific id.
<label control=quot;txtquot; value=quot;Comments:quot;/>
<textbox id=quot;txtquot; value=quot;Add texts here!quot;
multiline=quot;truequot; rows=quot;3quot; />
38. <button>
• Attributes
– label
• Beware: <button label=quot;quot; /> but <label value=quot;quot; /> !
– accesskey
– Image
• Events
– oncommand: beware!
(though onclick can be OK, but oncommand is
usually used in XUL)
39. <button> Example
• With a little scripting
<button label=quot;Testquot; accesskey=quot;Squot;
oncommand=quot;alert('hello!');quot; />
40. Layout controls: boxes & flex
• <hbox>: Horizontal Box
• <vbox>: Vertical Box
• <groupbox>: Group Box (can have a <caption>)
• <grid>: Like <table>
• flex (flexibility): An integer attribute in control
elements, which indicates the element in the box
should automatically change its width/height to fit
box/window's size.
– If there is multiple elements, elements with larger flex
values will be larger than ones with lower flex values.
43. Example, again
http://gist.github.com/108791
<label value=quot;Enter Your Name:quot; control=quot;namequot; accesskey=quot;Nquot; />
<textbox id=quot;namequot; value=quot;quot; />
<button label=quot;OKquot;
oncommand=quot;alert('Hello, ' + document.getElementById('name').value + '!');quot; />
44. Script in XUL
<script type=quot;application/x-javascriptquot;>
…
</script>
Will be used widly later
45. Checkbox / Radio
• Common: label/accesskey
• <checkbox>
– checked
• Radio: use a <radiogroup> to contain them
– <radiogroup>
• onselect: Fire when selection changed
• selectedIndex, selectedItem
– <radio>
• selected
• Note: oncommand will fire in a strange time! :
48. Menu: <menupopup>
• Can be used by <menu>, <menulist>,
<toolbarbutton> or <button type=quot;menuquot;>
• Or anything with popup=quot;idquot;
• Or anything with context=quot;idquot;
49. <menupopup> (I)
• In a <menulist>
<hbox>
<label value=quot;Select a Fruit:quot; />
<menulist id=quot;listquot;>
<menupopup>
<menuitem label=quot;Applequot; />
<menuitem label=quot;Bananaquot; />
<menuitem label=quot;Orangequot; />
</menupopup>
</menulist>
</hbox>
50. <menupopup> (II)
• For <button type=quot;menuquot;> :
<button type=quot;menuquot; label=quot;Click on me!quot; >
<menupopup>
<menuitem label=quot;Aboutquot; accesskey=quot;Aquot; />
<menuitem label=quot;Testquot; accesskey=quot;Tquot; />
</menupopup>
</button>
52. More complex
• For Popup / Menu mode:
– <menuitem> can set oncommand to handle the
command
– It can be quot;checkedquot; (like most menu)
• We will see a lot of these later ;)
53. <dialog>
• A quiet different type of window
• Have default buttons!
– <dialog buttons=quot;accept,cancelquot;
buttonlabelaccept=quot;OKquot;
buttonlabelcancel=quot;Cancel!quot;>
– Buttons can be accept, cancel, help, disclosure,
extra1, extra2
• Events: ondialogxxx
56. Scripting: From the very beginning…
<script type=quot;application/x-javascriptquot;>
alert('Hello Scripting in XUL!');
</script>
57. Load / unload
• <window onload=quot;onload()quot; … >
– Good, but sometimes you won't have chance to
modify onload
• <script type=quot;application/x-javascriptquot;>
window.addEventListener('load', onLoad, false);
window.addEventListener('unload', onUnload,
false);
</script>
• Why unload? ==> We usaually need to release
unneeded things
58. So we can…
<script type=quot;application/x-javascriptquot;>
<![CDATA[
window.addEventListener('load', function() {
document.getElementById('Hello').value=quot;Hello
World!quot;;
}, false);
]]>
</script>
<label value=quot;quot; id=quot;Helloquot;/>
61. Some recommended extensions
• Extension Developer:
https://addons.mozilla.org/firefox/addon/743
4
which helps you set up the environment,
doing extension packaging and find something
useful
64. A very simple extension structure
• this-is-a-extension@moztw.org
– install.rdf -- Your Addons info
– chrome.manifest -- Your file paths to register into quot;Chromequot;
– content
• XULs and JSs…
– defaults
• preferences
– skin -- CSS
65. Check our testing extension
• Go
%APPDATA%MozillaFirefoxProfilesxxxxxxxx
.defaultextensionsextension-tutorial-
may09@moztw.org
• Check the install.rdf and chrome.manifest!
67. Explain
• em:id
– identical to the folder name
– Unique ID to your extension
– Can be in Email format or GUID format
• em:version
• em:type
– 2: Extensions
• em:targetApplication
– Set compatible application
– Application can be identified with UUID, which can be also Email
or GUID format. For example:
• Firefox is {ec8030f7-c20a-464f-9b0e-13a3a9e97384}
• Songbird is songbird@songbirdnest.com
68. How about !!@#$%^&?
• L10n?
– Set <em:localized>
• Multiple Applications?
– A lot of <em:targetApplication>
• For details:
https://developer.mozilla.org/en/Install_Manifests
• See a complex example (My NicoFox install.rdf)
http://code.google.com/p/nicofox/source/brows
e/trunk/install.rdf
69. chrome.manifest
content tutorial content/
• First is the quot;instructionsquot;:
content/locale/skin/overlay/# (comment)
deciding what to do
• content instructions:
content packagename paths/to/files/ [flags]
– Will Register paths/to/files in
chrome://packagename/content !
70. chrome.manifest
• locale instruction:
locale packagename localename paths/to/files/ [flags]
– loacle is use to store l10n files, ex:
locale tutorial zh-TW locale/zh-TW/
• skin instruction:
skin packagename skinname paths/to/files/ [flags]
– skin is used to store skin files (CSS/pictures)
skin tutorial classic/1.0 skin/
71. chrome.manifest
• overlay instruction:
overlay chrome://to-be-overlaid chrome://overlay [flags]
– Use for XUL overlays
– quot;ADD SOMETHINGquot; in the existing XUL
– So we can do a lot of things in our browser
window!
• overlay chrome://browser/content/browser.xul
chrome://tutorial/content/overlay.xul
• For more, see:
https://developer.mozilla.org/en/Chrome_Registration
72. Go and see
• chrome://tutorial/content/test.xul
– Do you see a quot;Hello Worldquot; ?
73. Create another profile (optional)
• start quot;quot; quot;%ProgramFiles%Mozilla
Firefoxfirefox.exequot; -no-remote -P dev
– no-remote allows multiple profile at a time
– -P dev means open a “dev” profile
74. Go overlay
Change the browser window
(http://www.flickr.com/photos/ybite/367039657/ CC-BY-SA-2.0 by ybite)
75. At beginning, overlay.xul:
<?xml version=quot;1.0quot;?>
<overlay
xmlns=quot;http://www.mozilla.org/keymaster/ga
tekeeper/there.is.only.xulquot;>
</overlay>
76. You need to know your enemy
• chrome://browser/content/browser.xul
id=quot;main-menubarquot;
id=quot;navigator-
toolbox quot;
id=quot;menu_ToolsPopupquot;
id=quot;status-barquot;
77. Add an item in Tools Menu
<menupopup id=quot;menu_ToolsPopupquot;>
<menuitem label=quot;Hello Extensions!quot;
accesskey=quot;Hquot; oncommand=quot;alert('Hello!');quot;
insertafter=quot;devToolsSeparatorquot; />
</menupopup>
78. How to test?
• After disabling XUL cache, open a new
window and overlay will work
• Or using Extension Developer to Reload All
Chrome (Not suggested)
79. Add Item to the statusbar
<statustoolbar id=quot;status-barquot;>
<statusbarpanel id=quot;tutorial-custom-statusbarquot;
class=quot;statusbarpanel-iconic-textquot;
label=quot;Mybarquot;
tooltiptext=quot;It is my statusbar!quot; hidden=quot;falsequot;
src=quot;chrome://tutorial/skin/sport_basketball.pngquot;
oncommand=quot;alert('Hello!');quot; />
</statustoolbar>
Class:
• statusbarpanel-iconic-text: Icon & text
• statusbarpanel-iconic: Icon only
• statusbarpanel-menu-iconic: icon & popup menu
80. Custom Toolbar Button
or a new Toolbar?
• Custom Toolbar Button:
https://developer.mozilla.org/en/Creating_too
lbar_buttons
• Create a Toolbar:
http://www.borngeek.com/firefox/toolbar-
tutorial/
81. Localization Preparation in XUL
• Before <overlay>:
<!DOCTYPE overlay SYSTEM
quot;chrome://tutorial/locale/tutorial.dtdquot;>
• Add a file zh-TW/tutorial.dtd:
<!ENTITY tutorial.hello quot;我的狀態列quot;>
• Add a file en-US/tutorial.dtd:
<!ENTITY tutorial.hello quot;MyBarquot;>
• Change the overlay.xul:
label=quot;&tutorial.hello;quot;
82. L10n normal tips
• Entities naming:
– xxxxx.label
– xxxxx.accesskey
• Remember to l10n as most as you can
• If your strings consists of variable value, try
JavaScript way (explain later)
83. JavaScript time
Basic JavaScript technique in Extension development
(http://www.flickr.com/photos/nicksieger/280662871/ CC-BY-SA-2.0 by
nicksieger)
84. Review: DOM Tree
previousSibling
firstChild
element
parentNode
lastChild
nextSibling
85. Review: Some Simple DOM
• Find elements
– id: document.getElementById(‘…’)
– class: document.getElementsByClassName(‘…’)
(Support Firefox3+ / Gecko 1.9+ only
Workaround: XPath :D)
• Work with elements
– element.style.xxx;
– element.disabled = true;
– element.setAttribute(‘disabled’, true);
– var value = element.getAttribute(‘value’);
86. Add Script code in our overlay
<script type=quot;application/x-javascriptquot;
src=quot;chrome://tutorial/content/overlay.jsquot; />
• Insert right after <overlay>
87. overlay.js
var moztw_tutorial = {
onLoad: function() {
// Fire when browser window loading
},
onUnload: function() {
// Fire when browser window unloading
}
};
window.addEventListener('load', moztw_tutorial.onLoad, false);
window.addEventListener('unload', moztw_tutorial.onUnload, false);
88. Why use a object to wrap everything?
• The global object may be used by more than 50
extensions (so easy to conflict!)
• So wrap everything in an object is a safe way
• Some better implementations:
– http://blogger.ziesemer.com/2007/10/respecting-
javascript-global-namespace.html
– http://www.softwareishard.com/blog/planet-
mozilla/firefox-extensions-global-namespace-
pollution/
89. Code snippets
• Open a XUL Dialog
window.openDialog('chrome://tutorial/content/test.xul',
'chrome,centerscreen,dialog=no,resizable=yes ');
– chrome: needed for chrome-level window
– dialog=no: needed if it is not a <dialog>
– resizable=yes: can it be resize?
– modal: will it lock the outer window?
• Window size?
– Define it on your XUL window CSS
90. Sending data
• A very complex job!
• There exists some way like using the
window.openDialog to send
• https://developer.mozilla.org/en/Working_wit
h_windows_in_chrome_code
• https://developer.mozilla.org/en/Code_snippe
ts/Interaction_between_privileged_and_non-
privileged_pages
92. Coping with the page
• Can we cope with the our viewing content in
our browser? Yes, But Strictly Limited
93. Getting document of currently
selected tab
• content.document or
gBrowser.selectedBrowser.contentDocument
• So you can modify the content!
• The following code is a little dirty!
fixIt: function() {
if (content.document) {
var h1 = content.document.getElementsByTagName('h1');
if (h1 && h1.length > 0) { h1[0].innerHTML = quot;Testquot;; }
}
}
94. Get JavaScript variable in currently
selected tab
• … Are You sure?
– It can be very dangerous
– And it is very hard
• Try Greasemonkey and understand
unsafeWindow carefully
– It has a compiler to make your userscript an
independent xpi
95. Tab browser related?
• https://developer.mozilla.org/En/Code_snippe
ts/Tabbed_browser
• It has a lot of data, and very useful!
96. XPCOM
• You will be able to use some XPCOM in the
following way:
– Instance:
var file = Components.classes[quot;@mozilla.org/file/local;1quot;].
createInstance(Components.interfaces.nsILocalFile);
file.initWithPath(quot;D:doggy.txtquot;);
– Usually, Cc = Components.classes, Ci = Components.interfaces
– Service:
var bookmarksSvc = Cc[quot;@mozilla.org/browser/nav-bookmarks-
service;1quot;]. getService(Ci.nsINavBookmarksService);
97. What can I do with XPCOM?
• File access: nsILocalFIle
• Cross-site XMLHTTPRequest: nsIXMLHTTPRequest
• Advanced window operations: nsIWindowMediator
• Access places database (Firefox3+ / Gecko 1.9+):
nsINavBookmarksService, nsITaggingService, …
• Access password manager: nsILoginManager (Fx3+/Gecko1.9+)
• Save pages into files: nsIPersist
• Etc…
98. JS l10n ways (I)
• You need a .properties file
• put locale/en-US/tutorial.properties:
hello=Hello World!
• And locale/zh-TW/tutorial.properties:
hello=哈囉世界!
99. JS l10n ways (II)
• In overlay.xul, add:
<stringbundleset id=quot;stringbundlesetquot;>
<stringbundle id=quot;tutorial-bundlequot;
src=quot;chrome://tutorial/locale/tutorial.properti
esquot; />
</stringbundleset>
• Now you can access hello locale in
document.getElementById('tutorial-bundle').getString('hello');
100. Full l10n examples
• I will add two new entities in .dtd (XUL-l10n)
<!ENTITY tutorial.helloMenu.label quot;打聲招呼quot;>
<!ENTITY tutorial.helloMenu.accesskey quot;Hquot;>
• Then, modify the overlay.xul:
<stringbundleset id=quot;stringbundlesetquot;>
<stringbundle id=quot;tutorial-bundlequot;
src=quot;chrome://tutorial/locale/tutorial.propertiesquot; />
</stringbundleset>
And
<menupopup id=quot;menu_ToolsPopupquot;>
<menuitem label=quot;&tutorial.helloMenu.label;quot;
accesskey=quot;&tutorial.helloMenu.accesskey;quot;
oncommand=quot;moztw_tutorial.hello();quot; insertafter=quot;devToolsSeparatorquot; />
</menupopup>
101. Full l10n examples (II)
• Then, the overlay.js:
hello: function() {
alert( document.getElementById('tutorial-
bundle').getString('hello'));
}
102. Example: TagHelper++
• Improve Gomita's TagHelper example
• Make it more easy and accurate
• A complete demo for JavaScript, XUL and
XPCOM!
106. Overlay: JavaScript
onLoad: function() {
// Fire when browser window loading
var contextMenu = document.getElementById(quot;contentAreaContextMenuquot;);
if (contextMenu) {
contextMenu.addEventListener(quot;popupshowingquot;, taghelper2.popupShowing, false);
}
},
popupShowing: function(e) {
var item = document.getElementById(quot;taghelper2-menuitemquot;);
if (gContextMenu.isContentSelected) { // Popup will show when selected
item.hidden = false;
} else {
item.hidden = true;
}
},
107. Overlay: JavaScript (II)
addTags: function() {
// Check selection
var selection = window.content.getSelection();
var texts = [];
for (var i = 0; i < selection.rangeCount; i++) {
var text = selection.getRangeAt(i).toString();
// Trim
text = text.replace(/^s/,'').replace(/s$/,'');
texts.push(text);
}
var text = texts.join(quot;,quot;);
selection.removeAllRanges();
// Open Dialog
var params = {text: text, url: window.content.document.location.href, title:
window.content.document.title};
window.openDialog(quot;chrome://taghelper2/content/taghelper2.xulquot;, quot;quot;,
quot;chrome,centerscreen,modalquot;, params);
}
113. XPI packaging, the easiest way
• Zip your extensions
Make sure install.rdf & chrome.manifest is in
the first level of zip files
• Rename the file to xxx.xpi
• And you are done!
114. Advanced: pack a .jar for chrome files
• File structure:
– chrome
• taghelper2.jar (a zip file)
– content
»…
– locale
»…
– skin
»…
• The correspoding chrome.manifest fix:
before: locale/zh-TW/
after: chrome/taghelper2.jar!/locale/zh-TW/
116. Send it to a public website
• Spread your .xpi file
• Or, use Mozilla Add-ons
– A good add-ons hosting
– Strict review process
– Public extension will have automatically update