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); deferSignals()45 bool deferSignals() const { return m_deferSignals; } 46 void setDeferSignals(bool); 47 48 typedef void (QNetworkReplyHandler::*EnqueuedCall)(); 49 void push(EnqueuedCall method); clear()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 reply()70 QNetworkReply* reply() const { return m_reply; } 71 QNetworkReply* release(); 72 synchronousLoad()73 void synchronousLoad() { receiveMetaData(); } 74 redirectionTargetUrl()75 QUrl redirectionTargetUrl() const { return m_redirectionTargetUrl; } encoding()76 QString encoding() const { return m_encoding; } advertisedMIMEType()77 QString advertisedMIMEType() const { return m_advertisedMIMEType; } mimeType()78 QString mimeType() const { return m_sniffedMIMEType.isEmpty() ? m_advertisedMIMEType : m_sniffedMIMEType; } 79 responseContainsData()80 bool responseContainsData() const { return m_responseContainsData; } wasRedirected()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); setLoadingDeferred(bool deferred)117 void setLoadingDeferred(bool deferred) { m_queue.setDeferSignals(deferred); } 118 reply()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&); wasAborted()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; getFormDataSize()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