Your SlideShare is downloading. ×
Mozilla Firefox Extension Development Course 2: Advanced
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Introducing the official SlideShare app

Stunning, full-screen experience for iPhone and Android

Text the download link to your phone

Standard text messaging rates apply

Mozilla Firefox Extension Development Course 2: Advanced

1,945
views

Published on


0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
1,945
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
34
Comments
0
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Mozilla Firefox Extension Development Course 2: Advanced 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. Review
    • Do you remember…?
      • XUL and controls?
      • Some JavaScript technique?
      • install.rdf and chrome.manifest?
      • Some XPCOM introduction?
  • 3. Preference System
    • Make options for your extension
  • 4. Why preferences?
    • Provide options to user
      • Which can be set in an option window
      • Or in the program operation
    • Record user's choice
  • 5. about:config
  • 6. Available types
    • String
    • Integer
    • Boolean: true / false
  • 7. Default Preferences
    • Can be included in the Extension Dir / XPI file
    • Will be loaded as default value of preferences
    • Place .js files in [ext-dir] /defaults/preferences/
    • Example of .js file content of default preferences : pref("extensions. extensionname .preferencename", false);
      • Name: has a widely used naming convention
      • Value: Boolean / Integer / String
  • 8. Take an example
    • See defaults/preferences/ tutorial.js
    • pref("extensions.tutorial.option1", false);
    • pref("extensions.tutorial.option2", "");
    • pref("extensions.tutorial.option3", 32);
    • pref("extensions.tutorial.default_editor", "");
  • 9. See about:config
  • 10. Preference System: <prefwindow>
    • Way to make a &quot;option window&quot;
    • It is XUL, again
    • But it has a special system, in that system, you don't need to write too much JavaScript/XPCOM to support changing preferences.
  • 11. Set install.rdf, again
    • <em:optionsURL>chrome://tutorial/content/options.xul</em:optionsURL>
    • This will point the &quot;Options&quot; button of your extension to the corresponding XUL pages:
  • 12. <prefpane>
    • Must be a child of <prefwindow>
    • Reprensent a pane (tab) in the prefwindow
    • Attributes:
      • label
      • image
      • onpaneload: a onload-like on this panel
      • src: Content can be external XUL <prefpane id=&quot;paneGeneral&quot; label=&quot;General&quot; src=&quot;chrome://path/to/paneOverlay.xul&quot;/>
  • 13. <preferences> <preference>
    • <preferences>: Container
    • <preference>: &quot;Magic Attribute&quot; to hold the actual preference, attributes:
      • id
      • name: Corresponding preference name
      • type: bool/string/ unichar /int/file
    • In controls, use preference=&quot;id&quot; to connect the magic!
  • 14. Example: options.xul
    • <?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?>
    • <?xml-stylesheet href=&quot;chrome://global/skin/&quot; type=&quot;text/css&quot;?>
    • <?xml-stylesheet href=&quot;chrome://mozapps/content/preferences/preferences.css&quot;?>
    • <?xml-stylesheet href=&quot;chrome://browser/skin/preferences/preferences.css&quot;?>
    • <prefwindow xmlns=&quot;http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul&quot;>
    • <prefpane id=&quot;panel1&quot; label=&quot;panel1&quot;>
    • <preferences>
    • <preference name=&quot;extensions.tutorial.option1&quot; id=&quot;extensions.tutorial.option1&quot; type=&quot;bool&quot; />
    • <preference name=&quot;extensions.tutorial.option2&quot; id=&quot;extensions.tutorial.option2&quot; type=&quot;unichar&quot; />
    • </preferences>
    • <checkbox id=&quot;option1&quot; preference=&quot;extensions.tutorial.option1&quot; label=&quot;Check me!&quot; />
    • <hbox>
    • <label value=&quot;Type Your Name:&quot; accesskey=&quot;N&quot; control=&quot;option2&quot; />
    • <textbox id=&quot;option2&quot; preference=&quot;extensions.tutorial.option2&quot; />
    • </hbox>
    • </prefpane>
    • <prefpane id=&quot;panel2&quot; label=&quot;panel2&quot; src=&quot;chrome://tutorial/content/panel2.xul&quot;/>
    • </prefwindow>
  • 15. Example: panel2.xul
    • <?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?>
    • <overlay id=&quot;Pane2Overlay&quot;
    • xmlns=&quot;http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul&quot;>
    • <prefpane id=&quot;panel2&quot;>
    • <preferences>
    • <preference name=&quot;extensions.tutorial.option3&quot; id=&quot;extensions.tutorial.option3&quot; type=&quot;int&quot; />
    • </preferences>
    • <hbox>
    • <label value=&quot;Type a Integer:&quot; accesskey=&quot;I&quot; control=&quot;option3&quot; />
    • <textbox id=&quot;option3&quot; preference=&quot;extensions.tutorial.option3&quot; type=&quot;number&quot; />
    • </hbox>
    • </prefpane>
    • </overlay>
  • 16. Result
  • 17. Part 2: Read/Write in XPCOM
    • XPCOM: nsIPrefService / nsIPrefBranch
    • Changes Preferences in JavaScript
    • First step: Read branch
    • // Get the root branch
    • var prefs = Components.classes[&quot;@mozilla.org/preferences-service;1&quot;] .getService(Components.interfaces.nsIPrefBranch);
    • // Get the &quot;extensions.tutorial.&quot; branch
    • var prefs = Components.classes[&quot;@mozilla.org/preferences-service;1&quot;] .getService(Components.interfaces.nsIPrefService);
    • prefs = prefs.getBranch(&quot;extensions.tutorial.&quot;);
  • 18. Part 2: Read/Write in XPCOM
    • Then, read/write
    • getBoolPref(), setBoolPref()
    • getCharPref(), setCharPref()
      • BEWARE: Not Unicode Compatible!
    • getIntPref() and setIntPref()
  • 19. Part 2: Read/Write in XPCOM
    • Examples to run in JavaScript Shell:
    • // Get the &quot;extensions.tutorial.&quot; branch
    • var prefs = Components.classes[&quot;@mozilla.org/preferences-service;1&quot;] .getService(Components.interfaces.nsIPrefService);
    • prefs = prefs.getBranch(&quot;extensions.tutorial.&quot;);
    • // Get the value of option3 (a number)
    • var option3 = prefs.getIntPref('option3');
    • alert(option3);
    • // Set the value of option1 (a boolean) to true
    • prefs.setBoolPref('option1', true);
    • var option1 = prefs.getBoolPref('option1');
    • alert(option1);
  • 20. Part 2: Read/Write in XPCOM
    • Read/Write Unicode Strings:
    • (from https://developer.mozilla.org/en/Code_snippets/Preferences )
    • // Example 1: getting Unicode value
    • var option2 = prefs.getComplexValue(&quot;option2&quot;, Components.interfaces.nsISupportsString).data;
    • alert(option2);
    • // Example 2: setting Unicode value
    • var str = Components.classes[&quot;@mozilla.org/supports-string;1&quot;]
    • .createInstance(Components.interfaces.nsISupportsString);
    • str.data = &quot; 火狐 &quot;;
    • prefs.setComplexValue(&quot;option2&quot;,
    • Components.interfaces.nsISupportsString, str);
  • 21. When you should use XPCOM
    • First run:
      • Make a default pref to detect first run (Change it after first run processing is ended)
    • Dialog to remember something:
      • Like &quot;Exit Firefox&quot;:
  • 22. File Processing
    • Access local files
    • https://developer.mozilla.org/en/Code_snippets/File_I%2f%2fO
  • 23. The nsIFile / nsILocalFile
    • nsIFile: Cross-platform File I/O interface
    • nsILocalFile: extends nsIFile, can access local filesystem
    • It is a &quot;LOCATION INDICATOR&quot;
    • What can nsILocalFile object do?
      • Check whether the file exists
      • Copy / Delete / Move files
      • Create files / folders
      • Work as a parameter to a lot of function
        • Saving webpage into files, etc…
  • 24. &quot;Create&quot; a nsILocalFile
    • With a absolute path:
    • var file = Components.classes[&quot;@mozilla.org/file/local;1&quot;]
    • .createInstance(Components.interfaces.nsILocalFile);
    • file.initWithPath(&quot;C:amp;quot;);
    • &quot;Path&quot; should be in a &quot;native&quot; way like /home/littlebtc in Linux, C: in Windows
    • file:// URI? Explained later
  • 25. &quot;Create&quot; nsIFile pointing to special folders
    • Get an object located to Profile Directory:
    • // get profile directory
    • var file = Components.classes[&quot;@mozilla.org/file/directory_service;1&quot;]
    • .getService(Components.interfaces.nsIProperties)
    • .get(&quot;ProfD&quot;, Components.interfaces.nsIFile);
    • You can replace the ProfD with:
    With… Where With… Where CurProcD (Firefox) Installation Dir Desk Desktop C:UsersLittlebtcDesktop Home User's Dir C:UsersLittlebtc /home/littlebtc/ Progs &quot;Programs&quot; directory in Windows Start Menu resource:app XULRunner App Directory
  • 26. How to…
    • Assuming we have a nsIFile object file , how to
    • Get the native path representation of a nsIFile?
      • file.path
    • Know whether the path refers to a existed thing?
      • file.exists()
      • Return true or false
    • Distinguish the path which this file object refers to from a folder, a file, or a link, or others?
      • Use file.isFile() file.isFolder() file.isSymlink() file.isSpecial()
  • 27. How to…
    • Whether the path is readable/writable/executable/hidden?
        • Use file.isWritable() file.isReadable() file.isExecutable() file.isHidden()
    • Know the filesize (if it is a file)?
      • file.fileSize
    • The file name without path?
      • file.leafName
    • The parent of the path?
      • file.parent (It is a nsIFile object, and can be null !)
  • 28. How to…
    • &quot;Open the file&quot; by the OS?
        • file.launch();
    • Do something like &quot;Open containing folder&quot; in download manager?
        • file.reveal();
    • Both of them are not work on Unix-like!
  • 29. How to…
    • Delete the path?
          • file.remove();
          • For folder, you can only remove empty folder
    • Copy path?
          • file.copyTo(file2, 'newname');
          • file2 represents the parent path for the target item, if it is null , it will be copied to the same parent of file
    • Move path?
      • file.moveTo(file2, 'newname');
      • file2 is the same as above
      • You can only move empty folder
  • 30. How to…
    • How to &quot;run the file&quot; if it is a executable?
      • file.launch(); (Not recommended)
      • Use nsIProcess: https://developer.mozilla.org/En/Code_snippets/Running_applications
      • nsIProcess cannot accept Unicode parameters on Windows… 
  • 31. How to…
    • Assuming file is a nsIFile object refering to a folder path, how to:
    • Access a file in this directory?
      • file.append('filename'); Then file will be changed, will refer to this file, not the original folder!
    • Access multiple files? Clone object, then append
      • var file1 = file.clone(); // Clone file object file1.append('filename');
    • How to create a subfolder?
      • file.append(&quot;DIR&quot;); // Still, append first if( !file.exists() || !file.isDirectory() ) { // if it doesn't exist, create file.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0777); }
  • 32. File contents read/write
    • https://developer.mozilla.org/en/Code_snippets/File_I%2f%2fO
    • A little complex, why? When it comes to the encoding, it will be complex 
  • 33. File Picker / <filefield>
    • File Open / File Save / Select Folder Dialog
    • See https://developer.mozilla.org/en/nsIFilePicker
    • <filefield> in the <prefwindow>, like Firefox options (UNDOCUMENTED): http://www.xuldev.org/blog/?p=142
    • We will have a small demo!
  • 34. File I/O demo 1
    • A run dialog like Windows, use undocumented <filefield>
  • 35. run.xul
    • <?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?>
    • <?xml-stylesheet href=&quot;chrome://global/skin&quot; type=&quot;text/css&quot;?>
    • <dialog title=&quot;Run application&quot; buttons=&quot;accept,cancel&quot; ondialogaccept=&quot;runApp.go();&quot;
    • xmlns=&quot;http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul&quot;>
    • <script type=&quot;application/x-javascript&quot; src=&quot;chrome://tutorial/content/run.js&quot;/>
    • <hbox>
    • <label value=&quot;Select an file:&quot; accesskey=&quot;F&quot; /> <filefield id=&quot;file&quot; />
    • <button label=&quot;Browse...&quot; oncommand=&quot;runApp.browse();&quot; />
    • </hbox>
    • <grid>
    • <columns> <column flex=&quot;1&quot; /> <column flex=&quot;2&quot; /></columns>
    • <rows>
    • <row> <label value=&quot;File name:&quot; /> <label value=&quot;&quot; id=&quot;file_name&quot; /> </row>
    • <row> <label value=&quot;File size:&quot; /> <label value=&quot;&quot; id=&quot;file_size&quot; /> </row>
    • </rows>
    • </grid>
    • </dialog>
  • 36. run.js (partial)
    • browse: function() {
    • // Initialize file picker
    • var fp = Cc[&quot;@mozilla.org/filepicker;1&quot;].createInstance(Ci.nsIFilePicker);
    • fp.init(window, 'Select a file', Ci.nsIFilePicker.modeOpen);
    • // Set Filter: file types
    • fp.appendFilter('Windows executable', '*.exe');
    • fp.appendFilter('All Files', '*.*');
    • // Show the dialog
    • var result = fp.show();
    • if (result == Ci.nsIFilePicker.returnOK) {
    • this.file = fp.file;
    • // This should not be happened, but this is a demo :P
    • if (!this.file.exists() || !this.file.isFile()) {
    • return;
    • }
    • // Include it into filefield
    • document.getElementById('file').file = this.file;
    • // Load file infos
    • document.getElementById('file_name').value = this.file.leafName;
    • document.getElementById('file_size').value = this.file.fileSize + ' bytes';
    • }
    • },
  • 37. run.js (partial 2)
    • go: function() {
    • if (this.file && this.file.exists() && this.file.isFile()) {
    • this.file.launch();
    • }
    • }
  • 38. URI Problem
    • In XPCOM, nsIURI is a common interface to represent an URI (It can handle all types of URI)
    • nsIURI <-> String URL: Use nsIIOService
      • var uri = Components.classes[&quot;@mozilla.org/network/io-service;1&quot;] .getService(Components.interfaces.nsIIOService) . newURI('http://moztw.org/', null, null);
      • uri.spec will contain the string representation of the URI
    • nsIURI <-> nsIFile
      • var file_uri = Components.classes[&quot;@mozilla.org/network/io-service;1&quot;] .getService(Components.interfaces.nsIIOService) . newFileURI(file); // Assuming file is a nsIFIle
      • var file = file_uri. QueryInterface(Components.interfaces.nsIFileURL) .file;
  • 39. When you will need nsIURI / nsIFile
    • Downloading files https://developer.mozilla.org/en/Code_snippets/Downloading_Files (Basic) http://www.xuldev.org/blog/?p=163 (Advanced, by Gomita, a good intro to nsIWebBrowserPersist)
    • Use Places API (Bookmarks, Tags, History) https://developer.mozilla.org/en/Places
    • Progress listeners https://developer.mozilla.org/en/Code_snippets/Progress_Listeners
    • And much more…
  • 40. Tree
    • A somehow complex XUL structure
  • 41. What is a tree?
    • A complex item lists
    • An item may have some childs
  • 42. Why is it so complex
    • There are A LOT OF way to implement
    • But none of them are NOT trivial 
    • Some is easier but not so easy to be extended
    • Some is harder, but fully functional
  • 43. The easiest: Content Tree
    • (Try XUL Editor!)
    • From https://developer.mozilla.org/En/XUL/Tree
    • <tree flex=&quot;1&quot; rows=&quot;2&quot;>
    • <treecols>
    • <treecol id=&quot;sender&quot; label=&quot;Sender&quot; flex=&quot;1&quot;/> <treecol id=&quot;subject&quot; label=&quot;Subject&quot; flex=&quot;2&quot;/>
    • </treecols>
    • <treechildren>
    • <treeitem>
    • <treerow>
    • <treecell label=&quot;joe@somewhere.com&quot;/> <treecell label=&quot;Top secret plans&quot;/>
    • </treerow>
    • </treeitem>
    • <treeitem>
    • <treerow>
    • <treecell label=&quot;mel@whereever.com&quot;/> <treecell label=&quot;Let's do lunch&quot;/>
    • </treerow>
    • </treeitem>
    • </treechildren>
    • </tree>
  • 44. The easiest: Content Tree
    • <tree>: Sent a row number as rows attribute is recommended?
    • <treecols>, <treecol>: Define the columns
      • Use flex to modify column width in <treecol>
      • Use id to build an identifier of the column
    • <treeitem>, <treerow>: Represents a row
    • <treecell>: Represents a cell
      • Attribute: label
  • 45. A tree with nested items
    • From https://developer.mozilla.org/En/XUL/Tree
    • <tree id=&quot;myTree&quot; flex=&quot;1&quot; hidecolumnpicker=&quot;false&quot; seltype=&quot;single&quot; class=&quot;tree&quot; rows=&quot;5&quot;>
    • <treecols id=&quot;myTree2-treeCols&quot;>
    • <treecol id=&quot;myTree2-treeCol0&quot; primary=&quot;true&quot; flex=&quot;2&quot; label=&quot;Column A&quot; persist=&quot;width&quot; ordinal=&quot;1&quot;/>
    • <splitter class=&quot;tree-splitter&quot; ordinal=&quot;2&quot;/>
    • <treecol id=&quot;myTree2-treeCol1&quot; flex=&quot;1&quot; label=&quot;Column B&quot; persist=&quot;width&quot; ordinal=&quot;3&quot;/>
    • </treecols>
    • <treechildren>
    • <treeitem>
    • <treerow>
    • <treecell label=&quot;1&quot;/> <treecell label=&quot;a&quot;/>
    • </treerow>
    • </treeitem>
    • <!-- Make sure to set container=&quot;true&quot; -->
    • <treeitem container=&quot;true&quot; open=&quot;true&quot;>
    • <treerow>
    • <treecell label=&quot;2&quot;/> <treecell label=&quot;b&quot;/>
    • </treerow>
    • <treechildren>
    • <treeitem>
    • <treerow>
    • <treecell label=&quot;2a&quot;/> <treecell label=&quot;ba&quot;/>
    • </treerow>
    • </treeitem>
    • </treechildren>
    • </treeitem>
    • </treechildren>
    • </tree>
  • 46. Wait, a lot of new thing…?
    • <splitter>: Between columns, to make them resizable
    • Nested items: <treechildren> under <treeitem>
    • hidecolumnpicker=&quot;false&quot;
      • Whether to hide the column picker on the right
      • seltype=&quot;single&quot;: you can select only one item or seltype=&quot;multiple&quot; for multiple selection support
    • persist=&quot;attributename1 attributename2&quot;
      • Make Firefox &quot;remember&quot; user's settings on specific attribute
  • 47. OK, now, what is wrong?
    • Though we can multiply the tree with DOM, but it will the code will be somehow complex due to the bad XUL structure
    • So DOM way is not a popular way if it comes to dynamic content trees
  • 48. The most common: Custom TreeView
    • Implements nsITreeView to create a tree
    • Set custom tree view into view property
    • It can be fully functional and dynamic
      • … But somehow hard: poorly documented and buggy if having bad implementation
      • You should check Firefox's code to understand 
      • It takes me almost 20 hours to make <tree> on NicoFox works and another 20 hours to fix bugs…
    • Are you ready? :D
    • https://developer.mozilla.org/en/XUL_Tutorial/Custom_Tree_Views
    • http://www.xuldev.org/blog/?p=127 (Thank you again, Gomita!)
  • 49. Tree Selection / Box Object
    • Tree Selection: Get currently selected items https://developer.mozilla.org/en/XUL_Tutorial/Tree_Selection
      • A little like text selection we had mentioned at the previous lecture (?)
    • Box Objects: Handle Tree's display Needed, for example, if you need to know the which cell the cursor is at https://developer.mozilla.org/en/XUL_Tutorial/Tree_Box_Objects
  • 50. LUNCH TIME AGAIN!
    • Take a break, there is a final boss: SQLite!
  • 51. Storage: SQLite
    • Great storage choice
  • 52. What is SQLite?
    • A lightweight relational database management system
    • Its C/C++ library is very small (418KB in Firefox 3.5) and very easy-to-use
    • Can use most of the SQL command
    • Resulting database is a single file
    • PUBLIC DOMAIN !(No any copyright restriction)
    • Used by a lot of software / framework
  • 53. SQLite is in …
    • Firefox, Safari, Google Chrome
    • Google Gears
    • Photoshop lightroom, Adobe AIR
    • Skype, McAfee, Songbird
    • PHP, Python…
    • iPhone, Symbian, Android…
    • Almost everywhere!!!!
  • 54. Now, make a new database!
  • 55. Now, make a new database!
    • Find your profile dir and copy the path Orz
  • 56. Now, make a new database!
    • Close SQLite manager and restart:
  • 57. Create a table
  • 58. Table is ready!
  • 59. Add a record
  • 60. Simple way to display SQLite DB
    • Use template https://developer.mozilla.org/en/XUL/Template_Guide/SQLite_Templates
    • Simple, but useful for our demo! :D
    • We will use the template technique and <tree> in the following demo
  • 61. students.xul
    • <tree flex=&quot;1&quot;>
    • <treecols>
    • <treecol id=&quot;col-no&quot; label=&quot;No&quot; flex=&quot;1&quot;/>
    • <treecol id=&quot;col-name&quot; label=&quot;Name&quot; flex=&quot;1&quot;/>
    • <treecol id=&quot;col-score&quot; label=&quot;Score&quot; flex=&quot;1&quot;/>
    • </treecols>
    • <treechildren datasources=&quot;profile:tutorial.sqlite&quot; ref=&quot;*&quot; querytype=&quot;storage&quot; >
    • <template>
    • <query>
    • SELECT * FROM students ORDER BY score DESC
    • </query>
    • <action>
    • <treeitem uri=&quot;?&quot;>
    • <treerow>
    • <treecell label=&quot;?no&quot;/>
    • <treecell label=&quot;?name&quot;/>
    • <treecell label=&quot;?score&quot;/>
    • </treerow>
    • </treeitem>
    • </action>
    • </template>
    • </treechildren>
    • </tree>
  • 62. Explain
    • <treechildren datasources=&quot;profile:tutorial.sqlite&quot; ref=&quot;*&quot; querytype=&quot;storage&quot; >
    • Use SQLite database as a template datasources
    • <template>: <query> and <action>
      • <query>: SQL command
        • SELECT * FROM students: Select all fields from students table
        • ORDER BY score DESC: Order by score field in descendant order
      • <action>: Applied template
        • uri=&quot;?&quot;: (?)
        • Read score field from ?score
  • 63. mozStorage API
    • Mozilla's way to multiply SQLite database
    • So it is XPCOM again … 
    • But it is not so difficult!
    • I don't want to talk in detail, so go straight to examples!
  • 64. Final Demo: &quot;Add a record&quot; function
  • 65. A SQL preview
    • INSERT INTO students (name, score) VALUES (&quot;Littlebtc&quot;, 30)
    • Insert a data into students table
    • Two fields: name and score
    • Their values: Littlebtc and 30
  • 66. students.xul, again
    • <hbox>
    • <label value=&quot;Student Name:&quot; accesskey=&quot;N&quot; control=&quot;new_name&quot; />
    • <textbox id=&quot;new_name&quot; style=&quot;width: 8em;&quot;/>
    • <label value=&quot;Score:&quot; accesskey=&quot;S&quot; control=&quot;new_score&quot; />
    • <textbox id=&quot;new_score&quot; type=&quot;number&quot; style=&quot;width: 4em;&quot; max=&quot;100&quot; min=&quot;0&quot;/>
    • <button label=&quot;Add&quot; oncommand=&quot;students.add();&quot;/>
    • </hbox>
  • 67. student.js: student.add();
    • /* use nsIPromptService to alert */
    • /* https://developer.mozilla.org/en/Code_snippets/Dialogs_and_Prompts */
    • var prompts = Cc[&quot;@mozilla.org/embedcomp/prompt-service;1&quot;]
    • .getService(Ci.nsIPromptService);
    • /* Record user's choice */
    • var name = document.getElementById('new-name').value;
    • var score = document.getElementById('new-score').value;
    • /* Required to enter a name */
    • if (!name) {
    • prompts.alert(null, 'Error', 'Please Enter a Name.');
    • return;
    • }
  • 68. … continued
    • try { // try-catch exception handling
    • /* We will see here later */
    • } catch(e) { // There may be some error in XPCOM, we can handle it
    • prompts.alert(null, 'Error', 'Database/XPCOM Error:' + e);
    • }
    • XPCOM Will throw exception when error
    • So we need a good way to handle it
    • … Or it will be displayed in the error console
  • 69. Connect to DB
    • /* Find the tutorial.sqlite */
    • var file = Components.classes[&quot;@mozilla.org/file/directory_service;1&quot;]
    • .getService(Components.interfaces.nsIProperties)
    • .get(&quot;ProfD&quot;, Components.interfaces.nsIFile);
    • file.append(&quot;tutorial.sqlite&quot;);
    • /* Open database */
    • var storageService = Cc[&quot;@mozilla.org/storage/service;1&quot;]
    • .getService(Ci.mozIStorageService);
    • var db = storageService.openDatabase(file);
  • 70. Execute a &quot;statement&quot;
    • var sql = &quot;INSERT INTO students (name, score) VALUES (?1, ?2)&quot;;
    • var statement = db.createStatement(sql);
    • statement.bindUTF8StringParameter(0, name);
    • statement.bindInt32Parameter(1, score);
    • /* Execute the statement */
    • statement.execute();
    • /* Finallize */
    • statement.finalize();
    • &quot;Statement&quot; is a SQL command in mozStorage
    • Why we should use the &quot;binding&quot; way? Prevent SQL injection , make database safe
    • https://developer.mozilla.org/en/mozIStorageStatement#Binding_Functions
  • 71. Finally…
    • Don't forget to close your DB! db.close();
  • 72. After try{…} catch{…}
    • We should update the tree and show a message
    • /* Update the tree */
    • document.getElementById('students-treechildren')
    • .builder.rebuild();
    • /* Prompt the user */
    • prompts.alert(null, 'OK', 'Thank you!');
  • 73. Working Example
  • 74. How to do for you later
    • Understand how to CRUD (Create, Read, Update, Delete) in SQLite
      • SQL commands: INSERT, SELECT, UPDATE, DELETE
    • Remember: Always Binding , NEVER directly apply variables into SQL command strings
      • Google &quot;SQL Injection&quot; for details
    • SQLite is simple but powerful – have fun!
  • 75. This is the basic!
    • Actually, SQLite storage access with <tree> is usually implemented in Custom Tree View way, both in Firefox and NicoFox
    • That is another reason that I had spent 40 hours on a tree
    • Edit / Remove may be a very hard work
  • 76. THANK YOU!
    • It is 5:34am, I had finished my slide 
  • 77. …… .NOT YET!!!