SlideShare a Scribd company logo
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.
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
Suggested Reading
• Firefox addons developer guide (CC-BY-SA-
  2.1JP)
  https://developer.mozilla.org/En/Firefox_add
  ons_developer_guide/
• Firefox 3ではじめる拡張機能開発 (Japanese)
  http://gihyo.jp/dev/feature/01/firefox-addons
  by Gomita
About Speaker

A undergraduate, a web designer, etc.
NicoFox
• ~5000 Users
A busy undergraduate
in Taiwan
     (PTT: ybite)
http://littlebtc.blogspot.com
Introduction to Extension
Which makes Firefox better
Extensions
• One of the “Add-ons”:
  – Extensions, Themes, Plugin
• “Extend” your browser
  – Provide more features
  – Fix some problem
  – Integrate with sites or applications
Extensions with Single Feature…
• Locationbar2




• Hide Menubar (Made in Taiwan!)

    After Press Alt
Extensions with Feature
            Enhancements
• NoScript
Web Application Integration
•   TwitterFox
•   GmailManager
•   Forestfox
•   S3Fox
    (For Amazon S3)
Extensions with New Feature(s)
• Adblock Plus




• New Tong Wen Tang
  – Conversion between Chinese characters
• Greasemonkey
Extensions with New Feature(s)
• IE Tab (Made in Taiwan!)
• Stylish (Custom CSS for every site & user interface)
• FireGuestures




• Andmore!
Application Level
• Sage
• Scrapbook
• Firebug
One trick
• Together with Foxkeh
• Glasser
  – Apply Vista / 7 Aero Glass in toolbar
Ways to custom your Firefox?
Method                     Website                          Application (Firefox, …)
User Style Sheets (CSS)    UserContent.css, Stylish         UserChrome.css
User Script (JavaScript)   Bookmarklet, Greasemonkey        UserChrome.js
Extensions                                     Easy but powerful
Themes                     (Not supported)                  Very flexible
Next:

DIVE INTO EXTENSIONS
About Mozilla Technology
Why we can extend Firefox easily
Photo: http://www.flickr.com/photos/ews/2603070503/
CC-BY-2.0 by JP Puerta
This is the Firefox…
… and this is part of the the
 “Main Browser Window”.
Wait? Wait!




Is this HTML / JavaScript?
 => No, but something similar to this
• 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.
XUL Periodic Table
• http://www.hevanet.com/acorbin/xul/top.xul
CSS
• It’s true!
• CSS can also modify user interface’s style
• For example: Toolbar icon
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>
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
Above all…
•   XPCOM is the “brain”
•   XUL is the “skeleton”
•   JavaScript is the “muscle”
•   CSS is the “skin”
Break #1
• Try to Install some extensions on your Firefox!
• And remember to install our tutorial
  extensions set
Break #1
• Don't forget a little set up:
Go Writing XUL
From the very beginning
Use a tool to help you
Real-time XUL Editor

  Beware!
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
<label>
• <label>
  – Attributes
     • value
     • control (explain later)
     • accesskey: Used for Alt+…


<label value=quot;好玩!quot; accesskey=quot;Fquot; />
<textbox>
• <textbox>                      <textbox value=quot;Add texts here!“
                                 multiline=quot;truequot; rows=quot;3quot; cols=quot;12quot; />
  – Attributes
     • id
     • value
     • type:
           – number/password
           – timed/search        <hbox>
     •   rows/cols                <textbox type=quot;passwordquot; />
     •   size                    </hbox>
     •   multiline: true/false
     •   readonly: true/false
  – Events
     • onchange
<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; />
<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)
<button> Example
• With a little scripting
<button label=quot;Testquot; accesskey=quot;Squot;
 oncommand=quot;alert('hello!');quot; />
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.
Boxes & flex: example
<label value=quot;Horizontal layoutquot;/>
<hbox>
 <button label=quot;horizontal1quot; flex=quot;1quot;/>
 <button label=quot;horizontal2quot; flex=quot;2quot;/>
 <button label=quot;horizontal3quot; flex=quot;3quot;/>
