Reviewed by Darin.
[WebKit-https.git] / WebCore / kwq / KWQKJobClasses.mm
1 /*
2  * Copyright (C) 2003 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 namespace KIO {
36
37     // The allocations and releases in TransferJobPrivate are
38     // definitely Cocoa-exception-free (either simple Foundation
39     // classes or our own KWQResourceLoader which avoides doing work
40     // in dealloc
41
42 class TransferJobPrivate
43 {
44 public:
45     TransferJobPrivate(const KURL& kurl)
46         : status(0)
47         , metaData(KWQRetainNSRelease([[NSMutableDictionary alloc] initWithCapacity:17]))
48         , URL(kurl)
49         , loader(nil)
50         , method("GET")
51         , response(0)
52         , assembledResponseHeaders(true)
53         , retrievedCharset(true)
54     {
55     }
56
57     TransferJobPrivate(const KURL& kurl, const QByteArray &_postData)
58         : status(0)
59         , metaData(KWQRetainNSRelease([[NSMutableDictionary alloc] initWithCapacity:17]))
60         , URL(kurl)
61         , loader(nil)
62         , method("POST")
63         , postData(_postData)
64         , response(0)
65         , assembledResponseHeaders(true)
66         , retrievedCharset(true)
67     {
68     }
69
70     ~TransferJobPrivate()
71     {
72         KWQReleaseResponse(response);
73         KWQRelease(metaData);
74         KWQRelease(loader);
75     }
76
77     int status;
78     NSMutableDictionary *metaData;
79     KURL URL;
80     KWQResourceLoader *loader;
81     QString method;
82     QByteArray postData;
83
84     void *response;
85     bool assembledResponseHeaders;
86     bool retrievedCharset;
87     QString responseHeaders;
88 };
89
90 TransferJob::TransferJob(const KURL &url, bool reload, bool showProgressInfo)
91     : d(new TransferJobPrivate(url)),
92       m_data(this, SIGNAL(data(KIO::Job*, const char*, int))),
93       m_redirection(this, SIGNAL(redirection(KIO::Job*, const KURL&))),
94       m_result(this, SIGNAL(result(KIO::Job*))),
95       m_receivedResponse(this, SIGNAL(receivedResponse(KIO::Job*, void *)))
96 {
97 }
98
99 TransferJob::TransferJob(const KURL &url, const QByteArray &postData, bool showProgressInfo)
100     : d(new TransferJobPrivate(url, postData)),
101       m_data(this, SIGNAL(data(KIO::Job*, const char*, int))),
102       m_redirection(this, SIGNAL(redirection(KIO::Job*, const KURL&))),
103       m_result(this, SIGNAL(result(KIO::Job*))),
104       m_receivedResponse(this, SIGNAL(receivedResponse(KIO::Job*, void *)))
105 {
106 }
107
108 TransferJob::~TransferJob()
109 {
110     // This will cancel the handle, and who knows what that could do
111     KWQ_BLOCK_EXCEPTIONS;
112     [d->loader jobWillBeDeallocated];
113     KWQ_UNBLOCK_EXCEPTIONS;
114     delete d;
115 }
116
117 bool TransferJob::isErrorPage() const
118 {
119     return d->status != 0;
120 }
121
122 int TransferJob::error() const
123 {
124     return d->status;
125 }
126
127 void TransferJob::setError(int e)
128 {
129     d->status = e;
130 }
131
132 QString TransferJob::errorText() const
133 {
134     LOG(NotYetImplemented, "not yet implemented");
135     return QString::null;
136 }
137
138 void TransferJob::assembleResponseHeaders() const
139 {
140     if (!d->assembledResponseHeaders) {
141         d->responseHeaders = QString::fromNSString((NSString *)KWQResponseHeaderString(d->response));
142         d->assembledResponseHeaders = true;
143     }
144 }
145
146 void TransferJob::retrieveCharset() const
147 {
148     if (!d->retrievedCharset) {
149         NSString *charset = (NSString *)KWQResponseTextEncodingName(d->response);
150         if (charset) {
151             [d->metaData setObject:charset forKey:@"charset"];
152         }
153         d->retrievedCharset = true;
154     }
155 }
156
157 QString TransferJob::queryMetaData(const QString &key) const
158 {
159     if (key == "HTTP-Headers") {
160         assembleResponseHeaders();
161         return d->responseHeaders;
162     } 
163
164     if (key == "charset") {
165         // this will put it in the regular metadata dictionary
166         retrieveCharset();
167     }
168
169     NSString *value = [d->metaData objectForKey:key.getNSString()]; 
170     return value ? QString::fromNSString(value) : QString::null;
171 }
172
173 void TransferJob::addMetaData(const QString &key, const QString &value)
174 {
175     [d->metaData setObject:value.getNSString() forKey:key.getNSString()];
176 }
177
178 void TransferJob::addMetaData(const QMap<QString, QString> &keysAndValues)
179 {
180     QMapConstIterator<QString, QString> it = keysAndValues.begin();
181     QMapConstIterator<QString, QString> end = keysAndValues.end();
182     while (it != end) {
183         [d->metaData setObject:it.data().getNSString() forKey:it.key().getNSString()];
184         ++it;
185     }
186 }
187
188 void TransferJob::kill()
189 {
190     delete this;
191 }
192
193 void TransferJob::setLoader(KWQResourceLoader *loader)
194 {
195     KWQRetain(loader);
196     KWQRelease(d->loader);
197     d->loader = loader;
198 }
199
200 KURL TransferJob::url() const
201 {
202     return d->URL;
203 }
204
205 QByteArray TransferJob::postData() const
206 {
207     return d->postData;
208 }
209
210 QString TransferJob::method() const
211 {
212     return d->method;
213 }
214
215 void TransferJob::emitData(const char *data, int size)
216 {
217     m_data.call(this, data, size);
218 }
219
220 void TransferJob::emitRedirection(const KURL &url)
221 {
222     m_redirection.call(this, url);
223 }
224
225 void TransferJob::emitResult()
226 {
227     m_result.call(this);
228 }
229
230 void TransferJob::emitReceivedResponse(void *response)
231 {
232     d->assembledResponseHeaders = false;
233     d->retrievedCharset = false;
234     d->response = response;
235     KWQRetainResponse(d->response);
236
237     m_receivedResponse.call(this, response);
238 }
239
240 } // namespace KIO