1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qnetworkaccessbackend_p.h"
5#include "qnetworkreplyimpl_p.h"
6#include "qnetworkaccessmanager_p.h"
7#include "qnetworkrequest.h"
8#include "qnetworkreply.h"
9#include "qnetworkreply_p.h"
10#include "QtCore/qmutex.h"
11#include "QtCore/qstringlist.h"
12
13#include "qnetworkaccesscachebackend_p.h"
14#include "qabstractnetworkcache.h"
15#include "qhostinfo.h"
16
17#include "private/qnoncontiguousbytedevice_p.h"
18
19QT_BEGIN_NAMESPACE
20
21class QNetworkAccessBackendFactoryData: public QList<QNetworkAccessBackendFactory *>
22{
23public:
24 QNetworkAccessBackendFactoryData()
25 {
26 valid.ref();
27 }
28 ~QNetworkAccessBackendFactoryData()
29 {
30 QMutexLocker locker(&mutex); // why do we need to lock?
31 valid.deref();
32 }
33
34 QRecursiveMutex mutex;
35 //this is used to avoid (re)constructing factory data from destructors of other global classes
36 static QBasicAtomicInt valid;
37};
38Q_GLOBAL_STATIC(QNetworkAccessBackendFactoryData, factoryData)
39Q_CONSTINIT QBasicAtomicInt QNetworkAccessBackendFactoryData::valid = Q_BASIC_ATOMIC_INITIALIZER(0);
40
41class QNetworkAccessBackendPrivate : public QObjectPrivate
42{
43public:
44 QNetworkAccessBackend::TargetTypes m_targetTypes;
45 QNetworkAccessBackend::SecurityFeatures m_securityFeatures;
46 QNetworkAccessBackend::IOFeatures m_ioFeatures;
47 std::shared_ptr<QNonContiguousByteDevice> uploadByteDevice;
48 QIODevice *wrappedUploadByteDevice = nullptr;
49 QNetworkReplyImplPrivate *m_reply = nullptr;
50 QNetworkAccessManagerPrivate *m_manager = nullptr;
51
52 bool m_canCache = false;
53 bool m_isSynchronous = false;
54};
55
56QNetworkAccessBackend *
57QNetworkAccessManagerPrivate::findBackend(QNetworkAccessManager::Operation op,
58 const QNetworkRequest &request)
59{
60 if (QNetworkAccessBackendFactoryData::valid.loadRelaxed()) {
61 QMutexLocker locker(&factoryData()->mutex);
62 QNetworkAccessBackendFactoryData::ConstIterator it = factoryData()->constBegin(),
63 end = factoryData()->constEnd();
64 while (it != end) {
65 QNetworkAccessBackend *backend = (*it)->create(op, request);
66 if (backend) {
67 backend->setManagerPrivate(this);
68 return backend; // found a factory that handled our request
69 }
70 ++it;
71 }
72 }
73 return nullptr;
74}
75
76QStringList QNetworkAccessManagerPrivate::backendSupportedSchemes() const
77{
78 if (QNetworkAccessBackendFactoryData::valid.loadRelaxed()) {
79 QMutexLocker locker(&factoryData()->mutex);
80 QNetworkAccessBackendFactoryData::ConstIterator it = factoryData()->constBegin();
81 QNetworkAccessBackendFactoryData::ConstIterator end = factoryData()->constEnd();
82 QStringList schemes;
83 while (it != end) {
84 schemes += (*it)->supportedSchemes();
85 ++it;
86 }
87 return schemes;
88 }
89 return QStringList();
90}
91
92/*!
93 \class QNetworkAccessBackendFactory
94 \brief QNetworkAccessBackendFactory is the base class to inherit
95 from for Qt to instantiate and query your QNetworkAccessBackend
96 plugin.
97 \since 6.0
98 \internal
99
100//! [semi-private-notice]
101 The class is considered semi-private and as such requires linking
102 to "NetworkPrivate" to access the header. Furthermore it means
103 the class is not under the same binary compatibility restrictions
104 as the rest of Qt. While we still try to avoid breakage it may
105 still occur. The class is primarily meant to be used by plugins
106 which would be recompiled every time Qt is updated.
107//! [semi-private-notice]
108
109 This class acts as the primary interface to the plugin and must
110 be derived from. It deals with both querying supported schemes
111 and the creation of QNetworkAccessBackend
112
113 Since they are both abstract function you are required to
114 implement supportedSchemes() and create().
115*/
116
117/*!
118 \fn QStringList QNetworkAccessBackendFactory::supportedSchemes() const
119
120 Override this method in your own derived class to let Qt know
121 what schemes your class can handle.
122*/
123
124/*!
125 \fn QNetworkAccessBackendFactory::create(QNetworkAccessManager::Operation op, const QNetworkRequest &request) const
126
127 Override this method in your own class and return a
128 heap-allocated instance of your class derived from
129 QNetworkAccessBackend.
130
131 If \a op or a property of \a request is not supported (for
132 example the URL's scheme) then you must return \nullptr.
133
134 \sa QNetworkRequest::attribute(), QNetworkRequest::url(), QUrl::scheme()
135*/
136
137/*!
138 \class QNetworkAccessBackend
139 \brief QNetworkAccessBackend is the base class for implementing
140 support for schemes used by QNetworkAccessManager.
141 \since 6.0
142 \internal
143
144 \include access/qnetworkaccessbackend.cpp semi-private-notice
145
146 This class can be derived from to add support for further schemes
147 in QNetworkAccessManager.
148
149 The design of QNetworkAccessBackend makes it possible to specialize
150 behavior as needed for certain backends.
151 This was done using the (currently) 3 enums TargetType,
152 SecurityFeatures and IOFeatures. For example while only open()
153 and close() are abstract functions you are also required to
154 implement either read() or readPointer() and advanceReadPointer()
155 depending on whether you enable IOFeature::ZeroCopy or not.
156 Read more about it in the documentation for each of the
157 enumerators.
158
159 \sa TargetType, SecurityFeatures, IOFeatures
160*/
161
162/*!
163 \enum QNetworkAccessBackend::TargetType
164
165 Use the values in this enum to specify what type of target
166 the plugin supports. Setting the right type can be important,
167 for example: proxyList() is only available for a Networked
168 plugin.
169
170 \value Networked
171 The plugin supports and expect to connect to networked
172 resources. E.g. over TCP, UDP or similar.
173 \value Local
174 The plugin supports and expects to access local files,
175 generate data and/or locally connected devices.
176*/
177
178/*!
179 \enum QNetworkAccessBackend::SecurityFeature
180
181 Use the values in this enum to specify what type of security
182 features the plugin may utilize. Setting the right type(s)
183 can be important, for example: setSslConfiguration() may not
184 be called for any plugin that do not claim to support TLS.
185
186 \value None
187 No specific features are claimed to be supported.
188 \value TLS
189 The plugin supports and expects to use TLS.
190*/
191
192/*!
193 \enum QNetworkAccessBackend::IOFeature
194
195 Use the values in this enum to specify what type of IO
196 features the plugin may utilize.
197
198 \value None
199 No specific features are claimed to be supported.
200 \value ZeroCopy
201 The plugin will have raw data available in contiguous
202 segments and can return a pointer to the data at request.
203 Claiming to support this requires implementing readPointer()
204 and advanceReadPointer().
205 \value NeedResetableUpload
206 The plugin may encounter scenarios where data to upload that
207 has already been consumed needs to be restored and re-sent.
208 E.g. some data was consumed and sent before a redirect
209 response was received, and after the redirect the
210 previously-consumed data needs to be re-sent.
211 \omitvalue SupportsSynchronousMode
212*/
213
214/*!
215 Constructs the QNetworkAccessBackend.
216 You can opt in to specific backend behaviors with \a targetTypes,
217 \a securityFeatures and \a ioFeatures.
218 See their respective enums and values for more information.
219
220 \sa TargetType, SecurityFeature, IOFeature
221*/
222QNetworkAccessBackend::QNetworkAccessBackend(TargetTypes targetTypes,
223 SecurityFeatures securityFeatures,
224 IOFeatures ioFeatures)
225 : QObject(*(new QNetworkAccessBackendPrivate), nullptr)
226{
227 Q_D(QNetworkAccessBackend);
228 d->m_targetTypes = targetTypes;
229 d->m_securityFeatures = securityFeatures;
230 d->m_ioFeatures = ioFeatures;
231}
232
233/*!
234 \overload
235*/
236QNetworkAccessBackend::QNetworkAccessBackend(TargetTypes targetTypes)
237 : QNetworkAccessBackend(targetTypes, SecurityFeature::None, IOFeature::None)
238{
239}
240
241/*!
242 \overload
243*/
244QNetworkAccessBackend::QNetworkAccessBackend(TargetTypes targetTypes,
245 SecurityFeatures securityFeatures)
246 : QNetworkAccessBackend(targetTypes, securityFeatures, IOFeature::None)
247{
248}
249
250/*!
251 \overload
252*/
253QNetworkAccessBackend::QNetworkAccessBackend(TargetTypes targetTypes, IOFeatures ioFeatures)
254 : QNetworkAccessBackend(targetTypes, SecurityFeature::None, ioFeatures)
255{
256}
257
258/*!
259 Destructs the QNetworkAccessBackend base class.
260*/
261QNetworkAccessBackend::~QNetworkAccessBackend() { }
262
263/*!
264 Returns the security related features that the backend claims to
265 support.
266
267 \sa SecurityFeature
268*/
269QNetworkAccessBackend::SecurityFeatures QNetworkAccessBackend::securityFeatures() const noexcept
270{
271 return d_func()->m_securityFeatures;
272}
273
274/*!
275 Returns the TargetTypes that the backend claims to target.
276
277 \sa TargetType
278*/
279QNetworkAccessBackend::TargetTypes QNetworkAccessBackend::targetTypes() const noexcept
280{
281 return d_func()->m_targetTypes;
282}
283
284/*!
285 Returns the I/O features that the backend claims to support.
286
287 \sa IOFeature
288*/
289QNetworkAccessBackend::IOFeatures QNetworkAccessBackend::ioFeatures() const noexcept
290{
291 return d_func()->m_ioFeatures;
292}
293
294/*!
295 Prepares the backend and calls open().
296 E.g. for TargetType::Networked it will prepare proxyList().
297
298 \sa TargetType, targetTypes
299*/
300bool QNetworkAccessBackend::start()
301{
302 Q_D(QNetworkAccessBackend);
303#ifndef QT_NO_NETWORKPROXY
304 if (targetTypes() & QNetworkAccessBackend::TargetType::Networked)
305 d->m_reply->proxyList = d->m_manager->queryProxy(query: QNetworkProxyQuery(url()));
306#endif
307
308 // now start the request
309 open();
310 return true;
311}
312
313/*!
314 \fn void QNetworkAccessBackend::open() = 0
315
316 You must implement this in your derived class.
317 During this call you must open the connection and begin the request
318 (see: request()).
319
320 As the connection progresses you must call the various public and
321 protected slots on QNetworkAccessBackend. As an example, when you have
322 received some data you must call readyRead(). And when all the data has been
323 received you must call finished(). This could, for example, be done by
324 binding signals inside your own implementation to the slots, or by calling
325 them directly.
326
327 \sa close()
328*/
329
330/*!
331 \fn void QNetworkAccessBackend::close() = 0
332
333 You must implement this function in your derived class.
334 This function gets called when the QNetworkReply is closed or aborted.
335
336 You should not emit an error or call finished() during this call since
337 QtNetwork will set and emit the \c{QNetworkReply::OperationCanceledError}
338 error by itself after control flow returns from this function.
339*/
340
341/*!
342 \fn qint64 QNetworkAccessBackend::bytesAvailable() const = 0
343
344 You must implement this function in your derived class.
345 This function is called at various times. It may be called because the user
346 called QNetworkReply::bytesAvailable(), and it may be called before an
347 attempt to read is made.
348
349 While this function doesn't technically need to return an accurate number,
350 it may result in reduced performance if it does not. This function must
351 return zero if there are no bytes available.
352*/
353
354#if QT_CONFIG(ssl)
355/*!
356 Passes a \a configuration with the user's desired TLS
357 configuration. If you don't have the TLS security feature this
358 may not be called.
359
360 \sa SecurityFeature, securityFeatures
361*/
362void QNetworkAccessBackend::setSslConfiguration(const QSslConfiguration &configuration)
363{
364 Q_UNUSED(configuration);
365 if (securityFeatures() & SecurityFeature::TLS) {
366 qWarning(msg: "Backend (%s) claiming to use TLS hasn't overridden setSslConfiguration.",
367 metaObject()->className());
368 }
369}
370
371/*!
372 Override this and return the QSslConfiguration used if you
373 have the TLS security feature
374
375 \sa SecurityFeature, securityFeatures
376*/
377QSslConfiguration QNetworkAccessBackend::sslConfiguration() const
378{
379 if (securityFeatures() & SecurityFeature::TLS) {
380 qWarning(msg: "Backend (%s) claiming to use TLS hasn't overridden sslConfiguration.",
381 metaObject()->className());
382 }
383 return {};
384}
385#endif
386
387/*!
388 This function will be called when the user wants to ignore
389 all TLS handshake errors. Derive this function if TLS is
390 supported.
391
392 \sa SecurityFeature, securityFeatures
393*/
394void QNetworkAccessBackend::ignoreSslErrors()
395{
396 if (securityFeatures() & SecurityFeature::TLS) {
397 qWarning(msg: "Backend (%s) claiming to use TLS hasn't overridden ignoreSslErrors.",
398 metaObject()->className());
399 }
400}
401
402/*!
403 This function will be called when the user wants to ignore
404 specific \a errors. Derive this function if TLS is supported.
405
406 \sa SecurityFeature, securityFeatures
407*/
408void QNetworkAccessBackend::ignoreSslErrors(const QList<QSslError> &errors)
409{
410 Q_UNUSED(errors);
411 if (securityFeatures() & SecurityFeature::TLS) {
412 qWarning(msg: "Backend (%s) claiming to use TLS hasn't overridden ignoreSslErrors.",
413 metaObject()->className());
414 }
415}
416
417/*!
418 The data which the returned value views must stay valid until
419 at least the next call to a non-const function. advanceReadPointer
420 will be called if any of the data was used.
421
422 Note: This will only be called if IOFeature::ZeroCopy was
423 specified in the call to the constructor.
424
425 \sa advanceReadPointer, read
426*/
427QByteArrayView QNetworkAccessBackend::readPointer()
428{
429 if (ioFeatures() & IOFeature::ZeroCopy) {
430 qWarning(msg: "Backend (%s) claiming to support ZeroCopy hasn't overridden readPointer.",
431 metaObject()->className());
432 }
433 return {};
434}
435
436/*!
437 This function is to notify your class that \a distance
438 bytes have been read using readPointer and next time
439 readPointer() is called those bytes should not be included.
440
441 Note: This will only be called if IOFeature::ZeroCopy was
442 specified in the call to the constructor.
443
444 \sa readPointer
445*/
446void QNetworkAccessBackend::advanceReadPointer(qint64 distance)
447{
448 Q_UNUSED(distance);
449 if (ioFeatures() & IOFeature::ZeroCopy) {
450 qWarning(msg: "Backend (%s) claiming to support ZeroCopy hasn't overridden advanceReadPointer.",
451 metaObject()->className());
452 }
453}
454
455/*!
456 Implement this function to support reading from the resource
457 made available by your plugin.
458 Store data in \a data, up to a maximum of \a maxlen bytes.
459 Then return the total amount of bytes that was copied.
460
461 \sa readPointer, wantToRead
462*/
463qint64 QNetworkAccessBackend::read(char *data, qint64 maxlen)
464{
465 Q_UNUSED(data);
466 Q_UNUSED(maxlen);
467 if ((ioFeatures() & IOFeature::ZeroCopy) == 0) {
468 qWarning(msg: "Backend (%s) is not ZeroCopy and has not implemented read(...)!",
469 metaObject()->className());
470 }
471 return 0;
472}
473
474/*!
475 This is called before we read if there are no bytes available
476 and we are ready to read more. Return \c true if new data was
477 made available.
478
479 \sa read, readPointer
480*/
481bool QNetworkAccessBackend::wantToRead()
482{
483 // Base implementation does nothing
484 return false;
485}
486
487#if QT_CONFIG(networkproxy)
488/*!
489 Returns a list of proxies configured for the URL returned by
490 url().
491
492 It is only valid to call this function if TargetType::Networked
493 was specified in the call to the constructor.
494*/
495QList<QNetworkProxy> QNetworkAccessBackend::proxyList() const
496{
497 Q_ASSERT(targetTypes() & TargetType::Networked);
498 return d_func()->m_reply->proxyList;
499}
500#endif
501
502/*!
503 Returns the current URL of the reply
504*/
505QUrl QNetworkAccessBackend::url() const
506{
507 return d_func()->m_reply->url;
508}
509
510/*!
511 Sets the URL of the reply. This could e.g. be needed if a
512 redirect or similar was performed.
513*/
514void QNetworkAccessBackend::setUrl(const QUrl &url)
515{
516 d_func()->m_reply->url = url;
517}
518
519/*!
520 Returns the value of the \a header.
521 If no such header was known it returns a default-constructed
522 QVariant.
523
524 \sa setHeader, rawHeader, setRawHeader
525*/
526QVariant QNetworkAccessBackend::header(QNetworkRequest::KnownHeaders header) const
527{
528 return d_func()->m_reply->cookedHeaders.value(key: header);
529}
530
531/*!
532 Sets the value of the \a header to \a value.
533 This can be queried on the QNetworkReply instance which was
534 returned when calling one of the appropriate functions on
535 QNetworkAccessManager.
536
537 \sa header, rawHeader, setRawHeader
538*/
539void QNetworkAccessBackend::setHeader(QNetworkRequest::KnownHeaders header, const QVariant &value)
540{
541 d_func()->m_reply->setCookedHeader(header, value);
542}
543
544/*!
545 Returns the value of the \a header.
546 If no such header was known it returns a default-constructed
547 QVariant.
548
549 \sa setHeader, rawHeader, setRawHeader
550*/
551QByteArray QNetworkAccessBackend::rawHeader(const QByteArray &header) const
552{
553 return d_func()->m_reply->q_func()->rawHeader(headerName: header);
554}
555
556/*!
557 Sets the value of the \a header to \a value.
558
559 This value is accessible on the QNetworkReply instance which was
560 returned when calling one of the appropriate functions on
561 QNetworkAccessManager.
562
563 \sa header, rawHeader, setRawHeader
564*/
565void QNetworkAccessBackend::setRawHeader(const QByteArray &header, const QByteArray &value)
566{
567 d_func()->m_reply->setRawHeader(key: header, value);
568}
569
570/*!
571 \since 6.8
572
573 Returns headers that are set in this QNetworkAccessBackend instance.
574
575 \sa setHeaders()
576*/
577QHttpHeaders QNetworkAccessBackend::headers() const
578{
579 return d_func()->m_reply->headers();
580}
581
582/*!
583 \since 6.8
584
585 Sets \a newHeaders as headers, overriding any previously set headers.
586
587 These headers are accessible on the QNetworkReply instance which was
588 returned when calling one of the appropriate functions on
589 QNetworkAccessManager.
590
591 \sa headers()
592*/
593void QNetworkAccessBackend::setHeaders(QHttpHeaders &&newHeaders)
594{
595 d_func()->m_reply->setHeaders(std::move(newHeaders));
596}
597
598/*!
599 \overload
600 \since 6.8
601*/
602void QNetworkAccessBackend::setHeaders(const QHttpHeaders &newHeaders)
603{
604 d_func()->m_reply->setHeaders(newHeaders);
605}
606
607/*!
608 Returns the operation which was requested when calling
609 QNetworkAccessManager.
610*/
611QNetworkAccessManager::Operation QNetworkAccessBackend::operation() const
612{
613 return d_func()->m_reply->operation;
614}
615
616/*!
617 Returns \c true if setCachingEnabled was previously called with \c true.
618 Returns \c false otherwise, which is the default value.
619
620 \sa setCachingEnabled
621*/
622bool QNetworkAccessBackend::isCachingEnabled() const
623{
624 return d_func()->m_canCache;
625}
626
627/*!
628 If \a canCache is \c true then this hints to us that we can cache
629 the reply that is created.
630
631 \sa isCachingEnabled
632*/
633void QNetworkAccessBackend::setCachingEnabled(bool canCache)
634{
635 d_func()->m_canCache = canCache;
636}
637
638/*!
639 Set \a attribute to \a value. If \c{value.isValid()} returns
640 \c false then the attribute is unset.
641
642 This value is accessible on the QNetworkReply instance which was
643 returned when calling one of the appropriate functions on
644 QNetworkAccessManager.
645*/
646void QNetworkAccessBackend::setAttribute(QNetworkRequest::Attribute attribute,
647 const QVariant &value)
648{
649 Q_D(QNetworkAccessBackend);
650 if (value.isValid())
651 d->m_reply->attributes.insert(key: attribute, value);
652 else
653 d->m_reply->attributes.remove(key: attribute);
654}
655
656/*!
657 Creates a QIODevice for the data provided to upload, if any.
658
659 Emission of upload progress is handled internally as the device
660 gets read from.
661
662 Returns a pointer to a device with data or nullptr if there was
663 no data to upload.
664*/
665QIODevice *QNetworkAccessBackend::createUploadByteDevice()
666{
667 Q_D(QNetworkAccessBackend);
668
669 if (d->m_reply->outgoingDataBuffer)
670 d->uploadByteDevice =
671 QNonContiguousByteDeviceFactory::createShared(ringBuffer: d->m_reply->outgoingDataBuffer);
672 else if (d->m_reply->outgoingData) {
673 d->uploadByteDevice =
674 QNonContiguousByteDeviceFactory::createShared(device: d->m_reply->outgoingData);
675 } else {
676 return nullptr;
677 }
678
679 // We want signal emissions only for normal asynchronous uploads
680 if (!isSynchronous()) {
681 connect(sender: d->uploadByteDevice.get(), signal: &QNonContiguousByteDevice::readProgress, context: this,
682 slot: [this](qint64 a, qint64 b) {
683 Q_D(QNetworkAccessBackend);
684 if (!d->m_reply->isFinished)
685 d->m_reply->emitUploadProgress(bytesSent: a, bytesTotal: b);
686 });
687 }
688
689 d->wrappedUploadByteDevice = QNonContiguousByteDeviceFactory::wrap(byteDevice: d->uploadByteDevice.get());
690 return d->wrappedUploadByteDevice;
691}
692
693/*!
694 Returns the upload byte device associated with the current
695 request. This does not create the request but simply returns
696 the pointer stored in this base class so it doesn't need to be
697 stored in the subclass too.
698*/
699QIODevice *QNetworkAccessBackend::uploadByteDevice()
700{
701 return d_func()->wrappedUploadByteDevice;
702}
703
704/*!
705 \internal
706 Returns \c true if synchronous mode is enabled.
707 If it is disabled or not supported it will return \c {false}.
708*/
709bool QNetworkAccessBackend::isSynchronous() const
710{
711 return d_func()->m_isSynchronous;
712}
713
714/*!
715 \internal
716 Enables or disables synchronous mode depending on \a synchronous
717 if the backend supports it. Otherwise it will always be disabled.
718*/
719void QNetworkAccessBackend::setSynchronous(bool synchronous)
720{
721 if ((ioFeatures() & IOFeature::SupportsSynchronousMode) == 0)
722 return;
723 d_func()->m_isSynchronous = synchronous;
724}
725
726/*!
727 Call this slot when you have more data available to notify
728 the backend that we can attempt to read again.
729*/
730void QNetworkAccessBackend::readyRead()
731{
732 d_func()->m_reply->backendNotify(notification: QNetworkReplyImplPrivate::NotifyDownstreamReadyWrite);
733}
734
735/*!
736 Call this slot when there will be no more data available,
737 regardless of whether the transfer was successful or unsuccessful.
738 For unsuccessful transfers make sure to call error() first!
739*/
740void QNetworkAccessBackend::finished()
741{
742 d_func()->m_reply->finished();
743}
744
745/*!
746 Call this slot if an error occurs. An error would be something
747 you cannot recover from (e.g. the file requested is missing).
748 The \a code and \a errorString is transferred to and stored in
749 the QNetworkReply and the \a code is emitted through the
750 QNetworkReply::errorOccurred() signal.
751*/
752void QNetworkAccessBackend::error(QNetworkReply::NetworkError code, const QString &errorString)
753{
754 Q_ASSERT(!d_func()->m_reply->isFinished);
755 d_func()->m_reply->error(code, errorString);
756}
757
758#ifndef QT_NO_NETWORKPROXY
759/*!
760 Call this slot if, when connecting through a proxy, it requests
761 authentication. This may cause the
762 QNetworkAccessManager::proxyAuthenticationRequired() signal to be
763 emitted if the credentials are not already stored in an internal
764 cache.
765 To be able to make the lookup in the cache and potentially the
766 subsequent request the \a proxy needs to be known. The credentials
767 will be stored in \a authenticator. While \a authenticator is a
768 pointer, passing \c nullptr is invalid.
769*/
770void QNetworkAccessBackend::proxyAuthenticationRequired(const QNetworkProxy &proxy,
771 QAuthenticator *authenticator)
772{
773 Q_D(QNetworkAccessBackend);
774 Q_ASSERT(authenticator);
775 d->m_manager->proxyAuthenticationRequired(url: QUrl(), proxy, synchronous: isSynchronous(), authenticator,
776 lastProxyAuthentication: &d->m_reply->lastProxyAuthentication);
777}
778#endif
779
780/*!
781 Call this slot if the remote resource requests authentication.
782 This may cause the
783 QNetworkAccessManager::authenticationRequired() signal to be
784 emitted if the credentials are not already stored in an internal
785 cache.
786 The credentials will be stored in \a authenticator. While
787 \a authenticator is a pointer, passing \c nullptr is invalid.
788*/
789void QNetworkAccessBackend::authenticationRequired(QAuthenticator *authenticator)
790{
791 Q_D(QNetworkAccessBackend);
792 Q_ASSERT(authenticator);
793 d->m_manager->authenticationRequired(authenticator, reply: d->m_reply->q_func(), synchronous: isSynchronous(),
794 url&: d->m_reply->url, urlForLastAuthentication: &d->m_reply->urlForLastAuthentication);
795}
796
797/*!
798 Call this slot, if appropriate, after having processed and
799 updated metadata (e.g. headers).
800*/
801void QNetworkAccessBackend::metaDataChanged()
802{
803 d_func()->m_reply->metaDataChanged();
804}
805
806/*!
807 Call this slot if, when connecting to the resource, a redirect
808 to \a destination was requested.
809*/
810void QNetworkAccessBackend::redirectionRequested(const QUrl &destination)
811{
812 d_func()->m_reply->redirectionRequested(target: destination);
813}
814
815/*!
816 \internal
817*/
818void QNetworkAccessBackend::setReplyPrivate(QNetworkReplyImplPrivate *reply)
819{
820 d_func()->m_reply = reply;
821}
822
823/*!
824 \internal
825*/
826void QNetworkAccessBackend::setManagerPrivate(QNetworkAccessManagerPrivate *manager)
827{
828 d_func()->m_manager = manager;
829}
830
831/*!
832 Returns the network cache object that was available when the
833 request was started. Returns \c nullptr if none was available.
834*/
835QAbstractNetworkCache *QNetworkAccessBackend::networkCache() const
836{
837 return d_func()->m_manager->networkCache;
838}
839
840// -- QNetworkAccessBackendFactory
841/*!
842 Constructs QNetworkAccessBackendFactory
843*/
844QNetworkAccessBackendFactory::QNetworkAccessBackendFactory()
845{
846 if (factoryData())
847 factoryData->append(t: this);
848}
849
850/*!
851 Destructs QNetworkAccessBackendFactory
852*/
853QNetworkAccessBackendFactory::~QNetworkAccessBackendFactory()
854{
855 if (factoryData.exists())
856 factoryData->removeAll(t: this);
857};
858
859QT_END_NAMESPACE
860
861#include "moc_qnetworkaccessbackend_p.cpp"
862

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

source code of qtbase/src/network/access/qnetworkaccessbackend.cpp