File indexing completed on 2024-05-19 05:01:22
0001 /* 0002 This file is part of the KDE project. 0003 0004 SPDX-FileCopyrightText: 2017 Stefano Crocco <stefano.crocco@alice.it> 0005 0006 SPDX-License-Identifier: LGPL-2.1-or-later 0007 */ 0008 0009 #ifndef WEBENGINEPARTDOWNLOADMANAGER_H 0010 #define WEBENGINEPARTDOWNLOADMANAGER_H 0011 0012 #include <QObject> 0013 #include <QVector> 0014 #include <QTemporaryDir> 0015 #include <QDateTime> 0016 #include <QSet> 0017 #include <KJob> 0018 #include <QPointer> 0019 0020 #include "qtwebengine6compat.h" 0021 0022 #include "browseropenorsavequestion.h" 0023 #include "interfaces/downloaderextension.h" 0024 0025 class WebEnginePage; 0026 class QWebEngineProfile; 0027 class WebEngineDownloadJob; 0028 0029 class WebEnginePartDownloadManager : public QObject 0030 { 0031 Q_OBJECT 0032 0033 public: 0034 ~WebEnginePartDownloadManager() override; 0035 0036 WebEnginePartDownloadManager(QWebEngineProfile *profile, QObject *parent = nullptr); 0037 0038 /** 0039 * @brief Enum which describes what the user wants to do with a URL once it has been downloaded 0040 * 0041 * Currently there are three possibilities: 0042 * - the user wants to open the URL in the application embedding the part (for example, when 0043 * clicking on a link). This is the default download objective 0044 * - the user wants to save locally the file represented by the URL (for example, when using 0045 * the "save link as..." context menu entry 0046 * - the user wants to save the currently displayed page locally (for example, when using the "Save as" 0047 * menu entry 0048 */ 0049 enum class DownloadObjective { 0050 OpenInApplication, //!< A URL is to be downloaded to be opened in the application 0051 SaveAs, //!< The current page is to saved locally 0052 SaveOnly //!< A URL is to be saved locally 0053 }; 0054 0055 /** 0056 * @brief Tells the download manager that the next download of the given URL for the given page 0057 * has a special objective 0058 * 0059 * This is needed to ensure that if the user choses, for example "Save As..." the page or document will actually be saved and not 0060 * opened with an external application or embedded. 0061 * 0062 * By default, downloads are considered having the \link DownloadObjective::OpenInApplication OpenInApplication\endlink objective; 0063 * this function is only needed to specify a different objective. 0064 * 0065 * @param url the url this setting applies to 0066 * @param page the page this setting applies to. Requests to download @p url made by pages other than @p page will be processed as 0067 * usual 0068 * @param objective the special objective for the download 0069 */ 0070 void specifyDownloadObjective(const QUrl &url, WebEnginePage *page, DownloadObjective objective); 0071 0072 private: 0073 0074 static QString generateDownloadTempFileName(QString const &suggestedName, const QString &ext); 0075 0076 /** 0077 * @brief Struct encapsulating a download objective with the page it refers to 0078 */ 0079 struct DownloadObjectiveWithPage { 0080 QPointer<WebEnginePage> page = nullptr; //!< The page requesting the download 0081 DownloadObjective downloadObjective = DownloadObjective::OpenInApplication; //!< The objective of the download 0082 bool operator==(const DownloadObjectiveWithPage &other) const {return page == other.page && downloadObjective == other.downloadObjective;} //!< Equality operator 0083 }; 0084 0085 /** 0086 * @brief Retrieves the special objective for a download, if any 0087 * 0088 * This function is used to retrieve data set using specifyDownloadObjective(). 0089 * 0090 * @param req the url to download 0091 * @param page the page requesting the download 0092 * @return the specified objective for the URL in @p url and page @p page, if any, and 0093 * \link DownloadObjective::OpenInApplication OpenInApplication\endlink otherwise 0094 */ 0095 DownloadObjective fetchDownloadObjective(const QUrl &url, WebEnginePage *page); 0096 0097 /** 0098 * @brief Checks whether a download request for the given URL by the given page should be treated as a forced download or not 0099 * 0100 * @warning This function @b should only be called @b once for each download, because it removes information about the download from the internal 0101 * state (this is for performance reasons). 0102 * @param req the download request 0103 * @param page the page which requested the download 0104 * @return `true` if the page should be downloaded by the download manager and `false` if it should be processed as usual 0105 */ 0106 // bool checkForceDownload(QWebEngineDownloadRequest *req, WebEnginePage *page); 0107 0108 /** 0109 * @brief Saves a full HTML page, after asking the user which formats he wants to use 0110 * 0111 * The available formats are described in `QWebEngineDownloadRequest::SavePageFormat` 0112 * @param it the item to use for the download 0113 * @param page the page which requested the download 0114 */ 0115 void saveHtmlPage(QWebEngineDownloadRequest *it, WebEnginePage *page); 0116 0117 static QTemporaryDir& tempDownloadDir(); 0118 0119 public Q_SLOTS: 0120 void addPage(WebEnginePage *page); 0121 void removePage(QObject *page); 0122 0123 private Q_SLOTS: 0124 void performDownload(QWebEngineDownloadRequest *it); 0125 0126 0127 private: 0128 QVector<WebEnginePage*> m_pages; 0129 0130 /** 0131 * @brief Information about download objectives 0132 * 0133 * @see specifyDownloadObjective 0134 * @see fetchDownloadObjective 0135 * @todo See wether it would be possible to use both url and page as key 0136 */ 0137 QMultiHash<QUrl, DownloadObjectiveWithPage> m_downloadObjectives; 0138 }; 0139 0140 class WebEngineDownloadJob : public KonqInterfaces::DownloaderJob 0141 { 0142 Q_OBJECT 0143 0144 public: 0145 WebEngineDownloadJob(QWebEngineDownloadRequest *it, QObject *parent = nullptr); 0146 ~WebEngineDownloadJob() override; 0147 0148 QUrl url() const override; 0149 0150 void start() override; 0151 0152 QString errorString() const override; 0153 0154 bool setDownloadPath(const QString & path) override; 0155 QString downloadPath() const override; 0156 bool canChangeDownloadPath() const override; 0157 bool finished() const override; 0158 0159 QWebEngineDownloadRequest* item() const; 0160 0161 protected: 0162 bool doKill() override; 0163 bool doResume() override; 0164 bool doSuspend() override; 0165 0166 private slots: 0167 #if QT_VERSION_MAJOR < 6 0168 void downloadProgressed(qint64 received, qint64 total); 0169 #else 0170 void downloadProgressed(); 0171 #endif 0172 0173 void stateChanged(QWebEngineDownloadRequest::DownloadState state); 0174 void startDownloading(); 0175 void downloadFinished(); 0176 void emitDownloadResult(KJob *job); 0177 0178 private: 0179 bool m_started = false; ///<! @brief Whether the job has been started or not 0180 QPointer<QWebEngineDownloadRequest> m_downloadItem; 0181 QDateTime m_startTime; 0182 }; 0183 0184 #endif // WEBENGINEPARTDOWNLOADMANAGER_H