qhttpthreaddelegate.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/network/access/qhttpthreaddelegate.cpp
Source codeSwitch to Preprocessed file
LineSourceCount
1/****************************************************************************-
2**-
3** Copyright (C) 2016 The Qt Company Ltd.-
4** Contact: https://www.qt.io/licensing/-
5**-
6** This file is part of the QtNetwork module of the Qt Toolkit.-
7**-
8** $QT_BEGIN_LICENSE:LGPL$-
9** Commercial License Usage-
10** Licensees holding valid commercial Qt licenses may use this file in-
11** accordance with the commercial license agreement provided with the-
12** Software or, alternatively, in accordance with the terms contained in-
13** a written agreement between you and The Qt Company. For licensing terms-
14** and conditions see https://www.qt.io/terms-conditions. For further-
15** information use the contact form at https://www.qt.io/contact-us.-
16**-
17** GNU Lesser General Public License Usage-
18** Alternatively, this file may be used under the terms of the GNU Lesser-
19** General Public License version 3 as published by the Free Software-
20** Foundation and appearing in the file LICENSE.LGPL3 included in the-
21** packaging of this file. Please review the following information to-
22** ensure the GNU Lesser General Public License version 3 requirements-
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.-
24**-
25** GNU General Public License Usage-
26** Alternatively, this file may be used under the terms of the GNU-
27** General Public License version 2.0 or (at your option) the GNU General-
28** Public license version 3 or any later version approved by the KDE Free-
29** Qt Foundation. The licenses are as published by the Free Software-
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3-
31** included in the packaging of this file. Please review the following-
32** information to ensure the GNU General Public License requirements will-
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and-
34** https://www.gnu.org/licenses/gpl-3.0.html.-
35**-
36** $QT_END_LICENSE$-
37**-
38****************************************************************************/-
39-
40//#define QHTTPTHREADDELEGATE_DEBUG-
41#include "qhttpthreaddelegate_p.h"-
42-
43#include <QThread>-
44#include <QTimer>-
45#include <QAuthenticator>-
46#include <QEventLoop>-
47-
48#include "private/qhttpnetworkreply_p.h"-
49#include "private/qnetworkaccesscache_p.h"-
50#include "private/qnoncontiguousbytedevice_p.h"-
51-
52#ifndef QT_NO_HTTP-
53-
54QT_BEGIN_NAMESPACE-
55-
56static QNetworkReply::NetworkError statusCodeFromHttp(int httpStatusCode, const QUrl &url)-
57{-
58 QNetworkReply::NetworkError code;-
59 // we've got an error-
60 switch (httpStatusCode) {-
61 case 400: // Bad Request-
62 code = QNetworkReply::ProtocolInvalidOperationError;-
63 break;-
64-
65 case 401: // Authorization required-
66 code = QNetworkReply::AuthenticationRequiredError;-
67 break;-
68-
69 case 403: // Access denied-
70 code = QNetworkReply::ContentOperationNotPermittedError;-
71 break;-
72-
73 case 404: // Not Found-
74 code = QNetworkReply::ContentNotFoundError;-
75 break;-
76-
77 case 405: // Method Not Allowed-
78 code = QNetworkReply::ContentOperationNotPermittedError;-
79 break;-
80-
81 case 407:-
82 code = QNetworkReply::ProxyAuthenticationRequiredError;-
83 break;-
84-
85 case 409: // Resource Conflict-
86 code = QNetworkReply::ContentConflictError;-
87 break;-
88-
89 case 410: // Content no longer available-
90 code = QNetworkReply::ContentGoneError;-
91 break;-
92-
93 case 418: // I'm a teapot-
94 code = QNetworkReply::ProtocolInvalidOperationError;-
95 break;-
96-
97 case 500: // Internal Server Error-
98 code = QNetworkReply::InternalServerError;-
99 break;-
100-
101 case 501: // Server does not support this functionality-
102 code = QNetworkReply::OperationNotImplementedError;-
103 break;-
104-
105 case 503: // Service unavailable-
106 code = QNetworkReply::ServiceUnavailableError;-
107 break;-
108-
109 default:-
110 if (httpStatusCode > 500) {-
111 // some kind of server error-
112 code = QNetworkReply::UnknownServerError;-
113 } else if (httpStatusCode >= 400) {-
114 // content error we did not handle above-
115 code = QNetworkReply::UnknownContentError;-
116 } else {-
117 qWarning("QNetworkAccess: got HTTP status code %d which is not expected from url: \"%s\"",-
118 httpStatusCode, qPrintable(url.toString()));-
119 code = QNetworkReply::ProtocolFailure;-
120 }-
121 }-
122-
123 return code;-
124}-
125-
126-
127static QByteArray makeCacheKey(QUrl &url, QNetworkProxy *proxy)-
128{-
129 QString result;-
130 QUrl copy = url;-
131 QString scheme = copy.scheme();-
132 bool isEncrypted = scheme == QLatin1String("https");-
133 copy.setPort(copy.port(isEncrypted ? 443 : 80));-
134 if (scheme == QLatin1String("preconnect-http")) {-
135 copy.setScheme(QLatin1String("http"));-
136 } else if (scheme == QLatin1String("preconnect-https")) {-
137 copy.setScheme(QLatin1String("https"));-
138 }-
139 result = copy.toString(QUrl::RemoveUserInfo | QUrl::RemovePath |-
140 QUrl::RemoveQuery | QUrl::RemoveFragment | QUrl::FullyEncoded);-
141-
142#ifndef QT_NO_NETWORKPROXY-
143 if (proxy && proxy->type() != QNetworkProxy::NoProxy) {-
144 QUrl key;-
145-
146 switch (proxy->type()) {-
147 case QNetworkProxy::Socks5Proxy:-
148 key.setScheme(QLatin1String("proxy-socks5"));-
149 break;-
150-
151 case QNetworkProxy::HttpProxy:-
152 case QNetworkProxy::HttpCachingProxy:-
153 key.setScheme(QLatin1String("proxy-http"));-
154 break;-
155-
156 default:-
157 break;-
158 }-
159-
160 if (!key.scheme().isEmpty()) {-
161 key.setUserName(proxy->user());-
162 key.setHost(proxy->hostName());-
163 key.setPort(proxy->port());-
164 key.setQuery(result);-
165 result = key.toString(QUrl::FullyEncoded);-
166 }-
167 }-
168#else-
169 Q_UNUSED(proxy)-
170#endif-
171-
172 return "http-connection:" + result.toLatin1();-
173}-
174-
175class QNetworkAccessCachedHttpConnection: public QHttpNetworkConnection,-
176 public QNetworkAccessCache::CacheableObject-
177{-
178 // Q_OBJECT-
179public:-
180#ifdef QT_NO_BEARERMANAGEMENT-
181 QNetworkAccessCachedHttpConnection(const QString &hostName, quint16 port, bool encrypt,-
182 QHttpNetworkConnection::ConnectionType connectionType)-
183 : QHttpNetworkConnection(hostName, port, encrypt, connectionType)-
184#else-
185 QNetworkAccessCachedHttpConnection(const QString &hostName, quint16 port, bool encrypt,-
186 QHttpNetworkConnection::ConnectionType connectionType,-
187 QSharedPointer<QNetworkSession> networkSession)-
188 : QHttpNetworkConnection(hostName, port, encrypt, connectionType, /*parent=*/0,-
189 qMove(networkSession))-
190#endif-
191 {-
192 setExpires(true);-
193 setShareable(true);-
194 }-
195-
196 virtual void dispose() Q_DECL_OVERRIDE-
197 {-
198#if 0 // sample code; do this right with the API-
199 Q_ASSERT(!isWorking());-
200#endif-
201 delete this;-
202 }-
203};-
204-
205-
206QThreadStorage<QNetworkAccessCache *> QHttpThreadDelegate::connections;-
207-
208-
209QHttpThreadDelegate::~QHttpThreadDelegate()-
210{-
211 // It could be that the main thread has asked us to shut down, so we need to delete the HTTP reply-
212 if (httpReply) {-
213 delete httpReply;-
214 }-
215-
216 // Get the object cache that stores our QHttpNetworkConnection objects-
217 // and release the entry for this QHttpNetworkConnection-
218 if (connections.hasLocalData() && !cacheKey.isEmpty()) {-
219 connections.localData()->releaseEntry(cacheKey);-
220 }-
221}-
222-
223-
224QHttpThreadDelegate::QHttpThreadDelegate(QObject *parent) :-
225 QObject(parent)-
226 , ssl(false)-
227 , downloadBufferMaximumSize(0)-
228 , readBufferMaxSize(0)-
229 , bytesEmitted(0)-
230 , pendingDownloadData(0)()-
231 , pendingDownloadProgress(0)()-
232 , synchronous(false)-
233 , incomingStatusCode(0)-
234 , isPipeliningUsed(false)-
235 , isSpdyUsed(false)-
236 , incomingContentLength(-1)-
237 , incomingErrorCode(QNetworkReply::NoError)-
238 , downloadBuffer(0)()-
239 , httpConnection(0)-
240 , httpReply(0)-
241 , synchronousRequestLoop(0)-
242{-
243}
executed 869 times by 8 tests: end of block
Executed by:
  • tst_QAbstractNetworkCache
  • tst_QHttpNetworkConnection
  • tst_QNetworkAccessManager_And_QProgressDialog
  • tst_QNetworkDiskCache
  • tst_QNetworkProxyFactory
  • tst_QNetworkReply
  • tst_QXmlInputSource
  • tst_Spdy
