Mozilla Firefox  Extension Development Course 2: Advanced Littlebtc OSSF Workshop / MozTW Acitivity The text of the slide ...
Review <ul><li>Do you remember…? </li></ul><ul><ul><li>XUL and controls? </li></ul></ul><ul><ul><li>Some JavaScript techni...
Preference System <ul><li>Make options for your extension </li></ul>
Why preferences? <ul><li>Provide options to user </li></ul><ul><ul><li>Which can be set in an option window </li></ul></ul...
about:config
Available types <ul><li>String </li></ul><ul><li>Integer </li></ul><ul><li>Boolean: true / false </li></ul>
Default Preferences <ul><li>Can be included in the Extension Dir / XPI file </li></ul><ul><li>Will be loaded as default va...
Take an example <ul><li>See defaults/preferences/ tutorial.js </li></ul><ul><li>pref(&quot;extensions.tutorial.option1&quo...
See about:config
Preference System: <prefwindow> <ul><li>Way to make a &quot;option window&quot; </li></ul><ul><li>It is XUL, again </li></...
Set install.rdf, again <ul><li><em:optionsURL>chrome://tutorial/content/options.xul</em:optionsURL> </li></ul><ul><li>This...
<prefpane> <ul><li>Must be a child of <prefwindow> </li></ul><ul><li>Reprensent a pane (tab) in the prefwindow </li></ul><...
<preferences> <preference> <ul><li><preferences>: Container </li></ul><ul><li><preference>: &quot;Magic Attribute&quot; to...
Example: options.xul <ul><li><?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?> </li></ul><ul><li><?xml-stylesheet...
Example: panel2.xul <ul><li><?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?> </li></ul><ul><li><overlay id=&quot...
Result
Part 2: Read/Write in XPCOM <ul><li>XPCOM: nsIPrefService / nsIPrefBranch </li></ul><ul><li>Changes Preferences in JavaScr...
Part 2: Read/Write in XPCOM <ul><li>Then, read/write </li></ul><ul><li>getBoolPref(), setBoolPref() </li></ul><ul><li>getC...
Part 2: Read/Write in XPCOM <ul><li>Examples to run in JavaScript Shell: </li></ul><ul><li>// Get the &quot;extensions.tut...
Part 2: Read/Write in XPCOM <ul><li>Read/Write Unicode Strings: </li></ul><ul><li>(from  https://developer.mozilla.org/en/...
When you should use XPCOM <ul><li>First run: </li></ul><ul><ul><li>Make a default pref to detect first run (Change it afte...
File Processing <ul><li>Access local files </li></ul><ul><li>https://developer.mozilla.org/en/Code_snippets/File_I%2f%2fO ...
The nsIFile / nsILocalFile <ul><li>nsIFile: Cross-platform File I/O interface </li></ul><ul><li>nsILocalFile: extends nsIF...
&quot;Create&quot; a nsILocalFile <ul><li>With a absolute path: </li></ul><ul><li>var file = Components.classes[&quot;@moz...
&quot;Create&quot; nsIFile pointing to special folders <ul><li>Get an object located to Profile Directory: </li></ul><ul><...
How to… <ul><li>Assuming we have a nsIFile object   file , how to </li></ul><ul><li>Get the native path representation of ...
How to… <ul><li>Whether the path is readable/writable/executable/hidden? </li></ul><ul><ul><ul><li>Use  file.isWritable() ...
How to… <ul><li>&quot;Open the file&quot; by the OS? </li></ul><ul><ul><ul><li>file.launch(); </li></ul></ul></ul><ul><li>...
How to… <ul><li>Delete the path? </li></ul><ul><ul><ul><ul><li>file.remove(); </li></ul></ul></ul></ul><ul><ul><ul><ul><li...
How to… <ul><li>How to &quot;run the file&quot; if it is a executable? </li></ul><ul><ul><li>file.launch(); (Not recommend...
How to… <ul><li>Assuming  file  is a nsIFile object refering to a folder path, how to: </li></ul><ul><li>Access a file in ...
File contents read/write <ul><li>https://developer.mozilla.org/en/Code_snippets/File_I%2f%2fO </li></ul><ul><li>A little c...
File Picker / <filefield> <ul><li>File Open / File Save / Select Folder Dialog </li></ul><ul><li>See  https://developer.mo...
File I/O demo 1 <ul><li>A run dialog like Windows, use undocumented  <filefield> </li></ul>
run.xul <ul><li><?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?> </li></ul><ul><li><?xml-stylesheet href=&quot;c...
run.js (partial) <ul><li>browse: function() { </li></ul><ul><li>// Initialize file picker </li></ul><ul><li>var fp =  Cc[&...
run.js (partial 2) <ul><li>go: function() { </li></ul><ul><li>if (this.file && this.file.exists() && this.file.isFile()) {...
URI Problem <ul><li>In XPCOM, nsIURI is a common interface to represent an URI (It can handle all types of URI) </li></ul>...
When you will need nsIURI / nsIFile <ul><li>Downloading files https://developer.mozilla.org/en/Code_snippets/Downloading_F...
Tree <ul><li>A somehow complex XUL structure </li></ul>
What is a tree? <ul><li>A complex item lists </li></ul><ul><li>An item may have some childs </li></ul>
Why is it so complex <ul><li>There are A LOT OF way to implement </li></ul><ul><li>But none of them are NOT trivial   </l...
The easiest: Content Tree <ul><li>(Try XUL Editor!) </li></ul><ul><li>From  https://developer.mozilla.org/En/XUL/Tree </li...
The easiest: Content Tree <ul><li><tree>: Sent a row number as rows attribute is recommended? </li></ul><ul><li><treecols>...
A tree with nested items <ul><li>From  https://developer.mozilla.org/En/XUL/Tree </li></ul><ul><li><tree id=&quot;myTree&q...
Wait, a lot of new thing…? <ul><li><splitter>: Between columns, to make them resizable </li></ul><ul><li>Nested items: <tr...
OK, now, what is wrong? <ul><li>Though we can multiply the tree with DOM, but it will the code will be somehow complex due...
The most common:  Custom TreeView <ul><li>Implements nsITreeView to create a tree </li></ul><ul><li>Set custom tree view i...
Tree Selection / Box Object <ul><li>Tree Selection: Get currently selected items https://developer.mozilla.org/en/XUL_Tuto...
LUNCH TIME AGAIN! <ul><li>Take a break, there is a final boss: SQLite! </li></ul>
Storage: SQLite <ul><li>Great storage choice </li></ul>
What is SQLite? <ul><li>A lightweight relational database management system </li></ul><ul><li>Its C/C++ library is  very s...
SQLite is in … <ul><li>Firefox, Safari, Google Chrome </li></ul><ul><li>Google Gears </li></ul><ul><li>Photoshop lightroom...
Now, make a new database!
Now, make a new database! <ul><li>Find your profile dir and copy the path  Orz </li></ul>
Now, make a new database! <ul><li>Close SQLite manager and restart: </li></ul>
Create a table
Table is ready!
Add a record
Simple way to display SQLite DB <ul><li>Use template https://developer.mozilla.org/en/XUL/Template_Guide/SQLite_Templates ...
students.xul <ul><li><tree flex=&quot;1&quot;> </li></ul><ul><li><treecols> </li></ul><ul><li><treecol id=&quot;col-no&quo...
Explain <ul><li><treechildren  datasources=&quot;profile:tutorial.sqlite&quot; ref=&quot;*&quot; querytype=&quot;storage&q...
mozStorage API <ul><li>Mozilla's way to multiply SQLite database </li></ul><ul><li>So it is XPCOM again …   </li></ul><ul...
Final Demo: &quot;Add a record&quot; function
A SQL preview <ul><li>INSERT INTO students (name, score) VALUES (&quot;Littlebtc&quot;, 30) </li></ul><ul><li>Insert a dat...
students.xul, again <ul><li><hbox> </li></ul><ul><li><label value=&quot;Student Name:&quot; accesskey=&quot;N&quot; contro...
student.js: student.add(); <ul><li>/* use nsIPromptService to alert */ </li></ul><ul><li>/* https://developer.mozilla.org/...
… continued <ul><li>try { // try-catch exception handling </li></ul><ul><li>/* We will see here later */ </li></ul><ul><li...
Connect to DB <ul><li>/* Find the tutorial.sqlite */ </li></ul><ul><li>var file = Components.classes[&quot;@mozilla.org/fi...
Execute a &quot;statement&quot; <ul><li>var sql = &quot;INSERT INTO students (name, score) VALUES (?1, ?2)&quot;; </li></u...
Finally… <ul><li>Don't forget to close your DB!  db.close(); </li></ul>
After try{…} catch{…} <ul><li>We should update the tree and show a message </li></ul><ul><li>/* Update the tree */ </li></...
Working Example
How to do for you later <ul><li>Understand how to CRUD (Create, Read, Update, Delete) in SQLite </li></ul><ul><ul><li>SQL ...
This is the basic! <ul><li>Actually, SQLite storage access with <tree> is usually implemented in Custom Tree View way, bot...
THANK YOU! <ul><li>It is 5:34am, I had finished my slide   </li></ul>
…… .NOT YET!!!
Upcoming SlideShare
Loading in …5
×

Mozilla Firefox Extension Development Course 2: Advanced

2,223 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
2,223
On SlideShare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
35
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Mozilla Firefox Extension Development Course 2: Advanced

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

×