</hbox>
<label value=quot;Vertical layoutquot;/>
<vbox>
 <button label=quot;vertical1quot;/>
 <button label=quot;vertical2quot;/>
</vbox>
<label value=quot;mixedquot;/>
<hbox>
                                          http://gist.github.com/108776
 <button label=quot;mixed1quot; flex=quot;3quot;/>
 <vbox flex=quot;2quot;>
  <button label=quot;mixed2quot; />
  <button label=quot;mixed3quot; />
  <button label=quot;mixed4quot; />
 </vbox>
 <button label=quot;mixed5quot; flex=quot;1quot;/>
</hbox>
Grid & Groupbox: Example
<groupbox>
 <caption label=quot;Loginquot;/>
 <grid>
  <columns>
   <column flex=quot;1quot;/>
   <column flex=quot;2quot;/>                           http://gist.github.com/108802
  </columns>
  <rows>
   <row>
    <label value=quot;IDquot;/>
    <textbox id=quot;idquot;/>
   </row>
   <row>
    <label value=quot;Passwordquot;/>
    <textbox id=quot;passwordquot; type=quot;passwordquot; />
   </row>
  </rows>
 </grid>
 <button label=quot;Loginquot; />
</groupbox>
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; />
Script in XUL
<script type=quot;application/x-javascriptquot;>
…
</script>

Will be used widly later
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! :
Checkbox / Radio
<checkbox id=quot;sugarquot; label=quot;Sugarquot; checked=quot;truequot;/>
<checkbox id=quot;icequot; label=quot;Icequot; checked=quot;falsequot; oncommand=quot;alert(this.checked);quot;/>
<radiogroup onselect=quot;alert(this.selectedItem.id);quot;>
 <radio id=quot;nonequot; label=quot;Nonequot; disabled=quot;truequot;/>
 <radio id=quot;halfquot; label=quot;Halfquot; />
 <radio id=quot;fullquot; label=quot;Fullquot; selected=quot;truequot;/>
</radiogroup>
Menus
• In XUL, the following are similar!
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;
<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>
<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>
<menupopup> (III)
• For popup=quot;xquot; or context=quot;xquot;:
 <label value=quot;Left-Click here!quot; popup=quot;mymenuquot; />
 <label value=quot;Right-Click here!quot; context=quot;mymenuquot;/>

 <menupopup id=quot;mymenuquot;>
  <menuitem label=quot;Aboutquot; accesskey=quot;Aquot; />
  <menuitem label=quot;Testquot; accesskey=quot;Tquot; />
 </menupopup>
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 ;)
<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
<dialog> example
<?xml version=quot;1.0quot;?>
<?xml-stylesheet href=quot;chrome://global/skin/global.cssquot; type=quot;text/cssquot;?>
<dialog id=quot;mydialogquot; title=quot;Dialog Examplequot;
 xmlns=quot;http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xulquot;
 buttons=quot;accept,cancelquot;
 buttonlabelcancel=quot;Cancelquot;
 buttonlabelaccept=quot;Sendquot;
 ondialogaccept=quot;alert('Thank you, ' + document.getElementById('name').value + '!');quot;
 ondialogcancel=quot;alert('canceled!');quot;>

  <dialogheader title=quot;Hello!quot; description=quot;Welcome to the my dialog!quot;/>
 <vbox>
  <label value=quot;Please introduce yourself :)quot; />
  <hbox>
   <label value=quot;Your Name:quot; control=quot;namequot; accesskey=quot;Nquot; />
   <textbox id=quot;namequot; value=quot;quot; />
  </hbox>
 </vbox>

</dialog>
Result
Scripting: From the very beginning…
<script type=quot;application/x-javascriptquot;>
 alert('Hello Scripting in XUL!');
</script>
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
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;/>
Thank you!

LET'S HAVE A LUNCH!
“Create Project”
Setup the environment
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
Some recommended extensions
• Console2
  Change Error Console, Speed Up Your Debug
  Speed
Some recommended extensions
• DOM Inspector
  Watch the structure of webpages or XUL
  pages
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
Check our testing extension
• Go
  %APPDATA%MozillaFirefoxProfilesxxxxxxxx
  .defaultextensionsextension-tutorial-
  may09@moztw.org
