WebCore:
[WebKit-https.git] / WebCore / kwq / KWQKJobClasses.mm
1 /*
2  * Copyright (C) 2004 Apple Computer, Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #import "KWQLogging.h"
27
28 #import "KWQExceptions.h"
29 #import "KWQKJobClasses.h"
30 #import "KWQLoader.h"
31 #import "KWQResourceLoader.h"
32 #import "KWQString.h"
33 #import "KWQFoundationExtras.h"
34
35 #import "formdata.h"
36
37 using khtml::FormData;
38
39 namespace KIO {
40
41     // The allocations and releases in TransferJobPrivate are
42     // definitely Cocoa-exception-free (either simple Foundation
43     // classes or our own KWQResourceLoader which avoides doing work
44     // in dealloc
45
46 class TransferJobPrivate
47 {
48 public:
49     TransferJobPrivate(const KURL& kurl)
50         : status(0)
51         , metaData(KWQRetainNSRelease([[NSMutableDictionary alloc] initWithCapacity:17]))
52         , URL(kurl)
53         , loader(nil)
54         , method("GET")
55         , response(nil)
56         , assembledResponseHeaders(true)
57         , retrievedCharset(true)
58     {
59     }
60
61     TransferJobPrivate(const KURL& kurl, const FormData &_postData)
62         : status(0)
63         , metaData(KWQRetainNSRelease([[NSMutableDictionary alloc] initWithCapacity:17]))
64         , URL(kurl)
65         , loader(nil)
66         , method("POST")
67         , postData(_postData)
68         , response(nil)
69         , assembledResponseHeaders(true)
70         , retrievedCharset(true)
71     {
72     }
73
74     ~TransferJobPrivate()
75     {
76         KWQRelease(response);
77         KWQRelease(metaData);
78         KWQRelease(loader);
79     }
80
81     int status;
82     NSMutableDictionary *metaData;
83     KURL URL;
84     KWQResourceLoader *loader;
85     QString method;
86     FormData postData;
87
88     NSURLResponse *response;
89     bool assembledResponseHeaders;
90     bool retrievedCharset;
91     QString responseHeaders;
92 };
93
94 TransferJob::TransferJob(const KURL &url, bool reload)
95     : d(new TransferJobPrivate(url)),
96       m_data(this, SIGNAL(data(KIO::Job*, const char*, int))),
97       m_redirection(this, SIGNAL(redirection(KIO::Job*, const KURL&))),
98       m_result(this, SIGNAL(result(KIO::Job*))),
99       m_receivedResponse(this, SIGNAL(receivedResponse(KIO::Job*, NSURLResponse *))),
100       m_allData(this, SIGNAL(allData(KIO::Job*, NSData *)))
101 {
102 }
103
104 TransferJob::TransferJob(const KURL &url, const FormData &postData)
105     : d(new TransferJobPrivate(url, postData)),
106       m_data(this, SIGNAL(data(KIO::Job*, const char*, int))),
107       m_redirection(this, SIGNAL(redirection(KIO::Job*, const KURL&))),
108       m_result(this, SIGNAL(result(KIO::Job*))),
109       m_receivedResponse(this, SIGNAL(receivedResponse(KIO::Job*, NSURLResponse *))),
110       m_allData(this, SIGNAL(allData(KIO::Job*, NSData *)))
111 {
112 }
113
114 TransferJob::~TransferJob()
115 {
116     // This will cancel the handle, and who knows what that could do
117     KWQ_BLOCK_EXCEPTIONS;
118     [d->loader jobWillBeDeallocated];
119     KWQ_UNBLOCK_EXCEPTIONS;
120     delete d;
121 }
122
123 bool TransferJob::isErrorPage() const
124 {
125     return d->status != 0;
126 }
127
128 int TransferJob::error() const
129 {
130     return d->status;
131 }
132
133 void TransferJob::setError(int e)
134 {
135     d->status = e;
136 }
137
138 QString TransferJob::errorText() const
139 {
140     LOG(NotYetImplemented, "not yet implemented");
141     return QString::null;
142 }
143
144 void TransferJob::assembleResponseHeaders() const
145 {
146     if (!d->assembledResponseHeaders) {
147         if ([d->response isKindOfClass:[NSHTTPURLResponse class]]) {
148             NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)d->response;
149             NSDictionary *headers = [httpResponse allHeaderFields];
150             d->responseHeaders = QString::fromNSString(KWQHeaderStringFromDictionary(headers, [httpResponse statusCode]));
151         }
152         d->assembledResponseHeaders = true;
153     }
154 }
155
156 void TransferJob::retrieveCharset() const
157 {
158     if (!d->retrievedCharset) {
159         NSString *charset = [d->response textEncodingName];
160         if (charset) {
161             [d->metaData setObject:charset forKey:@"charset"];
162         }
163         d->retrievedCharset = true;
164     }
165 }
166
167 QString TransferJob::queryMetaData(const QString &key) const
168 {
169     if (key == "HTTP-Headers") {
170         assembleResponseHeaders();
171         return d->responseHeaders;
172     } 
173
174     if (key == "charset") {
175         // this will put it in the regular metadata dictionary
176         retrieveCharset();
177     }
178
179     NSString *value = [d->metaData objectForKey:key.getNSString()]; 
180     return value ? QString::fromNSString(value) : QString::null;
181 }
182
183 void TransferJob::addMetaData(const QString &key, const QString &value)
184 {
185     [d->metaData setObject:value.getNSString() forKey:key.getNSString()];
186 }
187
188 void TransferJob::addMetaData(const QMap<QString, QString> &keysAndValues)
189 {
190     QMapConstIterator<QString, QString> it = keysAndValues.begin();
191     QMapConstIterator<QString, QString> end = keysAndValues.end();
192     while (it != end) {
193         [d->metaData setObject:it.data().getNSString() forKey:it.key().getNSString()];
194         ++it;
195     }
196 }
197
198 void TransferJob::kill()
199 {
200     delete this;
201 }
202
203 void TransferJob::setLoader(KWQResourceLoader *loader)
204 {
205     KWQRetain(loader);
206     KWQRelease(d->loader);
207     d->loader = loader;
208 }
209
210 KURL TransferJob::url() const
211 {
212     return d->URL;
213 }
214
215 FormData TransferJob::postData() const
216 {
217     return d->postData;
218 }
219
220 QString TransferJob::method() const
221 {
222     return d->method;
223 }
224
225 void TransferJob::emitData(const char *data, int size)
226 {
227     m_data.call(this, data, size);
228 }
229
230 void TransferJob::emitRedirection(const KURL &url)
231 {
232     m_redirection.call(this, url);
233 }
234
235 void TransferJob::emitResult()
236 {
237     m_result.call(this);
238 }
239
240 void TransferJob::emitReceivedResponse(NSURLResponse *response)
241 {
242     d->assembledResponseHeaders = false;
243     d->retrievedCharset = false;
244     d->response = response;
245     KWQRetain(d->response);
246
247     m_receivedResponse.call(this, response);
248 }
249
250 void TransferJob::emitAllData(NSData *data)
251 {
252     m_allData.call(this, data);
253 }
254
255 } // namespace KIO