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.
How to access local file via chrome URL?
-
- Posts: 2
- Joined: November 3rd, 2004, 12:13 am
-
- Posts: 1634
- Joined: November 4th, 2002, 8:34 pm
- Location: Kyoto, Nippon (GMT +9)
- Contact:
Re: How to access local file via chrome URL?
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["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);
var scriptableStream=Components
.classes["@mozilla.org/scriptableinputstream;1"]
.getService(Components.interfaces.nsIScriptableInputStream);
var channel=ioService.newChannel(aURL,null,null);
var input=channel.open();
scriptableStream.init(input);
var str=scriptableStream.read(input.available());
scriptableStream.close();
input.close();
return str;
}
try{
alert(getContents("chrome://browser/content/browser.css"));
alert(getContents("http://www.mozillazine.org/"));
}catch(e){alert(e)}
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.
http://www.xulplanet.com/references/xpc ... _asyncOpen
- mcm_ham
- Posts: 1747
- Joined: June 16th, 2004, 6:09 am
- Location: Christchurch, New Zealand
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 "channel.open()" 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.
Instead of:
Edit
Have filed Bug 304414 for the first issue.
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 "channel.open()" 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;
else
length = input.available();
while (str.length < length)
str += streamIO.read(length - str.length);
Instead of:
Code: Select all
var str=scriptableStream.read(input.available());
Edit
Have filed Bug 304414 for the first issue.
-
- Posts: 4
- Joined: March 21st, 2008, 7:43 pm
First note that you can read an xml file with the chrome url, but for writing you need something like the following...
the above will translate chrome urls to local file adreesses... in another function you could...
Hope this helps. There may be a faster way to do things but this gets the job done.
Code: Select all
function chromeToPath (aPath) {
if (!aPath || !(/^chrome:/.test(aPath)))
return; //not a chrome url
var rv;
var ios = Components.classes['@mozilla.org/network/io-service;1'].getService(Components.interfaces["nsIIOService"]);
var uri = ios.newURI(aPath, "UTF-8", null);
var cr = Components.classes['@mozilla.org/chrome/chrome-registry;1'].getService(Components.interfaces["nsIChromeRegistry"]);
rv = cr.convertChromeURL(uri).spec;
if (/^file:/.test(rv))
rv = this.urlToPath(rv);
else
rv = this.urlToPath("file://"+rv);
return rv;
}
function urlToPath (aPath) {
if (!aPath || !/^file:/.test(aPath))
return ;
var rv;
var ph = Components.classes["@mozilla.org/network/protocol;1?name=file"]
.createInstance(Components.interfaces.nsIFileProtocolHandler);
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["@mozilla.org/file/local;1"]
.createInstance(Components.interfaces.nsILocalFile);
file.initWithPath(somefile);
if (!(file.exists())) {
var fcStream = Components.classes["@mozilla.org/network/file-output-stream;1"]
.createInstance(Components.interfaces.nsIFileOutputStream);
fcStream.init(file, 0x02 | 0x08 | 0x20, 0666, 0); // write, create, truncate
var data = '<xml><rootnode></rootnode>';
fcStream.write(data,data.length);
fcStream.close
}
xmlDoc = document.implementation.createDocument("","",null);
xmlDoc.load("chrome://piratequesting/content/trainingLog.xml");
xmlDoc.onload = function () {
xmlDoc.documentElement.appendChild(....whatever you want to append....);
var foStream = Components.classes["@mozilla.org/network/file-output-stream;1"]
.createInstance(Components.interfaces.nsIFileOutputStream);
//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, "");
foStream.close();
}
}
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
Re: How to access local file via chrome URL?
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
When I try next code (content descriptor in chrome.manifest has "contentacessible=yes" flag)
I get
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) [nsIChannel.open]" 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["@mozilla.org/xul/xul-document;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
Re: How to access local file via chrome URL?
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)
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
Re: How to access local file via chrome URL?
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').
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