quick/QuickHtmlReader.h
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #pragma once | ||
| 2 | |||
| 3 | #include <QObject> | ||
| 4 | #include <QPointer> | ||
| 5 | #include <QTimer> | ||
| 6 | #include <QUrl> | ||
| 7 | #include <QPointF> | ||
| 8 | #include <QThreadPool> | ||
| 9 | #include <atomic> | ||
| 10 | #include <memory> | ||
| 11 | #include <optional> | ||
| 12 | |||
| 13 | class QQmlEngine; | ||
| 14 | class QQuickWebEngineProfile; | ||
| 15 | class MailReaderState; | ||
| 16 | class MailSessionCore; | ||
| 17 | class DesignTokens; | ||
| 18 | class HtmlSanitizer; | ||
| 19 | class HtmlDocumentDelivery; | ||
| 20 | class ExternalContentInterceptor; | ||
| 21 | class WorkspaceState; | ||
| 22 | |||
| 23 | // One scene-owned view/profile lease for all logical mail tabs. Native demand | ||
| 24 | // creates neither a Quick profile nor a sanitizer page. The engine destroys | ||
| 25 | // its views before this owner destroys the profile prototype. | ||
| 26 | class QuickHtmlReader final : public QObject { | ||
| 27 | ✗ | Q_OBJECT | |
| 28 | Q_PROPERTY(QObject *profile READ profile NOTIFY profileChanged) | ||
| 29 | Q_PROPERTY(bool resident READ resident NOTIFY changed) | ||
| 30 | Q_PROPERTY(bool ready READ ready NOTIFY changed) | ||
| 31 | Q_PROPERTY(QUrl documentUrl READ documentUrl NOTIFY documentUrlChanged) | ||
| 32 | Q_PROPERTY(bool blocked READ blocked NOTIFY changed) | ||
| 33 | // Hosts whose external content this document requested and was denied. | ||
| 34 | Q_PROPERTY(QStringList blockedDomains READ blockedDomains NOTIFY changed) | ||
| 35 | public: | ||
| 36 | QuickHtmlReader(MailReaderState &, MailSessionCore &, DesignTokens &, WorkspaceState &, QObject *parent = nullptr); | ||
| 37 | ~QuickHtmlReader() override; | ||
| 38 | 767 | void setEngine(QQmlEngine *engine) { m_engine = engine; } | |
| 39 | QObject *profile() const; | ||
| 40 | 4271 | bool resident() const { return m_resident; } | |
| 41 | // Test seam: how long the renderer stays warm after leaving HTML (5 s). | ||
| 42 | ✗ | void setRetentionInterval(int ms) { m_retention.setInterval(ms); } | |
| 43 | ✗ | bool ready() const { return m_ready; } | |
| 44 | ✗ | bool blocked() const { return m_blocked; } | |
| 45 | QStringList blockedDomains() const; | ||
| 46 | ✗ | QUrl documentUrl() const { return m_url; } | |
| 47 | Q_INVOKABLE void loaded(const QUrl &url, bool ok); | ||
| 48 | Q_INVOKABLE void crashed(); | ||
| 49 | Q_INVOKABLE void allowExternal(); | ||
| 50 | Q_INVOKABLE void openLink(const QUrl &url, bool userInitiated); | ||
| 51 | Q_INVOKABLE bool isCurrentDocument(const QUrl &document) const; | ||
| 52 | Q_INVOKABLE bool canOpenLink(const QUrl &url) const; | ||
| 53 | Q_INVOKABLE bool copyLink(const QUrl &document, const QUrl &url); | ||
| 54 | Q_INVOKABLE void rememberScroll(const QUrl &document, const QPointF &position); | ||
| 55 | Q_INVOKABLE void scrollRestored(const QUrl &document); | ||
| 56 | ✗ | Q_INVOKABLE void viewCreated() { ++m_liveViews; } | |
| 57 | Q_INVOKABLE void viewReleased(); | ||
| 58 | signals: | ||
| 59 | void changed(); | ||
| 60 | void profileChanged(); | ||
| 61 | void documentUrlChanged(); | ||
| 62 | void externalLinkRequested(const QUrl &url); | ||
| 63 | void restoreScrollRequested(const QUrl &document, const QPointF &position); | ||
| 64 | private: | ||
| 65 | void synchronize(); | ||
| 66 | void invalidate(); | ||
| 67 | void start(); | ||
| 68 | void refreshPolicy(); | ||
| 69 | bool ensureProfile(); | ||
| 70 | bool current(quint64 lease) const; | ||
| 71 | void fail(const QString &error); | ||
| 72 | void queueEnvelope(QString clean, quint64 lease); | ||
| 73 | void dispatchEnvelope(); | ||
| 74 | void retire(); | ||
| 75 | void releaseProfile(); | ||
| 76 | struct EnvelopeJob { | ||
| 77 | QString clean; | ||
| 78 | QString surface; | ||
| 79 | QString text; | ||
| 80 | QString accent; | ||
| 81 | quint64 lease = 0; | ||
| 82 | std::shared_ptr<std::atomic_bool> cancelled; | ||
| 83 | }; | ||
| 84 | MailReaderState &m_reader; | ||
| 85 | MailSessionCore &m_session; | ||
| 86 | DesignTokens &m_tokens; | ||
| 87 | WorkspaceState &m_workspace; | ||
| 88 | QPointer<QQmlEngine> m_engine; | ||
| 89 | std::unique_ptr<QObject> m_prototype; | ||
| 90 | QPointer<QQuickWebEngineProfile> m_profile; | ||
| 91 | HtmlDocumentDelivery *m_delivery; | ||
| 92 | ExternalContentInterceptor *m_interceptor; | ||
| 93 | QPointer<HtmlSanitizer> m_sanitizer; | ||
| 94 | QTimer m_retention, m_timeout; | ||
| 95 | // One running conversion and only the newest waiting document; rapid | ||
| 96 | // selection cannot queue an unbounded number of large HTML payloads. | ||
| 97 | QThreadPool m_envelopePool; | ||
| 98 | std::optional<EnvelopeJob> m_pendingEnvelope; | ||
| 99 | std::shared_ptr<std::atomic_bool> m_activeEnvelopeCancelled; | ||
| 100 | bool m_envelopeBusy = false; | ||
| 101 | quint64 m_revision = 0, m_lease = 0, m_accountGeneration = 0; | ||
| 102 | quint32 m_leaseUidValidity = 0; | ||
| 103 | bool m_resident = false, m_ready = false, m_blocked = false, m_allowExternal = false; | ||
| 104 | int m_liveViews = 0; | ||
| 105 | QUrl m_url; | ||
| 106 | QString m_tabId; | ||
| 107 | QByteArray m_digest; | ||
| 108 | QPointF m_scrollTarget; | ||
| 109 | bool m_restoringScroll = false; | ||
| 110 | }; | ||
| 111 |