test_bug682305.html (3970B)
1 <!DOCTYPE HTML> 2 <html> 3 <!-- 4 https://bugzilla.mozilla.org/show_bug.cgi?id=682305 5 --> 6 <head> 7 <title>XMLHttpRequest send and channel implemented in JS</title> 8 <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> 9 <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script> 10 <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> 11 </head> 12 <body> 13 <a target="_blank" 14 href="https://bugzilla.mozilla.org/show_bug.cgi?id=682305">Mozilla Bug 682305</a> 15 <p id="display"></p> 16 <div id="content" style="display: none"> 17 18 </div> 19 <pre id="test"> 20 <script class="testbody" type="application/javascript"> 21 22 "use strict"; 23 24 SimpleTest.waitForExplicitFinish(); 25 26 /* 27 * Register a custom nsIProtocolHandler service 28 * in order to be able to implement *and use* an 29 * nsIChannel component written in Javascript. 30 */ 31 32 const { ComponentUtils } = ChromeUtils.importESModule( 33 "resource://gre/modules/ComponentUtils.sys.mjs" 34 ); 35 36 var contentSecManager = Cc["@mozilla.org/contentsecuritymanager;1"] 37 .getService(Ci.nsIContentSecurityManager); 38 39 var PROTOCOL_SCHEME = "jsproto"; 40 41 42 function CustomChannel(uri, loadInfo) { 43 this.URI = this.originalURI = uri; 44 this.loadInfo = loadInfo; 45 } 46 CustomChannel.prototype = { 47 URI: null, 48 originalURI: null, 49 loadInfo: null, 50 contentCharset: "utf-8", 51 contentLength: 0, 52 contentType: "text/plain", 53 owner: Cc["@mozilla.org/systemprincipal;1"].createInstance(Ci.nsIPrincipal), 54 securityInfo: null, 55 notificationCallbacks: null, 56 loadFlags: 0, 57 loadGroup: null, 58 name: null, 59 status: Cr.NS_OK, 60 asyncOpen(listener) { 61 // throws an error if security checks fail 62 var outListener = contentSecManager.performSecurityCheck(this, listener); 63 let stream = this.open(); 64 try { 65 outListener.onStartRequest(this); 66 } catch (e) {} 67 try { 68 outListener.onDataAvailable(this, stream, 0, stream.available()); 69 } catch (e) {} 70 try { 71 outListener.onStopRequest(this, Cr.NS_OK); 72 } catch (e) {} 73 }, 74 open() { 75 // throws an error if security checks fail 76 contentSecManager.performSecurityCheck(this, null); 77 78 let data = "bar"; 79 let stream = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(Ci.nsIStringInputStream); 80 stream.setByteStringData(data); 81 return stream; 82 }, 83 isPending() { 84 return false; 85 }, 86 cancel() { 87 throw Components.Exception("", Cr.NS_ERROR_NOT_IMPLEMENTED); 88 }, 89 suspend() { 90 throw Components.Exception("", Cr.NS_ERROR_NOT_IMPLEMENTED); 91 }, 92 resume() { 93 throw Components.Exception("", Cr.NS_ERROR_NOT_IMPLEMENTED); 94 }, 95 QueryInterface: ChromeUtils.generateQI(["nsIChannel", "nsIRequest"]), 96 }; 97 98 99 function CustomProtocol() {} 100 CustomProtocol.prototype = { 101 get scheme() { 102 return PROTOCOL_SCHEME; 103 }, 104 allowPort: function allowPort() { 105 return false; 106 }, 107 newChannel: function newChannel(URI, loadInfo) { 108 return new CustomChannel(URI, loadInfo); 109 }, 110 QueryInterface: ChromeUtils.generateQI(["nsISupportsWeakReference", "nsIProtocolHandler"]), 111 }; 112 113 var gFactory = { 114 register() { 115 Services.io.registerProtocolHandler( 116 PROTOCOL_SCHEME, 117 new CustomProtocol(), 118 Ci.nsIProtocolHandler.URI_NORELATIVE | 119 Ci.nsIProtocolHandler.URI_IS_LOCAL_RESOURCE | 120 Ci.nsIProtocolHandler.URI_DANGEROUS_TO_LOAD, 121 -1 122 ); 123 124 this.unregister = function() { 125 Services.io.unregisterProtocolHandler(PROTOCOL_SCHEME); 126 delete this.unregister; 127 }; 128 }, 129 }; 130 131 // Register the custom procotol handler 132 gFactory.register(); 133 134 // Then, checks if XHR works with it 135 var xhr = new XMLHttpRequest(); 136 xhr.open("GET", PROTOCOL_SCHEME + ":foo", true); 137 xhr.onload = function() { 138 is(xhr.responseText, "bar", "protocol doesn't work"); 139 gFactory.unregister(); 140 SimpleTest.finish(); 141 }; 142 try { 143 xhr.send(null); 144 } catch (e) { 145 ok(false, e); 146 } 147 </script> 148 </pre> 149 </body> 150 </html>