• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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