869
244-
245// This is invoked as BlockingQueuedConnection from QNetworkAccessHttpBackend in the user thread-
246void QHttpThreadDelegate::startRequestSynchronously()-
247{-
248#ifdef QHTTPTHREADDELEGATE_DEBUG-
249 qDebug() << "QHttpThreadDelegate::startRequestSynchronously() thread=" << QThread::currentThreadId();-
250#endif-
251 synchronous = true;-
252-
253 QEventLoop synchronousRequestLoop;-
254 this->synchronousRequestLoop = &synchronousRequestLoop;-
255-
256 // Worst case timeout-
257 QTimer::singleShot(30*1000, this, SLOT(abortRequest()));-
258-
259 QMetaObject::invokeMethod(this, "startRequest", Qt::QueuedConnection);-
260 synchronousRequestLoop.exec();-
261-
262 connections.localData()->releaseEntry(cacheKey);-
263 connections.setLocalData(0);-
264-
265#ifdef QHTTPTHREADDELEGATE_DEBUG-
266 qDebug() << "QHttpThreadDelegate::startRequestSynchronously() thread=" << QThread::currentThreadId() << "finished";-
267#endif-
268}-
269-
270-
271// This is invoked as QueuedConnection from QNetworkAccessHttpBackend in the user thread-
272void QHttpThreadDelegate::startRequest()-
273{-
274#ifdef QHTTPTHREADDELEGATE_DEBUG-
275 qDebug() << "QHttpThreadDelegate::startRequest() thread=" << QThread::currentThreadId();-
276#endif-
277 // Check QThreadStorage for the QNetworkAccessCache-
278 // If not there, create this connection cache-
279 if (!connections.hasLocalData()) {-
280 connections.setLocalData(new QNetworkAccessCache());-
281 }-
282-
283 // check if we have an open connection to this host-
284 QUrl urlCopy = httpRequest.url();-
285 urlCopy.setPort(urlCopy.port(ssl ? 443 : 80));-
286-
287 QHttpNetworkConnection::ConnectionType connectionType-
288 = QHttpNetworkConnection::ConnectionTypeHTTP;-
289#ifndef QT_NO_SSL-
290 if (httpRequest.isSPDYAllowed() && ssl) {-
291 connectionType = QHttpNetworkConnection::ConnectionTypeSPDY;-
292 urlCopy.setScheme(QStringLiteral("spdy")); // to differentiate SPDY requests from HTTPS requests-
293 QList<QByteArray> nextProtocols;-
294 nextProtocols << QSslConfiguration::NextProtocolSpdy3_0-
295 << QSslConfiguration::NextProtocolHttp1_1;-
296 incomingSslConfiguration.setAllowedNextProtocols(nextProtocols);-
297 }-
298#endif // QT_NO_SSL-
299-
300#ifndef QT_NO_NETWORKPROXY-
301 if (transparentProxy.type() != QNetworkProxy::NoProxy)-
302 cacheKey = makeCacheKey(urlCopy, &transparentProxy);-
303 else if (cacheProxy.type() != QNetworkProxy::NoProxy)-
304 cacheKey = makeCacheKey(urlCopy, &cacheProxy);-
305 else-
306#endif-
307 cacheKey = makeCacheKey(urlCopy, 0);-
308-
309-
310 // the http object is actually a QHttpNetworkConnection-
311 httpConnection = static_cast<QNetworkAccessCachedHttpConnection *>(connections.localData()->requestEntryNow(cacheKey));-
312 if (httpConnection == 0) {-
313 // no entry in cache; create an object-
314 // the http object is actually a QHttpNetworkConnection-
315#ifdef QT_NO_BEARERMANAGEMENT-
316 httpConnection = new QNetworkAccessCachedHttpConnection(urlCopy.host(), urlCopy.port(), ssl,-
317 connectionType);-
318#else-
319 httpConnection = new QNetworkAccessCachedHttpConnection(urlCopy.host(), urlCopy.port(), ssl,-
320 connectionType,-
321 networkSession);-
322#endif-
323#ifndef QT_NO_SSL-
324 // Set the QSslConfiguration from this QNetworkRequest.-
325 if (ssl && incomingSslConfiguration != QSslConfiguration::defaultConfiguration()) {-
326 httpConnection->setSslConfiguration(incomingSslConfiguration);-
327 }-
328#endif-
329-
330#ifndef QT_NO_NETWORKPROXY-
331 httpConnection->setTransparentProxy(transparentProxy);-
332 httpConnection->setCacheProxy(cacheProxy);-
333#endif-
334-
335 // cache the QHttpNetworkConnection corresponding to this cache key-
336 connections.localData()->addEntry(cacheKey, httpConnection);-
337 } else {-
338 if (httpRequest.withCredentials()) {-
339 QNetworkAuthenticationCredential credential = authenticationManager->fetchCachedCredentials(httpRequest.url(), 0);-
340 if (!credential.user.isEmpty() && !credential.password.isEmpty()) {-
341 QAuthenticator auth;-
342 auth.setUser(credential.user);-
343 auth.setPassword(credential.password);-
344 httpConnection->d_func()->copyCredentials(-1, &auth, false);-
345 }-
346 }-
347 }-
348-
349-
350 // Send the request to the connection-
351 httpReply = httpConnection->sendRequest(httpRequest);-
352 httpReply->setParent(this);-
353-
354 // Connect the reply signals that we need to handle and then forward-
355 if (synchronous) {-
356 connect(httpReply,SIGNAL(headerChanged()), this, SLOT(synchronousHeaderChangedSlot()));-
357 connect(httpReply,SIGNAL(finished()), this, SLOT(synchronousFinishedSlot()));-
358 connect(httpReply,SIGNAL(finishedWithError(QNetworkReply::NetworkError,QString)),-
359 this, SLOT(synchronousFinishedWithErrorSlot(QNetworkReply::NetworkError,QString)));-
360-
361 connect(httpReply, SIGNAL(authenticationRequired(QHttpNetworkRequest,QAuthenticator*)),-
362 this, SLOT(synchronousAuthenticationRequiredSlot(QHttpNetworkRequest,QAuthenticator*)));-
363#ifndef QT_NO_NETWORKPROXY-
364 connect(httpReply, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),-
365 this, SLOT(synchronousProxyAuthenticationRequiredSlot(QNetworkProxy,QAuthenticator*)));-
366#endif-
367-
368 // Don't care about ignored SSL errors for now in the synchronous HTTP case.-
369 } else if (!synchronous) {-
370 connect(httpReply,SIGNAL(headerChanged()), this, SLOT(headerChangedSlot()));-
371 connect(httpReply,SIGNAL(finished()), this, SLOT(finishedSlot()));-
372 connect(httpReply,SIGNAL(finishedWithError(QNetworkReply::NetworkError,QString)),-
373 this, SLOT(finishedWithErrorSlot(QNetworkReply::NetworkError,QString)));-
374 // some signals are only interesting when normal asynchronous style is used-
375 connect(httpReply,SIGNAL(readyRead()), this, SLOT(readyReadSlot()));-
376 connect(httpReply,SIGNAL(dataReadProgress(qint64,qint64)), this, SLOT(dataReadProgressSlot(qint64,qint64)));-
377#ifndef QT_NO_SSL-
378 connect(httpReply,SIGNAL(encrypted()), this, SLOT(encryptedSlot()));-
379 connect(httpReply,SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(sslErrorsSlot(QList<QSslError>)));-
380 connect(httpReply,SIGNAL(preSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator*)),-
381 this, SLOT(preSharedKeyAuthenticationRequiredSlot(QSslPreSharedKeyAuthenticator*)));-
382#endif-
383-
384 // In the asynchronous HTTP case we can just forward those signals-
385 // Connect the reply signals that we can directly forward-
386 connect(httpReply, SIGNAL(authenticationRequired(QHttpNetworkRequest,QAuthenticator*)),-
387 this, SIGNAL(authenticationRequired(QHttpNetworkRequest,QAuthenticator*)));-
388#ifndef QT_NO_NETWORKPROXY-
389 connect(httpReply, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),-
390 this, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));-
391#endif-
392 }-
393-
394 connect(httpReply, SIGNAL(cacheCredentials(QHttpNetworkRequest,QAuthenticator*)),-
395 this, SLOT(cacheCredentialsSlot(QHttpNetworkRequest,QAuthenticator*)));-
396}-
397-
398// This gets called from the user thread or by the synchronous HTTP timeout timer-
399void QHttpThreadDelegate::abortRequest()-
400{-
401#ifdef QHTTPTHREADDELEGATE_DEBUG-
402 qDebug() << "QHttpThreadDelegate::abortRequest() thread=" << QThread::currentThreadId() << "sync=" << synchronous;-
403#endif-
404 if (httpReply) {-
405 httpReply->abort();-
406 delete httpReply;-
407 httpReply = 0;-
408 }-
409-
410 // Got aborted by the timeout timer-
411 if (synchronous) {-
412 incomingErrorCode = QNetworkReply::TimeoutError;-
413 QMetaObject::invokeMethod(synchronousRequestLoop, "quit", Qt::QueuedConnection);-
414 } else {-
415 //only delete this for asynchronous mode or QNetworkAccessHttpBackend will crash - see QNetworkAccessHttpBackend::postRequest()-
416 this->deleteLater();-
417 }-
418}-
419-
420void QHttpThreadDelegate::readBufferSizeChanged(qint64 size)-
421{-
422#ifdef QHTTPTHREADDELEGATE_DEBUG-
423 qDebug() << "QHttpThreadDelegate::readBufferSizeChanged() size " << size;-
424#endif-
425 if (httpReply) {-
426 httpReply->setDownstreamLimited(size > 0);-
427 httpReply->setReadBufferSize(size);-
428 readBufferMaxSize = size;-
429 }-
430}-
431-
432void QHttpThreadDelegate::readBufferFreed(qint64 size)-
433{-
434 if (readBufferMaxSize) {-
435 bytesEmitted -= size;-
436-
437 QMetaObject::invokeMethod(this, "readyReadSlot", Qt::QueuedConnection);-
438 }-
439}-
440-
441void QHttpThreadDelegate::readyReadSlot()-
442{-
443 if (!httpReply)-
444 return;-
445-
446 // Don't do in zerocopy case-
447 if (!downloadBuffer.isNull())-
448 return;-
449-
450 if (readBufferMaxSize) {-
451 if (bytesEmitted < readBufferMaxSize) {-
452 qint64 sizeEmitted = 0;-
453 while (httpReply->readAnyAvailable() && (sizeEmitted < (readBufferMaxSize-bytesEmitted))) {-
454 if (httpReply->sizeNextBlock() > (readBufferMaxSize-bytesEmitted)) {-
455 sizeEmitted = readBufferMaxSize-bytesEmitted;-
456 bytesEmitted += sizeEmitted;-
457 pendingDownloadData->fetchAndAddRelease(1);-
458 emit downloadData(httpReply->read(sizeEmitted));-
459 } else {-
460 sizeEmitted = httpReply->sizeNextBlock();-
461 bytesEmitted += sizeEmitted;-
462 pendingDownloadData->fetchAndAddRelease(1);-
463 emit downloadData(httpReply->readAny());-
464 }-
465 }-
466 } else {-
467 // We need to wait until we empty data from the read buffer in the reply.-
468 }-
469-
470 } else {-
471 while (httpReply->readAnyAvailable()) {-
472 pendingDownloadData->fetchAndAddRelease(1);-
473 emit downloadData(httpReply->readAny());-
474 }-
475 }-
476}-
477-
478void QHttpThreadDelegate::finishedSlot()-
479{-
480 if (!httpReply)-
481 return;-
482-
483#ifdef QHTTPTHREADDELEGATE_DEBUG-
484 qDebug() << "QHttpThreadDelegate::finishedSlot() thread=" << QThread::currentThreadId() << "result=" << httpReply->statusCode();-
485#endif-
486-
487 // If there is still some data left emit that now-
488 while (httpReply->readAnyAvailable()) {-
489 pendingDownloadData->fetchAndAddRelease(1);-
490 emit downloadData(httpReply->readAny());-
491 }-
492-
493#ifndef QT_NO_SSL-
494 if (ssl)-
495 emit sslConfigurationChanged(httpReply->sslConfiguration());-
496#endif-
497-
498 if (httpReply->statusCode() >= 400) {-
499 // it's an error reply-
500 QString msg = QLatin1String(QT_TRANSLATE_NOOP("QNetworkReply",-
501 "Error transferring %1 - server replied: %2"));-
502 msg = msg.arg(httpRequest.url().toString(), httpReply->reasonPhrase());-
503 emit error(statusCodeFromHttp(httpReply->statusCode(), httpRequest.url()), msg);-
504 }-
505-
506 if (httpRequest.isFollowRedirects() && httpReply->isRedirecting())-
507 emit redirected(httpReply->redirectUrl(), httpReply->statusCode(), httpReply->request().redirectCount() - 1);-
508-
509 emit downloadFinished();-
510-
511 QMetaObject::invokeMethod(httpReply, "deleteLater", Qt::QueuedConnection);-
512 QMetaObject::invokeMethod(this, "deleteLater", Qt::QueuedConnection);-
513 httpReply = 0;-
514}-
515-
516void QHttpThreadDelegate::synchronousFinishedSlot()-
517{-
518 if (!httpReply)-
519 return;-
520-
521#ifdef QHTTPTHREADDELEGATE_DEBUG-
522 qDebug() << "QHttpThreadDelegate::synchronousFinishedSlot() thread=" << QThread::currentThreadId() << "result=" << httpReply->statusCode();-
523#endif-
524 if (httpReply->statusCode() >= 400) {-
525 // it's an error reply-
526 QString msg = QLatin1String(QT_TRANSLATE_NOOP("QNetworkReply",-
527 "Error transferring %1 - server replied: %2"));-
528 incomingErrorDetail = msg.arg(httpRequest.url().toString(), httpReply->reasonPhrase());-
529 incomingErrorCode = statusCodeFromHttp(httpReply->statusCode(), httpRequest.url());-
530 }-
531-
532 synchronousDownloadData = httpReply->readAll();-
533-
534 QMetaObject::invokeMethod(httpReply, "deleteLater", Qt::QueuedConnection);-
535 QMetaObject::invokeMethod(synchronousRequestLoop, "quit", Qt::QueuedConnection);-
536 httpReply = 0;-
537}-
538-
539void QHttpThreadDelegate::finishedWithErrorSlot(QNetworkReply::NetworkError errorCode, const QString &detail)-
540{-
541 if (!httpReply)-
542 return;-
543-
544#ifdef QHTTPTHREADDELEGATE_DEBUG-
545 qDebug() << "QHttpThreadDelegate::finishedWithErrorSlot() thread=" << QThread::currentThreadId() << "error=" << errorCode << detail;-
546#endif-
547-
548#ifndef QT_NO_SSL-
549 if (ssl)-
550 emit sslConfigurationChanged(httpReply->sslConfiguration());-
551#endif-
552 emit error(errorCode,detail);-
553 emit downloadFinished();-
554-
555-
556 QMetaObject::invokeMethod(httpReply, "deleteLater", Qt::QueuedConnection);-
557 QMetaObject::invokeMethod(this, "deleteLater", Qt::QueuedConnection);-
558 httpReply = 0;-
559}-
560-
561-
562void QHttpThreadDelegate::synchronousFinishedWithErrorSlot(QNetworkReply::NetworkError errorCode, const QString &detail)-
563{-
564 if (!httpReply)-
565 return;-
566-
567#ifdef QHTTPTHREADDELEGATE_DEBUG-
568 qDebug() << "QHttpThreadDelegate::synchronousFinishedWithErrorSlot() thread=" << QThread::currentThreadId() << "error=" << errorCode << detail;-
569#endif-
570 incomingErrorCode = errorCode;-
571 incomingErrorDetail = detail;-
572-
573 synchronousDownloadData = httpReply->readAll();-
574-
575 QMetaObject::invokeMethod(httpReply, "deleteLater", Qt::QueuedConnection);-
576 QMetaObject::invokeMethod(synchronousRequestLoop, "quit", Qt::QueuedConnection);-
577 httpReply = 0;-
578}-
579-
580static void downloadBufferDeleter(char *ptr)-
581{-
582 delete[] ptr;-
583}-
584-
585void QHttpThreadDelegate::headerChangedSlot()-
586{-
587 if (!httpReply)-
588 return;-
589-
590#ifdef QHTTPTHREADDELEGATE_DEBUG-
591 qDebug() << "QHttpThreadDelegate::headerChangedSlot() thread=" << QThread::currentThreadId();-
592#endif-
593-
594#ifndef QT_NO_SSL-
595 if (ssl)-
596 emit sslConfigurationChanged(httpReply->sslConfiguration());-
597#endif-
598-
599 // Is using a zerocopy buffer allowed by user and possible with this reply?-
600 if (httpReply->supportsUserProvidedDownloadBuffer()-
601 && (downloadBufferMaximumSize > 0) && (httpReply->contentLength() <= downloadBufferMaximumSize)) {-
602 QT_TRY {-
603 char *buf = new char[httpReply->contentLength()]; // throws if allocation fails-
604 if (buf) {-
605 downloadBuffer = QSharedPointer<char>(buf, downloadBufferDeleter);-
606 httpReply->setUserProvidedDownloadBuffer(buf);-
607 }-
608 } QT_CATCH(const std::bad_alloc &) {
dead code: { }
-
609 // in out of memory situations, don't use downloadbuffer.
dead code: { }
-
610 }
dead code: { }
-
611 }-
612-
613 // We fetch this into our own-
614 incomingHeaders = httpReply->header();-
615 incomingStatusCode = httpReply->statusCode();-
616 incomingReasonPhrase = httpReply->reasonPhrase();-
617 isPipeliningUsed = httpReply->isPipeliningUsed();-
618 incomingContentLength = httpReply->contentLength();-
619 isSpdyUsed = httpReply->isSpdyUsed();-
620-
621 emit downloadMetaData(incomingHeaders,-
622 incomingStatusCode,-
623 incomingReasonPhrase,-
624 isPipeliningUsed,-
625 downloadBuffer,-
626 incomingContentLength,-
627 isSpdyUsed);-
628}-
629-
630void QHttpThreadDelegate::synchronousHeaderChangedSlot()-
631{-
632 if (!httpReply)-
633 return;-
634-
635#ifdef QHTTPTHREADDELEGATE_DEBUG-
636 qDebug() << "QHttpThreadDelegate::synchronousHeaderChangedSlot() thread=" << QThread::currentThreadId();-
637#endif-
638 // Store the information we need in this object, the QNetworkAccessHttpBackend will later read it-
639 incomingHeaders = httpReply->header();-
640 incomingStatusCode = httpReply->statusCode();-
641 incomingReasonPhrase = httpReply->reasonPhrase();-
642 isPipeliningUsed = httpReply->isPipeliningUsed();-
643 isSpdyUsed = httpReply->isSpdyUsed();-
644 incomingContentLength = httpReply->contentLength();-
645}-
646-
647-
648void QHttpThreadDelegate::dataReadProgressSlot(qint64 done, qint64 total)-
649{-
650 // If we don't have a download buffer don't attempt to go this codepath-
651 // It is not used by QNetworkAccessHttpBackend-
652 if (downloadBuffer.isNull())-
653 return;-
654-
655 pendingDownloadProgress->fetchAndAddRelease(1);-
656 emit downloadProgress(done, total);-
657}-
658-
659void QHttpThreadDelegate::cacheCredentialsSlot(const QHttpNetworkRequest &request, QAuthenticator *authenticator)-
660{-
661 authenticationManager->cacheCredentials(request.url(), authenticator);-
662}-
663-
664-
665#ifndef QT_NO_SSL-
666void QHttpThreadDelegate::encryptedSlot()-
667{-
668 if (!httpReply)-
669 return;-
670-
671 emit sslConfigurationChanged(httpReply->sslConfiguration());-
672 emit encrypted();-
673}-
674-
675void QHttpThreadDelegate::sslErrorsSlot(const QList<QSslError> &errors)-
676{-
677 if (!httpReply)-
678 return;-
679-
680 emit sslConfigurationChanged(httpReply->sslConfiguration());-
681-
682 bool ignoreAll = false;-
683 QList<QSslError> specificErrors;-
684 emit sslErrors(errors, &ignoreAll, &specificErrors);-
685 if (ignoreAll)-
686 httpReply->ignoreSslErrors();-
687 if (!specificErrors.isEmpty())-
688 httpReply->ignoreSslErrors(specificErrors);-
689}-
690-
691void QHttpThreadDelegate::preSharedKeyAuthenticationRequiredSlot(QSslPreSharedKeyAuthenticator *authenticator)-
692{-
693 if (!httpReply)-
694 return;-
695-
696 emit preSharedKeyAuthenticationRequired(authenticator);-
697}-
698#endif-
699-
700void QHttpThreadDelegate::synchronousAuthenticationRequiredSlot(const QHttpNetworkRequest &request, QAuthenticator *a)-
701{-
702 if (!httpReply)-
703 return;-
704-
705 Q_UNUSED(request);-
706#ifdef QHTTPTHREADDELEGATE_DEBUG-
707 qDebug() << "QHttpThreadDelegate::synchronousAuthenticationRequiredSlot() thread=" << QThread::currentThreadId();-
708#endif-
709-
710 // Ask the credential cache-
711 QNetworkAuthenticationCredential credential = authenticationManager->fetchCachedCredentials(httpRequest.url(), a);-
712 if (!credential.isNull()) {-
713 a->setUser(credential.user);-
714 a->setPassword(credential.password);-
715 }-
716-
717 // Disconnect this connection now since we only want to ask the authentication cache once.-
718 QObject::disconnect(httpReply, SIGNAL(authenticationRequired(QHttpNetworkRequest,QAuthenticator*)),-
719 this, SLOT(synchronousAuthenticationRequiredSlot(QHttpNetworkRequest,QAuthenticator*)));-
720}-
721-
722#ifndef QT_NO_NETWORKPROXY-
723void QHttpThreadDelegate::synchronousProxyAuthenticationRequiredSlot(const QNetworkProxy &p, QAuthenticator *a)-
724{-
725 if (!httpReply)-
726 return;-
727-
728#ifdef QHTTPTHREADDELEGATE_DEBUG-
729 qDebug() << "QHttpThreadDelegate::synchronousProxyAuthenticationRequiredSlot() thread=" << QThread::currentThreadId();-
730#endif-
731 // Ask the credential cache-
732 QNetworkAuthenticationCredential credential = authenticationManager->fetchCachedProxyCredentials(p, a);-
733 if (!credential.isNull()) {-
734 a->setUser(credential.user);-
735 a->setPassword(credential.password);-
736 }-
737-
738#ifndef QT_NO_NETWORKPROXY-
739 // Disconnect this connection now since we only want to ask the authentication cache once.-
740 QObject::disconnect(httpReply, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),-
741 this, SLOT(synchronousProxyAuthenticationRequiredSlot(QNetworkProxy,QAuthenticator*)));-
742#endif-
743}-
744-
745#endif-
746-
747#endif // QT_NO_HTTP-
748-
749QT_END_NAMESPACE-
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial 4.3.0-BETA-master-30-08-2018-4cb69e9