diff options
author | Michal Klocek <michal.klocek@qt.io> | 2020-08-07 08:27:00 +0200 |
---|---|---|
committer | Michal Klocek <michal.klocek@qt.io> | 2020-08-17 16:05:43 +0200 |
commit | cc31847a8a7fc36e970a5048de4a91f9e9f8f573 (patch) | |
tree | 80bc467190146a28f1eb7c2f1d37136bc6ad2385 /src/core | |
parent | cf830e3122c94e429321f43ddc81b860bd223a72 (diff) |
Move QWebEngineDownloadItem to QtWebEngineCore
Use QWebEngineDownloadItem class in qml instead of
QQuickWebEngineDonloadItem.
Change-Id: I0fc9595f8675c9b082be873adead6de3df1e669d
Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/api/core_api.pro | 7 | ||||
-rw-r--r-- | src/core/api/qwebenginedownloaditem.cpp | 785 | ||||
-rw-r--r-- | src/core/api/qwebenginedownloaditem.h | 203 | ||||
-rw-r--r-- | src/core/api/qwebenginedownloaditem_p.h | 100 |
4 files changed, 1093 insertions, 2 deletions
diff --git a/src/core/api/core_api.pro b/src/core/api/core_api.pro index aca83c7bb..533ebf03f 100644 --- a/src/core/api/core_api.pro +++ b/src/core/api/core_api.pro @@ -52,7 +52,9 @@ HEADERS = \ qwebengineurlscheme.h \ qwebengineurlschemehandler.h \ qwebenginecontextmenurequest.h \ - qwebenginecontextmenurequest_p.h + qwebenginecontextmenurequest_p.h \ + qwebenginedownloaditem.h \ + qwebenginedownloaditem_p.h SOURCES = \ qtwebenginecoreglobal.cpp \ @@ -69,7 +71,8 @@ SOURCES = \ qwebengineurlrequestjob.cpp \ qwebengineurlscheme.cpp \ qwebengineurlschemehandler.cpp \ - qwebenginecontextmenurequest.cpp + qwebenginecontextmenurequest.cpp \ + qwebenginedownloaditem.cpp # Chromium headers included are not remotely clean CONFIG -= warning_clean diff --git a/src/core/api/qwebenginedownloaditem.cpp b/src/core/api/qwebenginedownloaditem.cpp new file mode 100644 index 000000000..f7ddf024b --- /dev/null +++ b/src/core/api/qwebenginedownloaditem.cpp @@ -0,0 +1,785 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwebenginedownloaditem.h" +#include "qwebenginedownloaditem_p.h" + +#include "profile_adapter.h" + +#include <QDir> +#include "QFileInfo" + +QT_BEGIN_NAMESPACE + +using QtWebEngineCore::ProfileAdapterClient; + +ASSERT_ENUMS_MATCH(ProfileAdapterClient::NoReason, QWebEngineDownloadItem::NoReason) +ASSERT_ENUMS_MATCH(ProfileAdapterClient::FileFailed, QWebEngineDownloadItem::FileFailed) +ASSERT_ENUMS_MATCH(ProfileAdapterClient::FileAccessDenied, QWebEngineDownloadItem::FileAccessDenied) +ASSERT_ENUMS_MATCH(ProfileAdapterClient::FileNoSpace, QWebEngineDownloadItem::FileNoSpace) +ASSERT_ENUMS_MATCH(ProfileAdapterClient::FileNameTooLong, QWebEngineDownloadItem::FileNameTooLong) +ASSERT_ENUMS_MATCH(ProfileAdapterClient::FileTooLarge, QWebEngineDownloadItem::FileTooLarge) +ASSERT_ENUMS_MATCH(ProfileAdapterClient::FileVirusInfected, QWebEngineDownloadItem::FileVirusInfected) +ASSERT_ENUMS_MATCH(ProfileAdapterClient::FileTransientError, QWebEngineDownloadItem::FileTransientError) +ASSERT_ENUMS_MATCH(ProfileAdapterClient::FileBlocked, QWebEngineDownloadItem::FileBlocked) +ASSERT_ENUMS_MATCH(ProfileAdapterClient::FileSecurityCheckFailed, QWebEngineDownloadItem::FileSecurityCheckFailed) +ASSERT_ENUMS_MATCH(ProfileAdapterClient::FileTooShort, QWebEngineDownloadItem::FileTooShort) +ASSERT_ENUMS_MATCH(ProfileAdapterClient::FileHashMismatch, QWebEngineDownloadItem::FileHashMismatch) +ASSERT_ENUMS_MATCH(ProfileAdapterClient::NetworkFailed, QWebEngineDownloadItem::NetworkFailed) +ASSERT_ENUMS_MATCH(ProfileAdapterClient::NetworkTimeout, QWebEngineDownloadItem::NetworkTimeout) +ASSERT_ENUMS_MATCH(ProfileAdapterClient::NetworkDisconnected, QWebEngineDownloadItem::NetworkDisconnected) +ASSERT_ENUMS_MATCH(ProfileAdapterClient::NetworkServerDown, QWebEngineDownloadItem::NetworkServerDown) +ASSERT_ENUMS_MATCH(ProfileAdapterClient::NetworkInvalidRequest, QWebEngineDownloadItem::NetworkInvalidRequest) +ASSERT_ENUMS_MATCH(ProfileAdapterClient::ServerFailed, QWebEngineDownloadItem::ServerFailed) +//ASSERT_ENUMS_MATCH(ProfileAdapterClient::ServerNoRange, QWebEngineDownloadItem::ServerNoRange) +ASSERT_ENUMS_MATCH(ProfileAdapterClient::ServerBadContent, QWebEngineDownloadItem::ServerBadContent) +ASSERT_ENUMS_MATCH(ProfileAdapterClient::ServerUnauthorized, QWebEngineDownloadItem::ServerUnauthorized) +ASSERT_ENUMS_MATCH(ProfileAdapterClient::ServerCertProblem, QWebEngineDownloadItem::ServerCertProblem) +ASSERT_ENUMS_MATCH(ProfileAdapterClient::ServerForbidden, QWebEngineDownloadItem::ServerForbidden) +ASSERT_ENUMS_MATCH(ProfileAdapterClient::ServerUnreachable, QWebEngineDownloadItem::ServerUnreachable) +ASSERT_ENUMS_MATCH(ProfileAdapterClient::UserCanceled, QWebEngineDownloadItem::UserCanceled) +//ASSERT_ENUMS_MATCH(ProfileAdapterClient::UserShutdown, QWebEngineDownloadItem::UserShutdown) +//ASSERT_ENUMS_MATCH(ProfileAdapterClient::Crash, QWebEngineDownloadItem::Crash) + +static inline QWebEngineDownloadItem::DownloadState toDownloadState(int state) +{ + switch (state) { + case ProfileAdapterClient::DownloadInProgress: + return QWebEngineDownloadItem::DownloadInProgress; + case ProfileAdapterClient::DownloadCompleted: + return QWebEngineDownloadItem::DownloadCompleted; + case ProfileAdapterClient::DownloadCancelled: + return QWebEngineDownloadItem::DownloadCancelled; + case ProfileAdapterClient::DownloadInterrupted: + return QWebEngineDownloadItem::DownloadInterrupted; + default: + Q_UNREACHABLE(); + return QWebEngineDownloadItem::DownloadCancelled; + } +} + +static inline QWebEngineDownloadItem::DownloadInterruptReason toDownloadInterruptReason(int reason) +{ + return static_cast<QWebEngineDownloadItem::DownloadInterruptReason>(reason); +} + +/*! + \class QWebEngineDownloadItem + \brief The QWebEngineDownloadItem class provides information about a download. + + \inmodule QtWebEngineCore + + QWebEngineDownloadItem models a download throughout its life cycle, starting + with a pending download request and finishing with a completed download. It + can be used, for example, to get information about new downloads, to monitor + progress, and to pause, resume, and cancel downloads. + + Downloads are usually triggered by user interaction on a web page. It is the + QWebEngineProfile's responsibility to notify the application of new download + requests, which it does by emitting the + \l{QWebEngineProfile::downloadRequested}{downloadRequested} signal together + with a newly created QWebEngineDownloadItem. The application can then + examine this item and decide whether to accept it or not. A signal handler + must explicitly call accept() on the item for \QWE to actually start + downloading and writing data to disk. If no signal handler calls accept(), + then the download request will be automatically rejected and nothing will be + written to disk. + + \note Some properties, such as setting the path and file name where the file + will be saved (see \l downloadDirectory() and \l downloadFileName()), can + only be changed before calling accept(). + + \section2 Object Life Cycle + + All items are guaranteed to be valid during the emission of the + \l{QWebEngineProfile::downloadRequested}{downloadRequested} signal. If + accept() is \e not called by any signal handler, then the item will be + deleted \e immediately after signal emission. This means that the + application \b{must not} keep references to rejected download items. It also + means the application should not use a queued connection to this signal. + + If accept() \e is called by a signal handler, then the QWebEngineProfile + will take ownership of the item. However, it is safe for the application to + delete the item at any time, except during the handling of the + \l{QWebEngineProfile::downloadRequested}{downloadRequested} signal. The + QWebEngineProfile being a long-lived object, it is in fact recommended that + the application delete any items it is no longer interested in. + + \note Deleting an item will also automatically cancel a download since 5.12.2, + but it is recommended to cancel manually before deleting for portability. + + \section2 Web Page Downloads + + In addition to normal file downloads, which consist simply of retrieving + some raw bytes from the network and writing them to disk, \QWE also + supports saving complete web pages, which involves parsing the page's HTML, + downloading any dependent resources, and potentially packaging everything + into a special file format (\l savePageFormat). To check if a download is + for a file or a web page, use \l isSavePageDownload. + + \sa QWebEngineProfile, QWebEngineProfile::downloadRequested, + QWebEnginePage::download, QWebEnginePage::save +*/ + +QWebEngineDownloadItemPrivate::QWebEngineDownloadItemPrivate(QtWebEngineCore::ProfileAdapter *adapter, const QUrl &url) + : m_profileAdapter(adapter) + , downloadFinished(false) + , downloadId(-1) + , downloadState(QWebEngineDownloadItem::DownloadCancelled) + , savePageFormat(QWebEngineDownloadItem::MimeHtmlSaveFormat) + , type(QWebEngineDownloadItem::Attachment) + , interruptReason(QWebEngineDownloadItem::NoReason) + , downloadUrl(url) + , downloadPaused(false) + , isCustomFileName(false) + , totalBytes(-1) + , receivedBytes(0) + , page(nullptr) +{ +} + +QWebEngineDownloadItemPrivate::~QWebEngineDownloadItemPrivate() +{ +} + +void QWebEngineDownloadItemPrivate::update(const ProfileAdapterClient::DownloadItemInfo &info) +{ + Q_Q(QWebEngineDownloadItem); + + Q_ASSERT(downloadState != QWebEngineDownloadItem::DownloadRequested); + + if (toDownloadInterruptReason(info.downloadInterruptReason) != interruptReason) { + interruptReason = toDownloadInterruptReason(info.downloadInterruptReason); + Q_EMIT q->interruptReasonChanged(); + } + if (toDownloadState(info.state) != downloadState) { + downloadState = toDownloadState(info.state); + Q_EMIT q->stateChanged(downloadState); + } + + if (info.receivedBytes != receivedBytes || info.totalBytes != totalBytes) { + + if (info.receivedBytes != receivedBytes) { + receivedBytes = info.receivedBytes; + Q_EMIT q->receivedBytesChanged(); + } + if (info.totalBytes != totalBytes) { + totalBytes = info.totalBytes; + Q_EMIT q->totalBytesChanged(); + } + Q_EMIT q->downloadProgress(receivedBytes, totalBytes); + } + + if (info.done) + setFinished(); + + if (downloadPaused != info.paused) { + downloadPaused = info.paused; + Q_EMIT q->isPausedChanged(); + } +} + +void QWebEngineDownloadItemPrivate::setFinished() +{ + if (downloadFinished) + return; + + downloadFinished = true; + Q_EMIT q_ptr->isFinishedChanged(); +} + +/*! + Accepts the current download request, which will start the download. + + If the item is in the \l DownloadRequested state, then it will transition + into the \l DownloadInProgress state and the downloading will begin. If the + item is in any other state, then nothing will happen. + + \sa finished(), stateChanged() +*/ + +void QWebEngineDownloadItem::accept() +{ + Q_D(QWebEngineDownloadItem); + + if (d->downloadState != QWebEngineDownloadItem::DownloadRequested) + return; + + d->downloadState = QWebEngineDownloadItem::DownloadInProgress; + Q_EMIT stateChanged(d->downloadState); +} + +/*! + Cancels the current download. + + If the item is in the \l DownloadInProgress state, then it will transition + into the \l DownloadCancelled state, the downloading will stop, and partially + downloaded files will be deleted from disk. + + If the item is in the \l DownloadCompleted state, then nothing will happen. + If the item is in any other state, then it will transition into the \l + DownloadCancelled state without further effect. + + \sa finished(), stateChanged() +*/ + +void QWebEngineDownloadItem::cancel() +{ + Q_D(QWebEngineDownloadItem); + + QWebEngineDownloadItem::DownloadState state = d->downloadState; + + if (state == QWebEngineDownloadItem::DownloadCompleted + || state == QWebEngineDownloadItem::DownloadCancelled) + return; + + // We directly cancel the download request if the user cancels + // before it even started, so no need to notify the profile here. + if (state == QWebEngineDownloadItem::DownloadInProgress) { + if (d->m_profileAdapter) + d->m_profileAdapter->cancelDownload(d->downloadId); + } else { + d->downloadState = QWebEngineDownloadItem::DownloadCancelled; + Q_EMIT stateChanged(d->downloadState); + d->setFinished(); + } +} + +/*! + Pauses the download. + + Has no effect if the state is not \l DownloadInProgress. Does not change the + state. + + \sa resume(), isPaused() +*/ + +void QWebEngineDownloadItem::pause() +{ + Q_D(QWebEngineDownloadItem); + + QWebEngineDownloadItem::DownloadState state = d->downloadState; + + if (state != QWebEngineDownloadItem::DownloadInProgress) + return; + + if (d->m_profileAdapter) + d->m_profileAdapter->pauseDownload(d->downloadId); +} + +/*! + Resumes the current download if it was paused or interrupted. + + Has no effect if the state is not \l DownloadInProgress or \l + DownloadInterrupted. Does not change the state. + + \sa pause(), isPaused(), state() +*/ +void QWebEngineDownloadItem::resume() +{ + Q_D(QWebEngineDownloadItem); + + QWebEngineDownloadItem::DownloadState state = d->downloadState; + + if (d->downloadFinished || (state != QWebEngineDownloadItem::DownloadInProgress && state != QWebEngineDownloadItem::DownloadInterrupted)) + return; + if (d->m_profileAdapter) + d->m_profileAdapter->resumeDownload(d->downloadId); +} + +/*! + Returns the download item's ID. +*/ + +quint32 QWebEngineDownloadItem::id() const +{ + Q_D(const QWebEngineDownloadItem); + return d->downloadId; +} + +/*! + \fn void QWebEngineDownloadItem::finished() + + This signal is emitted when the download finishes. + + \sa state(), isFinished() +*/ + +/*! + \fn void QWebEngineDownloadItem::isPausedChanged(bool isPaused) + + This signal is emitted whenever \a isPaused changes. + + \sa pause(), isPaused() +*/ + +/*! + \fn void QWebEngineDownloadItem::stateChanged(DownloadState state) + + This signal is emitted whenever the download's \a state changes. + + \sa state(), DownloadState +*/ + +/*! + \fn void QWebEngineDownloadItem::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) + + This signal is emitted to indicate the progress of the download request. + + The \a bytesReceived parameter indicates the number of bytes received, while + \a bytesTotal indicates the total number of bytes expected to be downloaded. + If the size of the file to be downloaded is not known, \c bytesTotal will be + 0. + + \sa totalBytes(), receivedBytes() +*/ + +/*! + \enum QWebEngineDownloadItem::DownloadState + + This enum describes the state of the download: + + \value DownloadRequested Download has been requested, but has not been accepted yet. + \value DownloadInProgress Download is in progress. + \value DownloadCompleted Download completed successfully. + \value DownloadCancelled Download has been cancelled. + \value DownloadInterrupted Download has been interrupted (by the server or because of lost + connectivity). +*/ + +/*! + \enum QWebEngineDownloadItem::SavePageFormat + + This enum describes the format that is used to save a web page. + + \value UnknownSaveFormat This is not a request for downloading a complete web page. + \value SingleHtmlSaveFormat The page is saved as a single HTML page. Resources such as images + are not saved. + \value CompleteHtmlSaveFormat The page is saved as a complete HTML page, for example a directory + containing the single HTML page and the resources. + \value MimeHtmlSaveFormat The page is saved as a complete web page in the MIME HTML format. +*/ + +/*! + \enum QWebEngineDownloadItem::DownloadType + \obsolete + + Describes the requested download's type. + + \value Attachment The web server's response includes a + \c Content-Disposition header with the \c attachment directive. If \c Content-Disposition + is present in the reply, the web server is indicating that the client should prompt the + user to save the content regardless of the content type. + See \l {RFC 2616 section 19.5.1} for details. + \value DownloadAttribute The user clicked a link with the \c download + attribute. + \value UserRequested The user initiated the download, for example by + selecting a web action. + \value SavePage Saving of the current page was requested (for example by + the \l{QWebEnginePage::WebAction}{QWebEnginePage::SavePage} web action). +*/ + +/*! + \enum QWebEngineDownloadItem::DownloadInterruptReason + + Describes the reason why a download was interrupted: + + \value NoReason Unknown reason or not interrupted. + \value FileFailed General file operation failure. + \value FileAccessDenied The file cannot be written locally, due to access restrictions. + \value FileNoSpace Insufficient space on the target drive. + \value FileNameTooLong The directory or file name is too long. + \value FileTooLarge The file size exceeds the file system limitation. + \value FileVirusInfected The file is infected with a virus. + \value FileTransientError Temporary problem (for example the file is in use, + out of memory, or too many files are opened at once). + \value FileBlocked The file was blocked due to local policy. + \value FileSecurityCheckFailed An attempt to check the safety of the download + failed due to unexpected reasons. + \value FileTooShort An attempt was made to seek past the end of a file when + opening a file (as part of resuming a previously interrupted download). + \value FileHashMismatch The partial file did not match the expected hash. + + \value NetworkFailed General network failure. + \value NetworkTimeout The network operation has timed out. + \value NetworkDisconnected The network connection has been terminated. + \value NetworkServerDown The server has gone down. + \value NetworkInvalidRequest The network request was invalid (for example, the + original or redirected URL is invalid, has an unsupported scheme, or is disallowed by policy). + + \value ServerFailed General server failure. + \value ServerBadContent The server does not have the requested data. + \value ServerUnauthorized The server did not authorize access to the resource. + \value ServerCertProblem A problem with the server certificate occurred. + \value ServerForbidden Access forbidden by the server. + \value ServerUnreachable Unexpected server response (might indicate that + the responding server may not be the intended server). + \value UserCanceled The user canceled the download. +*/ + +/*! + Returns the download item's current state. + + \sa DownloadState +*/ + +QWebEngineDownloadItem::DownloadState QWebEngineDownloadItem::state() const +{ + Q_D(const QWebEngineDownloadItem); + return d->downloadState; +} + +/*! + Returns the the total amount of data to download in bytes. + + \c -1 means the size is unknown. +*/ + +qint64 QWebEngineDownloadItem::totalBytes() const +{ + Q_D(const QWebEngineDownloadItem); + return d->totalBytes; +} + +/*! + Returns the amount of data in bytes that has been downloaded so far. + + \c -1 means the size is unknown. +*/ + +qint64 QWebEngineDownloadItem::receivedBytes() const +{ + Q_D(const QWebEngineDownloadItem); + return d->receivedBytes; +} + +/*! + Returns the download's origin URL. +*/ + +QUrl QWebEngineDownloadItem::url() const +{ + Q_D(const QWebEngineDownloadItem); + return d->downloadUrl; +} + +/*! + Returns the MIME type of the download. +*/ + +QString QWebEngineDownloadItem::mimeType() const +{ + Q_D(const QWebEngineDownloadItem); + return d->mimeType; +} + +/*! + \obsolete + + Use \l suggestedFileName(), \l downloadDirectory(), and + \l downloadFileName() instead. + + Returns the full target path where data is being downloaded to. + + The path includes the file name. The default suggested path is the standard download location + and file name is deduced not to overwrite already existing files. +*/ + +QString QWebEngineDownloadItem::path() const +{ + Q_D(const QWebEngineDownloadItem); + return QDir::cleanPath(QDir(d->downloadDirectory).filePath(d->downloadFileName)); +} + +/*! + \obsolete + + Use \l setDownloadDirectory() and \l setDownloadFileName() instead. + + Sets the full target path to download the file to. + + The \a path should also include the file name. The download path can only be set in response + to the QWebEngineProfile::downloadRequested() signal before the download is accepted. + Past that point, this function has no effect on the download item's state. +*/ +void QWebEngineDownloadItem::setPath(QString path) +{ + Q_D(QWebEngineDownloadItem); + if (d->downloadState != QWebEngineDownloadItem::DownloadRequested) { + qWarning("Setting the download path is not allowed after the download has been accepted."); + return; + } + if (QDir(d->downloadDirectory).filePath(d->downloadFileName) != path) { + if (QFileInfo(path).fileName().isEmpty()) { + qWarning("The download path does not include file name."); + return; + } + + if (QFileInfo(path).isDir()) { + qWarning("The download path matches with an already existing directory path."); + return; + } + + QString newDirectory; + QString newFileName; + + if (QFileInfo(path).fileName() == path) { + newDirectory = QStringLiteral(""); + newFileName = path; + } else { + newDirectory = QFileInfo(path).path(); + newFileName = QFileInfo(path).fileName(); + } + + if (d->downloadDirectory != newDirectory) { + d->downloadDirectory = newDirectory; + Q_EMIT pathChanged(); + Q_EMIT downloadDirectoryChanged(); + } + + if (d->downloadFileName != newFileName) { + d->downloadFileName = newFileName; + Q_EMIT pathChanged(); + Q_EMIT downloadFileNameChanged(); + } + } +} + +/*! + Returns the download directory path. +*/ + +QString QWebEngineDownloadItem::downloadDirectory() const +{ + Q_D(const QWebEngineDownloadItem); + return d->downloadDirectory; +} + +/*! + Sets \a directory as the directory path to download the file to. + + The download directory path can only be set in response to the QWebEngineProfile::downloadRequested() + signal before the download is accepted. Past that point, this function has no effect on the + download item's state. +*/ + +void QWebEngineDownloadItem::setDownloadDirectory(const QString &directory) +{ + Q_D(QWebEngineDownloadItem); + if (d->downloadState != QWebEngineDownloadItem::DownloadRequested) { + qWarning("Setting the download directory is not allowed after the download has been accepted."); + return; + } + + if (!directory.isEmpty() && d->downloadDirectory != directory) + d->downloadDirectory = directory; + + if (!d->isCustomFileName && d->m_profileAdapter) + d->downloadFileName = QFileInfo(d->m_profileAdapter->determineDownloadPath(d->downloadDirectory, + d->suggestedFileName, + d->startTime)).fileName(); +} + +/*! + Returns the file name to download the file to. +*/ + +QString QWebEngineDownloadItem::downloadFileName() const +{ + Q_D(const QWebEngineDownloadItem); + return d->downloadFileName; +} + +/*! + Sets \a fileName as the file name to download the file to. + + The download file name can only be set in response to the QWebEngineProfile::downloadRequested() + signal before the download is accepted. Past that point, this function has no effect on the + download item's state. +*/ + +void QWebEngineDownloadItem::setDownloadFileName(const QString &fileName) +{ + Q_D(QWebEngineDownloadItem); + if (d->downloadState != QWebEngineDownloadItem::DownloadRequested) { + qWarning("Setting the download file name is not allowed after the download has been accepted."); + return; + } + + if (!fileName.isEmpty()) { + d->downloadFileName = fileName; + d->isCustomFileName = true; + } +} + +/*! + Returns the suggested file name. +*/ + +QString QWebEngineDownloadItem::suggestedFileName() const +{ + Q_D(const QWebEngineDownloadItem); + return d->suggestedFileName; +} + +/*! + Returns whether this download is finished (completed, cancelled, or non-resumable interrupted state). + + \sa finished(), state(), +*/ + +bool QWebEngineDownloadItem::isFinished() const +{ + Q_D(const QWebEngineDownloadItem); + return d->downloadFinished; +} + +/*! + Returns whether this download is paused. + + \sa pause(), resume() +*/ + +bool QWebEngineDownloadItem::isPaused() const +{ + Q_D(const QWebEngineDownloadItem); + return d->downloadPaused; +} + +/*! + Returns the format the web page will be saved in if this is a download request for a web page. + \sa setSavePageFormat(), isSavePageDownload() +*/ +QWebEngineDownloadItem::SavePageFormat QWebEngineDownloadItem::savePageFormat() const +{ + Q_D(const QWebEngineDownloadItem); + return d->savePageFormat; +} + +/*! + Sets the \a format the web page will be saved in if this is a download request for a web page. + + \sa savePageFormat(), isSavePageDownload() +*/ +void QWebEngineDownloadItem::setSavePageFormat(QWebEngineDownloadItem::SavePageFormat format) +{ + Q_D(QWebEngineDownloadItem); + if (d->savePageFormat != format) { + d->savePageFormat = format; + Q_EMIT savePageFormatChanged(); + } +} + +/*! + Returns the requested download's type. + \obsolete + + \note This property works unreliably, except for \c SavePage + downloads. Use \l isSavePageDownload() instead. + */ + +QWebEngineDownloadItem::DownloadType QWebEngineDownloadItem::type() const +{ + Q_D(const QWebEngineDownloadItem); + return d->type; +} + +/*! + Returns \c true if this is a download request for saving a web page. + + \sa savePageFormat(), setSavePageFormat() + */ +bool QWebEngineDownloadItem::isSavePageDownload() const +{ + Q_D(const QWebEngineDownloadItem); + return d->type == QWebEngineDownloadItem::SavePage; +} + +/*! + Returns the reason why the download was interrupted. + + \sa interruptReasonString() +*/ + +QWebEngineDownloadItem::DownloadInterruptReason QWebEngineDownloadItem::interruptReason() const +{ + Q_D(const QWebEngineDownloadItem); + return d->interruptReason; +} + +/*! + Returns a human-readable description of the reason for interrupting the download. + + \sa interruptReason() +*/ + +QString QWebEngineDownloadItem::interruptReasonString() const +{ + return ProfileAdapterClient::downloadInterruptReasonToString( + static_cast<ProfileAdapterClient::DownloadInterruptReason>(interruptReason())); +} + +/*! + Returns the page the download was requested on. If the download was not triggered by content in a page, + \c nullptr is returned. +*/ +QObject *QWebEngineDownloadItem::page() const +{ + Q_D(const QWebEngineDownloadItem); + return d->page; +} + +QWebEngineDownloadItem::QWebEngineDownloadItem(QWebEngineDownloadItemPrivate *p, QObject *parent) + : QObject(parent) + , d_ptr(p) +{ + p->q_ptr = this; +} + +/*! \internal +*/ +QWebEngineDownloadItem::~QWebEngineDownloadItem() +{ + // MEMO Items are owned by profile by default and will be destroyed on profile's destruction + // It's not safe to access profile in that case, so we rely on profile to clean up items + if (!isFinished()) + cancel(); +} + +QT_END_NAMESPACE diff --git a/src/core/api/qwebenginedownloaditem.h b/src/core/api/qwebenginedownloaditem.h new file mode 100644 index 000000000..9310d95db --- /dev/null +++ b/src/core/api/qwebenginedownloaditem.h @@ -0,0 +1,203 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWEBENGINEDOWNLOADITEM_H +#define QWEBENGINEDOWNLOADITEM_H + +#include <QtWebEngineCore/qtwebenginecoreglobal.h> + +#include <QtCore/qobject.h> +#include <QtCore/QUrl> + +QT_BEGIN_NAMESPACE + +//TODO: class QWebEnginePage; +class QWebEngineDownloadItemPrivate; +class QWebEngineProfilePrivate; + +class Q_WEBENGINECORE_EXPORT QWebEngineDownloadItem : public QObject +{ + Q_OBJECT +public: + Q_PROPERTY(quint32 id READ id CONSTANT FINAL) + Q_PROPERTY(DownloadState state READ state NOTIFY stateChanged FINAL) + Q_PROPERTY(SavePageFormat savePageFormat READ savePageFormat WRITE setSavePageFormat NOTIFY savePageFormatChanged REVISION 2 FINAL) + Q_PROPERTY(qint64 totalBytes READ totalBytes NOTIFY totalBytesChanged FINAL) + Q_PROPERTY(qint64 receivedBytes READ receivedBytes NOTIFY receivedBytesChanged FINAL) + Q_PROPERTY(QString mimeType READ mimeType REVISION 1 FINAL) + Q_PROPERTY(QString path READ path WRITE setPath NOTIFY pathChanged FINAL) + Q_PROPERTY(DownloadType type READ type REVISION 3 FINAL) + Q_PROPERTY(DownloadInterruptReason interruptReason READ interruptReason NOTIFY interruptReasonChanged REVISION 4 FINAL) + Q_PROPERTY(QString interruptReasonString READ interruptReasonString NOTIFY interruptReasonChanged REVISION 4 FINAL) + Q_PROPERTY(bool isFinished READ isFinished NOTIFY isFinishedChanged REVISION 5 FINAL) + Q_PROPERTY(bool isPaused READ isPaused NOTIFY isPausedChanged REVISION 5 FINAL) + Q_PROPERTY(bool isSavePageDownload READ isSavePageDownload CONSTANT REVISION 6 FINAL) + //TODO: Q_PROPERTY(QQuickWebEngineView *view READ view CONSTANT REVISION 7 FINAL) + Q_PROPERTY(QUrl url READ url CONSTANT REVISION 10 FINAL) + Q_PROPERTY(QString suggestedFileName READ suggestedFileName CONSTANT REVISION 10 FINAL) + Q_PROPERTY(QString downloadDirectory READ downloadDirectory WRITE setDownloadDirectory NOTIFY downloadDirectoryChanged REVISION 10 FINAL) + Q_PROPERTY(QString downloadFileName READ downloadFileName WRITE setDownloadFileName NOTIFY downloadFileNameChanged REVISION 10 FINAL) + + ~QWebEngineDownloadItem(); + + enum DownloadState { + DownloadRequested, + DownloadInProgress, + DownloadCompleted, + DownloadCancelled, + DownloadInterrupted + }; + Q_ENUM(DownloadState) + + enum SavePageFormat { + UnknownSaveFormat = -1, + SingleHtmlSaveFormat, + CompleteHtmlSaveFormat, + MimeHtmlSaveFormat + }; + Q_ENUM(SavePageFormat) + + enum DownloadInterruptReason { + NoReason = 0, + FileFailed = 1, + FileAccessDenied = 2, + FileNoSpace = 3, + FileNameTooLong = 5, + FileTooLarge = 6, + FileVirusInfected = 7, + FileTransientError = 10, + FileBlocked = 11, + FileSecurityCheckFailed = 12, + FileTooShort = 13, + FileHashMismatch = 14, + NetworkFailed = 20, + NetworkTimeout = 21, + NetworkDisconnected = 22, + NetworkServerDown = 23, + NetworkInvalidRequest = 24, + ServerFailed = 30, + //ServerNoRange = 31, + ServerBadContent = 33, + ServerUnauthorized = 34, + ServerCertProblem = 35, + ServerForbidden = 36, + ServerUnreachable = 37, + UserCanceled = 40, + //UserShutdown = 41, + //Crash = 50 + }; + Q_ENUM(DownloadInterruptReason) + + enum DownloadType { + Attachment = 0, + DownloadAttribute, + UserRequested, + SavePage + }; + Q_ENUM(DownloadType) + + quint32 id() const; + DownloadState state() const; + qint64 totalBytes() const; + qint64 receivedBytes() const; + QUrl url() const; + QString mimeType() const; +#if QT_DEPRECATED_SINCE(5, 14) +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + QT_DEPRECATED_VERSION_X(5, 14, "Use downloadDirectory() and downloadFileName() instead") + QString path() const; + QT_DEPRECATED_VERSION_X(5, 14, "Use setDownloadDirectory() and setDownloadFileName() instead") + void setPath(QString path); +#else + QT_DEPRECATED_X("Use downloadDirectory() and downloadFileName() instead") + QString path() const; + QT_DEPRECATED_X("Use setDownloadDirectory() and setDownloadFileName() instead") + void setPath(QString path); +#endif +#endif + bool isFinished() const; + bool isPaused() const; + SavePageFormat savePageFormat() const; + void setSavePageFormat(SavePageFormat format); + DownloadType Q_DECL_DEPRECATED type() const; + DownloadInterruptReason interruptReason() const; + QString interruptReasonString() const; + bool isSavePageDownload() const; + QString suggestedFileName() const; + QString downloadDirectory() const; + void setDownloadDirectory(const QString &directory); + QString downloadFileName() const; + void setDownloadFileName(const QString &fileName); + + //TODO: + QObject *page() const; + +public Q_SLOTS: + void accept(); + void cancel(); + void pause(); + void resume(); + +Q_SIGNALS: + void stateChanged(QWebEngineDownloadItem::DownloadState state); + //TODO: fix it for qml + void downloadProgress(qint64 bytesReceived, qint64 bytesTotal); + Q_REVISION(2) void savePageFormatChanged(); + void receivedBytesChanged(); + void totalBytesChanged(); + void pathChanged(); + Q_REVISION(4) void interruptReasonChanged(); + Q_REVISION(5) void isFinishedChanged(); + Q_REVISION(5) void isPausedChanged(); + Q_REVISION(10) void downloadDirectoryChanged(); + Q_REVISION(10) void downloadFileNameChanged(); + +private: + Q_DISABLE_COPY(QWebEngineDownloadItem) + Q_DECLARE_PRIVATE(QWebEngineDownloadItem) + + friend class QWebEngineProfilePrivate; + friend class QQuickWebEngineProfilePrivate; + QWebEngineDownloadItem(QWebEngineDownloadItemPrivate*, QObject *parent = Q_NULLPTR); + QScopedPointer<QWebEngineDownloadItemPrivate> d_ptr; +}; + +QT_END_NAMESPACE + +#endif // QWEBENGINEDOWNLOADITEM_H diff --git a/src/core/api/qwebenginedownloaditem_p.h b/src/core/api/qwebenginedownloaditem_p.h new file mode 100644 index 000000000..b40a21250 --- /dev/null +++ b/src/core/api/qwebenginedownloaditem_p.h @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWEBENGINEDOWNLOADITEM_P_H +#define QWEBENGINEDOWNLOADITEM_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qtwebenginecoreglobal.h" +#include "qwebenginedownloaditem.h" +#include "profile_adapter_client.h" +#include <QString> +#include <QPointer> + +namespace QtWebEngineCore { +class ProfileAdapter; +} + +QT_BEGIN_NAMESPACE + +class Q_WEBENGINECORE_PRIVATE_EXPORT QWebEngineDownloadItemPrivate { +public: + QWebEngineDownloadItemPrivate(QtWebEngineCore::ProfileAdapter *adapter, const QUrl &url); + ~QWebEngineDownloadItemPrivate(); + + void update(const QtWebEngineCore::ProfileAdapterClient::DownloadItemInfo &info); + void setFinished(); + + bool downloadFinished; + quint32 downloadId; + qint64 startTime; + QWebEngineDownloadItem::DownloadState downloadState; + QWebEngineDownloadItem::SavePageFormat savePageFormat; + QWebEngineDownloadItem::DownloadType type; + QWebEngineDownloadItem::DownloadInterruptReason interruptReason; + QString downloadPath; + const QUrl downloadUrl; + QString mimeType; + bool downloadPaused; + QString suggestedFileName; + QString downloadDirectory; + QString downloadFileName; + bool isCustomFileName; + qint64 totalBytes; + qint64 receivedBytes; + QWebEngineDownloadItem *q_ptr; + QPointer<QtWebEngineCore::ProfileAdapter> m_profileAdapter; + QObject *page; + Q_DECLARE_PUBLIC(QWebEngineDownloadItem) +}; + +QT_END_NAMESPACE + +#endif // QWEBENGINEDOWNLOADITEM_P_H + |