Reading Client-side Files with XPCOM

Recently I wrote a tutorial on how to use XPCOM in FireFox to access the user’s disk drive. With XPCOM you can access core browser functionality and with the right permissions can even read files and data off the user’s disk drive, access the network, and much more. In this code walk through we will look at how to read the contents of a file saved on the users desktop using JavaScript code from FireFox.

Before we get started we need to define XPCOM contract id and interface used to access files on the client-side. To access user files, you need to enable the correct privileges and for that you negotiate with the browser Privilege Manager.

// Id and interface for file reference
var fileContractId = "@mozilla.org/file/local;1";
var fileInterface = Components.interfaces.nsILocalFile;

// Id and interface for input stream
var inputContractId = "@mozilla.org/network/file-input-stream;1";
var inputInterface = Components.interfaces.nsIFileInputStream;

// Id and interface for scriptable input stream
var sinputContractId = "@mozilla.org/scriptableinputstream;1";
var sinputInterface = Components.interfaces.nsIScriptableInputStream;

// Request proper security privileges
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");

The XPCOM interfaces we will be using here is the local file which acts as a reference to the file. The file input stream and scriptable input stream will be used to read in the file data.

As noted in the previous XPCOM tutorial, you use the contract id and interfaces get objects that implement them. The next snippet of code will define the path of the file whose data will be read and it will crate the correct file and input file objects to do so.

// Path to file
var readFilePath = "/Users/juixe/Desktop/temp.txt";

// Get file reference
var fileClass = Components.classes[fileContractId];
var file = fileClass.createInstance(fileInterface);
file.initWithPath(readFilePath);

// Get input stream
var inputClass = Components.classes[inputContractId];
var inputStream = inputClass.createInstance(inputInterface);
inputStream.init(file,0x01,null, null);

Notice that to initialize the file input stream I passed in a file reference to the file and a few other parameters. There is some XPCOM documentation on XUL Planet descring these parameters but it is probably best to find sample code to see its usage in the field as I had some difficulty making heads or tails out the documentation.

To get access at the data in the temp file use the scriptable input stream such as the following code.

// Need scriptable input stream to get content
var sinputClass = Components.classes[sinputContractId];
var sinputStream = sinputClass.createInstance(sinputInterface);
sinputStream.init(inputStream);

// Print file data
document.write("File Data: "+sinputStream.read(sinputStream.available()));

Notice that the scriptable input stream was initialized with the input stream created earlier. To read the date in the temp file use read in as many bytes as you would like.

Once done with the input streams you can just close them.

sinputStream.close();
inputStream.close();