blob: d675c2f2f435c3883d6a50feb9bda119205969cb [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
Jeff Thompson57d07382012-10-29 23:25:54 -070014/* Create an nsIChannel for returning content to the caller of asyncOpen.
15 * For requestContent detail, see asyncOpen.
Jeff Thompson08ab3cd2012-10-08 02:56:20 -070016 */
17function ContentChannel(uri, requestContent) {
18 this.requestContent = requestContent;
19
20 this.done = false;
21
Jeff Thompson60c95c82012-10-28 22:15:32 -070022 this.name = uri.spec;
23 // This is set by the caller of asyncOpen.
Jeff Thompson08ab3cd2012-10-08 02:56:20 -070024 this.loadFlags = 0;
25 this.loadGroup = null;
26 this.status = 200;
27
28 // We don't know these yet.
29 this.contentLength = -1;
30 this.contentType = null;
31 this.contentCharset = null;
32 this.URI = uri;
33 this.originalURI = uri;
34 this.owner = null;
35 this.notificationCallback = null;
36 this.securityInfo = null;
Jeff Thompson57d07382012-10-29 23:25:54 -070037
38 // Save the mostRecentWindow from the moment of creating the channel.
39 var wm = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);
40 this.mostRecentWindow = wm.getMostRecentWindow("navigator:browser");
Jeff Thompson08ab3cd2012-10-08 02:56:20 -070041}
42
43ContentChannel.prototype = {
44 QueryInterface: function(aIID) {
45 if (aIID.equals(Ci.nsISupports))
46 return this;
47
48 if (aIID.equals(Ci.nsIRequest))
49 return this;
50
51 if (aIID.equals(Ci.nsIChannel))
52 return this;
53
54 throw Cr.NS_ERROR_NO_INTERFACE;
55 },
56
57 isPending: function() {
58 return !this.done;
59 },
60
61 cancel: function(aStatus){
62 this.status = aStatus;
63 this.done = true;
64 },
65
66 suspend: function(aStatus){
67 this.status = aStatus;
68 },
69
70 resume: function(aStatus){
71 this.status = aStatus;
72 },
73
74 open: function() {
75 throw Cr.NS_ERROR_NOT_IMPLEMENTED;
Jeff Thompson08ab3cd2012-10-08 02:56:20 -070076 }
77};
Jeff Thompson57d07382012-10-29 23:25:54 -070078
79/* Call requestContent(contentListener). When the content is available, you should call
80 * contentListener.onReceivedContent(content, contentType, contentCharset, uri),
81 * which sends the content aListener. If uri is not null, update this.URI and if this.loadFlags
82 * LOAD_INITIAL_DOCUMENT_URI bit is set, then update the URL bar of the mostRecentWindow.
83 * (Note that the caller of asyncOpen sets this.loadFlags.)
84 */
85ContentChannel.prototype.asyncOpen = function(aListener, aContext) {
86 try {
87 var thisContentChannel = this;
88
89 var threadManager = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager);
90 var callingThread = threadManager.currentThread;
91
92 var contentListener = {
93 onReceivedContent : function(content, contentType, contentCharset, uri) {
94 if (uri)
95 thisContentChannel.URI = uri;
96 thisContentChannel.contentLength = content.length;
97 thisContentChannel.contentType = contentType;
98 thisContentChannel.contentCharset = contentCharset;
99
100 var pipe = Cc["@mozilla.org/pipe;1"].createInstance(Ci.nsIPipe);
101 pipe.init(true, true, 0, 0, null);
102 pipe.outputStream.write(content, content.length);
103 pipe.outputStream.close();
104
105 // nsIChannel requires us to call aListener on its calling thread.
106 // Set dispatch flags to 0 to return immediately.
107 callingThread.dispatch({
108 run: function() {
109 aListener.onStartRequest(thisContentChannel, aContext);
110 // Load flags bit 19 "LOAD_INITIAL_DOCUMENT_URI" means this channel is
111 // for the main window with the URL bar.
112 if (uri && thisContentChannel.loadFlags & (1<<19))
113 // aListener.onStartRequest may set the URL bar but now we update it.
114 thisContentChannel.mostRecentWindow.gURLBar.value =
115 thisContentChannel.URI.spec;
116
117 aListener.onDataAvailable(thisContentChannel, aContext,
118 pipe.inputStream, 0, content.length);
119
120 thisContentChannel.done = true;
121 aListener.onStopRequest(thisContentChannel, aContext,
122 thisContentChannel.status);
123 }
124 }, 0);
125 }
126 };
127
128 this.requestContent(contentListener);
129 } catch (ex) {
130 dump("ContentChannel.asyncOpen exception: " + ex + "\n");
131 }
132};
133