<!
DOCTYPE HTML>
<
html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=682305
-->
<
head>
<
title>XMLHttpRequest send and channel implemented in JS</
title>
<
script 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">
"use strict";
SimpleTest.waitForExplicitFinish();
/*
* Register a custom nsIProtocolHandler service
* in order to be able to implement *and use* an
* nsIChannel component written in Javascript.
*/
const { ComponentUtils } = ChromeUtils.importESModule(
"resource://gre/modules/ComponentUtils.sys.mjs"
);
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(listener) {
// throws an error if security checks fail
var outListener = contentSecManager.performSecurityCheck(this, listener);
let stream = this.open();
try {
outListener.onStartRequest(this);
} catch (e) {}
try {
outListener.onDataAvailable(this, stream, 0, stream.available());
} catch (e) {}
try {
outListener.onStopRequest(this, Cr.NS_OK);
} catch (e) {}
},
open() {
// throws an error if security checks fail
contentSecManager.performSecurityCheck(this, null);
let data =
"bar";
let stream = Cc[
"@mozilla.org/io/string-input-stream;1"].createInstance(Ci.nsIStrin
gInputStream);
stream.setByteStringData(data);
return stream;
},
isPending() {
return false;
},
cancel() {
throw Components.Exception("", Cr.NS_ERROR_NOT_IMPLEMENTED);
},
suspend() {
throw Components.Exception("", Cr.NS_ERROR_NOT_IMPLEMENTED);
},
resume() {
throw Components.Exception("", Cr.NS_ERROR_NOT_IMPLEMENTED);
},
QueryInterface: ChromeUtils.generateQI(["nsIChannel", "nsIRequest"]),
};
function CustomProtocol() {}
CustomProtocol.prototype = {
get scheme() {
return PROTOCOL_SCHEME;
},
allowPort: function allowPort() {
return false;
},
newChannel: function newChannel(URI, loadInfo) {
return new CustomChannel(URI, loadInfo);
},
QueryInterface: ChromeUtils.generateQI(["nsISupportsWeakReference", "nsIProtocolHandler"]),
};
var gFactory = {
register() {
Services.io.registerProtocolHandler(
PROTOCOL_SCHEME,
new CustomProtocol(),
Ci.nsIProtocolHandler.URI_NORELATIVE |
Ci.nsIProtocolHandler.URI_IS_LOCAL_RESOURCE |
Ci.nsIProtocolHandler.URI_DANGEROUS_TO_LOAD,
-1
);
this.unregister = function() {
Services.io.unregisterProtocolHandler(PROTOCOL_SCHEME);
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>