2009-12-07 Rolf Bjarne Kvinge <RKvinge@novell.com>
[moon.git] / plugin / firefox / browser-http.inc
blob9d6dd5e077543987b9ff343f794e182cde960089
1 #include <nsCOMPtr.h>
2 #include <nsXPCOM.h>
3 #include <nsIURI.h>
4 #include <nsIServiceManager.h>
5 #include <nsIComponentManager.h>
6 #include <nsComponentManagerUtils.h>
7 #include <nsIIOService.h>
8 #include <nsStringAPI.h>
9 #include <nsIInputStream.h>
10 #include <nsIOutputStream.h>
11 #include <nsIStreamListener.h>
12 #include <nsEmbedString.h>
13 #include <nsIChannel.h>
14 #include <nsIRequest.h>
15 #include <nsIRequestObserver.h>
16 #include <nsIHttpChannel.h>
17 #include <nsIHttpHeaderVisitor.h>
18 #include <nsEmbedString.h>
19 #include <nsIUploadChannel.h>
21 // unfrozen apis
22 #if WITH_LIBXUL_UNSTABLE
23 #include <nsNetError.h>
24 #include <nsIStorageStream.h>
25 #else
26 #include <necko/nsNetError.h>
27 #include <xpcom/nsIStorageStream.h>
28 #endif
30 class GECKO_SYM(HeaderVisitor) : public nsIHttpHeaderVisitor {
31  public:
32         NS_DECL_ISUPPORTS
33         NS_DECL_NSIHTTPHEADERVISITOR
35         GECKO_SYM(HeaderVisitor) (DownloaderResponseHeaderCallback cb, gpointer context)
36         {
37                 this->callback = cb;
38                 this->context = context;
39         }
40         virtual ~GECKO_SYM(HeaderVisitor)()
41         {
42         }
44  private:
45         DownloaderResponseHeaderCallback callback;
46         gpointer context;
49 NS_IMPL_ISUPPORTS1(GECKO_SYM(HeaderVisitor), nsIHttpHeaderVisitor)
51 NS_IMETHODIMP
52 GECKO_SYM(HeaderVisitor)::VisitHeader(const nsACString &header, const nsACString &value)
54         const char *name, *val;
55         PRUint32 nl, vl;
57         nl = NS_CStringGetData (header, &name);
58         vl = NS_CStringGetData (value, &val);
60         name = g_strndup (name, nl);
61         val = g_strndup (val, vl);
63         callback (context, name, val);
65         g_free ((gpointer) name);
66         g_free ((gpointer) val);
68         return NS_OK;
71 class GECKO_SYM(DownloaderResponse) : public DownloaderResponse, public nsIStreamListener {
72  private:
73         nsCOMPtr<nsIChannel> channel;
74         bool aborted;
76  protected:
77         NS_DECL_NSIREQUESTOBSERVER
78         NS_DECL_NSISTREAMLISTENER
80  public:
81         NS_DECL_ISUPPORTS
83         GECKO_SYM(DownloaderResponse) (nsCOMPtr<nsIChannel> channel, DownloaderResponseStartedHandler started, DownloaderResponseDataAvailableHandler available, DownloaderResponseFinishedHandler finished, gpointer context)
84                 : DownloaderResponse (started, available, finished, context)
85         {
86                 this->channel = channel;
87                 this->aborted = false;
88         }
90         virtual ~GECKO_SYM(DownloaderResponse) ()
91         {
92         }
94         virtual void ref ()
95         {
96                 AddRef ();
97         }
98         
99         virtual void unref ()
100         {
101                 Release ();
102         }
104         void Abort ();
105         virtual void SetHeaderVisitor (DownloaderResponseHeaderCallback visitor, gpointer context);
106         int GetResponseStatus ();
107         const char *GetResponseStatusText ();
110 class GECKO_SYM(DownloaderRequest) : public DownloaderRequest {
111  private:
112         bool disable_cache;
113         nsCOMPtr<nsIChannel> channel;
115         void CreateChannel ();
117  public:
118         GECKO_SYM(DownloaderRequest) (const char *method, const char *uri, bool disable_cache)
119             : DownloaderRequest (method, uri)
120         {
121                 this->disable_cache = disable_cache;
122                 CreateChannel ();
123         }
125         ~GECKO_SYM(DownloaderRequest) ()
126         {
127         }
129         DownloaderResponse *GetResponse ();
130         bool GetResponse (DownloaderResponseStartedHandler started, DownloaderResponseDataAvailableHandler available, DownloaderResponseFinishedHandler finished, gpointer context);
131         void SetHttpHeader (const char *name, const char *value);
132         void SetBody (void *body, int size);
133         
134         void Abort ();
137 // DownloaderResponse
139 NS_IMPL_ISUPPORTS1 (GECKO_SYM(DownloaderResponse), nsIStreamListener)
141 void
142 GECKO_SYM(DownloaderResponse)::SetHeaderVisitor (DownloaderResponseHeaderCallback visitor, gpointer context)
144         GECKO_SYM(HeaderVisitor) *hv = new GECKO_SYM(HeaderVisitor) (visitor, context);
145         nsCOMPtr<nsIHttpChannel> httpchannel = do_QueryInterface (channel);
147         httpchannel->VisitResponseHeaders (hv); 
151 GECKO_SYM(DownloaderResponse)::GetResponseStatus ()
153         PRUint32 status;
154         nsCOMPtr<nsIHttpChannel> httpchannel = do_QueryInterface (channel);
156         httpchannel->GetResponseStatus (&status);
158         return status;
161 const char *
162 GECKO_SYM(DownloaderResponse)::GetResponseStatusText ()
164         nsCString status;
165         nsCOMPtr<nsIHttpChannel> httpchannel = do_QueryInterface (channel);
167         httpchannel->GetResponseStatusText (status);
169         return status.get();
172 void
173 GECKO_SYM(DownloaderResponse)::Abort ()
175         if (!aborted) {
176                 this->channel->Cancel (NS_BINDING_ABORTED);
177                 aborted = true;
178         }
181 NS_IMETHODIMP
182 GECKO_SYM(DownloaderResponse)::OnStartRequest (nsIRequest *request, nsISupports *context)
184         if (!aborted)
185                 return started (this, this->context);
186         return NS_OK;
189 NS_IMETHODIMP
190 GECKO_SYM(DownloaderResponse)::OnStopRequest (nsIRequest *request, nsISupports *ctx, nsresult status)
192         if (!aborted)
193                 return finished (this, this->context, (status == NS_OK), NULL, NULL);
194         return NS_OK;
197 NS_IMETHODIMP
198 GECKO_SYM(DownloaderResponse)::OnDataAvailable (nsIRequest *request, nsISupports *context, nsIInputStream *input, PRUint32 offset, PRUint32 count)
200         PRUint32 length = 0;
201         nsresult res;
203         if (aborted)
204                 return NS_OK;
206         char *buffer = (char *) NS_Alloc (count);
207         input->Read (buffer, count, &length);
208         res = available (this, this->context, buffer, length);
209         NS_Free (buffer);
211         return res;
214 // DownloaderRequest
216 void
217 GECKO_SYM(DownloaderRequest)::CreateChannel ()
219         nsresult rv = NS_OK;
220         nsCOMPtr<nsIServiceManager> mgr;
221         rv = NS_GetServiceManager (getter_AddRefs (mgr));
222         if (NS_FAILED (rv)) {
223                 printf ("failed to ge a ServiceManager \n");
224                 return;
225         }
227         nsCOMPtr<nsIIOService> ioservice;
228         rv = mgr->GetServiceByContractID ("@mozilla.org/network/io-service;1",
229                         NS_GET_IID (nsIIOService), getter_AddRefs (ioservice));
231         if (NS_FAILED (rv)) {
232                 printf ("failed to get a IOService \n");
233                 return;
234         }
236         nsEmbedCString url;
237         url = this->uri;
239         printf ("DownloaderRequest: %s\n", uri);
241         nsCOMPtr<nsIURI> uri;
242         rv = ioservice->NewURI (url, nsnull, nsnull, getter_AddRefs (uri));
244         ioservice->NewChannelFromURI (uri, getter_AddRefs (this->channel));
246         nsCOMPtr<nsIHttpChannel> httpchannel = do_QueryInterface (channel);
247         if (!httpchannel)
248                 return;
250         nsEmbedCString meth;
251         meth = this->method;
252         httpchannel->SetRequestMethod (meth);
255 void
256 GECKO_SYM(DownloaderRequest)::Abort ()
258         channel->Cancel (NS_BINDING_ABORTED);
259         
260         if (response != NULL && !response->IsAborted ())
261                 response->Abort ();
264 bool
265 GECKO_SYM(DownloaderRequest)::GetResponse (DownloaderResponseStartedHandler started, DownloaderResponseDataAvailableHandler available, DownloaderResponseFinishedHandler finished, gpointer context)
267         nsresult rs = NS_OK;
268         GECKO_SYM(DownloaderResponse) *response;
269         nsCOMPtr<nsIHttpChannel> httpchannel = do_QueryInterface (channel);
271         response = new GECKO_SYM(DownloaderResponse) (channel, started, available, finished, context);
272         response->SetDownloaderRequest (this);
273         if (disable_cache)
274                 httpchannel->SetLoadFlags (nsIRequest::INHIBIT_CACHING);
276         rs = channel->AsyncOpen (response, (GECKO_SYM(DownloaderResponse)*)response);
277         
278         this->response = response;
279         return !NS_FAILED (rs);
282 void
283 GECKO_SYM(DownloaderRequest)::SetHttpHeader (const char *name, const char *value)
285         nsCOMPtr<nsIHttpChannel> httpchannel = do_QueryInterface (channel);
286         if (!httpchannel)
287                 return;
289         nsEmbedCString nsname, nsvalue;
290         nsname = name;
291         nsvalue = value;
293         httpchannel->SetRequestHeader (nsname, nsvalue, true);
296 void
297 GECKO_SYM(DownloaderRequest)::SetBody (void *body, int size)
299         nsCOMPtr<nsIHttpChannel> httpchannel = do_QueryInterface (channel);
300         if (!httpchannel)
301                 return;
303         nsCOMPtr<nsIUploadChannel> upload = do_QueryInterface (channel);
304         if (!upload)
305                 return;
307         nsEmbedCString type;
308         nsresult rv;
310         nsCOMPtr<nsIStorageStream> storage = do_CreateInstance ("@mozilla.org/storagestream;1", &rv);
311         storage->Init (2048, PR_UINT32_MAX, nsnull);
313         nsCOMPtr<nsIOutputStream> output;
314         storage->GetOutputStream (0, getter_AddRefs (output));
316         PRUint32 written;
317         output->Write ((const char *)body, size, &written);
318         output->Close ();
320         nsCOMPtr<nsIInputStream> input;
321         rv = storage->NewInputStream (0, getter_AddRefs (input));
323         nsCString method;
324         httpchannel->GetRequestMethod (method);
325         
326         upload->SetUploadStream (input, type, -1);
327         
328         httpchannel->SetRequestMethod (method);