mirror of
https://github.com/status-im/status-app.git
synced 2026-08-31 00:51:10 +00:00
The QML engine gets a network access factory that hands out managers with a
disk cache and per-host accounting, so every image, animation and XHR the QML
layer issues can be seen and capped.
HttpStats is a GUI-thread singleton recording per-host totals split by whether
the bytes came from the network or from the cache. Bytes are taken from
downloadProgress rather than Content-Length, which is absent on some responses
and wrong on chunked ones. It is constructed on the GUI thread before any
factory worker can first-touch it with the wrong QObject affinity, and it
reports a finished cache clear on its own cacheCleared() signal — separate from
changed(), which fires on every reply and so cannot be what a reader hangs an
expensive re-measurement on.
The cache takes an explicit budget instead of Qt's 50 MB default, which a
single collectibles page can evict on its own.
The factory also sends Accept: image/webp,image/png,image/jpeg on Cloudinary
delivery URLs, so the f_auto in the rewritten media URLs has something to
resolve against. The list is narrow on purpose: f_auto returns AVIF or JPEG XL
to a client that claims them and Qt decodes neither. It is a statement about
this client's decoders, which is why it lives here and not in QML — see
docs/adr/0006-qt-http-cache.md.
All of it lives in networkaccessfactory.{h,cpp} rather than in externc.cpp,
which exists to be a thin C-ABI shim for Nim: the shim now casts the engine
pointer and delegates. That also lets Storybook install the same factory, so
media traffic measured on a Storybook page is the traffic the application
produces — and it lets the Accept policy be tested, which as a static function
in a .cpp with no header it could not be.
TestHttpStats and TestNetworkAccessFactory cover the thread affinity, both
clear paths, and the Accept policy as a table.
60 lines
2.0 KiB
C++
60 lines
2.0 KiB
C++
#pragma once
|
|
|
|
#include <QNetworkRequest>
|
|
#include <QQmlNetworkAccessManagerFactory>
|
|
#include <QString>
|
|
#include <QtGlobal>
|
|
|
|
class QNetworkAccessManager;
|
|
class QQmlEngine;
|
|
|
|
namespace Status {
|
|
|
|
/*!
|
|
* Returns \a request with an \c Accept header claiming the image formats Qt can
|
|
* actually decode, or unchanged when the header does not apply.
|
|
*
|
|
* Cloudinary's \c f_auto picks a format from \c Accept; Qt image loading sends
|
|
* none, so without this the delivery hints written by \c Utils.resizedMediaSource
|
|
* come back as PNG (see docs/adr/0006-qt-http-cache.md). The list is
|
|
* narrow on purpose: \c f_auto would otherwise return AVIF or JPEG XL, which Qt
|
|
* decodes neither of. Scoped to the two Cloudinary delivery paths that carry those
|
|
* hints — the same manager also serves status-go, XHR and everything else the QML
|
|
* layer fetches.
|
|
*
|
|
* A request that already carries an \c Accept header is returned untouched: the
|
|
* caller stated its own terms and they win.
|
|
*/
|
|
QNetworkRequest withAcceptedImageFormats(const QNetworkRequest& request);
|
|
|
|
/*!
|
|
* Hands the QML engine network access managers that cache to disk and report
|
|
* every reply to \c HttpStats.
|
|
*
|
|
* Every manager the factory creates shares one cache directory, so \a maxCacheSize
|
|
* is the budget for the whole QML layer rather than a per-manager allowance.
|
|
*/
|
|
class NetworkAccessFactory : public QQmlNetworkAccessManagerFactory
|
|
{
|
|
public:
|
|
NetworkAccessFactory(const QString& cacheDir, qint64 maxCacheSize);
|
|
|
|
QNetworkAccessManager* create(QObject* parent) override;
|
|
|
|
private:
|
|
QString m_cacheDir;
|
|
qint64 m_maxCacheSize;
|
|
};
|
|
|
|
/*!
|
|
* Installs a \c NetworkAccessFactory on \a engine. Call from the GUI thread,
|
|
* before the engine loads anything.
|
|
*
|
|
* The factory must outlive the engine and is intentionally never deleted
|
|
* (process lifetime, as in DOtherSide).
|
|
*/
|
|
void setupNetworkAccessManagerFactory(QQmlEngine* engine, const QString& cacheDir,
|
|
qint64 maxCacheSize);
|
|
|
|
} // namespace Status
|