How to access local file via chrome URL?

Talk about add-ons and extension development.
Posts: 2
Joined: November 3rd, 2004, 12:13 am

Post Posted November 3rd, 2004, 12:21 am

Hi all,

in my Wikipedia extension I want to read a locale specific XML file from "chrome://wikipedia/locale/templates.xml". I have code using the nsILocalFile interface which definitely works for windows filename like c:\test.txt using initWithPath() but does not work for such a chrome URL. What do I need to do to translate the chrome URL to a local file name or do I need to use another interface?

Ciao and Thanks, Michael.

Posts: 1634
Joined: November 4th, 2002, 8:34 pm
Location: Kyoto, Nippon (GMT +9)

Post Posted November 3rd, 2004, 1:23 am

Bananeweizen wrote:What do I need to do to translate the chrome URL to a local file name or do I need to use another interface?

A file in a package is not a normal local file, so there might not be no "path". How about such a script?
Code: Select all
function getContents(aURL){
  var ioService=Components.classes[";1"]
  var scriptableStream=Components

  var channel=ioService.newChannel(aURL,null,null);
  return str;


Note: Such a synch reading freezes the UI during its operation. If the contents is too large to put up with waiting for the result, please use asyncOpen instead. ... _asyncOpen


User avatar
Posts: 1747
Joined: June 16th, 2004, 6:09 am
Location: Christchurch, New Zealand

Post Posted August 11th, 2005, 7:23 pm

Very useful Torisugari,

I have one problem though, in my extension I'm allowing the user to set the URL path to load from. On Deer Park Alpha though if it is set to a directory like "file:///C:/" then "" works (on Fx 1.0.6 it throws a not implemented exception) and crashes on the scriptable stream read because "input.available()" returns a very large number.

Secondly I've found when reading files from a website address (http://...), it often does not read more then a single packet (I'm guessing) cutting the file off. Some astute person helped by suggesting this code which fixed that problem.

Code: Select all
var length, str = "";

if (channel.contentLength > 0)
  length = channel.contentLength;
  length = input.available();
while (str.length < length)
  str += - str.length);

Instead of:

Code: Select all

Have filed Bug 304414 for the first issue.

Posts: 9
Joined: January 24th, 2007, 3:59 pm

Post Posted March 22nd, 2007, 6:00 pm

How could I extend the example Torisugari posted so that I can stream in well formed XML from a chrome path and then manipulate it/read it via DOM methods???


Posts: 4
Joined: March 21st, 2008, 7:43 pm

Post Posted March 31st, 2008, 8:30 pm

First note that you can read an xml file with the chrome url, but for writing you need something like the following...

Code: Select all
function chromeToPath (aPath) {

   if (!aPath || !(/^chrome:/.test(aPath)))
      return; //not a chrome url
   var rv;
      var ios = Components.classes[';1'].getService(Components.interfaces["nsIIOService"]);
        var uri = ios.newURI(aPath, "UTF-8", null);
        var cr = Components.classes[';1'].getService(Components.interfaces["nsIChromeRegistry"]);
        rv = cr.convertChromeURL(uri).spec;

        if (/^file:/.test(rv))
          rv = this.urlToPath(rv);
          rv = this.urlToPath("file://"+rv);

      return rv;

function urlToPath (aPath) {

    if (!aPath || !/^file:/.test(aPath))
      return ;
    var rv;
   var ph = Components.classes[";1?name=file"]
    rv = ph.getFileFromURLSpec(aPath).path;
    return rv;

the above will translate chrome urls to local file adreesses... in another function you could...

Code: Select all
function doXmlStuff () {
   var somefile = chromeToPath("chrome://path/to/file");
   var xmlDoc;
   var file = Components.classes[";1"]
   if (!(file.exists())) {
      var fcStream = Components.classes[";1"]
      fcStream.init(file, 0x02 | 0x08 | 0x20, 0666, 0); // write, create, truncate

      var data = '<xml><rootnode></rootnode>';

   xmlDoc = document.implementation.createDocument("","",null);
   xmlDoc.onload = function () {
      xmlDoc.documentElement.appendChild(....whatever you want to append....);
      var foStream = Components.classes[";1"]
      //clear the file for writing the new doc
      foStream.init(file, 0x02 | 0x08 | 0x20, 0666, 0); // write, create, truncate
      var ser = new XMLSerializer();
      //write the serialized XML to file
      ser.serializeToStream(xmlDoc, foStream, "");

Hope this helps. There may be a faster way to do things but this gets the job done.

Posts: 4
Joined: June 18th, 2006, 8:22 am

Post Posted January 8th, 2009, 10:27 am

So, is there a way to get a file content from within xpi package ?

I need do it in js xpcom.

When I try Torisugari approach (second post in this theme) I get
Code: Select all
[Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) []"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: ...

When I try next code (content descriptor in chrome.manifest has "contentacessible=yes" flag)
Code: Select all
var domdoc = Components.classes[";1"].createInstance (Components.interfaces.nsIDOMXULDocument);
var doc = domdoc.implementation.createDocument("","",null);
doc.async = false;
doc. load("chrome://myext/content/overlay.xul");

I get
Code: Select all
[Exception... "Access to restricted URI denied"  code: "1012" nsresult: "0x805303f4 (NS_ERROR_DOM_BAD_URI)"  location: ...
immemorial to be born

Posts: 2810
Joined: November 15th, 2004, 5:03 am

Post Posted January 8th, 2009, 11:23 pm

XMLHttpRequest can read xml from chrome:// (even jarred) or file:// like in this reply. If you keep file out of jar you can use like in this reply to get a file:// url, or the var file is an nsIFile, and see Getting_special_files

say if the user specified file location not set and file not in profile folder, read a default from chrome:// or extension's folder,

and for modified xml, if the user specified file location not set, save then read from profile

note: all for chrome code not web page, (requesting xul I had troubles with)

Posts: 4
Joined: June 18th, 2006, 8:22 am

Post Posted January 10th, 2009, 6:38 am

Now I have some more info.
channel. open () fails if document being opened is already used as overlay. (i.e. there is an 'overlay' line in chrome.manifest).
I can't use XMLHttpRequest object because it isn't defined in js xpcom runtime environment. I tried to use nsIXMLHttpRequest but it returns 'null' in '.responseXML' ('.async' property was set to 'false').
immemorial to be born

Return to Extension Development

Who is online

Users browsing this forum: No registered users and 1 guest