This fails by giving result of 0 instead of 200. Im sure this has to do with xmlhttprequests being not allowed to access local drive but that should only apply to web scope,
XHR for local files will result in status
0. That is normal and doesn't mean there was an error.
XMLHttpRequest
status
refers to actual HTTP server response which is not the case in accessing local files, therefore a 0 is passed as status
.
From: How to convert an overlay extension to restartless
Note: When using XMLHttpRequest to access a file:// URL the request.status is not properly set to 200 to indicate success. In such cases, request.readyState == 4, request.status == 0 and request.response will evaluate to true.
Update:
Personally I would use the API and not bother with status
Example from: Connecting to Remote Content
let url = "http://www.example.com/";
let request = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]
.createInstance(Components.interfaces.nsIXMLHttpRequest);
request.onload = function(aEvent) {
// code to do on success
//window.alert("Response Text: " + aEvent.target.responseText);
};
request.onerror = function(aEvent) {
// there was a problem, handle error
//window.alert("Error Status: " + aEvent.target.status);
};
request.open("GET", url, true);
request.send(null);
I use a modified version of above in my own add-ons.
Thanks to @erosman an XHR to local file always returns status 0 but there is data in it. So I modified my xhr function to check on load if scheme of url is file uri and if its file uri than it accepts request.
var {Cu: utils, Cc: classes, Ci: instances } = Components;
Cu.import('resource://gre/modules/Services.jsm');
Cu.import('resource://gre/modules/osfile.jsm');
var pathh = OS.Path.toFileURI(OS.Path.join(OS.Constants.Path.desktopDir, 'mdn.png'));
xhr(pathh, data => {
Services.prompt.alert(null, 'XHR Success', data);
});
/****my xhr func****/
function xhr(url, cb) {
let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);
let handler = ev => {
evf(m => xhr.removeEventListener(m, handler, !1));
Services.ww.activeWindow.alert('ev.type=' + ev.type);
switch (ev.type) {
case 'load':
if (xhr.status == 200) {
cb(xhr.response);
break;
} else if (xhr.status == 0) {
var uritest = Services.io.newURI(url, null, null);
if (uritest.schemeIs("file")) {
//http://stackoverflow.com/a/25585661/1828637
//xhr'ing file uri always returns status 0 so this is not a real error
//so lets call cb and break
cb(xhr.response);
break;
} else {
//dont break so it goes into default error report
console.log('uri scheme is not file so it was real error, scheme was: ', uritest.scheme);
}
}
default:
Services.prompt.alert(null, 'XHR Error', 'Error Fetching Package: ' + xhr.statusText + ' [' + ev.type + ':' + xhr.status + ']');
break;
}
};
let evf = f => ['load', 'error', 'abort'].forEach(f);
evf(m => xhr.addEventListener(m, handler, false));
xhr.mozBackgroundRequest = true;
xhr.open('GET', url, true);
xhr.channel.loadFlags |= Ci.nsIRequest.LOAD_ANONYMOUS | Ci.nsIRequest.LOAD_BYPASS_CACHE | Ci.nsIRequest.INHIBIT_PERSISTENT_CACHING;
//xhr.responseType = "arraybuffer"; //dont set it, so it returns string, you dont want arraybuffer. you only want this if your url is to a zip file or some file you want to download and make a nsIArrayBufferInputStream out of it or something
xhr.send(null);
}