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;
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 Returns the operation which was requested when calling
572 QNetworkAccessManager.
573*/
574QNetworkAccessManager::Operation QNetworkAccessBackend::operation() const
575{
576 return d_func()->m_reply->operation;
577}
578
579/*!
580 Returns \c true if setCachingEnabled was previously called with \c true.
581 Returns \c false otherwise, which is the default value.
582
583 \sa setCachingEnabled
584*/
585bool QNetworkAccessBackend::isCachingEnabled() const
586{
587 return d_func()->m_canCache;
588}
589
590/*!
591 If \a canCache is \c true then this hints to us that we can cache
592 the reply that is created.
593
594 \sa isCachingEnabled
595*/
596void QNetworkAccessBackend::setCachingEnabled(bool canCache)
597{
598 d_func()->m_canCache = canCache;
599}
600
601/*!
602 Set \a attribute to \a value. If \c{value.isValid()} returns
603 \c false then the attribute is unset.
604
605 This value is accessible on the QNetworkReply instance which was
606 returned when calling one of the appropriate functions on
607 QNetworkAccessManager.
608*/
609void QNetworkAccessBackend::setAttribute(QNetworkRequest::Attribute attribute,
610 const QVariant &value)
611{
612 Q_D(QNetworkAccessBackend);
613 if (value.isValid())
614 d->m_reply->attributes.insert(key: attribute, value);
615 else
616 d->m_reply->attributes.remove(key: attribute);
617}
618
619/*!
620 Creates a QIODevice for the data provided to upload, if any.
621
622 Emission of upload progress is handled internally as the device
623 gets read from.
624
625 Returns a pointer to a device with data or nullptr if there was
626 no data to upload.
627*/
628QIODevice *QNetworkAccessBackend::createUploadByteDevice()
629{
630 Q_D(QNetworkAccessBackend);
631
632 if (d->m_reply->outgoingDataBuffer)
633 d->uploadByteDevice =
634 QNonContiguousByteDeviceFactory::createShared(ringBuffer: d->m_reply->outgoingDataBuffer);
635 else if (d->m_reply->outgoingData) {
636 d->uploadByteDevice =
637 QNonContiguousByteDeviceFactory::createShared(device: d->m_reply->outgoingData);
638 } else {
639 return nullptr;
640 }
641
642 // We want signal emissions only for normal asynchronous uploads
643 if (!isSynchronous()) {
644 connect(sender: d->uploadByteDevice.get(), signal: &QNonContiguousByteDevice::readProgress, context: this,
645 slot: [this](qint64 a, qint64 b) {
646 Q_D(QNetworkAccessBackend);
647 if (!d->m_reply->isFinished)
648 d->m_reply->emitUploadProgress(bytesSent: a, bytesTotal: b);
649 });
650 }
651
652 d->wrappedUploadByteDevice = QNonContiguousByteDeviceFactory::wrap(byteDevice: d->uploadByteDevice.get());
653 return d->wrappedUploadByteDevice;
654}
655
656/*!
657 Returns the upload byte device associated with the current
658 request. This does not create the request but simply returns
659 the pointer stored in this base class so it doesn't need to be
660 stored in the subclass too.
661*/
662QIODevice *QNetworkAccessBackend::uploadByteDevice()
663{
664 return d_func()->wrappedUploadByteDevice;
665}
666
667/*!
668 \internal
669 Returns \c true if synchronous mode is enabled.
670 If it is disabled or not supported it will return \c {false}.
671*/
672bool QNetworkAccessBackend::isSynchronous() const
673{
674 return d_func()->m_isSynchronous;
675}
676
677/*!
678 \internal
679 Enables or disables synchronous mode depending on \a synchronous
680 if the backend supports it. Otherwise it will always be disabled.
681*/
682void QNetworkAccessBackend::setSynchronous(bool synchronous)
683{
684 if ((ioFeatures() & IOFeature::SupportsSynchronousMode) == 0)
685 return;
686 d_func()->m_isSynchronous = synchronous;
687}
688
689/*!
690 Call this slot when you have more data available to notify
691 the backend that we can attempt to read again.
692*/
693void QNetworkAccessBackend::readyRead()
694{
695 d_func()->m_reply->backendNotify(notification: QNetworkReplyImplPrivate::NotifyDownstreamReadyWrite);
696}
697
698/*!
699 Call this slot when there will be no more data available,
700 regardless of whether the transfer was successful or unsuccessful.
701 For unsuccessful transfers make sure to call error() first!
702*/
703void QNetworkAccessBackend::finished()
704{
705 d_func()->m_reply->finished();
706}
707
708/*!
709 Call this slot if an error occurs. An error would be something
710 you cannot recover from (e.g. the file requested is missing).
711 The \a code and \a errorString is transferred to and stored in
712 the QNetworkReply and the \a code is emitted through the
713 QNetworkReply::errorOccurred() signal.
714*/
715void QNetworkAccessBackend::error(QNetworkReply::NetworkError code, const QString &errorString)
716{
717 Q_ASSERT(!d_func()->m_reply->isFinished);
718 d_func()->m_reply->error(code, errorString);
719}
720
721#ifndef QT_NO_NETWORKPROXY
722/*!
723 Call this slot if, when connecting through a proxy, it requests
724 authentication. This may cause the
725 QNetworkAccessManager::proxyAuthenticationRequired() signal to be
726 emitted if the credentials are not already stored in an internal
727 cache.
728 To be able to make the lookup in the cache and potentially the
729 subsequent request the \a proxy needs to be known. The credentials
730 will be stored in \a authenticator. While \a authenticator is a
731 pointer, passing \c nullptr is invalid.
732*/
733void QNetworkAccessBackend::proxyAuthenticationRequired(const QNetworkProxy &proxy,
734 QAuthenticator *authenticator)
735{
736 Q_D(QNetworkAccessBackend);
737 Q_ASSERT(authenticator);
738 d->m_manager->proxyAuthenticationRequired(url: QUrl(), proxy, synchronous: isSynchronous(), authenticator,
739 lastProxyAuthentication: &d->m_reply->lastProxyAuthentication);
740}
741#endif
742
743/*!
744 Call this slot if the remote resource requests authentication.
745 This may cause the
746 QNetworkAccessManager::authenticationRequired() signal to be
747 emitted if the credentials are not already stored in an internal
748 cache.
749 The credentials will be stored in \a authenticator. While
750 \a authenticator is a pointer, passing \c nullptr is invalid.
751*/
752void QNetworkAccessBackend::authenticationRequired(QAuthenticator *authenticator)
753{
754 Q_D(QNetworkAccessBackend);
755 Q_ASSERT(authenticator);
756 d->m_manager->authenticationRequired(authenticator, reply: d->m_reply->q_func(), synchronous: isSynchronous(),
757 url&: d->m_reply->url, urlForLastAuthentication: &d->m_reply->urlForLastAuthentication);
758}
759
760/*!
761 Call this slot, if appropriate, after having processed and
762 updated metadata (e.g. headers).
763*/
764void QNetworkAccessBackend::metaDataChanged()
765{
766 d_func()->m_reply->metaDataChanged();
767}
768
769/*!
770 Call this slot if, when connecting to the resource, a redirect
771 to \a destination was requested.
772*/
773void QNetworkAccessBackend::redirectionRequested(const QUrl &destination)
774{
775 d_func()->m_reply->redirectionRequested(target: destination);
776}
777
778/*!
779 \internal
780*/
781void QNetworkAccessBackend::setReplyPrivate(QNetworkReplyImplPrivate *reply)
782{
783 d_func()->m_reply = reply;
784}
785
786/*!
787 \internal
788*/
789void QNetworkAccessBackend::setManagerPrivate(QNetworkAccessManagerPrivate *manager)
790{
791 d_func()->m_manager = manager;
792}
793
794/*!
795 Returns the network cache object that was available when the
796 request was started. Returns \c nullptr if none was available.
797*/
798QAbstractNetworkCache *QNetworkAccessBackend::networkCache() const
799{
800 return d_func()->m_manager->networkCache;
801}
802
803// -- QNetworkAccessBackendFactory
804/*!
805 Constructs QNetworkAccessBackendFactory
806*/
807QNetworkAccessBackendFactory::QNetworkAccessBackendFactory()
808{
809 if (factoryData())
810 factoryData->append(t: this);
811}
812
813/*!
814 Destructs QNetworkAccessBackendFactory
815*/
816QNetworkAccessBackendFactory::~QNetworkAccessBackendFactory()
817{
818 if (factoryData.exists())
819 factoryData->removeAll(t: this);
820};
821
822QT_END_NAMESPACE
823
824#include "moc_qnetworkaccessbackend_p.cpp"
825

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