top level:
[WebKit-https.git] / WebCore / platform / network / qt / ResourceHandleManager.cpp
1 /*
2  * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org>
3  *
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
16  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
19  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #include "config.h"
29
30 #if PLATFORM(KDE)
31 #include <kio/job.h>
32 #endif
33
34 #include <QEvent>
35 #include <QFile>
36
37 #include "FrameQt.h"
38 #include "ResourceHandleManager.h"
39 #include "ResourceHandleInternal.h"
40
41 namespace WebCore {
42
43 static ResourceHandleManager* s_self = 0;
44
45
46 ResourceHandleManager* ResourceHandleManager::self()
47 {
48     if (!s_self)
49         s_self = new ResourceHandleManager();
50
51     return s_self;
52 }
53
54 QtJob::QtJob(const QString& path)
55     : m_path(path)
56 {
57     startTimer(0);
58 }
59
60 void QtJob::timerEvent(QTimerEvent* e)
61 {
62     killTimer(e->timerId());
63
64     QFile f(m_path);
65     QByteArray data;
66     if (f.open(QIODevice::ReadOnly)) {
67         data = f.readAll();
68         f.close();
69     };
70
71     emit finished(this, data);
72
73     deleteLater();
74 }
75 #if PLATFORM(KDE)
76
77 ResourceHandleManager::ResourceHandleManager()
78     : m_jobToKioMap()
79     , m_kioToJobMap()
80     , m_frameClient(0)
81 {
82 }
83
84 ResourceHandleManager::~ResourceHandleManager()
85 {
86 }
87
88
89 void ResourceHandleManager::deliverJobData(QtJob*, const QByteArray&)
90 {
91
92 }
93 void ResourceHandleManager::slotData(KIO::Job* kioJob, const QByteArray& data)
94 {
95     ResourceHandle* job = 0;
96
97     // Check if we know about 'kioJob'...
98     QMap<KIO::Job*, ResourceHandle*>::const_iterator it = m_kioToJobMap.find(kioJob);
99     if (it != m_kioToJobMap.end())
100         job = it.value();
101
102     if (!job)
103         return;
104
105     ResourceHandleInternal* d = job->getInternal();
106     if (!d || !d->m_client)
107         return;
108
109     d->m_client->didReceiveData(job, data.data(), data.size());
110 }
111
112 void ResourceHandleManager::slotMimetype(KIO::Job* kioJob, const QString& type)
113 {
114     ResourceHandle* job = 0;
115
116     // Check if we know about 'kioJob'...
117     QMap<KIO::Job*, ResourceHandle*>::const_iterator it = m_kioToJobMap.find(kioJob);
118     if (it != m_kioToJobMap.end())
119         job = it.value();
120
121     if (!job)
122         return;
123
124     ResourceHandleInternal* d = job->getInternal();
125     if (!d || !d->m_client)
126         return;
127
128     d->m_mimetype = type;
129 }
130
131 void ResourceHandleManager::slotResult(KJob* kjob)
132 {
133     KIO::Job* kioJob = qobject_cast<KIO::Job*>(kjob);
134     if (!kioJob)
135         return;
136
137     ResourceHandle* job = 0;
138
139     // Check if we know about 'kioJob'...
140     QMap<KIO::Job*, ResourceHandle*>::const_iterator it = m_kioToJobMap.find(kioJob);
141     if (it != m_kioToJobMap.end())
142         job = it.value();
143
144     if (!job)
145         return;
146
147     //FIXME: should report an error
148     //job->setError(kjob->error());
149     remove(job);
150
151     ASSERT(m_frameClient);
152     m_frameClient->checkLoaded();
153 }
154
155 void ResourceHandleManager::remove(ResourceHandle* job)
156 {
157     ResourceHandleInternal* d = job->getInternal();
158     if (!d || !d->m_client)
159         return;
160
161     KIO::Job* kioJob = 0;
162
163     // Check if we know about 'job'...
164     QMap<ResourceHandle*, KIO::Job*>::const_iterator it = m_jobToKioMap.find(job);
165     if (it != m_jobToKioMap.end())
166         kioJob = it.value();
167
168     if (!kioJob)
169         return;
170
171     QString headers = kioJob->queryMetaData("HTTP-Headers");
172     if (job->method() == "GET")
173         d->m_charset = job->extractCharsetFromHeaders(headers);
174     else if (job->method() == "POST") {
175         // Will take care of informing our client...
176         // This must be called before didFinishLoading(),
177         // otherwhise assembleResponseHeaders() is called too early...
178         RefPtr<PlatformResponseQt> response(new PlatformResponseQt());
179         response->data = headers;
180         response->url = job->url().url();
181
182         job->receivedResponse(response);
183     }
184
185     d->m_client->receivedAllData(job, 0);
186     d->m_client->didFinishLoading(job);
187
188     m_jobToKioMap.remove(job);
189     m_kioToJobMap.remove(kioJob);
190 }
191
192 void ResourceHandleManager::add(ResourceHandle* job, FrameQtClient* frameClient)
193 {
194     ResourceHandleInternal* d = job->getInternal();
195     DeprecatedString url = d->m_request.url().url();
196
197     KIO::Job* kioJob = 0;
198
199     if (job->method() == "POST") {
200         ASSERT(job->postData());
201         DeprecatedString postData = job->postData()->flattenToString().deprecatedString();
202         QByteArray postDataArray(postData.ascii(), postData.length());
203
204         kioJob = KIO::http_post(KUrl(url), postDataArray, false);
205         kioJob->addMetaData("PropagateHttpHeader", "true");
206         kioJob->addMetaData("content-type", "Content-Type: application/x-www-form-urlencoded");
207     } else
208         kioJob = KIO::get(KUrl(url), false, false);
209
210     Q_ASSERT(kioJob != 0);
211
212     QObject::connect(kioJob, SIGNAL(data(KIO::Job*, const QByteArray&)), this, SLOT(slotData(KIO::Job*, const QByteArray&)));
213     QObject::connect(kioJob, SIGNAL(mimetype(KIO::Job*, const QString&)), this, SLOT(slotMimetype(KIO::Job*, const QString&)));
214     QObject::connect(kioJob, SIGNAL(result(KJob*)), this, SLOT(slotResult(KJob*)));
215
216     m_jobToKioMap.insert(job, kioJob);
217     m_kioToJobMap.insert(kioJob, job);
218
219     if (!m_frameClient)
220         m_frameClient = frameClient;
221     else
222         ASSERT(m_frameClient == frameClient);
223 }
224
225 void ResourceHandleManager::cancel(ResourceHandle* job)
226 {
227     remove(job);
228     //FIXME set an error state
229     //job->setError(1);
230 }
231
232 // Qt Resource Handle Manager
233 #else
234 ResourceHandleManager::ResourceHandleManager()
235     : m_frameClient(0)
236 {
237 }
238
239 ResourceHandleManager::~ResourceHandleManager()
240 {
241 }
242
243
244 void ResourceHandleManager::remove(ResourceHandle* job)
245 {
246     ResourceHandleInternal* d = job->getInternal();
247     if (!d || !d->m_client)
248         return;
249
250     // Check if we know about 'job'...
251     QtJob *qtJob = m_resourceToJob.value(job);
252     if (!qtJob)
253         return;
254
255     d->m_client->receivedAllData(job, 0);
256     d->m_client->didFinishLoading(job);
257
258     m_resourceToJob.remove(job);
259     m_jobToResource.remove(qtJob);
260 }
261
262 void ResourceHandleManager::add(ResourceHandle* resource, FrameQtClient* frameClient)
263 {
264     ResourceHandleInternal* d = resource->getInternal();
265
266     if (resource->method() == "POST"
267         || !d->m_request.url().isLocalFile()) {
268         // ### not supported for the local filesystem
269         return;
270     }
271     QtJob* qtJob =  new QtJob(d->m_request.url().path());
272     connect(qtJob, SIGNAL(finished(QtJob *, const QByteArray &)),
273             this, SLOT(deliverJobData(QtJob *, const QByteArray &)));
274
275     m_resourceToJob.insert(resource, qtJob);
276     m_jobToResource.insert(qtJob, resource);
277
278     if (!m_frameClient)
279         m_frameClient = frameClient;
280     else
281         ASSERT(m_frameClient == frameClient);
282 }
283
284 void ResourceHandleManager::cancel(ResourceHandle* job)
285 {
286     remove(job);
287     //FIXME set an error state
288     //job->setError(1);
289 }
290
291 void ResourceHandleManager::slotData(KIO::Job*, const QByteArray& data)
292 {
293     // dummy, never called in a Qt-only build
294 }
295
296 void ResourceHandleManager::slotMimetype(KIO::Job*, const QString& type)
297 {
298     // dummy, never called in a Qt-only build
299 }
300
301 void ResourceHandleManager::slotResult(KJob*)
302 {
303     // dummy, never called in a Qt-only build
304 }
305
306 void ResourceHandleManager::deliverJobData(QtJob* job, const QByteArray& data)
307 {
308     ResourceHandle* handle = m_jobToResource.value(job);
309     if (!handle)
310         return;
311
312     ResourceHandleInternal* d = handle->getInternal();
313     if (!d || !d->m_client)
314         return;
315
316     d->m_client->didReceiveData(handle, data.data(), data.size());
317
318     //FIXME: should report an error
319     //handle->setError(0);
320     remove(handle);
321
322     ASSERT(m_frameClient);
323     m_frameClient->checkLoaded();
324 }
325
326 #endif
327
328 } // namespace WebCore
329
330 #include "ResourceHandleManager.moc"