blob: 12badcf7b06942017c6341745c922cc01c9f5677 [file] [log] [blame]
Jeff Thompson745026e2012-10-13 12:49:20 -07001/*
2 * @author: ucla-cs
3 * See COPYING for copyright and distribution information.
4 */
5
Jeff Thompson08ab3cd2012-10-08 02:56:20 -07006var EXPORTED_SYMBOLS = ["ContentChannel"];
7
8const Cc = Components.classes;
9const Ci = Components.interfaces;
10const Cr = Components.results;
11
12Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
13
14/** Create an nsIChannel where asyncOpen calls requestContent(contentListener). When the content
Jeff Thompson60c95c82012-10-28 22:15:32 -070015 is available, call contentListener.onReceivedContent(content, contentType, contentCharset),
16 which sends the content to the listener passed to asyncOpen and returns after calling its
17 onStopRequest.
Jeff Thompson08ab3cd2012-10-08 02:56:20 -070018 */
19function ContentChannel(uri, requestContent) {
20 this.requestContent = requestContent;
21
22 this.done = false;
23
Jeff Thompson60c95c82012-10-28 22:15:32 -070024 this.name = uri.spec;
25 // This is set by the caller of asyncOpen.
Jeff Thompson08ab3cd2012-10-08 02:56:20 -070026 this.loadFlags = 0;
27 this.loadGroup = null;
28 this.status = 200;
29
30 // We don't know these yet.
31 this.contentLength = -1;
32 this.contentType = null;
33 this.contentCharset = null;
34 this.URI = uri;
35 this.originalURI = uri;
36 this.owner = null;
37 this.notificationCallback = null;
38 this.securityInfo = null;
39}
40
41ContentChannel.prototype = {
42 QueryInterface: function(aIID) {
43 if (aIID.equals(Ci.nsISupports))
44 return this;
45
46 if (aIID.equals(Ci.nsIRequest))
47 return this;
48
49 if (aIID.equals(Ci.nsIChannel))
50 return this;
51
52 throw Cr.NS_ERROR_NO_INTERFACE;
53 },
54
55 isPending: function() {
56 return !this.done;
57 },
58
59 cancel: function(aStatus){
60 this.status = aStatus;
61 this.done = true;
62 },
63
64 suspend: function(aStatus){
65 this.status = aStatus;
66 },
67
68 resume: function(aStatus){
69 this.status = aStatus;
70 },
71
72 open: function() {
73 throw Cr.NS_ERROR_NOT_IMPLEMENTED;
74 },
75
76 asyncOpen: function(aListener, aContext) {
Jeff Thompsonc4bc3692012-10-15 22:18:40 -070077 try {
78 var thisContentChannel = this;
Jeff Thompson60c95c82012-10-28 22:15:32 -070079
80 var threadManager = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager);
81 var callingThread = threadManager.currentThread;
82
Jeff Thompsonc4bc3692012-10-15 22:18:40 -070083 var contentListener = {
84 onReceivedContent : function(content, contentType, contentCharset) {
85 thisContentChannel.contentLength = content.length;
86 thisContentChannel.contentType = contentType;
87 thisContentChannel.contentCharset = contentCharset;
Jeff Thompson08ab3cd2012-10-08 02:56:20 -070088
Jeff Thompsonc4bc3692012-10-15 22:18:40 -070089 var pipe = Cc["@mozilla.org/pipe;1"].createInstance(Ci.nsIPipe);
90 pipe.init(true, true, 0, 0, null);
91 pipe.outputStream.write(content, content.length);
92 pipe.outputStream.close();
Jeff Thompson08ab3cd2012-10-08 02:56:20 -070093
Jeff Thompson60c95c82012-10-28 22:15:32 -070094 // nsIChannel requires us to call aListener on its calling thread.
95 // Set dispatch flags to 1 to wait for it to finish.
96 callingThread.dispatch({
97 run: function() {
98 aListener.onStartRequest(thisContentChannel, aContext);
99 aListener.onDataAvailable(thisContentChannel, aContext,
100 pipe.inputStream, 0, content.length);
Jeff Thompson08ab3cd2012-10-08 02:56:20 -0700101
Jeff Thompson60c95c82012-10-28 22:15:32 -0700102 thisContentChannel.done = true;
103 aListener.onStopRequest(thisContentChannel, aContext,
104 thisContentChannel.status);
105 }
106 }, 1);
Jeff Thompsonc4bc3692012-10-15 22:18:40 -0700107 }
108 };
Jeff Thompson08ab3cd2012-10-08 02:56:20 -0700109
Jeff Thompsonc4bc3692012-10-15 22:18:40 -0700110 this.requestContent(contentListener);
111 } catch (ex) {
112 dump("ContentChannel.asyncOpen exception: " + ex + "\n");
113 }
Jeff Thompson08ab3cd2012-10-08 02:56:20 -0700114 }
115};