XUL:File Input

Here is a simple implementation of a file input control written in XBL. I tried returning a stream instead of a string from the inputText property, but the calling script didn't have the priviliges to call the readLine methods and such. Instead, I used an interface similar to XMLHttpRequest. Perhaps I should add a inputXML property.


<?xml version="1.0"?>
<bindings xmlns="http://www.mozilla.org/xbl" xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 <binding id="fileinput">
   <content>
     <xul:textbox flex="1" readonly="true"/>
     <xul:button label="Browse..."/>
   </content>
   
   <implementation>
     <constructor><![CDATA[
         var textbox = document.getAnonymousNodes(this)[0];
         var button = document.getAnonymousNodes(this)[1];
         textbox.thefile = null;

         var pickFunc = function pickFile() {
           netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
           var nsIFilePicker = Components.interfaces.nsIFilePicker;
           var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
           fp.init(window, "Select a File", nsIFilePicker.modeOpen);
           fp.appendFilters( nsIFilePicker.filterAll );
           var res = fp.show();
           if (res == nsIFilePicker.returnOK) {
             textbox.thefile = fp.file;
             textbox.value = textbox.thefile.path;
           } else {
             textbox.thefile = null;
             textbox.value = "";
           }
         }
         button.addEventListener("command", pickFunc, false);
     ]]></constructor>

     <property name="inputText" readonly="true">
       <getter><![CDATA[
           var textbox = document.getAnonymousNodes(this)[0];
           if (textbox.thefileĀ != null) {
             netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
             var is = Components.classes["@mozilla.org/network/file-input-stream;1"]
               .createInstance( Components.interfaces.nsIFileInputStream );
             var sstream = Components.classes["@mozilla.org/scriptableinputstream;1"]
                .createInstance(Components.interfaces.nsIScriptableInputStream);

             is.init( textbox.thefile, 0x01, 00004, null);
             sstream.init(is);

             var data = "";
             var count = 0;

             while (sstream.available() > 0) {
               count = sstream.available();
               if (count > 2048) {
                 count = 2048;
               }
               data += sstream.read(count);
             }
             return data;
           } else {
             return "";
           }
       ]]></getter>
     </property>
   </implementation>
 </binding>
</bindings>