• Check the install.rdf and chrome.manifest!
install.rdf
<?xml version=quot;1.0quot; encoding=quot;UTF-8quot;?>
<RDF xmlns=quot;http://www.w3.org/1999/02/22-rdf-syntax-ns#quot;
xmlns:em=quot;http://www.mozilla.org/2004/em-rdf#quot;>
 <Description about=quot;urn:mozilla:install-manifestquot;>
  <em:id>extension-tutorial-may09@moztw.org</em:id>
  <em:name>MozTW 擴充套件課程用教學套件</em:name>
  <em:version>0.1</em:version>
  <em:description>5/9和5/23的教學所使用!</em:description>
  <em:creator>Littlebtc</em:creator>
  <em:type>2</em:type>
  <em:targetApplication>
   <Description>
    <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> 
    <em:minVersion>3.0</em:minVersion>
    <em:maxVersion>3.6a1pre</em:maxVersion>
   </Description>
  </em:targetApplication>
 </Description>
</RDF>
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
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
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 !
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/
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
Go and see
• chrome://tutorial/content/test.xul
  – Do you see a quot;Hello Worldquot; ? 
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
Go overlay
Change the browser window
(http://www.flickr.com/photos/ybite/367039657/ CC-BY-SA-2.0 by ybite)
At beginning, overlay.xul:
<?xml version=quot;1.0quot;?>
<overlay
  xmlns=quot;http://www.mozilla.org/keymaster/ga
  tekeeper/there.is.only.xulquot;>
</overlay>
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;
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>
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)
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
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/
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;
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)
JavaScript time
Basic JavaScript technique in Extension development
(http://www.flickr.com/photos/nicksieger/280662871/ CC-BY-SA-2.0 by
nicksieger)
Review: DOM Tree

                previousSibling
                                  firstChild

                 element
parentNode

                                  lastChild

                 nextSibling
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’);
Add Script code in our overlay
<script type=quot;application/x-javascriptquot;
src=quot;chrome://tutorial/content/overlay.jsquot; />

• Insert right after <overlay>
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);
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/
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
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
Try JavaScript Shell
• This has the chrome privileges
Coping with the page
• Can we cope with the our viewing content in
  our browser? Yes, But Strictly Limited
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;; }
      }
    }
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
Tab browser related?
• https://developer.mozilla.org/En/Code_snippe
  ts/Tabbed_browser
• It has a lot of data, and very useful!
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);
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…
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=哈囉世界!
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');
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>
Full l10n examples (II)
• Then, the overlay.js:
 hello: function() {
   alert( document.getElementById('tutorial-
   bundle').getString('hello'));
 }
Example: TagHelper++
• Improve Gomita's TagHelper example
• Make it more easy and accurate
• A complete demo for JavaScript, XUL and
  XPCOM!
Our Target
• Select the text
• Right-click to add tag
First step
• Setup the developing environment
Overlay: popup menu
<popup id=quot;contentAreaContextMenuquot;>
 <menuitem id=quot;taghelper2-menuitemquot;
     label=quot;&taghelper2.menuItem.label;quot;
     accesskey=quot;&taghelper2.menuItem.accesskey;quot;
     oncommand=quot;taghelper2.addTags();quot; />
</popup>
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;
  }
},
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);
}
The Dialog
<?xml version=quot;1.0quot; encoding=quot;UTF-8quot;?>
<?xml-stylesheet href=quot;chrome://global/skinquot; type=quot;text/cssquot;?>
<!DOCTYPE dialog SYSTEM quot;chrome://taghelper2/locale/taghelper2.dtdquot;>

<dialog title=quot;&taghelper2.dialog.title;quot;
     xmlns=quot;http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xulquot;
     buttons=quot;accept,cancelquot;
     onload=quot;taghelper2Dialog.onLoad();quot;
     ondialogaccept=quot;return taghelper2Dialog.addTags();quot;
