diff --git a/src/core/browser_context_adapter_client.h b/src/core/browser_context_adapter_client.h index 1d84ffb45cf0c2d85c540f341d717ba74d0396d5..ff65f0c8f7f2167b0077fcaca8a64bb306ee96b7 100644 --- a/src/core/browser_context_adapter_client.h +++ b/src/core/browser_context_adapter_client.h @@ -60,7 +60,6 @@ public: const quint32 id; const QUrl url; const int state; - const int percentComplete; const qint64 totalBytes; const qint64 receivedBytes; diff --git a/src/core/download_manager_delegate_qt.cpp b/src/core/download_manager_delegate_qt.cpp index 78d5f909a6a17fcca021258a67c766b3c2a9a097..73a0976dae3ad8b0337d1130bbad46be20e311ad 100644 --- a/src/core/download_manager_delegate_qt.cpp +++ b/src/core/download_manager_delegate_qt.cpp @@ -131,7 +131,6 @@ bool DownloadManagerDelegateQt::DetermineDownloadTarget(content::DownloadItem* i item->GetId(), toQt(item->GetURL()), item->GetState(), - item->PercentComplete(), item->GetTotalBytes(), item->GetReceivedBytes(), suggestedFilePath, @@ -178,7 +177,6 @@ void DownloadManagerDelegateQt::OnDownloadUpdated(content::DownloadItem *downloa download->GetId(), toQt(download->GetURL()), download->GetState(), - download->PercentComplete(), download->GetTotalBytes(), download->GetReceivedBytes(), QString(), diff --git a/src/webengine/api/qquickwebenginedownloaditem.cpp b/src/webengine/api/qquickwebenginedownloaditem.cpp index 967638b7e997ade10c4eba748dc44241581da67f..6ee00d9a0af644f2752198f3e4610681a212f298 100644 --- a/src/webengine/api/qquickwebenginedownloaditem.cpp +++ b/src/webengine/api/qquickwebenginedownloaditem.cpp @@ -39,12 +39,26 @@ QT_BEGIN_NAMESPACE +static inline QQuickWebEngineDownloadItem::DownloadState toDownloadState(int state) { + switch (state) { + case BrowserContextAdapterClient::DownloadInProgress: + return QQuickWebEngineDownloadItem::DownloadInProgress; + case BrowserContextAdapterClient::DownloadCompleted: + return QQuickWebEngineDownloadItem::DownloadCompleted; + case BrowserContextAdapterClient::DownloadCancelled: + return QQuickWebEngineDownloadItem::DownloadCancelled; + case BrowserContextAdapterClient::DownloadInterrupted: + return QQuickWebEngineDownloadItem::DownloadInterrupted; + default: + Q_UNREACHABLE(); + return QQuickWebEngineDownloadItem::DownloadCancelled; + } +} + QQuickWebEngineDownloadItemPrivate::QQuickWebEngineDownloadItemPrivate(QQuickWebEngineProfilePrivate *p) : profile(p) - , downloadStarted(false) , downloadId(-1) , downloadState(QQuickWebEngineDownloadItem::DownloadCancelled) - , downloadProgress(0) { } @@ -53,64 +67,189 @@ QQuickWebEngineDownloadItemPrivate::~QQuickWebEngineDownloadItemPrivate() profile->downloadDestroyed(downloadId); } -void QQuickWebEngineDownloadItemPrivate::update(QQuickWebEngineDownloadItem::DownloadState state, int progress) +/*! + \qmltype WebEngineDownloadItem + \instantiates QQuickWebEngineDownloadItem + \inqmlmodule QtWebEngine 1.1 + \since QtWebEngine 1.1 + \brief A WebEngineDownloadItem provides information about a download. + + WebEngineDownloadItem stores the state of a download to be used to manage requested downloads. + + By default the download is rejected unless the user explicitly accepts it with + WebEngineDownloadItem::accept(). +*/ + +void QQuickWebEngineDownloadItemPrivate::update(const BrowserContextAdapterClient::DownloadItemInfo &info) { Q_Q(QQuickWebEngineDownloadItem); - if (state != downloadState) { - downloadState = state; - Q_EMIT q->stateChanged(); + + updateState(toDownloadState(info.state)); + + if (info.receivedBytes != receivedBytes) { + receivedBytes = info.receivedBytes; + Q_EMIT q->receivedBytesChanged(); + } + + if (info.totalBytes != totalBytes) { + totalBytes = info.totalBytes; + Q_EMIT q->totalBytesChanged(); } - if (progress != downloadProgress) { - downloadProgress = progress; - Q_EMIT q->progressChanged(); +} + +void QQuickWebEngineDownloadItemPrivate::updateState(QQuickWebEngineDownloadItem::DownloadState newState) +{ + Q_Q(QQuickWebEngineDownloadItem); + + if (downloadState != newState) { + downloadState = newState; + Q_EMIT q->stateChanged(); } } +/*! + \qmlmethod void WebEngineDownloadItem::accept() + + Accepts the download request, which will start the download. + + \sa WebEngineDownloadItem::cancel() +*/ + +void QQuickWebEngineDownloadItem::accept() +{ + Q_D(QQuickWebEngineDownloadItem); + + if (d->downloadState != QQuickWebEngineDownloadItem::DownloadRequested) + return; + + d->updateState(QQuickWebEngineDownloadItem::DownloadInProgress); +} + +/*! + \qmlmethod void WebEngineDownloadItem::cancel() + + Cancels the download. +*/ + void QQuickWebEngineDownloadItem::cancel() { Q_D(QQuickWebEngineDownloadItem); - if (d->downloadState == QQuickWebEngineDownloadItem::DownloadCompleted - || d->downloadState == QQuickWebEngineDownloadItem::DownloadCancelled) + QQuickWebEngineDownloadItem::DownloadState state = d->downloadState; + + if (state == QQuickWebEngineDownloadItem::DownloadCompleted + || state == QQuickWebEngineDownloadItem::DownloadCancelled) return; - d->update(QQuickWebEngineDownloadItem::DownloadCancelled, d->downloadProgress); + d->updateState(QQuickWebEngineDownloadItem::DownloadCancelled); // We directly cancel the download if the user cancels before // it even started, so no need to notify the profile here. - if (d->downloadStarted) + if (state == QQuickWebEngineDownloadItem::DownloadInProgress) d->profile->cancelDownload(d->downloadId); } -quint32 QQuickWebEngineDownloadItem::id() +/*! + \qmlproperty quint32 WebEngineDownloadItem::id + + The download item's id. +*/ + +quint32 QQuickWebEngineDownloadItem::id() const { - Q_D(QQuickWebEngineDownloadItem); + Q_D(const QQuickWebEngineDownloadItem); return d->downloadId; } -QQuickWebEngineDownloadItem::DownloadState QQuickWebEngineDownloadItem::state() +/*! + \qmlproperty enumeration WebEngineDownloadItem::state + + This property describes the state in which the download is in. + + The state can be one of: + + \table + + \header + \li Constant + \li Description + + \row + \li DownloadRequested + \li The download has been requested, but has not been accepted yet. + + \row + \li DownloadInProgress + \li The download is in progress. + + \row + \li DownloadCompleted + \li The download completed successfully. + + \row + \li DownloadInterrupted + \li The download has been interrupted (by the server or because of lost connectivity). + + \endtable +*/ + +QQuickWebEngineDownloadItem::DownloadState QQuickWebEngineDownloadItem::state() const { - Q_D(QQuickWebEngineDownloadItem); + Q_D(const QQuickWebEngineDownloadItem); return d->downloadState; } -int QQuickWebEngineDownloadItem::progress() +/*! + \qmlproperty int WebEngineDownloadItem::totalBytes + + The download's total size in bytes. + + -1 means the total size is unknown. +*/ + +qint64 QQuickWebEngineDownloadItem::totalBytes() const { - Q_D(QQuickWebEngineDownloadItem); - return d->downloadProgress; + Q_D(const QQuickWebEngineDownloadItem); + return d->totalBytes; } -QString QQuickWebEngineDownloadItem::path() +/*! + \qmlproperty int WebEngineDownloadItem::receivedBytes + + The download's bytes that have been received so far. +*/ + +qint64 QQuickWebEngineDownloadItem::receivedBytes() const { - Q_D(QQuickWebEngineDownloadItem); + Q_D(const QQuickWebEngineDownloadItem); + return d->receivedBytes; +} + +/*! + \qmlproperty QString WebEngineDownloadItem::path + + The download item's full target path where it 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. + + The download path can only be set in the \c WebEngineProfile.onDownloadRequested + handler before the download is accepted. + + \sa WebEngineProfile::downloadRequested(WebEngineDownloadItem download), WebEngineDownloadItem::accept() +*/ + +QString QQuickWebEngineDownloadItem::path() const +{ + Q_D(const QQuickWebEngineDownloadItem); return d->downloadPath; } void QQuickWebEngineDownloadItem::setPath(QString path) { Q_D(QQuickWebEngineDownloadItem); - if (d->downloadStarted) { - qWarning("Setting the download path is not allowed after the download has been started."); + if (d->downloadState != QQuickWebEngineDownloadItem::DownloadRequested) { + qWarning("Setting the download path is not allowed after the download has been accepted."); return; } if (d->downloadPath != path) { diff --git a/src/webengine/api/qquickwebenginedownloaditem_p.h b/src/webengine/api/qquickwebenginedownloaditem_p.h index 2cb140accbc988617166573cf1007d6a6c040df3..ea12c9c94e803452ca0b621a9b0396d04c317ee6 100644 --- a/src/webengine/api/qquickwebenginedownloaditem_p.h +++ b/src/webengine/api/qquickwebenginedownloaditem_p.h @@ -52,6 +52,7 @@ class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineDownloadItem: public QObject { public: ~QQuickWebEngineDownloadItem(); enum DownloadState { + DownloadRequested, DownloadInProgress, DownloadCompleted, DownloadCancelled, @@ -61,20 +62,24 @@ public: Q_PROPERTY(quint32 id READ id() CONSTANT FINAL) Q_PROPERTY(DownloadState state READ state NOTIFY stateChanged) - Q_PROPERTY(int progress READ progress NOTIFY progressChanged) + Q_PROPERTY(qint64 totalBytes READ totalBytes NOTIFY totalBytesChanged) + Q_PROPERTY(qint64 receivedBytes READ receivedBytes NOTIFY receivedBytesChanged) Q_PROPERTY(QString path READ path WRITE setPath NOTIFY pathChanged) + Q_INVOKABLE void accept(); Q_INVOKABLE void cancel(); - quint32 id(); - DownloadState state(); - int progress(); - QString path(); + quint32 id() const; + DownloadState state() const; + qint64 totalBytes() const; + qint64 receivedBytes() const; + QString path() const; void setPath(QString path); Q_SIGNALS: void stateChanged(); - void progressChanged(); + void receivedBytesChanged(); + void totalBytesChanged(); void pathChanged(); private: diff --git a/src/webengine/api/qquickwebenginedownloaditem_p_p.h b/src/webengine/api/qquickwebenginedownloaditem_p_p.h index 6b724b4c9d19a823594ecb7094d7dd84329e9073..0250a8faa472dd1bd31540449eeff56a4ac4e6f7 100644 --- a/src/webengine/api/qquickwebenginedownloaditem_p_p.h +++ b/src/webengine/api/qquickwebenginedownloaditem_p_p.h @@ -53,13 +53,14 @@ public: QQuickWebEngineDownloadItemPrivate(QQuickWebEngineProfilePrivate *p); ~QQuickWebEngineDownloadItemPrivate(); - bool downloadStarted; quint32 downloadId; QQuickWebEngineDownloadItem::DownloadState downloadState; - int downloadProgress; + qint64 totalBytes; + qint64 receivedBytes; QString downloadPath; - void update(QQuickWebEngineDownloadItem::DownloadState state, int progress); + void update(const BrowserContextAdapterClient::DownloadItemInfo &info); + void updateState(QQuickWebEngineDownloadItem::DownloadState newState); }; QT_END_NAMESPACE diff --git a/src/webengine/api/qquickwebengineprofile.cpp b/src/webengine/api/qquickwebengineprofile.cpp index 791f39263b13a0045bf13d3cfceec07e59f7ca27..cac309291ade47fd0980fa0dbec232d5ca1226ba 100644 --- a/src/webengine/api/qquickwebengineprofile.cpp +++ b/src/webengine/api/qquickwebengineprofile.cpp @@ -48,22 +48,6 @@ QT_BEGIN_NAMESPACE -static inline QQuickWebEngineDownloadItem::DownloadState toDownloadState(int state) { - switch (state) { - case BrowserContextAdapterClient::DownloadInProgress: - return QQuickWebEngineDownloadItem::DownloadInProgress; - case BrowserContextAdapterClient::DownloadCompleted: - return QQuickWebEngineDownloadItem::DownloadCompleted; - case BrowserContextAdapterClient::DownloadCancelled: - return QQuickWebEngineDownloadItem::DownloadCancelled; - case BrowserContextAdapterClient::DownloadInterrupted: - return QQuickWebEngineDownloadItem::DownloadInterrupted; - default: - Q_UNREACHABLE(); - return QQuickWebEngineDownloadItem::DownloadCancelled; - } -} - QQuickWebEngineProfilePrivate::QQuickWebEngineProfilePrivate(BrowserContextAdapter* browserContext, bool ownsContext) : m_settings(new QQuickWebEngineSettings()) , m_browserContext(browserContext) @@ -95,7 +79,6 @@ void QQuickWebEngineProfilePrivate::cancelDownload(quint32 downloadId) void QQuickWebEngineProfilePrivate::downloadDestroyed(quint32 downloadId) { m_ongoingDownloads.remove(downloadId); - cancelDownload(downloadId); } void QQuickWebEngineProfilePrivate::downloadRequested(DownloadItemInfo &info) @@ -105,7 +88,7 @@ void QQuickWebEngineProfilePrivate::downloadRequested(DownloadItemInfo &info) Q_ASSERT(!m_ongoingDownloads.contains(info.id)); QQuickWebEngineDownloadItemPrivate *itemPrivate = new QQuickWebEngineDownloadItemPrivate(this); itemPrivate->downloadId = info.id; - itemPrivate->downloadState = QQuickWebEngineDownloadItem::DownloadInProgress; + itemPrivate->downloadState = QQuickWebEngineDownloadItem::DownloadRequested; itemPrivate->downloadPath = info.path; QQuickWebEngineDownloadItem *download = new QQuickWebEngineDownloadItem(itemPrivate, q); @@ -113,11 +96,12 @@ void QQuickWebEngineProfilePrivate::downloadRequested(DownloadItemInfo &info) m_ongoingDownloads.insert(info.id, download); QQmlEngine::setObjectOwnership(download, QQmlEngine::JavaScriptOwnership); - Q_EMIT q->downloadStarted(download); - download->d_func()->downloadStarted = true; + Q_EMIT q->downloadRequested(download); + QQuickWebEngineDownloadItem::DownloadState state = download->state(); info.path = download->path(); - info.cancelled = download->state() == QQuickWebEngineDownloadItem::DownloadCancelled; + info.cancelled = state == QQuickWebEngineDownloadItem::DownloadCancelled + || state == QQuickWebEngineDownloadItem::DownloadRequested; } void QQuickWebEngineProfilePrivate::downloadUpdated(const DownloadItemInfo &info) @@ -134,7 +118,7 @@ void QQuickWebEngineProfilePrivate::downloadUpdated(const DownloadItemInfo &info return; } - download->d_func()->update(toDownloadState(info.state), info.percentComplete); + download->d_func()->update(info); if (info.state != BrowserContextAdapterClient::DownloadInProgress) { Q_EMIT q->downloadFinished(download); @@ -156,6 +140,24 @@ void QQuickWebEngineProfilePrivate::downloadUpdated(const DownloadItemInfo &info belongs to. */ +/*! + \qmlsignal WebEngineProfile::downloadRequested(WebEngineDownloadItem download) + + This signal is emitted whenever a download has been triggered. + The \a download argument holds the state of the download. + The \a download has to be explicitly accepted with WebEngineDownloadItem::accept(), + else the download will be cancelled by default. +*/ + +/*! + \qmlsignal WebEngineProfile::downloadFinished(WebEngineDownloadItem download) + + This signal is emitted whenever a download finishes downloading. + This can be due to the download finishing successfully, being cancelled or + interrupted by lost connectivity for example. + The \a download argument holds the state of the finished download instance. +*/ + QQuickWebEngineProfile::QQuickWebEngineProfile() : d_ptr(new QQuickWebEngineProfilePrivate(new BrowserContextAdapter(false), true)) { diff --git a/src/webengine/api/qquickwebengineprofile_p.h b/src/webengine/api/qquickwebengineprofile_p.h index 7a2ff08e1b6784c2ec792a76fcaade9857a651ef..f3e0f5c33fbcbaca023a8aed1400127c55e3a193 100644 --- a/src/webengine/api/qquickwebengineprofile_p.h +++ b/src/webengine/api/qquickwebengineprofile_p.h @@ -112,7 +112,7 @@ signals: void persistentCookiesPolicyChanged(); void httpCacheMaximumSizeChanged(); - void downloadStarted(QQuickWebEngineDownloadItem *download); + void downloadRequested(QQuickWebEngineDownloadItem *download); void downloadFinished(QQuickWebEngineDownloadItem *download); private: diff --git a/tests/quicktestbrowser/BrowserWindow.qml b/tests/quicktestbrowser/BrowserWindow.qml index 8d61ac590a2b8e00811bf4f37302d5f04f716bac..d438075d8d3cff0efd10dfad6586135222b22dd0 100644 --- a/tests/quicktestbrowser/BrowserWindow.qml +++ b/tests/quicktestbrowser/BrowserWindow.qml @@ -77,9 +77,10 @@ ApplicationWindow { id: testProfile storageName: "Test" httpCacheType: httpDiskCacheEnabled.checked ? WebEngineProfile.DiskHttpCache : WebEngineProfile.MemoryHttpCache; - onDownloadStarted: { + onDownloadRequested: { downloadView.visible = true downloadView.append(download) + download.accept() } } diff --git a/tests/quicktestbrowser/DownloadView.qml b/tests/quicktestbrowser/DownloadView.qml index 4475e183f64df464d9af541eed87ee7246d43c52..3367dfc71f5a73e9ddb3af0f273ca35292d59e98 100644 --- a/tests/quicktestbrowser/DownloadView.qml +++ b/tests/quicktestbrowser/DownloadView.qml @@ -72,11 +72,12 @@ Rectangle { Rectangle { id: progressBar - property int progress: downloadModel.downloads[index] ? downloadModel.downloads[index].progress : 0 + property real progress: downloadModel.downloads[index] + ? downloadModel.downloads[index].receivedBytes / downloadModel.downloads[index].totalBytes : 0 radius: 3 color: width == listView.width ? "green" : "#2b74c7" - width: listView.width / 100 * progress + width: listView.width * progress height: cancelButton.height Behavior on width {