Accessing Local Files With Mozilla XPCOM

A few months back I took a look at TIBCO General Interface, an AJAX/Web Development framework with an IDE/Builder than runs on your browser. The one thing that amazed me about General Interface was that it saved files to your local disk drive from the browser.

Earlier today I was experimenting with TiddlyWiki, a wiki that is self contained in one file and noticed that it can also save files to your hard drive from the browser. TiddlyWiki is a entire wiki system written in HTML, CSS, and JavaScript and self contained in a single HTML file. When you make a wiki edit, TiddlyWiki writes and saves the change to your local disk drive. To learn more about how to go about doing this I took a peak at the page source code, which was like opening a can of gummy worms.

As you can imagine, saving a file to the local disk from the browser is not a standardized process. IE uses ActiveX controls to go about doing this, will FireFox uses XPCOM objects. In this article I will explore getting at local files from Firefox using XPCOM.

XPCOM is Mozilla’s Cross-Platform Component Object Model used in FireFox. Many of FireFox’s services and component objects, such as your bookmarks, are available from through XPCOM. XPCOM authors can create components in either JavaScript or C which can then be added onto Mozilla as an extension. FireFox by default has a large set of core XPCOM services and objects. Once these components are available in your browser you can make use of them in JavaScript. To better illustrate this we will use the local file component in Firefox to read data from your local disk.

To get a reference to a XPCOM object you need a contract ID, which is like a registry entry string identifier for the object component, and an interface for that object. The XPCOM interface is just like a Java interface in that it defines methods and can inherit from other interfaces.

var fileContractId = "@mozilla.org/file/local;1";
var fileInterface = Components.interfaces.nsILocalFile;

Some components, such as the local file need special privileges, since you wouldn’t want any web page to read and write files on your local system. To enable the privileges you need to invoke the following JavaScript code in your script which asks the end user for these privileges.

netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");

Now that we have the component contract id, interface, and the right permissions we can create a file object.

var localFileClass = Components.classes[fileContractId];
var file = localFileClass.createInstance(fileInterface);

For the most part, a local file object is just a reference to a file. The nsILocalFile interface has methods that you would expect from a file reference such as append, create, copyTo, exists, isWritable, isReadable, isDirectory, isFile. The nsILocalFile interface also has attributes such as leafName and fileSize.

Once the file object has been created you can use any of the methods defined in the interface. The first method we should use is the initWithPath which set the path to the file.

file.initWithPath('/Users/juixe/Desktop/temp.txt');

Now that the file has been created and initialized properly, we can find out the file size and if it is a file or directory with code like the following.

document.write("The file "+file.leafName+" has "+file.fileSize+" bytes of data.");
document.write("Does file exists? "+file.exists());
document.write("Is file writable?"+file.isWritable());
document.write("Is file readable?"+file.isReadable());
document.write("Is file directory?"+file.isDirectory());
document.write("Is file file?"+file.isFile());

In this article we just scratched at the surface of what you can do with XPCOM, in the next article I’ll go over the code to read and write bytes to a file using a file input/output stream. If you can’t wait ’till next time, just view the source code of TiddlyWiki….