|
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 type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> |
|
9 <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script> |
|
10 <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/ChromeUtils.js"></script> |
|
11 <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> |
|
12 </head> |
|
13 <body> |
|
14 <a target="_blank" |
|
15 href="https://bugzilla.mozilla.org/show_bug.cgi?id=682305">Mozilla Bug 682305</a> |
|
16 <p id="display"></p> |
|
17 <div id="content" style="display: none"> |
|
18 |
|
19 </div> |
|
20 <pre id="test"> |
|
21 <script class="testbody" type="application/javascript;version=1.8"> |
|
22 SimpleTest.waitForExplicitFinish(); |
|
23 |
|
24 /* |
|
25 * Register a custom nsIProtocolHandler service |
|
26 * in order to be able to implement *and use* an |
|
27 * nsIChannel component written in Javascript. |
|
28 */ |
|
29 |
|
30 var Cc = Components.classes; |
|
31 var Ci = Components.interfaces; |
|
32 var Cr = Components.results; |
|
33 var Cu = Components.utils; |
|
34 |
|
35 Cu.import("resource://gre/modules/XPCOMUtils.jsm"); |
|
36 var SimpleURI = Cc["@mozilla.org/network/simple-uri;1"]; |
|
37 var ios = Cc["@mozilla.org/network/io-service;1"] |
|
38 .getService(Ci.nsIIOService); |
|
39 |
|
40 var PROTOCOL_SCHEME = "jsproto"; |
|
41 |
|
42 |
|
43 function CustomChannel(uri) { |
|
44 this.URI = this.originalURI = uri; |
|
45 } |
|
46 CustomChannel.prototype = { |
|
47 URI: null, |
|
48 originalURI: null, |
|
49 contentCharset: "utf-8", |
|
50 contentLength: 0, |
|
51 contentType: "text/plain", |
|
52 owner: Cc["@mozilla.org/systemprincipal;1"].createInstance(Ci.nsIPrincipal), |
|
53 securityInfo: null, |
|
54 notificationCallbacks: null, |
|
55 loadFlags: 0, |
|
56 loadGroup: null, |
|
57 name: null, |
|
58 status: Cr.NS_OK, |
|
59 asyncOpen: function(listener, context) { |
|
60 let stream = this.open(); |
|
61 try { |
|
62 listener.onStartRequest(this, context); |
|
63 } catch(e) {} |
|
64 try { |
|
65 listener.onDataAvailable(this, context, stream, 0, stream.available()); |
|
66 } catch(e) {} |
|
67 try { |
|
68 listener.onStopRequest(this, context, Cr.NS_OK); |
|
69 } catch(e) {} |
|
70 }, |
|
71 open: function() { |
|
72 let data = "bar"; |
|
73 let stream = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(Ci.nsIStringInputStream); |
|
74 stream.setData(data, data.length); |
|
75 return stream; |
|
76 }, |
|
77 isPending: function() { |
|
78 return false; |
|
79 }, |
|
80 cancel: function() { |
|
81 throw Cr.NS_ERROR_NOT_IMPLEMENTED; |
|
82 }, |
|
83 suspend: function() { |
|
84 throw Cr.NS_ERROR_NOT_IMPLEMENTED; |
|
85 }, |
|
86 resume: function() { |
|
87 throw Cr.NS_ERROR_NOT_IMPLEMENTED; |
|
88 }, |
|
89 QueryInterface: XPCOMUtils.generateQI([Ci.nsIChannel, Ci.nsIRequest]) |
|
90 }; |
|
91 |
|
92 |
|
93 function CustomProtocol() {} |
|
94 CustomProtocol.prototype = { |
|
95 get scheme() { |
|
96 return PROTOCOL_SCHEME; |
|
97 }, |
|
98 get protocolFlags() { |
|
99 return (Ci.nsIProtocolHandler.URI_NORELATIVE | |
|
100 Ci.nsIProtocolHandler.URI_IS_LOCAL_RESOURCE | |
|
101 Ci.nsIProtocolHandler.URI_DANGEROUS_TO_LOAD); |
|
102 }, |
|
103 get defaultPort() { |
|
104 return -1; |
|
105 }, |
|
106 allowPort: function allowPort() { |
|
107 return false; |
|
108 }, |
|
109 newURI: function newURI(spec, charset, baseURI) { |
|
110 var uri = SimpleURI.createInstance(Ci.nsIURI) |
|
111 uri.spec = spec; |
|
112 return uri.QueryInterface(Ci.nsIURI); |
|
113 }, |
|
114 newChannel: function newChannel(URI) { |
|
115 return new CustomChannel(URI); |
|
116 }, |
|
117 QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports, |
|
118 Ci.nsISupportsWeakReference, |
|
119 Ci.nsIProtocolHandler]) |
|
120 }; |
|
121 |
|
122 var gFactory = { |
|
123 register: function() { |
|
124 var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); |
|
125 |
|
126 var classID = Components.ID("{ed064287-1e76-49ba-a28d-dc74394a8334}"); |
|
127 var description = PROTOCOL_SCHEME + ": protocol"; |
|
128 var contractID = "@mozilla.org/network/protocol;1?name=" + PROTOCOL_SCHEME; |
|
129 var factory = XPCOMUtils._getFactory(CustomProtocol); |
|
130 |
|
131 registrar.registerFactory(classID, description, contractID, factory); |
|
132 |
|
133 this.unregister = function() { |
|
134 registrar.unregisterFactory(classID, factory); |
|
135 delete this.unregister; |
|
136 }; |
|
137 } |
|
138 }; |
|
139 |
|
140 // Register the custom procotol handler |
|
141 gFactory.register(); |
|
142 |
|
143 // Then, checks if XHR works with it |
|
144 var xhr = new XMLHttpRequest(); |
|
145 xhr.open("GET", PROTOCOL_SCHEME + ":foo", true); |
|
146 xhr.onload = function () { |
|
147 is(xhr.responseText, "bar", "protocol doesn't work"); |
|
148 gFactory.unregister(); |
|
149 SimpleTest.finish(); |
|
150 } |
|
151 try { |
|
152 xhr.send(null); |
|
153 } catch(e) { |
|
154 ok(false, e); |
|
155 } |
|
156 </script> |
|
157 </pre> |
|
158 </body> |
|
159 </html> |