+2007-05-21 Lars Knoll <lars@trolltech.com>
+
+ Reviewed by Zack.
+
+ Remove the ResourceHandleManager class, it is now part of
+ QWebNetworkInterface. Adapt ResourceHandle to the new way
+ of things.
+
+ * WebCore.pro:
+ * platform/network/ResourceHandleInternal.h:
+ (WebCore::ResourceHandleInternal::ResourceHandleInternal):
+ * platform/network/qt/ResourceHandleManagerKDE.cpp: Removed.
+ * platform/network/qt/ResourceHandleManagerKDE.h: Removed.
+ * platform/network/qt/ResourceHandleManagerQt.cpp: Removed.
+ * platform/network/qt/ResourceHandleManagerQt.h: Removed.
+ * platform/network/qt/ResourceHandleQt.cpp:
+ (WebCore::ResourceHandle::~ResourceHandle):
+ (WebCore::ResourceHandle::start):
+ (WebCore::ResourceHandle::cancel):
+
2007-05-21 David Hyatt <hyatt@apple.com>
Second half of fix for 13793, make sure rules=groups works properly with
MANUALMOC =
qt-port:MANUALMOC += \
- $$PWD/platform/network/qt/ResourceHandleManagerQt.h \
$$PWD/platform/qt/QWebPopup.h \
$$PWD/platform/qt/SharedTimerQt.h \
$$PWD/../WebKitQt/Api/qwebframe.h \
$$PWD/../WebKitQt/Api/qwebpage.h \
+ $$PWD/../WebKitQt/Api/qwebnetworkinterface.h \
+ $$PWD/../WebKitQt/Api/qwebnetworkinterface_p.h \
$$PWD/../WebKitQt/Api/qcookiejar.h \
$$PWD/../WebKitQt/WebCoreSupport/FrameLoaderClientQt.h
platform/graphics/qt/IntRectQt.cpp \
platform/graphics/qt/IntSizeQt.cpp \
platform/graphics/qt/PathQt.cpp \
- platform/network/qt/ResourceHandleManagerQt.cpp \
platform/network/qt/ResourceHandleQt.cpp \
editing/qt/EditorQt.cpp \
history/qt/CachedPageQt.cpp \
../WebKitQt/WebCoreSupport/EditCommandQt.cpp \
../WebKitQt/WebCoreSupport/FrameLoaderClientQt.cpp \
../WebKitQt/Api/qwebframe.cpp \
+ ../WebKitQt/Api/qwebnetworkinterface.cpp \
../WebKitQt/Api/qcookiejar.cpp \
../WebKitQt/Api/qwebpage.cpp \
../WebKitQt/Api/qwebpagehistory.cpp
#endif
#if PLATFORM(QT)
-#include <QString>
+class QWebNetworkJob;
#endif
#if PLATFORM(MAC)
, m_url(0)
, m_customHeaders(0)
#endif
+#if PLATFORM(QT)
+ , m_job(0)
+#endif
#if PLATFORM(MAC)
, m_currentMacChallenge(nil)
#elif USE(CFNETWORK)
char* m_url;
struct curl_slist* m_customHeaders;
#endif
+#if PLATFORM(QT)
+ QWebNetworkJob *m_job;
+#endif
#if PLATFORM(MAC)
NSURLAuthenticationChallenge *m_currentMacChallenge;
#endif
+++ /dev/null
-/*
- * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org>
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#include <kio/job.h>
-
-#include <QEvent>
-#include <QFile>
-
-#include "FrameQt.h"
-#include "ResourceHandleManager.h"
-#include "ResourceHandleInternal.h"
-
-namespace WebCore {
-
-static ResourceHandleManager* s_self = 0;
-
-
-ResourceHandleManager* ResourceHandleManager::self()
-{
- if (!s_self)
- s_self = new ResourceHandleManager();
-
- return s_self;
-}
-
-
-ResourceHandleManager::ResourceHandleManager()
- : m_jobToKioMap()
- , m_kioToJobMap()
- , m_frameClient(0)
-{
-}
-
-ResourceHandleManager::~ResourceHandleManager()
-{
-}
-
-void ResourceHandleManager::slotData(KIO::Job* kioJob, const QByteArray& data)
-{
- ResourceHandle* job = 0;
-
- // Check if we know about 'kioJob'...
- QMap<KIO::Job*, ResourceHandle*>::const_iterator it = m_kioToJobMap.find(kioJob);
- if (it != m_kioToJobMap.end())
- job = it.value();
-
- if (!job)
- return;
-
- ResourceHandleInternal* d = job->getInternal();
- if (!d || !d->m_client)
- return;
-
- d->m_client->didReceiveData(job, data.data(), data.size());
-}
-
-void ResourceHandleManager::slotMimetype(KIO::Job* kioJob, const QString& type)
-{
- ResourceHandle* job = 0;
-
- // Check if we know about 'kioJob'...
- QMap<KIO::Job*, ResourceHandle*>::const_iterator it = m_kioToJobMap.find(kioJob);
- if (it != m_kioToJobMap.end())
- job = it.value();
-
- if (!job)
- return;
-
- ResourceHandleInternal* d = job->getInternal();
- if (!d || !d->m_client)
- return;
-
- d->m_mimetype = type;
-}
-
-void ResourceHandleManager::slotResult(KJob* kjob)
-{
- KIO::Job* kioJob = qobject_cast<KIO::Job*>(kjob);
- if (!kioJob)
- return;
-
- ResourceHandle* job = 0;
-
- // Check if we know about 'kioJob'...
- QMap<KIO::Job*, ResourceHandle*>::const_iterator it = m_kioToJobMap.find(kioJob);
- if (it != m_kioToJobMap.end())
- job = it.value();
-
- if (!job)
- return;
-
- job->setError(kjob->error());
- remove(job);
-
- ASSERT(m_frameClient);
- m_frameClient->checkLoaded();
-}
-
-void ResourceHandleManager::remove(ResourceHandle* job)
-{
- ResourceHandleInternal* d = job->getInternal();
- if (!d || !d->m_client)
- return;
-
- KIO::Job* kioJob = 0;
-
- // Check if we know about 'job'...
- QMap<ResourceHandle*, KIO::Job*>::const_iterator it = m_jobToKioMap.find(job);
- if (it != m_jobToKioMap.end())
- kioJob = it.value();
-
- if (!kioJob)
- return;
-
- QString headers = kioJob->queryMetaData("HTTP-Headers");
- if (job->method() == "GET")
- d->m_charset = job->extractCharsetFromHeaders(headers);
- else if (job->method() == "POST") {
- // Will take care of informing our client...
- // This must be called before didFinishLoading(),
- // otherwhise assembleResponseHeaders() is called too early...
- RefPtr<PlatformResponseQt> response(new PlatformResponseQt());
- response->data = headers;
- response->url = job->url().url();
-
- job->receivedResponse(response);
- }
-
- d->m_client->receivedAllData(job, 0);
- d->m_client->didFinishLoading(job);
-
- m_jobToKioMap.remove(job);
- m_kioToJobMap.remove(kioJob);
-}
-
-void ResourceHandleManager::add(ResourceHandle* job, FrameQtClient* frameClient)
-{
- ResourceHandleInternal* d = job->getInternal();
- DeprecatedString url = d->m_request.url().url();
-
- KIO::Job* kioJob = 0;
-
- if (job->method() == "POST") {
- DeprecatedString postData = job->postData().flattenToString().deprecatedString();
- QByteArray postDataArray(postData.ascii(), postData.length());
-
- kioJob = KIO::http_post(KUrl(url), postDataArray, false);
- kioJob->addMetaData("PropagateHttpHeader", "true");
- kioJob->addMetaData("content-type", "Content-Type: application/x-www-form-urlencoded");
- } else
- kioJob = KIO::get(KUrl(url), false, false);
-
- Q_ASSERT(kioJob != 0);
-
- QObject::connect(kioJob, SIGNAL(data(KIO::Job*, const QByteArray&)), this, SLOT(slotData(KIO::Job*, const QByteArray&)));
- QObject::connect(kioJob, SIGNAL(mimetype(KIO::Job*, const QString&)), this, SLOT(slotMimetype(KIO::Job*, const QString&)));
- QObject::connect(kioJob, SIGNAL(result(KJob*)), this, SLOT(slotResult(KJob*)));
-
- m_jobToKioMap.insert(job, kioJob);
- m_kioToJobMap.insert(kioJob, job);
-
- if (!m_frameClient)
- m_frameClient = frameClient;
- else
- ASSERT(m_frameClient == frameClient);
-}
-
-void ResourceHandleManager::cancel(ResourceHandle* job)
-{
- remove(job);
- job->setError(1);
-}
-
-} // namespace WebCore
-
-#include "ResourceHandleManager.moc"
+++ /dev/null
-/*
- * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org>
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef ResourceHandleManagerKDE_h
-#define ResourceHandleManagerKDE_h
-
-#include <QMap>
-#include <QObject>
-
-#include "ResourceHandle.h"
-
-namespace KIO {
-class Job;
-}
-class KJob;
-
-namespace WebCore {
-
-class FrameQtClient;
-
-class ResourceHandleManager : public QObject
-{
- Q_OBJECT
-public:
- static ResourceHandleManager* self();
-
- void add(ResourceHandle*, FrameQtClient*);
- void cancel(ResourceHandle*);
-
-public Q_SLOTS:
- void slotData(KIO::Job*, const QByteArray& data);
- void slotMimetype(KIO::Job*, const QString& type);
- void slotResult(KJob*);
- void deliverJobData(QtJob* , const QByteArray&);
-
-private:
- ResourceHandleManager();
- ~ResourceHandleManager();
-
- void remove(ResourceHandle*);
-
- // KIO Job <-> WebKit Job mapping
- QMap<ResourceHandle*, KIO::Job*> m_jobToKioMap;
- QMap<KIO::Job*, ResourceHandle*> m_kioToJobMap;
-
- FrameQtClient* m_frameClient;
-};
-
-}
-
-#endif
+++ /dev/null
-/*
- * Copyright (C) 2006 Enrico Ros <enrico.ros@m31engineering.it>
- * Copyright (C) 2006 Trolltech ASA
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#include "CString.h"
-#include "CookieJar.h"
-#include "ResourceHandle.h"
-#include "ResourceHandleClient.h"
-#include "ResourceResponse.h"
-#include "ResourceHandleManagerQt.h"
-#include "ResourceHandleInternal.h"
-#include "ResourceError.h"
-#include "MimeTypeRegistry.h"
-
-#include <QCoreApplication>
-#include <QHttpRequestHeader>
-#include <QFile>
-#include <QMap>
-#include <QByteArray>
-#include <QUrl>
-#include <qdebug.h>
-
-#define notImplemented() qDebug("FIXME: UNIMPLEMENTED: %s:%d (%s)", __FILE__, __LINE__, __FUNCTION__)
-
-#if 0
-#define DEBUG qDebug
-#else
-#define DEBUG if (1) {} else qDebug
-#endif
-
-namespace WebCore {
-
-static ResourceHandleManager* s_self = 0;
-
-ResourceHandleManager::ResourceHandleManager()
-{
- m_fileLoader = new LoaderThread(this, LoaderThread::File);
- m_fileLoader->start();
- m_networkLoader = new LoaderThread(this, LoaderThread::Network);
- m_networkLoader->start();
-
- m_fileLoader->waitForSetup();
- m_networkLoader->waitForSetup();
-}
-
-ResourceHandleManager::~ResourceHandleManager()
-{
- m_networkLoader->quit();
- m_fileLoader->quit();
-}
-
-ResourceHandleManager* ResourceHandleManager::self()
-{
- if (!s_self)
- s_self = new ResourceHandleManager();
-
- return s_self;
-}
-
-RequestQt::RequestQt(ResourceHandle* res)
- : resource(res), redirected(false), cancelled(false)
-{
- setURL(res->url());
- request = QHttpRequestHeader(resource->method(), url.path() + url.query());
- request.setValue(QLatin1String("User-Agent"),
- QLatin1String("Mozilla/5.0 (PC; U; Intel; Linux; en) AppleWebKit/420+ (KHTML, like Gecko)"));
- request.setValue(QLatin1String("Connection"), QLatin1String("Keep-Alive"));
- QString cookies = WebCore::cookies(url);
- if (!cookies.isEmpty())
- request.setValue(QLatin1String("Cookie"), cookies);
-
- const HTTPHeaderMap& loaderHeaders = resource->requestHeaders();
- HTTPHeaderMap::const_iterator end = loaderHeaders.end();
- for (HTTPHeaderMap::const_iterator it = loaderHeaders.begin(); it != end; ++it)
- request.setValue(it->first, it->second);
-
- int port = url.port();
- if (port && port != 80)
- request.setValue(QLatin1String("Host"), url.host() + QLatin1Char(':') + QString::number(port));
- else
- request.setValue(QLatin1String("Host"), url.host());
-
- int id;
- // handle and perform a 'POST' request
- if (resource->method() == "POST") {
- request.setValue(QLatin1String("PropagateHttpHeader"), QLatin1String("true"));
- request.setValue(QLatin1String("content-type"), QLatin1String("Content-Type: application/x-www-form-urlencoded"));
-
- DeprecatedString pd = resource->postData()->flattenToString().deprecatedString();
- postData = QByteArray(pd.ascii(), pd.length());
- request.setValue(QLatin1String("content-length"), QString::number(postData.size()));
- } else if (resource->method() != "GET") {
- // or.. don't know what to do! (probably a request error!!)
- // but treat it like a 'GET' request
- notImplemented();
- qWarning("REQUEST: [%s]\n", qPrintable(request.toString()));
- }
-// DEBUG() << "RequestQt::RequestQt: http header:";
-// DEBUG() << request.toString();
-}
-
-
-void RequestQt::setURL(const KURL &u)
-{
- url = u;
- int port = url.port();
- if (port && port != 80)
- request.setValue(QLatin1String("Host"), url.host() + QLatin1Char(':') + QString::number(port));
- else
- request.setValue(QLatin1String("Host"), url.host());
- hostInfo = HostInfo(u);
- qurl = url.url();
-}
-
-void ResourceHandleManager::add(ResourceHandle* resource)
-{
- ASSERT(resource);
-
- // check for (probably) broken requests
- if (resource->method() != "GET" && resource->method() != "POST") {
- notImplemented();
- return;
- }
-
- RequestQt* request = new RequestQt(resource);
- add(request);
-}
-
-void ResourceHandleManager::add(RequestQt* request)
-{
- Q_ASSERT(!pendingRequests.value(request->resource));
-
- pendingRequests[request->resource] = request;
-
- //DEBUG() << "ResourceHandleManager::add" << request->hostInfo.protocol << request->hostInfo.host;
- // check for not implemented protocols
- String protocol = request->hostInfo.protocol;
- if (protocol == "http") {
- //DEBUG() << "networkRequest";
- emit networkRequest(request);
- return;
- }
-
- // "file", "data" and all unhandled stuff go through here
- //DEBUG() << "fileRequest";
- emit fileRequest(request);
- return;
-}
-
-
-void ResourceHandleManager::cancel(ResourceHandle* resource)
-{
- ResourceHandleClient* client = resource->client();
- if (!client)
- return;
- RequestQt *req = pendingRequests.value(resource);
- if (!req)
- return;
-
- DEBUG() << "ResourceHandleManager::cancel" << resource->url().path();
-
- RequestQt* request = pendingRequests.take(resource);
- if (!request)
- return;
- request->cancelled = true;
-
- String protocol = request->hostInfo.protocol;
- if (protocol == "http")
- emit networkCancel(request);
-}
-
-
-void ResourceHandleManager::receivedResponse(RequestQt* request)
-{
- if (request->cancelled)
- return;
- Q_ASSERT(pendingRequests.value(request->resource) == request);
- DEBUG() << "ResourceHandleManager::receivedResponse:";
- DEBUG() << request->response.toString();
-
- ResourceHandleClient* client = request->resource->client();
- if (!client)
- return;
-
- QStringList cookies = request->response.allValues("Set-Cookie");
- foreach (QString c, cookies) {
- setCookies(request->url, request->url, c);
- }
- QString contentType = request->response.value("Content-Type");
- QString encoding;
- int idx = contentType.indexOf(QLatin1Char(';'));
- if (idx > 0) {
- QString remainder = contentType.mid(idx + 1).toLower();
- contentType = contentType.left(idx).trimmed();
-
- idx = remainder.indexOf("charset");
- if (idx >= 0) {
- idx = remainder.indexOf(QLatin1Char('='), idx);
- if (idx >= 0)
- encoding = remainder.mid(idx + 1).trimmed();
- }
- }
- if (contentType.isEmpty()) {
- // let's try to guess from the extension
- QString extension = request->qurl.path();
- int index = extension.lastIndexOf(QLatin1Char('.'));
- if (index > 0) {
- extension = extension.mid(index + 1);
- contentType = MimeTypeRegistry::getMIMETypeForExtension(extension);
- }
- }
-// qDebug() << "Content-Type=" << contentType;
-// qDebug() << "Encoding=" << encoding;
-
-
- ResourceResponse response(request->url, contentType,
- 0 /* FIXME */,
- encoding,
- String() /* FIXME */);
-
- int statusCode = request->response.statusCode();
- response.setHTTPStatusCode(statusCode);
- /* Fill in the other fields */
-
- if (statusCode >= 300 && statusCode < 400) {
- // we're on a redirect page! if the 'Location:' field is valid, we redirect
- QString location = request->response.value("location");
- DEBUG() << "Redirection";
- if (!location.isEmpty()) {
- ResourceRequest newRequest = request->resource->request();
- newRequest.setURL(DeprecatedString(location));
- client->willSendRequest(request->resource, newRequest, response);
- request->request.setRequest(request->request.method(), newRequest.url().path() + newRequest.url().query());
- request->setURL(newRequest.url());
- request->redirected = true;
- return;
- }
- }
-
-
- client->didReceiveResponse(request->resource, response);
-}
-
-void ResourceHandleManager::receivedData(RequestQt* request, const QByteArray& data)
-{
- if (request->cancelled || request->redirected)
- return;
- Q_ASSERT(pendingRequests.value(request->resource) == request);
-
- ResourceHandleClient* client = request->resource->client();
- if (!client)
- return;
-
- DEBUG() << "receivedData" << request->url.path();
- client->didReceiveData(request->resource, data.constData(), data.length(), data.length() /*FixMe*/);
-}
-
-void ResourceHandleManager::receivedFinished(RequestQt* request, int errorCode)
-{
- if (request->cancelled) {
- delete request;
- return;
- }
- DEBUG() << "receivedFinished" << errorCode << request->url.path();
- Q_ASSERT(pendingRequests.value(request->resource) == request);
-
- pendingRequests.remove(request->resource);
-
- if (request->redirected) {
- request->redirected = false;
- add(request);
- return;
- }
-
- ResourceHandleClient* client = request->resource->client();
- if (!client)
- return;
-
- if (errorCode) {
- //FIXME: error setting error was removed from ResourceHandle
- client->didFail(request->resource,
- ResourceError(request->qurl.host(), request->response.statusCode(),
- request->qurl.toString(), String()));
- } else {
- client->didFinishLoading(request->resource);
- }
- DEBUG() << "receivedFinished done" << request->url.path();
- delete request;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-LoaderThread::LoaderThread(ResourceHandleManager *manager, Type type)
- : QThread(manager), m_type(type), m_loader(0), m_manager(manager), m_setup(false)
-{
-}
-
-void LoaderThread::run()
-{
- switch (m_type) {
- case Network:
- m_loader = new NetworkLoader;
- connect(m_manager, SIGNAL(networkRequest(RequestQt*)),
- m_loader, SLOT(request(RequestQt*)));
- connect(m_manager, SIGNAL(networkCancel(RequestQt*)),
- m_loader, SLOT(cancel(RequestQt*)));
- break;
- case File:
- m_loader = new FileLoader;
- connect(m_manager, SIGNAL(fileRequest(RequestQt*)),
- m_loader, SLOT(request(RequestQt*)));
- break;
- }
- connect(m_loader, SIGNAL(receivedResponse(RequestQt*)),
- m_manager, SLOT(receivedResponse(RequestQt*)));
- connect(m_loader, SIGNAL(receivedData(RequestQt*, QByteArray)),
- m_manager, SLOT(receivedData(RequestQt*, QByteArray)));
- connect(m_loader, SIGNAL(receivedFinished(RequestQt*, int)),
- m_manager, SLOT(receivedFinished(RequestQt*, int)));
- DEBUG() << "calling exec";
- m_setup = true;
- exec();
- DEBUG() << "done exec";
- delete m_loader;
-}
-
-/////////////////////////////////////////////////////////////////////////////
-FileLoader::FileLoader()
- : QObject(0)
-{
- DEBUG() << "FileLoader::FileLoader";
-}
-
-
-void FileLoader::request(RequestQt* request)
-{
- DEBUG() << "FileLoader::request" << request->request.path();
-
- if (request->cancelled) {
- sendData(request, 400, QByteArray());
- return;
- }
-
- if (request->hostInfo.protocol == QLatin1String("data")) {
- parseDataUrl(request);
- return;
- }
-
- int statusCode = 200;
- QByteArray data;
- if (!request->hostInfo.isLocalFile()) {
- statusCode = 404;
- } else if (request->postData.isEmpty()) {
- QFile f(QString(request->qurl.path()));
- DEBUG() << "opening" << QString(request->qurl.path());
-
- if (f.open(QIODevice::ReadOnly)) {
- request->response.setStatusLine(200);
- data = f.readAll();
- } else {
- statusCode = 404;
- }
- } else {
- statusCode = 404;
- }
- sendData(request, statusCode, data);
-}
-
-void FileLoader::sendData(RequestQt* request, int statusCode, const QByteArray &data)
-{
- int error = statusCode >= 400 ? 1 : 0;
- if (!request->cancelled) {
- request->response.setStatusLine(statusCode);
- emit receivedResponse(request);
- if (!data.isEmpty())
- emit receivedData(request, data);
- }
- emit receivedFinished(request, error);
-}
-
-void FileLoader::parseDataUrl(RequestQt* request)
-{
- QByteArray data = request->qurl.toString().toLatin1();
- //qDebug() << "handling data url:" << data;
-
- ASSERT(data.startsWith("data:"));
-
- // Here's the syntax of data URLs:
- // dataurl := "data:" [ mediatype ] [ ";base64" ] "," data
- // mediatype := [ type "/" subtype ] *( ";" parameter )
- // data := *urlchar
- // parameter := attribute "=" value
- QByteArray header;
- bool base64 = false;
-
- int index = data.indexOf(',');
- if (index != -1) {
- header = data.mid(5, index - 5);
- header = header.toLower();
- //qDebug() << "header=" << header;
- data = data.mid(index+1);
- //qDebug() << "data=" << data;
-
- if (header.endsWith(";base64")) {
- //qDebug() << "base64";
- base64 = true;
- header = header.left(header.length() - 7);
- //qDebug() << "mime=" << header;
- }
- } else {
- data = QByteArray();
- }
- if (base64) {
- data = QByteArray::fromBase64(data);
- } else {
- data = QUrl::fromPercentEncoding(data).toLatin1();
- }
-
- if (header.isEmpty())
- header = "text/plain;charset=US-ASCII";
- int statusCode = data.isEmpty() ? 404 : 200;
- request->response.setContentType(header);
- request->response.setContentLength(data.size());
-
- sendData(request, statusCode, data);
-}
-
-
-/////////////////////////////////////////////////////////////////////////////
-WebCoreHttp::WebCoreHttp(NetworkLoader* parent, const HostInfo &hi)
- : info(hi),
- m_loader(parent),
- m_inCancel(false)
-{
- for (int i = 0; i < 2; ++i) {
- connection[i].http = new QHttp(info.host, info.port);
- connection[i].current = 0;
- connect(connection[i].http, SIGNAL(responseHeaderReceived(const QHttpResponseHeader&)),
- this, SLOT(onResponseHeaderReceived(const QHttpResponseHeader&)));
- connect(connection[i].http, SIGNAL(readyRead(const QHttpResponseHeader&)),
- this, SLOT(onReadyRead()));
- connect(connection[i].http, SIGNAL(requestFinished(int, bool)),
- this, SLOT(onRequestFinished(int, bool)));
- connect(connection[i].http, SIGNAL(stateChanged(int)),
- this, SLOT(onStateChanged(int)));
- }
-}
-
-WebCoreHttp::~WebCoreHttp()
-{
-}
-
-void WebCoreHttp::request(RequestQt *req)
-{
- DEBUG() << ">>>>>>>>>>>>>> WebCoreHttp::request";
- DEBUG() << req->request.toString() << "\n";
- m_pendingRequests.append(req);
-
- scheduleNextRequest();
-}
-
-void WebCoreHttp::scheduleNextRequest()
-{
- int c = 0;
- for (; c < 2; ++c) {
- if (!connection[c].current)
- break;
- }
- if (c >= 2)
- return;
-
- RequestQt *req = 0;
- while (!req && !m_pendingRequests.isEmpty()) {
- req = m_pendingRequests.takeFirst();
- if (req->cancelled) {
- emit m_loader->receivedFinished(req, 1);
- req = 0;
- }
- }
- if (!req)
- return;
-
- QHttp *http = connection[c].http;
- if (!req->postData.isEmpty())
- http->request(req->request, req->postData);
- else
- http->request(req->request);
- connection[c].current = req;
-
- DEBUG() << "WebCoreHttp::scheduleNextRequest: using connection" << c;
-// DEBUG() << req->request.toString();
-}
-
-int WebCoreHttp::getConnection()
-{
- QObject *o = sender();
- int c;
- if (o == connection[0].http) {
- c = 0;
- } else {
- Q_ASSERT(o == connection[1].http);
- c = 1;
- }
- //Q_ASSERT(connection[c].current);
- return c;
-}
-
-void WebCoreHttp::onResponseHeaderReceived(const QHttpResponseHeader &resp)
-{
- int c = getConnection();
- RequestQt *req = connection[c].current;
- DEBUG() << "WebCoreHttp::slotResponseHeaderReceived connection=" << c;
-
- req->response = resp;
-
- emit m_loader->receivedResponse(req);
-}
-
-void WebCoreHttp::onReadyRead()
-{
- int c = getConnection();
- RequestQt *req = connection[c].current;
- QHttp *http = connection[c].http;
- DEBUG() << "WebCoreHttp::slotReadyRead connection=" << c;
-
- QByteArray data;
- data.resize(http->bytesAvailable());
- http->read(data.data(), data.length());
- emit m_loader->receivedData(req, data);
-}
-
-void WebCoreHttp::onRequestFinished(int, bool error)
-{
- int c = getConnection();
- RequestQt *req = connection[c].current;
- if (!req) {
- scheduleNextRequest();
- return;
- }
- QHttp *http = connection[c].http;
- DEBUG() << "WebCoreHttp::slotFinished connection=" << c << error << req;
-
- if (error)
- DEBUG() << " error: " << http->errorString();
-
- if (!error && http->bytesAvailable()) {
- QByteArray data;
- data.resize(http->bytesAvailable());
- http->read(data.data(), data.length());
- emit m_loader->receivedData(req, data);
- }
- emit m_loader->receivedFinished(req, error ? 1 : 0);
-
- connection[c].current = 0;
- scheduleNextRequest();
-}
-
-void WebCoreHttp::onStateChanged(int state)
-{
- if (state == QHttp::Closing || state == QHttp::Unconnected) {
- if (!m_inCancel && m_pendingRequests.isEmpty()
- && !connection[0].current && !connection[1].current)
- emit connectionClosed(info);
- }
-}
-
-void WebCoreHttp::cancel(RequestQt* request)
-{
- bool doEmit = true;
- m_inCancel = true;
- for (int i = 0; i < 2; ++i) {
- if (request == connection[i].current) {
- connection[i].http->abort();
- doEmit = false;
- }
- }
- m_pendingRequests.removeAll(request);
- m_inCancel = false;
-
- if (doEmit)
- emit m_loader->receivedFinished(request, 1);
-
- if (m_pendingRequests.isEmpty()
- && !connection[0].current && !connection[1].current)
- emit connectionClosed(info);
-}
-
-
-static uint qHash(const HostInfo &info)
-{
- return qHash(info.host) + info.port;
-}
-
-static bool operator==(const HostInfo &i1, const HostInfo &i2)
-{
- return i1.port == i2.port && i1.host == i2.host;
-}
-
-HostInfo::HostInfo(const KURL& url)
- : protocol(url.protocol())
- , host(url.host())
- , port(url.port())
-{
- if (!port)
- port = 80;
-}
-
-NetworkLoader::NetworkLoader()
- : QObject(0)
-{
-}
-
-NetworkLoader::~NetworkLoader()
-{
-}
-
-void NetworkLoader::request(RequestQt* request)
-{
- DEBUG() << "NetworkLoader::request";
- WebCoreHttp *httpConnection = m_hostMapping.value(request->hostInfo);
- if (!httpConnection) {
- // #### fix custom ports
- DEBUG() << " new connection to" << request->hostInfo.host << request->hostInfo.port;
- httpConnection = new WebCoreHttp(this, request->hostInfo);
- connect(httpConnection, SIGNAL(connectionClosed(const HostInfo&)),
- this, SLOT(connectionClosed(const HostInfo&)));
-
- m_hostMapping[request->hostInfo] = httpConnection;
- }
- httpConnection->request(request);
-}
-void NetworkLoader::connectionClosed(const HostInfo& info)
-{
- DEBUG() << "Disconnected";
- WebCoreHttp *connection = m_hostMapping.take(info);
- delete connection;
-}
-
-void NetworkLoader::cancel(RequestQt* request)
-{
- DEBUG() << "NetworkLoader::cancel";
- WebCoreHttp *httpConnection = m_hostMapping.value(request->hostInfo);
- if (httpConnection)
- httpConnection->cancel(request);
-}
-
-} // namespace WebCore
-
-#include "ResourceHandleManagerQt.moc"
+++ /dev/null
-/*
- * Copyright (C) 2006 Enrico Ros <enrico.ros@m31engineering.it>
- * Copyright (C) 2006 Trolltech ASA
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef ResourceHandleManagerQt_H
-#define ResourceHandleManagerQt_H
-
-#include <QHash>
-#include <QHttp>
-#include <QBuffer>
-#include <QObject>
-#include <QThread>
-#include <QString>
-#include <QEvent>
-#include <QUrl>
-
-namespace WebCore {
-
-class LoaderThread;
-class ResourceHandle;
-class NetworkLoader;
-
-struct HostInfo {
- HostInfo() {}
- HostInfo(const KURL& url);
- QString protocol;
- QString host;
- int port;
- bool isLocalFile() { return protocol.isEmpty() || protocol == QLatin1String("file"); }
-};
-
-class RequestQt
-{
-public:
- RequestQt(ResourceHandle*);
- void setURL(const KURL &url);
- // not thread safe, don't use in other threads
- KURL url;
-
- QUrl qurl;
- ResourceHandle* resource;
-
- // to be used by other threads
- HostInfo hostInfo;
- QByteArray postData;
- QHttpRequestHeader request;
- QHttpResponseHeader response;
- bool redirected;
- bool cancelled;
-};
-
-/**
- * @class ResourceHandleManager
- * @short Download Controller: handle ResourceHandles using a pool of threads
- */
-class ResourceHandleManager : public QObject {
- Q_OBJECT
-public:
- static ResourceHandleManager* self();
-
- void add(ResourceHandle*);
- void add(RequestQt* request);
- void cancel(ResourceHandle*);
-
-public slots:
- void receivedResponse(RequestQt*);
- void receivedData(RequestQt*, const QByteArray& data);
- void receivedFinished(RequestQt*, int errorCode);
-signals:
- void networkRequest(RequestQt*);
- void networkCancel(RequestQt*);
- void fileRequest(RequestQt*);
-
-private:
- ResourceHandleManager();
- ~ResourceHandleManager();
-
- LoaderThread *m_networkLoader;
- LoaderThread *m_fileLoader;
-
- QHash<ResourceHandle *, RequestQt *> pendingRequests;
-};
-
-
-class LoaderThread : public QThread {
- Q_OBJECT
-public:
- enum Type {
- Network,
- File
- };
- LoaderThread(ResourceHandleManager *manager, Type type);
-
- void waitForSetup() { while (!m_setup); }
-protected:
- void run();
-private:
- Type m_type;
- QObject* m_loader;
- ResourceHandleManager* m_manager;
- volatile bool m_setup;
-};
-
-class FileLoader : public QObject {
- Q_OBJECT
-public:
- FileLoader();
-
-public slots:
- void request(RequestQt*);
-
-signals:
- void receivedResponse(RequestQt* resource);
- void receivedData(RequestQt* resource, const QByteArray &data);
- void receivedFinished(RequestQt* resource, int errorCode);
-
-private:
- void parseDataUrl(RequestQt* request);
- void sendData(RequestQt* request, int statusCode, const QByteArray &data);
-};
-
-
-class WebCoreHttp : public QObject
-{
- Q_OBJECT
-public:
- WebCoreHttp(NetworkLoader* parent, const HostInfo&);
- ~WebCoreHttp();
-
- void request(RequestQt* resource);
- void cancel(RequestQt*);
-
-signals:
- void connectionClosed(const HostInfo &);
-
-private slots:
- void onResponseHeaderReceived(const QHttpResponseHeader& resp);
- void onReadyRead();
- void onRequestFinished(int, bool);
- void onStateChanged(int);
-
- void scheduleNextRequest();
-
- int getConnection();
-
-public:
- HostInfo info;
-private:
- NetworkLoader* m_loader;
- QList<RequestQt*> m_pendingRequests;
- struct HttpConnection {
- QHttp *http;
- RequestQt *current;
- };
- HttpConnection connection[2];
- bool m_inCancel;
-};
-
-class NetworkLoader : public QObject {
- Q_OBJECT
-public:
- NetworkLoader();
- ~NetworkLoader();
-
-
-public slots:
- void request(RequestQt*);
- void cancel(RequestQt*);
- void connectionClosed(const HostInfo &);
-
-signals:
- void receivedResponse(RequestQt* resource);
- void receivedData(RequestQt* resource, const QByteArray &data);
- void receivedFinished(RequestQt* resource, int errorCode);
-private:
- friend class WebCoreHttp;
- QHash<HostInfo, WebCoreHttp *> m_hostMapping;
-};
-
-
-}
-
-#endif
/*
* Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) 2007 Trolltech AS
*
* All rights reserved.
*
#include "config.h"
-#if PLATFORM(KDE)
-#include <kio/job.h>
-#endif
-
#include <QRegExp>
#include "Frame.h"
#include "DocLoader.h"
#include "ResourceHandle.h"
#include "DeprecatedString.h"
-#include "ResourceHandleManagerQt.h"
#include "ResourceHandleInternal.h"
+#include "qwebnetworkinterface_p.h"
+
#define notImplemented() qDebug("FIXME: UNIMPLEMENTED: %s:%d (%s)", __FILE__, __LINE__, __FUNCTION__)
ResourceHandle::~ResourceHandle()
{
- cancel();
+ if (d->m_job)
+ cancel();
}
bool ResourceHandle::start(Frame* frame)
{
- ASSERT(frame);
+ if (!frame)
+ return false;
+
+ // If we are no longer attached to a Page, this must be an attempted load from an
+ // onUnload handler, so let's just block it.
+ if (!frame->page())
+ return false;
+
+ // check for (probably) broken requests
+ if (method() != "GET" && method() != "POST") {
+ notImplemented();
+ return false;
+ }
- ResourceHandleManager::self()->add(this);
- return true;
+ return QWebNetworkManager::self()->add(this);
}
void ResourceHandle::cancel()
{
- ResourceHandleManager::self()->cancel(this);
+ QWebNetworkManager::self()->cancel(this);
}
bool ResourceHandle::loadsBlocked()
--- /dev/null
+/*
+ Copyright (C) 2006 Enrico Ros <enrico.ros@m31engineering.it>
+ Copyright (C) 2007 Trolltech ASA
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ This class provides all functionality needed for loading images, style sheets and html
+ pages from the web. It has a memory cache for these objects.
+*/
+#include <qglobal.h>
+namespace WebCore {
+ class HostInfo;
+}
+uint qHash(const WebCore::HostInfo &info);
+#include "qwebnetworkinterface.h"
+#include "qwebnetworkinterface_p.h"
+#include <qdebug.h>
+#include <qfile.h>
+
+#include "ResourceHandle.h"
+#include "ResourceHandleClient.h"
+#include "ResourceHandleInternal.h"
+#include "MimeTypeRegistry.h"
+#include "CookieJar.h"
+
+#define notImplemented() qDebug("FIXME: UNIMPLEMENTED: %s:%d (%s)", __FILE__, __LINE__, __FUNCTION__)
+
+#if 0
+#define DEBUG qDebug
+#else
+#define DEBUG if (1) {} else qDebug
+#endif
+
+static QWebNetworkInterface *default_interface = 0;
+static QWebNetworkManager *manager = 0;
+
+using namespace WebCore;
+
+void QWebNetworkJobPrivate::setURL(const QUrl &u)
+{
+ url = u;
+ int port = url.port();
+ if (port && port != 80)
+ request.setValue(QLatin1String("Host"), url.host() + QLatin1Char(':') + QString::number(port));
+ else
+ request.setValue(QLatin1String("Host"), url.host());
+}
+
+/*!
+ \class QWebNetworkJob
+
+ The QWebNetworkJob class represents a network job, that needs to be
+ processed by the QWebNetworkInterface.
+
+ This class is only required when implementing a new network layer (or
+ support for a special protocol) using QWebNetworkInterface.
+
+ QWebNetworkJob objects are created and owned by the QtWebKit library.
+ Most of it's properties are read-only.
+
+ The job is reference counted. This can be used to ensure that the job doesn't
+ get deleted while it's still stored in some data structure.
+*/
+
+/*!
+ \internal
+*/
+QWebNetworkJob::QWebNetworkJob()
+ : d(new QWebNetworkJobPrivate)
+{
+ d->ref = 1;
+ d->redirected = false;
+}
+
+/*!
+ \internal
+*/
+QWebNetworkJob::~QWebNetworkJob()
+{
+ delete d;
+}
+
+/*!
+ The requested URL
+*/
+QUrl QWebNetworkJob::url() const
+{
+ return d->url;
+}
+
+/*!
+ Post data associated with the job
+*/
+QByteArray QWebNetworkJob::postData() const
+{
+ return d->postData;
+}
+
+/*!
+ The HTTP request header that should be used to download the job.
+*/
+QHttpRequestHeader QWebNetworkJob::request() const
+{
+ return d->request;
+}
+
+/*!
+ The HTTP response header received from the network.
+*/
+QHttpResponseHeader QWebNetworkJob::response() const
+{
+ return d->response;
+}
+
+/*!
+ Sets the HTTP reponse header. The response header has to be called before
+ emitting QWebNetworkInterface::started.
+*/
+void QWebNetworkJob::setResponse(const QHttpResponseHeader &response)
+{
+ d->response = response;
+}
+
+/*!
+ returns true if the job has been cancelled by the WebKit framework
+*/
+bool QWebNetworkJob::cancelled() const
+{
+ return !d->resourceHandle;
+}
+
+/*!
+ reference the job.
+*/
+void QWebNetworkJob::ref()
+{
+ ++d->ref;
+}
+
+/*!
+ derefence the job.
+
+ If the reference count drops to 0 this method also deletes the job.
+
+ Returns false if the reference count has dropped to 0.
+*/
+bool QWebNetworkJob::deref()
+{
+ if (!--d->ref) {
+ delete this;
+ return false;
+ }
+ return true;
+}
+
+/*!
+ \internal
+*/
+void QWebNetworkJob::setUserHandle(void *handle)
+{
+ d->userHandle = handle;
+}
+
+/*!
+ \internal
+*/
+void *QWebNetworkJob::userHandle() const
+{
+ return d->userHandle;
+}
+
+
+/*!
+ \class QWebNetworkManager
+ \internal
+*/
+QWebNetworkManager::QWebNetworkManager()
+ : QObject(0)
+{
+}
+
+QWebNetworkManager *QWebNetworkManager::self()
+{
+ // ensure everything's constructed and connected
+ QWebNetworkInterface::defaultInterface();
+
+ return manager;
+}
+
+bool QWebNetworkManager::add(ResourceHandle *handle)
+{
+ ASSERT(resource);
+
+ QWebNetworkJob *job = new QWebNetworkJob();
+ handle->getInternal()->m_job = job;
+ job->d->resourceHandle = handle;
+
+ KURL url = handle->url();
+ QUrl qurl = QString(url.url());
+ qDebug() << QString(url.path() + url.query());
+ job->d->request = QHttpRequestHeader(handle->method(), url.path() + url.query());
+ job->d->request.setValue(QLatin1String("User-Agent"),
+ QLatin1String("Mozilla/5.0 (PC; U; Intel; Linux; en) AppleWebKit/420+ (KHTML, like Gecko)"));
+ job->d->request.setValue(QLatin1String("Connection"), QLatin1String("Keep-Alive"));
+
+ job->d->setURL(qurl);
+
+ QString cookies = WebCore::cookies(handle->url());
+ if (!cookies.isEmpty())
+ job->d->request.setValue(QLatin1String("Cookie"), cookies);
+
+ const HTTPHeaderMap& loaderHeaders = handle->requestHeaders();
+ HTTPHeaderMap::const_iterator end = loaderHeaders.end();
+ for (HTTPHeaderMap::const_iterator it = loaderHeaders.begin(); it != end; ++it)
+ job->d->request.setValue(it->first, it->second);
+
+ int id;
+ // handle and perform a 'POST' request
+ if (handle->method() == "POST") {
+ job->d->request.setValue(QLatin1String("PropagateHttpHeader"), QLatin1String("true"));
+ job->d->request.setValue(QLatin1String("content-type"), QLatin1String("Content-Type: application/x-www-form-urlencoded"));
+
+ DeprecatedString pd = handle->postData()->flattenToString().deprecatedString();
+ job->d->postData = QByteArray(pd.ascii(), pd.length());
+ job->d->request.setValue(QLatin1String("content-length"), QString::number(job->d->postData.size()));
+ } else if (handle->method() != "GET") {
+ // or.. don't know what to do! (probably a request error!!)
+ // but treat it like a 'GET' request
+ qWarning("REQUEST: [%s]\n", qPrintable(job->d->request.toString()));
+ }
+
+ qDebug() << "QWebNetworkManager::add:" << job->d->request.toString();
+
+ default_interface->addJob(job);
+
+ return true;
+}
+
+void QWebNetworkManager::cancel(ResourceHandle *handle)
+{
+ QWebNetworkJob *job = handle->getInternal()->m_job;
+ if (!job)
+ return;
+ job->d->resourceHandle = 0;
+ default_interface->cancelJob(job);
+ handle->getInternal()->m_job = 0;
+}
+
+void QWebNetworkManager::started(QWebNetworkJob *job)
+{
+ if (!job->d->resourceHandle)
+ return;
+
+ DEBUG() << "ResourceHandleManager::receivedResponse:";
+ DEBUG() << job->d->response.toString();
+
+ ResourceHandleClient* client = job->d->resourceHandle->client();
+ if (!client)
+ return;
+
+ QStringList cookies = job->d->response.allValues("Set-Cookie");
+ KURL url = job->d->resourceHandle->url();
+ foreach (QString c, cookies) {
+ setCookies(url, url, c);
+ }
+ QString contentType = job->d->response.value("Content-Type");
+ QString encoding;
+ int idx = contentType.indexOf(QLatin1Char(';'));
+ if (idx > 0) {
+ QString remainder = contentType.mid(idx + 1).toLower();
+ contentType = contentType.left(idx).trimmed();
+
+ idx = remainder.indexOf("charset");
+ if (idx >= 0) {
+ idx = remainder.indexOf(QLatin1Char('='), idx);
+ if (idx >= 0)
+ encoding = remainder.mid(idx + 1).trimmed();
+ }
+ }
+ if (contentType.isEmpty()) {
+ // let's try to guess from the extension
+ QString extension = job->d->url.path();
+ int index = extension.lastIndexOf(QLatin1Char('.'));
+ if (index > 0) {
+ extension = extension.mid(index + 1);
+ contentType = MimeTypeRegistry::getMIMETypeForExtension(extension);
+ }
+ }
+// qDebug() << "Content-Type=" << contentType;
+// qDebug() << "Encoding=" << encoding;
+
+
+ ResourceResponse response(url, contentType,
+ 0 /* FIXME */,
+ encoding,
+ String() /* FIXME */);
+
+ int statusCode = job->d->response.statusCode();
+ response.setHTTPStatusCode(statusCode);
+ /* Fill in the other fields */
+
+ if (statusCode >= 300 && statusCode < 400) {
+ // we're on a redirect page! if the 'Location:' field is valid, we redirect
+ QString location = job->d->response.value("location");
+ DEBUG() << "Redirection";
+ if (!location.isEmpty()) {
+ ResourceRequest newRequest = job->d->resourceHandle->request();
+ newRequest.setURL(DeprecatedString(location));
+ client->willSendRequest(job->d->resourceHandle, newRequest, response);
+ job->d->request.setRequest(job->d->request.method(), newRequest.url().path() + newRequest.url().query());
+ job->d->setURL(QString(newRequest.url().url()));
+ job->d->redirected = true;
+ return;
+ }
+ }
+
+ client->didReceiveResponse(job->d->resourceHandle, response);
+
+}
+
+void QWebNetworkManager::data(QWebNetworkJob *job, const QByteArray &data)
+{
+ if (!job->d->resourceHandle)
+ return;
+
+ ResourceHandleClient* client = job->d->resourceHandle->client();
+ if (!client)
+ return;
+
+ DEBUG() << "receivedData" << job->d->url.path();
+ client->didReceiveData(job->d->resourceHandle, data.constData(), data.length(), data.length() /*FixMe*/);
+
+}
+
+void QWebNetworkManager::finished(QWebNetworkJob *job, int errorCode)
+{
+ if (!job->d->resourceHandle) {
+ job->deref();
+ return;
+ }
+
+ DEBUG() << "receivedFinished" << errorCode << job->url();
+
+ if (job->d->redirected) {
+ job->d->redirected = false;
+ default_interface->addJob(job);
+ return;
+ }
+ job->d->resourceHandle->getInternal()->m_job = 0;
+
+ ResourceHandleClient* client = job->d->resourceHandle->client();
+ if (!client)
+ return;
+
+ if (errorCode) {
+ //FIXME: error setting error was removed from ResourceHandle
+ client->didFail(job->d->resourceHandle,
+ ResourceError(job->d->url.host(), job->d->response.statusCode(),
+ job->d->url.toString(), String()));
+ } else {
+ client->didFinishLoading(job->d->resourceHandle);
+ }
+ DEBUG() << "receivedFinished done" << job->d->url;
+
+ job->deref();
+}
+
+
+/*!
+ \class QWebNetworkInterface
+
+ The QWebNetworkInterface class provides an abstraction layer for
+ WebKit's network interface. It allows to completely replace or
+ extend the builtin network layer.
+
+ QWebNetworkInterface contains two virtual methods, addJob and
+ cancelJob that have to be reimplemented when implementing your own
+ networking layer.
+
+ QWebNetworkInterface can by default handle the http, https, file and
+ data URI protocols.
+
+*/
+
+/*!
+ Sets a new default interface that will be used by all of WebKit
+ for downloading data from the internet.
+*/
+void QWebNetworkInterface::setDefaultInterface(QWebNetworkInterface *defaultInterface)
+{
+ if (default_interface == defaultInterface)
+ return;
+ if (default_interface)
+ delete default_interface;
+ default_interface = defaultInterface;
+ QObject::connect(default_interface, SIGNAL(started(QWebNetworkJob*)),
+ manager, SLOT(started(QWebNetworkJob*)), Qt::QueuedConnection);
+ QObject::connect(default_interface, SIGNAL(data(QWebNetworkJob*, const QByteArray &)),
+ manager, SLOT(data(QWebNetworkJob*, const QByteArray &)), Qt::QueuedConnection);
+ QObject::connect(default_interface, SIGNAL(finished(QWebNetworkJob*, int)),
+ manager, SLOT(finished(QWebNetworkJob*, int)), Qt::QueuedConnection);
+}
+
+/*!
+ Returns the default interface that will be used by WebKit. If no
+ default interface has been set, QtWebkit will create an instance of
+ QWebNetworkInterface to do the work.
+*/
+QWebNetworkInterface *QWebNetworkInterface::defaultInterface()
+{
+ if (!default_interface)
+ setDefaultInterface(new QWebNetworkInterface);
+ return default_interface;
+}
+
+
+/*!
+ Constructs a QWebNetworkInterface object.
+*/
+QWebNetworkInterface::QWebNetworkInterface()
+ : QObject(0)
+{
+ d = new QWebNetworkInterfacePrivate;
+ if (!manager)
+ manager = new QWebNetworkManager;
+ d->fileLoader = new LoaderThread(this, LoaderThread::File);
+ d->fileLoader->start();
+ d->networkLoader = new LoaderThread(this, LoaderThread::Network);
+ d->networkLoader->start();
+
+ d->fileLoader->waitForSetup();
+ d->networkLoader->waitForSetup();
+}
+
+/*!
+ Destructs the QWebNetworkInterface object.
+*/
+QWebNetworkInterface::~QWebNetworkInterface()
+{
+ delete d;
+}
+
+/*!
+ This virtual method gets called whenever QtWebkit needs to add a
+ new job to download.
+
+ The QWebNetworkInterface should process this job, by first emitting
+ the started signal, then emitting data repeatedly as new data for
+ the Job is available, and finally ending the job with emitting a
+ finished signal.
+
+ After the finished signal has been emitted, the QWebNetworkInterface
+ is not allowed to access the job anymore.
+*/
+void QWebNetworkInterface::addJob(QWebNetworkJob *job)
+{
+ job->ref();
+ QString protocol = job->url().scheme();
+ if (protocol == QLatin1String("http")) {
+ //DEBUG() << "networkRequest";
+ emit manager->networkRequest(job);
+ return;
+ }
+
+ // "file", "data" and all unhandled stuff go through here
+ //DEBUG() << "fileRequest";
+ emit manager->fileRequest(job);
+}
+
+/*!
+ This virtual method gets called whenever QtWebkit needs to cancel a
+ new job.
+
+ The QWebNetworkInterface acknowledge the canceling of the job, by
+ emitting the finished signal with an error code of 1. After emitting
+ the finished signal, the interface should not access the job
+ anymore.
+*/
+void QWebNetworkInterface::cancelJob(QWebNetworkJob *job)
+{
+ QString protocol = job->url().scheme();
+ if (protocol == QLatin1String("http")) {
+ job->ref();
+ emit manager->networkCancel(job);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+LoaderThread::LoaderThread(QWebNetworkInterface *manager, Type type)
+ : QThread(manager), m_type(type), m_loader(0), m_manager(manager), m_setup(false)
+{
+}
+
+void LoaderThread::run()
+{
+ switch (m_type) {
+ case Network:
+ m_loader = new NetworkLoader;
+ connect(manager, SIGNAL(networkRequest(QWebNetworkJob*)),
+ m_loader, SLOT(request(QWebNetworkJob*)));
+ connect(manager, SIGNAL(networkCancel(QWebNetworkJob*)),
+ m_loader, SLOT(cancel(QWebNetworkJob*)));
+ break;
+ case File:
+ m_loader = new FileLoader;
+ connect(manager, SIGNAL(fileRequest(QWebNetworkJob*)),
+ m_loader, SLOT(request(QWebNetworkJob*)));
+ break;
+ }
+ connect(m_loader, SIGNAL(receivedResponse(QWebNetworkJob*)),
+ m_manager, SIGNAL(started(QWebNetworkJob*)));
+ connect(m_loader, SIGNAL(receivedData(QWebNetworkJob*, QByteArray)),
+ m_manager, SIGNAL(data(QWebNetworkJob*, QByteArray)));
+ connect(m_loader, SIGNAL(receivedFinished(QWebNetworkJob*, int)),
+ m_manager, SIGNAL(finished(QWebNetworkJob*, int)));
+ DEBUG() << "calling exec";
+ m_setup = true;
+ exec();
+ DEBUG() << "done exec";
+ delete m_loader;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+FileLoader::FileLoader()
+ : QObject(0)
+{
+ DEBUG() << "FileLoader::FileLoader";
+}
+
+
+void FileLoader::request(QWebNetworkJob* job)
+{
+ if (!job->deref())
+ return;
+
+ DEBUG() << "FileLoader::request" << job->url();
+
+ if (job->cancelled()) {
+ sendData(job, 400, QByteArray());
+ return;
+ }
+
+ QUrl url = job->url();
+ QString protocol = url.scheme();
+ if (protocol == QLatin1String("data")) {
+ parseDataUrl(job);
+ return;
+ }
+
+ int statusCode = 200;
+ QByteArray data;
+ if (!(protocol.isEmpty() || protocol == QLatin1String("file"))) {
+ statusCode = 404;
+ } else if (job->postData().isEmpty()) {
+ QFile f(url.path());
+ DEBUG() << "opening" << QString(url.path());
+
+ if (f.open(QIODevice::ReadOnly)) {
+ QHttpResponseHeader response;
+ response.setStatusLine(200);
+ job->setResponse(response);
+ data = f.readAll();
+ } else {
+ statusCode = 404;
+ }
+ } else {
+ statusCode = 404;
+ }
+ sendData(job, statusCode, data);
+}
+
+void FileLoader::sendData(QWebNetworkJob* job, int statusCode, const QByteArray &data)
+{
+ int error = statusCode >= 400 ? 1 : 0;
+ if (!job->cancelled()) {
+ QHttpResponseHeader response;
+ response.setStatusLine(statusCode);
+ emit receivedResponse(job);
+ if (!data.isEmpty())
+ emit receivedData(job, data);
+ }
+ emit receivedFinished(job, error);
+}
+
+void FileLoader::parseDataUrl(QWebNetworkJob* job)
+{
+ QByteArray data = job->url().toString().toLatin1();
+ //qDebug() << "handling data url:" << data;
+
+ ASSERT(data.startsWith("data:"));
+
+ // Here's the syntax of data URLs:
+ // dataurl := "data:" [ mediatype ] [ ";base64" ] "," data
+ // mediatype := [ type "/" subtype ] *( ";" parameter )
+ // data := *urlchar
+ // parameter := attribute "=" value
+ QByteArray header;
+ bool base64 = false;
+
+ int index = data.indexOf(',');
+ if (index != -1) {
+ header = data.mid(5, index - 5);
+ header = header.toLower();
+ //qDebug() << "header=" << header;
+ data = data.mid(index+1);
+ //qDebug() << "data=" << data;
+
+ if (header.endsWith(";base64")) {
+ //qDebug() << "base64";
+ base64 = true;
+ header = header.left(header.length() - 7);
+ //qDebug() << "mime=" << header;
+ }
+ } else {
+ data = QByteArray();
+ }
+ if (base64) {
+ data = QByteArray::fromBase64(data);
+ } else {
+ data = QUrl::fromPercentEncoding(data).toLatin1();
+ }
+
+ if (header.isEmpty())
+ header = "text/plain;charset=US-ASCII";
+ int statusCode = data.isEmpty() ? 404 : 200;
+ QHttpResponseHeader response;
+ response.setContentType(header);
+ response.setContentLength(data.size());
+ job->setResponse(response);
+
+ sendData(job, statusCode, data);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+WebCoreHttp::WebCoreHttp(NetworkLoader* parent, const HostInfo &hi)
+ : info(hi),
+ m_loader(parent),
+ m_inCancel(false)
+{
+ for (int i = 0; i < 2; ++i) {
+ connection[i].http = new QHttp(info.host, info.port);
+ connection[i].current = 0;
+ connect(connection[i].http, SIGNAL(responseHeaderReceived(const QHttpResponseHeader&)),
+ this, SLOT(onResponseHeaderReceived(const QHttpResponseHeader&)));
+ connect(connection[i].http, SIGNAL(readyRead(const QHttpResponseHeader&)),
+ this, SLOT(onReadyRead()));
+ connect(connection[i].http, SIGNAL(requestFinished(int, bool)),
+ this, SLOT(onRequestFinished(int, bool)));
+ connect(connection[i].http, SIGNAL(stateChanged(int)),
+ this, SLOT(onStateChanged(int)));
+ }
+}
+
+WebCoreHttp::~WebCoreHttp()
+{
+}
+
+void WebCoreHttp::request(QWebNetworkJob *job)
+{
+ DEBUG() << ">>>>>>>>>>>>>> WebCoreHttp::request";
+ DEBUG() << job->request().toString() << "\n";
+ m_pendingRequests.append(job);
+
+ scheduleNextRequest();
+}
+
+void WebCoreHttp::scheduleNextRequest()
+{
+ int c = 0;
+ for (; c < 2; ++c) {
+ if (!connection[c].current)
+ break;
+ }
+ if (c >= 2)
+ return;
+
+ QWebNetworkJob *job = 0;
+ while (!job && !m_pendingRequests.isEmpty()) {
+ job = m_pendingRequests.takeFirst();
+ if (job->cancelled()) {
+ emit m_loader->receivedFinished(job, 1);
+ job = 0;
+ }
+ }
+ if (!job)
+ return;
+
+ QHttp *http = connection[c].http;
+ QByteArray postData = job->postData();
+ if (!postData.isEmpty())
+ http->request(job->request(), postData);
+ else
+ http->request(job->request());
+ connection[c].current = job;
+
+ DEBUG() << "WebCoreHttp::scheduleNextRequest: using connection" << c;
+// DEBUG() << job->request.toString();
+}
+
+int WebCoreHttp::getConnection()
+{
+ QObject *o = sender();
+ int c;
+ if (o == connection[0].http) {
+ c = 0;
+ } else {
+ Q_ASSERT(o == connection[1].http);
+ c = 1;
+ }
+ //Q_ASSERT(connection[c].current);
+ return c;
+}
+
+void WebCoreHttp::onResponseHeaderReceived(const QHttpResponseHeader &resp)
+{
+ int c = getConnection();
+ QWebNetworkJob *job = connection[c].current;
+ DEBUG() << "WebCoreHttp::slotResponseHeaderReceived connection=" << c;
+
+ job->setResponse(resp);
+
+ emit m_loader->receivedResponse(job);
+}
+
+void WebCoreHttp::onReadyRead()
+{
+ int c = getConnection();
+ QWebNetworkJob *req = connection[c].current;
+ QHttp *http = connection[c].http;
+ DEBUG() << "WebCoreHttp::slotReadyRead connection=" << c;
+
+ QByteArray data;
+ data.resize(http->bytesAvailable());
+ http->read(data.data(), data.length());
+ emit m_loader->receivedData(req, data);
+}
+
+void WebCoreHttp::onRequestFinished(int, bool error)
+{
+ int c = getConnection();
+ QWebNetworkJob *req = connection[c].current;
+ if (!req) {
+ scheduleNextRequest();
+ return;
+ }
+ QHttp *http = connection[c].http;
+ DEBUG() << "WebCoreHttp::slotFinished connection=" << c << error << req;
+
+ if (error)
+ DEBUG() << " error: " << http->errorString();
+
+ if (!error && http->bytesAvailable()) {
+ QByteArray data;
+ data.resize(http->bytesAvailable());
+ http->read(data.data(), data.length());
+ emit m_loader->receivedData(req, data);
+ }
+ emit m_loader->receivedFinished(req, error ? 1 : 0);
+
+ connection[c].current = 0;
+ scheduleNextRequest();
+}
+
+void WebCoreHttp::onStateChanged(int state)
+{
+ if (state == QHttp::Closing || state == QHttp::Unconnected) {
+ if (!m_inCancel && m_pendingRequests.isEmpty()
+ && !connection[0].current && !connection[1].current)
+ emit connectionClosed(info);
+ }
+}
+
+void WebCoreHttp::cancel(QWebNetworkJob* request)
+{
+ bool doEmit = true;
+ m_inCancel = true;
+ for (int i = 0; i < 2; ++i) {
+ if (request == connection[i].current) {
+ connection[i].http->abort();
+ doEmit = false;
+ }
+ }
+ m_pendingRequests.removeAll(request);
+ m_inCancel = false;
+
+ if (doEmit)
+ emit m_loader->receivedFinished(request, 1);
+
+ if (m_pendingRequests.isEmpty()
+ && !connection[0].current && !connection[1].current)
+ emit connectionClosed(info);
+}
+
+HostInfo::HostInfo(const QUrl& url)
+ : protocol(url.scheme())
+ , host(url.host())
+ , port(url.port())
+{
+ if (port < 0) {
+ if (protocol == QLatin1String("http"))
+ port = 80;
+ else if (protocol == QLatin1String("https"))
+ port = 443;
+ }
+}
+
+
+uint qHash(const HostInfo &info)
+{
+ return qHash(info.host) + info.port;
+}
+
+static bool operator==(const HostInfo &i1, const HostInfo &i2)
+{
+ return i1.port == i2.port && i1.host == i2.host;
+}
+
+
+NetworkLoader::NetworkLoader()
+ : QObject(0)
+{
+}
+
+NetworkLoader::~NetworkLoader()
+{
+}
+
+void NetworkLoader::request(QWebNetworkJob* job)
+{
+ if (!job->deref())
+ return;
+ DEBUG() << "NetworkLoader::request";
+ HostInfo hostInfo(job->url());
+ WebCoreHttp *httpConnection = m_hostMapping.value(hostInfo);
+ if (!httpConnection) {
+ // #### fix custom ports
+ DEBUG() << " new connection to" << hostInfo.host << hostInfo.port;
+ httpConnection = new WebCoreHttp(this, hostInfo);
+ connect(httpConnection, SIGNAL(connectionClosed(const HostInfo&)),
+ this, SLOT(connectionClosed(const HostInfo&)));
+
+ m_hostMapping[hostInfo] = httpConnection;
+ }
+ httpConnection->request(job);
+}
+void NetworkLoader::connectionClosed(const HostInfo& info)
+{
+ DEBUG() << "Disconnected";
+ WebCoreHttp *connection = m_hostMapping.take(info);
+ delete connection;
+}
+
+void NetworkLoader::cancel(QWebNetworkJob* job)
+{
+ DEBUG() << "NetworkLoader::cancel";
+ WebCoreHttp *httpConnection = m_hostMapping.value(job->url());
+ if (httpConnection)
+ httpConnection->cancel(job);
+ job->deref();
+}
+
+#include "qwebnetworkinterface_p.moc"
+#include "qwebnetworkinterface.moc"
+
--- /dev/null
+/*
+ Copyright (C) 2007 Trolltech ASA
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ This class provides all functionality needed for loading images, style sheets and html
+ pages from the web. It has a memory cache for these objects.
+*/
+#ifndef QWEBNETWORKINTERFACE_H
+#define QWEBNETWORKINTERFACE_H
+
+#include <qobject.h>
+#include <qurl.h>
+#include <qhttp.h>
+#include <qbytearray.h>
+
+class QWebNetworkJobPrivate;
+
+class QWebNetworkJob
+{
+public:
+ QUrl url() const;
+ QByteArray postData() const;
+ QHttpRequestHeader request() const;
+
+ QHttpResponseHeader response() const;
+ void setResponse(const QHttpResponseHeader &response);
+
+ bool cancelled() const;
+
+ void ref();
+ bool deref();
+
+ template <typename T>
+ void setHandle(T *t);
+ template <typename T>
+ T *handle() const;
+
+private:
+ QWebNetworkJob();
+ ~QWebNetworkJob();
+
+ void setUserHandle(void *);
+ void *userHandle() const;
+
+ friend class QWebNetworkManager;
+ QWebNetworkJobPrivate *d;
+};
+
+template <typename T>
+void QWebNetworkJob::setHandle(T *t)
+{
+ setUserHandle(t);
+}
+
+template <typename T>
+T *QWebNetworkJob::handle() const
+{
+ return static_cast<T *>(userHandle());
+}
+
+class QWebNetworkInterfacePrivate;
+
+class QWebNetworkInterface : public QObject
+{
+ Q_OBJECT
+public:
+ QWebNetworkInterface();
+ ~QWebNetworkInterface();
+
+ static void setDefaultInterface(QWebNetworkInterface *defaultInterface);
+ static QWebNetworkInterface *defaultInterface();
+
+ virtual void addJob(QWebNetworkJob *job);
+ virtual void cancelJob(QWebNetworkJob *job);
+
+signals:
+ void started(QWebNetworkJob*);
+ void data(QWebNetworkJob*, const QByteArray &data);
+ void finished(QWebNetworkJob*, int errorCode);
+
+private:
+ friend class QWebNetworkInterfacePrivate;
+ QWebNetworkInterfacePrivate *d;
+};
+
+#endif
--- /dev/null
+/*
+ Copyright (C) 2007 Trolltech ASA
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ This class provides all functionality needed for loading images, style sheets and html
+ pages from the web. It has a memory cache for these objects.
+*/
+#ifndef QWEBNETWORKINTERFACE_P_H
+#define QWEBNETWORKINTERFACE_P_H
+
+#include "qwebnetworkinterface.h"
+#include <qthread.h>
+#include <qhash.h>
+
+namespace WebCore {
+ class ResourceHandle;
+}
+
+class QWebNetworkJobPrivate
+{
+public:
+ int ref;
+ QUrl url;
+ QHttpRequestHeader request;
+ QByteArray postData;
+
+ QHttpResponseHeader response;
+
+ WebCore::ResourceHandle *resourceHandle;
+ void *userHandle;
+ bool redirected;
+
+ void setURL(const QUrl &u);
+};
+
+
+class QWebNetworkManager : public QObject
+{
+ Q_OBJECT
+public:
+ static QWebNetworkManager *self();
+
+ bool add(WebCore::ResourceHandle *resourceHandle);
+ void cancel(WebCore::ResourceHandle *resourceHandle);
+
+public slots:
+ void started(QWebNetworkJob *);
+ void data(QWebNetworkJob *, const QByteArray &data);
+ void finished(QWebNetworkJob *, int errorCode);
+
+signals:
+ void networkRequest(QWebNetworkJob*);
+ void networkCancel(QWebNetworkJob*);
+ void fileRequest(QWebNetworkJob*);
+
+private:
+ friend class QWebNetworkInterface;
+ QWebNetworkManager();
+};
+
+
+namespace WebCore {
+
+ class LoaderThread : public QThread {
+ Q_OBJECT
+ public:
+ enum Type {
+ Network,
+ File
+ };
+ LoaderThread(QWebNetworkInterface *manager, Type type);
+
+ void waitForSetup() { while (!m_setup); }
+ protected:
+ void run();
+ private:
+ Type m_type;
+ QObject* m_loader;
+ QWebNetworkInterface* m_manager;
+ volatile bool m_setup;
+ };
+
+ class FileLoader : public QObject {
+ Q_OBJECT
+ public:
+ FileLoader();
+
+ public slots:
+ void request(QWebNetworkJob*);
+
+ signals:
+ void receivedResponse(QWebNetworkJob* resource);
+ void receivedData(QWebNetworkJob* resource, const QByteArray &data);
+ void receivedFinished(QWebNetworkJob* resource, int errorCode);
+
+ private:
+ void parseDataUrl(QWebNetworkJob* request);
+ void sendData(QWebNetworkJob* request, int statusCode, const QByteArray &data);
+ };
+
+ class NetworkLoader;
+
+ struct HostInfo {
+ HostInfo() {}
+ HostInfo(const QUrl& url);
+ QString protocol;
+ QString host;
+ int port;
+ };
+
+
+ class WebCoreHttp : public QObject
+ {
+ Q_OBJECT
+ public:
+ WebCoreHttp(NetworkLoader* parent, const HostInfo&);
+ ~WebCoreHttp();
+
+ void request(QWebNetworkJob* resource);
+ void cancel(QWebNetworkJob*);
+
+ signals:
+ void connectionClosed(const HostInfo &);
+
+ private slots:
+ void onResponseHeaderReceived(const QHttpResponseHeader& resp);
+ void onReadyRead();
+ void onRequestFinished(int, bool);
+ void onStateChanged(int);
+
+ void scheduleNextRequest();
+
+ int getConnection();
+
+ public:
+ HostInfo info;
+ private:
+ NetworkLoader* m_loader;
+ QList<QWebNetworkJob*> m_pendingRequests;
+ struct HttpConnection {
+ QHttp *http;
+ QWebNetworkJob *current;
+ };
+ HttpConnection connection[2];
+ bool m_inCancel;
+ };
+
+ class NetworkLoader : public QObject {
+ Q_OBJECT
+ public:
+ NetworkLoader();
+ ~NetworkLoader();
+
+
+ public slots:
+ void request(QWebNetworkJob*);
+ void cancel(QWebNetworkJob*);
+ void connectionClosed(const HostInfo &);
+
+ signals:
+ void receivedResponse(QWebNetworkJob* resource);
+ void receivedData(QWebNetworkJob* resource, const QByteArray &data);
+ void receivedFinished(QWebNetworkJob* resource, int errorCode);
+ private:
+ friend class WebCoreHttp;
+ QHash<HostInfo, WebCoreHttp *> m_hostMapping;
+ };
+
+}
+
+class QWebNetworkInterfacePrivate
+{
+public:
+ WebCore::LoaderThread *networkLoader;
+ WebCore::LoaderThread *fileLoader;
+};
+
+#endif
+2007-05-21 Lars Knoll <lars@trolltech.com>
+
+ Reviewed by Zack.
+
+ Add an API layer for network downloads. Basically QWebnetworkInterface
+ is an interface class for downloading resources. QWebnetworkJob describes
+ the actual object to download.
+
+ QWebNetworkInterface has a default implementation that replaces the
+ old ResourceHandleManager class in the Qt port.
+
+ * Api/qwebnetworkinterface.cpp: Added.
+ (QWebNetworkJobPrivate::setURL):
+ (QWebNetworkJob::QWebNetworkJob):
+ (QWebNetworkJob::~QWebNetworkJob):
+ (QWebNetworkJob::url):
+ (QWebNetworkJob::postData):
+ (QWebNetworkJob::request):
+ (QWebNetworkJob::response):
+ (QWebNetworkJob::setResponse):
+ (QWebNetworkJob::cancelled):
+ (QWebNetworkJob::ref):
+ (QWebNetworkJob::deref):
+ (QWebNetworkJob::setUserHandle):
+ (QWebNetworkJob::userHandle):
+ (QWebNetworkManager::QWebNetworkManager):
+ (QWebNetworkManager::self):
+ (QWebNetworkManager::add):
+ (QWebNetworkManager::cancel):
+ (QWebNetworkManager::started):
+ (QWebNetworkManager::data):
+ (QWebNetworkManager::finished):
+ (QWebNetworkInterface::setDefaultInterface):
+ (QWebNetworkInterface::defaultInterface):
+ (QWebNetworkInterface::QWebNetworkInterface):
+ (QWebNetworkInterface::~QWebNetworkInterface):
+ (QWebNetworkInterface::addJob):
+ (QWebNetworkInterface::cancelJob):
+ (LoaderThread::LoaderThread):
+ (LoaderThread::run):
+ (FileLoader::FileLoader):
+ (FileLoader::request):
+ (FileLoader::sendData):
+ (FileLoader::parseDataUrl):
+ (WebCoreHttp::WebCoreHttp):
+ (WebCoreHttp::~WebCoreHttp):
+ (WebCoreHttp::request):
+ (WebCoreHttp::scheduleNextRequest):
+ (WebCoreHttp::getConnection):
+ (WebCoreHttp::onResponseHeaderReceived):
+ (WebCoreHttp::onReadyRead):
+ (WebCoreHttp::onRequestFinished):
+ (WebCoreHttp::onStateChanged):
+ (WebCoreHttp::cancel):
+ (HostInfo::HostInfo):
+ (qHash):
+ (operator==):
+ (NetworkLoader::NetworkLoader):
+ (NetworkLoader::~NetworkLoader):
+ (NetworkLoader::request):
+ (NetworkLoader::connectionClosed):
+ (NetworkLoader::cancel):
+ * Api/qwebnetworkinterface.h: Added.
+ (QWebNetworkJob::setHandle):
+ (QWebNetworkJob::handle):
+ * Api/qwebnetworkinterface_p.h: Added.
+ (WebCore::LoaderThread::):
+ (WebCore::LoaderThread::waitForSetup):
+ (WebCore::HostInfo::HostInfo):
+
2007-05-18 Simon Hausmann <hausmann@kde.org>
Reviewed by Nikolas.