Home | History | Annotate | Download | only in qt
      1 /*
      2     Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
      3 
      4     This library is free software; you can redistribute it and/or
      5     modify it under the terms of the GNU Library General Public
      6     License as published by the Free Software Foundation; either
      7     version 2 of the License, or (at your option) any later version.
      8 
      9     This library is distributed in the hope that it will be useful,
     10     but WITHOUT ANY WARRANTY; without even the implied warranty of
     11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     12     Library General Public License for more details.
     13 
     14     You should have received a copy of the GNU Library General Public License
     15     along with this library; see the file COPYING.LIB.  If not, write to
     16     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     17     Boston, MA 02110-1301, USA.
     18 */
     19 #ifndef QNetworkReplyHandler_h
     20 #define QNetworkReplyHandler_h
     21 
     22 #include <QObject>
     23 
     24 #include <QNetworkRequest>
     25 #include <QNetworkAccessManager>
     26 
     27 #include "FormData.h"
     28 #include "QtMIMETypeSniffer.h"
     29 
     30 QT_BEGIN_NAMESPACE
     31 class QFile;
     32 class QNetworkReply;
     33 QT_END_NAMESPACE
     34 
     35 namespace WebCore {
     36 
     37 class ResourceHandle;
     38 class ResourceRequest;
     39 class ResourceResponse;
     40 class QNetworkReplyHandler;
     41 
     42 class QNetworkReplyHandlerCallQueue {
     43 public:
     44     QNetworkReplyHandlerCallQueue(QNetworkReplyHandler*, bool deferSignals);
     45     bool deferSignals() const { return m_deferSignals; }
     46     void setDeferSignals(bool);
     47 
     48     typedef void (QNetworkReplyHandler::*EnqueuedCall)();
     49     void push(EnqueuedCall method);
     50     void clear() { m_enqueuedCalls.clear(); }
     51 
     52     void lock();
     53     void unlock();
     54 private:
     55     QNetworkReplyHandler* m_replyHandler;
     56     int m_locks;
     57     bool m_deferSignals;
     58     bool m_flushing;
     59     QList<EnqueuedCall> m_enqueuedCalls;
     60 
     61     void flush();
     62 };
     63 
     64 class QNetworkReplyWrapper : public QObject {
     65     Q_OBJECT
     66 public:
     67     QNetworkReplyWrapper(QNetworkReplyHandlerCallQueue*, QNetworkReply*, bool sniffMIMETypes, QObject* parent = 0);
     68     ~QNetworkReplyWrapper();
     69 
     70     QNetworkReply* reply() const { return m_reply; }
     71     QNetworkReply* release();
     72 
     73     void synchronousLoad() { receiveMetaData(); }
     74 
     75     QUrl redirectionTargetUrl() const { return m_redirectionTargetUrl; }
     76     QString encoding() const { return m_encoding; }
     77     QString advertisedMIMEType() const { return m_advertisedMIMEType; }
     78     QString mimeType() const { return m_sniffedMIMEType.isEmpty() ? m_advertisedMIMEType : m_sniffedMIMEType; }
     79 
     80     bool responseContainsData() const { return m_responseContainsData; }
     81     bool wasRedirected() const { return m_redirectionTargetUrl.isValid(); }
     82 
     83 private Q_SLOTS:
     84     void receiveMetaData();
     85     void didReceiveFinished();
     86     void didReceiveReadyRead();
     87     void receiveSniffedMIMEType();
     88 
     89 private:
     90     void resetConnections();
     91     void emitMetaDataChanged();
     92 
     93     QNetworkReply* m_reply;
     94     QUrl m_redirectionTargetUrl;
     95 
     96     QString m_encoding;
     97     QNetworkReplyHandlerCallQueue* m_queue;
     98     bool m_responseContainsData;
     99 
    100     QString m_advertisedMIMEType;
    101 
    102     QString m_sniffedMIMEType;
    103     OwnPtr<QtMIMETypeSniffer> m_sniffer;
    104     bool m_sniffMIMETypes;
    105 };
    106 
    107 class QNetworkReplyHandler : public QObject
    108 {
    109     Q_OBJECT
    110 public:
    111     enum LoadType {
    112         AsynchronousLoad,
    113         SynchronousLoad
    114     };
    115 
    116     QNetworkReplyHandler(ResourceHandle*, LoadType, bool deferred = false);
    117     void setLoadingDeferred(bool deferred) { m_queue.setDeferSignals(deferred); }
    118 
    119     QNetworkReply* reply() const { return m_replyWrapper ? m_replyWrapper->reply() : 0; }
    120 
    121     void abort();
    122 
    123     QNetworkReply* release();
    124 
    125     void finish();
    126     void forwardData();
    127     void sendResponseIfNeeded();
    128 
    129 private slots:
    130     void uploadProgress(qint64 bytesSent, qint64 bytesTotal);
    131 
    132 private:
    133     void start();
    134     String httpMethod() const;
    135     void redirect(ResourceResponse&, const QUrl&);
    136     bool wasAborted() const { return !m_resourceHandle; }
    137     QNetworkReply* sendNetworkRequest(QNetworkAccessManager*, const ResourceRequest&);
    138 
    139     OwnPtr<QNetworkReplyWrapper> m_replyWrapper;
    140     ResourceHandle* m_resourceHandle;
    141     LoadType m_loadType;
    142     QNetworkAccessManager::Operation m_method;
    143     QNetworkRequest m_request;
    144 
    145     // defer state holding
    146     int m_redirectionTries;
    147 
    148     QNetworkReplyHandlerCallQueue m_queue;
    149 };
    150 
    151 // Self destructing QIODevice for FormData
    152 //  For QNetworkAccessManager::put we will have to gurantee that the
    153 //  QIODevice is valid as long finished() of the QNetworkReply has not
    154 //  been emitted. With the presence of QNetworkReplyHandler::release I do
    155 //  not want to gurantee this.
    156 class FormDataIODevice : public QIODevice {
    157     Q_OBJECT
    158 public:
    159     FormDataIODevice(FormData*);
    160     ~FormDataIODevice();
    161 
    162     bool isSequential() const;
    163     qint64 getFormDataSize() const { return m_fileSize + m_dataSize; }
    164 
    165 protected:
    166     qint64 readData(char*, qint64);
    167     qint64 writeData(const char*, qint64);
    168 
    169 private:
    170     void moveToNextElement();
    171     qint64 computeSize();
    172     void openFileForCurrentElement();
    173 
    174 private:
    175     Vector<FormDataElement> m_formElements;
    176     QFile* m_currentFile;
    177     qint64 m_currentDelta;
    178     qint64 m_fileSize;
    179     qint64 m_dataSize;
    180 };
    181 
    182 }
    183 
    184 #endif // QNetworkReplyHandler_h
    185