>
<script type=quot;application/x-javascriptquot; src=quot;chrome://taghelper2/content/taghelper2.jsquot; />
<vbox>
<label value=quot;&taghelper2.dialog.description.label;quot; id=quot;descriptionquot; />
<textbox value=quot;quot; id=quot;tagsquot; />

</vbox>
</dialog>
The Script
var Cc = Components.classes;
var Ci = Components.interfaces;

var taghelper2Dialog = {
 url: null,
 title: null,
 onLoad: function() { // Receive Arguments
   if (window.arguments[0] && window.arguments[0].text) {
     document.getElementById('tags').value =
     window.arguments[0].text;
     this.url = window.arguments[0].url;
     this.title = window.arguments[0].title;
   }
 },
The Script (II)
addTags: function() {
 try {
  var bookmarkServ = Cc[quot;@mozilla.org/browser/nav-bookmarks-service;1quot;]
            .getService(Ci.nsINavBookmarksService);

     var uri = Cc[quot;@mozilla.org/network/io-service;1quot;]
           .getService(Ci.nsIIOService)
           .newURI(this.url, null, null);

     /* Check if it was in bookmark */
     var checkArray = bookmarkServ.getBookmarkIdsForURI(uri, {});
     if (checkArray.length < 1)
     {
       var bookmarkId = bookmarkServ.insertBookmark(bookmarkServ.unfiledBookmarksFolder, uri, -1, quot;quot;);
       bookmarkServ.setItemTitle(bookmarkId, this.title);
     }
     /* Add tag to places */
     var taggingServ = Cc[quot;@mozilla.org/browser/tagging-service;1quot;]
                .getService(Ci.nsITaggingService);
     taggingServ.tagURI(uri, [document.getElementById('tags').value], 1 );
     return true;
   } catch (e) {
     alert(e);
     return true;
   }
 },

};
Result
XPI Package
Spread your extension!
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!
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/
Scripts available
• build.sh
  http://kb.mozillazine.org/Bash_build_script
  Create XPI with inner JAR attached
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
THANK YOU!

