// XHR -- XMLHttpRequest // Argmunets // // url // method // data // headers // Accept // Referer // User-Agent etc... // onload // onerror // onreadeychange // async (default: true) // Arguments of onload/onerror // // channel // responseText // responseHeaders // requestHeaders // status // finalUrl // etc... // TODO: // authentication // Example /* var opt = { url : 'http://localhost/index.rdf' , method : 'head' , headers : { 'Referer' : 'http://example.com/referer' , 'User-Agent' : 'Mozilla/5.0 foo bar baz' } , onload : function(response){ alert('onload \n\n' + response.responseXML) alert('onload \n\n' + response.requestHeaders) } , onerror : function(response){ alert('onerror \n\n' + response.responseXML) } } XHR(opt); */ function XHR({method,url,headers,data,onload,onerror,onreadystatechange,overrideMimeType,async}){ const Ci = Components.interfaces; const Cc = Components.classes; async = (typeof async == 'undefined') ? true : !!async; var cancel = false; var xhr = new XMLHttpRequest(); xhr.mozBackgroundRequest = async; xhr.open(method || (method = data ? "post" : "get"), url, async); if(overrideMimeType) xhr.overrideMimeType(overrideMimeType); xhr.onload = function(){ addHeadersInfo(); if(onload && !cancel) onload(xhr); }; xhr.onerror = function(){ addHeadersInfo(); if(onerror && !cancel) onerror(xhr); }; if(method == "post") xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); var referrer; if(headers){ for(var header in headers){ if(headers.hasOwnProperty(header)){ if(header == "Referer"){ referrer = headers[header]; }else{ xhr.setRequestHeader(header, headers[header]); } } } } if(referrer){ var RefererSetter = { observe: function(aSubject, aTopic, aData){ if ((aTopic == 'http-on-modify-request') && (typeof Components != "undefined")) { aSubject.QueryInterface(Ci.nsIHttpChannel); if(aSubject.originalURI.spec == url){ observer.removeObserver(RefererSetter, aTopic, false); aSubject.setRequestHeader('Referer',referrer,false); } } } }; var observer = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService); observer.addObserver(RefererSetter, "http-on-modify-request", false); } function addHeadersInfo(){ if(!xhr.channel.contentCharset && !overrideMimeType){ // wrong charset var mimeType = getEncoding(xhr.responseText); if(mimeType){ cancel = true; XHR({ method: method , url: url , headers: headers , data: data , onload: onload , onerror: onerror , onreadystatechange: onreadystatechange , overrideMimeType: mimeType , async: async }); return; } } xhr.channel.QueryInterface(Ci.nsIHttpChannel); xhr.responseHeaders = {}; xhr.channel.visitResponseHeaders({visitHeader: function(aHeader,aValue){xhr.responseHeaders[aHeader] = aValue}}); xhr.requestHeaders = {}; xhr.channel.visitRequestHeaders({visitHeader: function(aHeader,aValue){xhr.requestHeaders[aHeader] = aValue}}); xhr.finalUrl = xhr.channel.URI.spec; } function getEncoding(text){ var matched = text.match(new RegExp(">>'] (Arrow.fromCPS(function(x, k){ log('XHR.Arrow ', x) }))); arrow.run(); } // XHR.ArrowParallel --- XHR.ArrowParallel = function(opts){ var arrow = new Arrow; arrow.cpsFunction = function(x, k) { var arrows = this.arrows; var results = []; var count = arrows.length; for (var i = 0; i < arrows.length; i++) { with ({ i: i }) { arrows[i].callCPS(x, function(y) { results[i] = y; if (!--count) k(results) }); } } } arrow.type = '&&&'; arrow.arrows = opts.map(function(opt){ return XHR.Arrow(opt); }); return arrow; } XHR.ArrowParallel.Test = function(){ ((XHR.ArrowParallel([{url: "http://white.s151.xrea.com/"}, {url: "http://white.s151.xrea.com/wiki/"}, {url: "http://white.s151.xrea.com/blog/"}])) ['>>>'] (Arrow.fromCPS(function(x, k){ log('xhr response list:', x) }))).run(); }