<!DOCTYPE HTML> <html> <!-- https://bugzilla.mozilla.org/show_bug.cgi?id=682305 --> <head> <title>XMLHttpRequest send and channel implemented in JS</title> <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script> <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> </head> <body> <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=682305">Mozilla Bug 682305</a> <p id="display"></p> <div id="content" style="display: none"> </div> <pre id="test"> <script class="testbody" type="application/javascript;version=1.8"> SimpleTest.waitForExplicitFinish(); /* * Register a custom nsIProtocolHandler service * in order to be able to implement *and use* an * nsIChannel component written in Javascript. */ var Cc = Components.classes; var Ci = Components.interfaces; var Cr = Components.results; var Cu = Components.utils; Cu.import("resource://gre/modules/XPCOMUtils.jsm"); var SimpleURI = Cc["@mozilla.org/network/simple-uri;1"]; var ios = Cc["@mozilla.org/network/io-service;1"] .getService(Ci.nsIIOService); var contentSecManager = Cc["@mozilla.org/contentsecuritymanager;1"] .getService(Ci.nsIContentSecurityManager); var PROTOCOL_SCHEME = "jsproto"; function CustomChannel(uri, loadInfo) { this.URI = this.originalURI = uri; this.loadInfo = loadInfo; } CustomChannel.prototype = { URI: null, originalURI: null, loadInfo: null, contentCharset: "utf-8", contentLength: 0, contentType: "text/plain", owner: Cc["@mozilla.org/systemprincipal;1"].createInstance(Ci.nsIPrincipal), securityInfo: null, notificationCallbacks: null, loadFlags: 0, loadGroup: null, name: null, status: Cr.NS_OK, asyncOpen: function(listener, context) { let stream = this.open(); try { listener.onStartRequest(this, context); } catch(e) {} try { listener.onDataAvailable(this, context, stream, 0, stream.available()); } catch(e) {} try { listener.onStopRequest(this, context, Cr.NS_OK); } catch(e) {} }, asyncOpen2: function(listener) { // throws an error if security checks fail var outListener = contentSecManager.performSecurityCheck(this, listener); return this.asyncOpen(outListener, null); }, open: function() { let data = "bar"; let stream = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(Ci.nsIStringInputStream); stream.setData(data, data.length); return stream; }, open2: function() { // throws an error if security checks fail contentSecManager.performSecurityCheck(this, null); return this.open(); }, isPending: function() { return false; }, cancel: function() { throw Cr.NS_ERROR_NOT_IMPLEMENTED; }, suspend: function() { throw Cr.NS_ERROR_NOT_IMPLEMENTED; }, resume: function() { throw Cr.NS_ERROR_NOT_IMPLEMENTED; }, QueryInterface: XPCOMUtils.generateQI([Ci.nsIChannel, Ci.nsIRequest]) }; function CustomProtocol() {} CustomProtocol.prototype = { get scheme() { return PROTOCOL_SCHEME; }, get protocolFlags() { return (Ci.nsIProtocolHandler.URI_NORELATIVE | Ci.nsIProtocolHandler.URI_IS_LOCAL_RESOURCE | Ci.nsIProtocolHandler.URI_DANGEROUS_TO_LOAD); }, get defaultPort() { return -1; }, allowPort: function allowPort() { return false; }, newURI: function newURI(spec, charset, baseURI) { var uri = SimpleURI.createInstance(Ci.nsIURI) uri.spec = spec; return uri.QueryInterface(Ci.nsIURI); }, newChannel2: function newChannel2(URI, loadInfo) { return new CustomChannel(URI, loadInfo); }, newChannel: function newChannel(URI) { return newChannel2(URI); }, QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports, Ci.nsISupportsWeakReference, Ci.nsIProtocolHandler]) }; var gFactory = { register: function() { var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); var classID = Components.ID("{ed064287-1e76-49ba-a28d-dc74394a8334}"); var description = PROTOCOL_SCHEME + ": protocol"; var contractID = "@mozilla.org/network/protocol;1?name=" + PROTOCOL_SCHEME; var factory = XPCOMUtils._getFactory(CustomProtocol); registrar.registerFactory(classID, description, contractID, factory); this.unregister = function() { registrar.unregisterFactory(classID, factory); delete this.unregister; }; } }; // Register the custom procotol handler gFactory.register(); // Then, checks if XHR works with it var xhr = new XMLHttpRequest(); xhr.open("GET", PROTOCOL_SCHEME + ":foo", true); xhr.onload = function () { is(xhr.responseText, "bar", "protocol doesn't work"); gFactory.unregister(); SimpleTest.finish(); } try { xhr.send(null); } catch(e) { ok(false, e); } </script> </pre> </body> </html>