More Related Content

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
  • 3. Suggested Reading • Firefox addons developer guide (CC-BY-SA- 2.1JP) https://developer.mozilla.org/En/Firefox_add ons_developer_guide/ • Firefox 3ではじめる拡張機能開発 (Japanese) http://gihyo.jp/dev/feature/01/firefox-addons by Gomita
  • 4. About Speaker A undergraduate, a web designer, etc.
  • 6. A busy undergraduate in Taiwan (PTT: ybite)
  • 8. Introduction to Extension Which makes Firefox better
  • 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
  • 11. Extensions with Feature Enhancements • NoScript
  • 12. Web Application Integration • TwitterFox • GmailManager • Forestfox • S3Fox (For Amazon S3)
  • 13. Extensions with New Feature(s) • Adblock Plus • New Tong Wen Tang – Conversion between Chinese characters • Greasemonkey
  • 14. Extensions with New Feature(s) • IE Tab (Made in Taiwan!) • Stylish (Custom CSS for every site & user interface) • FireGuestures • Andmore!
  • 15. Application Level • Sage • Scrapbook • Firebug
  • 16. One trick • Together with Foxkeh • Glasser – Apply Vista / 7 Aero Glass in toolbar
  • 17. Ways to custom your Firefox? Method Website Application (Firefox, …) User Style Sheets (CSS) UserContent.css, Stylish UserChrome.css User Script (JavaScript) Bookmarklet, Greasemonkey UserChrome.js Extensions Easy but powerful Themes (Not supported) Very flexible
  • 19. About Mozilla Technology Why we can extend Firefox easily Photo: http://www.flickr.com/photos/ews/2603070503/ CC-BY-2.0 by JP Puerta
  • 20. This is the Firefox…
  • 21. … and this is part of the the “Main Browser Window”.
  • 22. Wait? Wait! Is this HTML / JavaScript? => No, but something similar to this
  • 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.
  • 24. XUL Periodic Table • http://www.hevanet.com/acorbin/xul/top.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
  • 30. Break #1 • Don't forget a little set up:
  • 31. Go Writing XUL From the very beginning
  • 32. Use a tool to help you
  • 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; />
  • 36. <textbox> • <textbox> <textbox value=quot;Add texts here!“ multiline=quot;truequot; rows=quot;3quot; cols=quot;12quot; /> – Attributes • id • value • type: – number/password – timed/search <hbox> • rows/cols <textbox type=quot;passwordquot; /> • size </hbox> • multiline: true/false • readonly: true/false – Events • onchange
  • 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.
  • 41. Boxes & flex: example <label value=quot;Horizontal layoutquot;/> <hbox> <button label=quot;horizontal1quot; flex=quot;1quot;/> <button label=quot;horizontal2quot; flex=quot;2quot;/> <button label=quot;horizontal3quot; flex=quot;3quot;/> </hbox> <label value=quot;Vertical layoutquot;/> <vbox> <button label=quot;vertical1quot;/> <button label=quot;vertical2quot;/> </vbox> <label value=quot;mixedquot;/> <hbox> http://gist.github.com/108776 <button label=quot;mixed1quot; flex=quot;3quot;/> <vbox flex=quot;2quot;> <button label=quot;mixed2quot; /> <button label=quot;mixed3quot; /> <button label=quot;mixed4quot; /> </vbox> <button label=quot;mixed5quot; flex=quot;1quot;/> </hbox>
  • 42. Grid & Groupbox: Example <groupbox> <caption label=quot;Loginquot;/> <grid> <columns> <column flex=quot;1quot;/> <column flex=quot;2quot;/> http://gist.github.com/108802 </columns> <rows> <row> <label value=quot;IDquot;/> <textbox id=quot;idquot;/> </row> <row> <label value=quot;Passwordquot;/> <textbox id=quot;passwordquot; type=quot;passwordquot; /> </row> </rows> </grid> <button label=quot;Loginquot; /> </groupbox>
  • 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! :
  • 46. Checkbox / Radio <checkbox id=quot;sugarquot; label=quot;Sugarquot; checked=quot;truequot;/> <checkbox id=quot;icequot; label=quot;Icequot; checked=quot;falsequot; oncommand=quot;alert(this.checked);quot;/> <radiogroup onselect=quot;alert(this.selectedItem.id);quot;> <radio id=quot;nonequot; label=quot;Nonequot; disabled=quot;truequot;/> <radio id=quot;halfquot; label=quot;Halfquot; /> <radio id=quot;fullquot; label=quot;Fullquot; selected=quot;truequot;/> </radiogroup>
  • 47. Menus • In XUL, the following are similar!
  • 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>
  • 51. <menupopup> (III) • For popup=quot;xquot; or context=quot;xquot;: <label value=quot;Left-Click here!quot; popup=quot;mymenuquot; /> <label value=quot;Right-Click here!quot; context=quot;mymenuquot;/> <menupopup id=quot;mymenuquot;> <menuitem label=quot;Aboutquot; accesskey=quot;Aquot; /> <menuitem label=quot;Testquot; accesskey=quot;Tquot; /> </menupopup>
  • 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
  • 54. <dialog> example <?xml version=quot;1.0quot;?> <?xml-stylesheet href=quot;chrome://global/skin/global.cssquot; type=quot;text/cssquot;?> <dialog id=quot;mydialogquot; title=quot;Dialog Examplequot; xmlns=quot;http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xulquot; buttons=quot;accept,cancelquot; buttonlabelcancel=quot;Cancelquot; buttonlabelaccept=quot;Sendquot; ondialogaccept=quot;alert('Thank you, ' + document.getElementById('name').value + '!');quot; ondialogcancel=quot;alert('canceled!');quot;> <dialogheader title=quot;Hello!quot; description=quot;Welcome to the my dialog!quot;/> <vbox> <label value=quot;Please introduce yourself :)quot; /> <hbox> <label value=quot;Your Name:quot; control=quot;namequot; accesskey=quot;Nquot; /> <textbox id=quot;namequot; value=quot;quot; /> </hbox> </vbox> </dialog>
  • 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
  • 62. Some recommended extensions • Console2 Change Error Console, Speed Up Your Debug Speed
  • 63. Some recommended extensions • DOM Inspector Watch the structure of webpages or XUL pages
  • 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!
  • 66. install.rdf <?xml version=quot;1.0quot; encoding=quot;UTF-8quot;?> <RDF xmlns=quot;http://www.w3.org/1999/02/22-rdf-syntax-ns#quot; xmlns:em=quot;http://www.mozilla.org/2004/em-rdf#quot;> <Description about=quot;urn:mozilla:install-manifestquot;> <em:id>extension-tutorial-may09@moztw.org</em:id> <em:name>MozTW 擴充套件課程用教學套件</em:name> <em:version>0.1</em:version> <em:description>5/9和5/23的教學所使用!</em:description> <em:creator>Littlebtc</em:creator> <em:type>2</em:type> <em:targetApplication> <Description> <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> <!-- Firefox / Iceweasel ... --> <em:minVersion>3.0</em:minVersion> <em:maxVersion>3.6a1pre</em:maxVersion> </Description> </em:targetApplication> </Description> </RDF>
  • 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
  • 91. Try JavaScript Shell • This has the chrome privileges
  • 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!
  • 103. Our Target • Select the text • Right-click to add tag
  • 104. First step • Setup the developing environment
  • 105. Overlay: popup menu <popup id=quot;contentAreaContextMenuquot;> <menuitem id=quot;taghelper2-menuitemquot; label=quot;&taghelper2.menuItem.label;quot; accesskey=quot;&taghelper2.menuItem.accesskey;quot; oncommand=quot;taghelper2.addTags();quot; /> </popup>
  • 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); }
  • 108. The Dialog <?xml version=quot;1.0quot; encoding=quot;UTF-8quot;?> <?xml-stylesheet href=quot;chrome://global/skinquot; type=quot;text/cssquot;?> <!DOCTYPE dialog SYSTEM quot;chrome://taghelper2/locale/taghelper2.dtdquot;> <dialog title=quot;&taghelper2.dialog.title;quot; xmlns=quot;http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xulquot; buttons=quot;accept,cancelquot; onload=quot;taghelper2Dialog.onLoad();quot; ondialogaccept=quot;return taghelper2Dialog.addTags();quot; > <script type=quot;application/x-javascriptquot; src=quot;chrome://taghelper2/content/taghelper2.jsquot; /> <vbox> <label value=quot;&taghelper2.dialog.description.label;quot; id=quot;descriptionquot; /> <textbox value=quot;quot; id=quot;tagsquot; /> </vbox> </dialog>
  • 109. The Script var Cc = Components.classes; var Ci = Components.interfaces; var taghelper2Dialog = { url: null, title: null, onLoad: function() { // Receive Arguments if (window.arguments[0] && window.arguments[0].text) { document.getElementById('tags').value = window.arguments[0].text; this.url = window.arguments[0].url; this.title = window.arguments[0].title; } },
  • 110. The Script (II) addTags: function() { try { var bookmarkServ = Cc[quot;@mozilla.org/browser/nav-bookmarks-service;1quot;] .getService(Ci.nsINavBookmarksService); var uri = Cc[quot;@mozilla.org/network/io-service;1quot;] .getService(Ci.nsIIOService) .newURI(this.url, null, null); /* Check if it was in bookmark */ var checkArray = bookmarkServ.getBookmarkIdsForURI(uri, {}); if (checkArray.length < 1) { var bookmarkId = bookmarkServ.insertBookmark(bookmarkServ.unfiledBookmarksFolder, uri, -1, quot;quot;); bookmarkServ.setItemTitle(bookmarkId, this.title); } /* Add tag to places */ var taggingServ = Cc[quot;@mozilla.org/browser/tagging-service;1quot;] .getService(Ci.nsITaggingService); taggingServ.tagURI(uri, [document.getElementById('tags').value], 1 ); return true; } catch (e) { alert(e); return true; } }, };
  • 111. Result
  • 112. XPI Package Spread your extension!
  • 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/
  • 115. Scripts available • build.sh http://kb.mozillazine.org/Bash_build_script Create XPI with inner JAR attached
  • 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