summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAndras Becsi <andras.becsi@theqtcompany.com>2014-12-11 19:57:58 +0100
committerAndras Becsi <andras.becsi@theqtcompany.com>2015-01-12 16:34:58 +0100
commite6a74159cebdbfec575f40469c216c90ee8651c1 (patch)
tree331f7a51b9d0c77568bb2744fbd8155733424374 /src
parent4557ccd9785f53abc11460211c84db3e564b364f (diff)
Add QML download API
This patch exposes downloadStarted and downloadFinished signals on the WebEngineProfile to notify about downloads. The WebEngineDownloadItem exposes a subset of Chromium's content::DownloadItem functionality. For now we expose minimal requirements to be able to control downloads in QML but this can be extended in the future. This patch also adds a DownloadView to quicktestbrowser to demonstrate the usage of the new API. [ChangeLog][QtWebEngineQML] Add QtQuick download API Change-Id: I8d8f0daf02c4e0151000427fc2a4b37d28b9db52 Reviewed-by: Jocelyn Turcotte <jocelyn.turcotte@digia.com>
Diffstat (limited to 'src')
-rw-r--r--src/core/browser_context_adapter.cpp22
-rw-r--r--src/core/browser_context_adapter.h10
-rw-r--r--src/core/browser_context_adapter_client.h63
-rw-r--r--src/core/browser_context_qt.cpp4
-rw-r--r--src/core/browser_context_qt.h4
-rw-r--r--src/core/core_gyp_generator.pro1
-rw-r--r--src/core/download_manager_delegate_qt.cpp216
-rw-r--r--src/core/download_manager_delegate_qt.h46
-rw-r--r--src/webengine/api/qquickwebenginedownloaditem.cpp134
-rw-r--r--src/webengine/api/qquickwebenginedownloaditem_p.h91
-rw-r--r--src/webengine/api/qquickwebenginedownloaditem_p_p.h67
-rw-r--r--src/webengine/api/qquickwebengineprofile.cpp83
-rw-r--r--src/webengine/api/qquickwebengineprofile_p.h4
-rw-r--r--src/webengine/api/qquickwebengineprofile_p_p.h20
-rw-r--r--src/webengine/api/qquickwebenginesingleton_p.h1
-rw-r--r--src/webengine/plugin/experimental/plugin.cpp5
-rw-r--r--src/webengine/webengine.pro3
17 files changed, 594 insertions, 180 deletions
diff --git a/src/core/browser_context_adapter.cpp b/src/core/browser_context_adapter.cpp
index 637003f96..95ddc4d87 100644
--- a/src/core/browser_context_adapter.cpp
+++ b/src/core/browser_context_adapter.cpp
@@ -36,8 +36,10 @@
#include "browser_context_adapter.h"
+#include "content/public/browser/browser_thread.h"
#include "browser_context_qt.h"
#include "content_client_qt.h"
+#include "download_manager_delegate_qt.h"
#include "web_engine_context.h"
#include "web_engine_visited_links_manager.h"
#include "url_request_context_getter_qt.h"
@@ -67,6 +69,7 @@ BrowserContextAdapter::BrowserContextAdapter(bool offTheRecord)
, m_httpCacheType(DiskHttpCache)
, m_persistentCookiesPolicy(AllowPersistentCookies)
, m_visitedLinksPolicy(TrackVisitedLinksOnDisk)
+ , m_client(0)
, m_httpCacheMaxSize(0)
{
}
@@ -84,6 +87,8 @@ BrowserContextAdapter::BrowserContextAdapter(const QString &storageName)
BrowserContextAdapter::~BrowserContextAdapter()
{
+ if (m_downloadManagerDelegate)
+ content::BrowserThread::DeleteSoon(content::BrowserThread::UI, FROM_HERE, m_downloadManagerDelegate.take());
}
void BrowserContextAdapter::setStorageName(const QString &storageName)
@@ -118,6 +123,23 @@ WebEngineVisitedLinksManager *BrowserContextAdapter::visitedLinksManager()
return m_visitedLinksManager.data();
}
+DownloadManagerDelegateQt *BrowserContextAdapter::downloadManagerDelegate()
+{
+ if (!m_downloadManagerDelegate)
+ m_downloadManagerDelegate.reset(new DownloadManagerDelegateQt(this));
+ return m_downloadManagerDelegate.data();
+}
+
+void BrowserContextAdapter::setClient(BrowserContextAdapterClient *adapterClient)
+{
+ m_client = adapterClient;
+}
+
+void BrowserContextAdapter::cancelDownload(quint32 downloadId)
+{
+ downloadManagerDelegate()->cancelDownload(downloadId);
+}
+
BrowserContextAdapter* BrowserContextAdapter::defaultContext()
{
return WebEngineContext::current()->defaultBrowserContext();
diff --git a/src/core/browser_context_adapter.h b/src/core/browser_context_adapter.h
index 8f03f2094..1c12c465d 100644
--- a/src/core/browser_context_adapter.h
+++ b/src/core/browser_context_adapter.h
@@ -43,7 +43,9 @@
#include <QSharedData>
#include <QString>
+class BrowserContextAdapterClient;
class BrowserContextQt;
+class DownloadManagerDelegateQt;
class WebEngineVisitedLinksManager;
class QWEBENGINE_EXPORT BrowserContextAdapter : public QSharedData
@@ -57,6 +59,12 @@ public:
static BrowserContextAdapter* offTheRecordContext();
WebEngineVisitedLinksManager *visitedLinksManager();
+ DownloadManagerDelegateQt *downloadManagerDelegate();
+
+ BrowserContextAdapterClient* client() { return m_client; }
+
+ void setClient(BrowserContextAdapterClient *adapterClient);
+ void cancelDownload(quint32 downloadId);
BrowserContextQt *browserContext();
@@ -116,12 +124,14 @@ private:
bool m_offTheRecord;
QScopedPointer<BrowserContextQt> m_browserContext;
QScopedPointer<WebEngineVisitedLinksManager> m_visitedLinksManager;
+ QScopedPointer<DownloadManagerDelegateQt> m_downloadManagerDelegate;
QString m_dataPath;
QString m_cachePath;
QString m_httpUserAgent;
HttpCacheType m_httpCacheType;
PersistentCookiesPolicy m_persistentCookiesPolicy;
VisitedLinksPolicy m_visitedLinksPolicy;
+ BrowserContextAdapterClient *m_client;
int m_httpCacheMaxSize;
Q_DISABLE_COPY(BrowserContextAdapter)
diff --git a/src/core/browser_context_adapter_client.h b/src/core/browser_context_adapter_client.h
new file mode 100644
index 000000000..2b6b4f434
--- /dev/null
+++ b/src/core/browser_context_adapter_client.h
@@ -0,0 +1,63 @@
+ /****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef BROWSER_CONTEXT_ADAPTER_CLIENT_H
+#define BROWSER_CONTEXT_ADAPTER_CLIENT_H
+
+#include "qtwebenginecoreglobal.h"
+#include <QString>
+
+class QWEBENGINE_EXPORT BrowserContextAdapterClient
+{
+public:
+ // Keep in sync with content::DownloadItem::DownloadState
+ enum DownloadState {
+ // Download is actively progressing.
+ DownloadInProgress = 0,
+ // Download is completely finished.
+ DownloadCompleted,
+ // Download has been cancelled.
+ DownloadCancelled,
+ // This state indicates that the download has been interrupted.
+ DownloadInterrupted
+ };
+ virtual ~BrowserContextAdapterClient() { }
+
+ virtual void downloadRequested(quint32 downloadId, QString &downloadPath, bool &cancelled) = 0;
+ virtual void downloadUpdated(quint32 downloadId, int downloadState, int percentComplete) = 0;
+};
+
+#endif // BROWSER_CONTEXT_ADAPTER_CLIENT_H
diff --git a/src/core/browser_context_qt.cpp b/src/core/browser_context_qt.cpp
index 9337b6b6b..4661f59fc 100644
--- a/src/core/browser_context_qt.cpp
+++ b/src/core/browser_context_qt.cpp
@@ -37,12 +37,12 @@
#include "browser_context_qt.h"
#include "browser_context_adapter.h"
+#include "download_manager_delegate_qt.h"
#include "type_conversion.h"
#include "qtwebenginecoreglobal.h"
#include "resource_context_qt.h"
#include "url_request_context_getter_qt.h"
-#include "base/files/scoped_temp_dir.h"
#include "base/time/time.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/storage_partition.h"
@@ -108,7 +108,7 @@ content::ResourceContext *BrowserContextQt::GetResourceContext()
content::DownloadManagerDelegate *BrowserContextQt::GetDownloadManagerDelegate()
{
- return downloadManagerDelegate.get();
+ return m_adapter->downloadManagerDelegate();
}
content::BrowserPluginGuestManager *BrowserContextQt::GetGuestManager()
diff --git a/src/core/browser_context_qt.h b/src/core/browser_context_qt.h
index c11a234ab..8ab6024ae 100644
--- a/src/core/browser_context_qt.h
+++ b/src/core/browser_context_qt.h
@@ -41,7 +41,8 @@
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/resource_context.h"
#include "net/url_request/url_request_context.h"
-#include "download_manager_delegate_qt.h"
+
+#include <QtCore/qcompilerdetection.h> // Needed for Q_DECL_OVERRIDE
class BrowserContextAdapter;
class URLRequestContextGetterQt;
@@ -72,7 +73,6 @@ public:
private:
scoped_ptr<content::ResourceContext> resourceContext;
scoped_refptr<URLRequestContextGetterQt> url_request_getter_;
- scoped_ptr<DownloadManagerDelegateQt> downloadManagerDelegate;
BrowserContextAdapter *m_adapter;
friend class BrowserContextAdapter;
diff --git a/src/core/core_gyp_generator.pro b/src/core/core_gyp_generator.pro
index 4514475ec..90a665e84 100644
--- a/src/core/core_gyp_generator.pro
+++ b/src/core/core_gyp_generator.pro
@@ -86,6 +86,7 @@ HEADERS = \
browser_accessibility_manager_qt.h \
browser_accessibility_qt.h \
browser_context_adapter.h \
+ browser_context_adapter_client.h \
browser_context_qt.h \
certificate_error_controller_p.h \
certificate_error_controller.h \
diff --git a/src/core/download_manager_delegate_qt.cpp b/src/core/download_manager_delegate_qt.cpp
index 3df03ffa3..3f6ec7bcc 100644
--- a/src/core/download_manager_delegate_qt.cpp
+++ b/src/core/download_manager_delegate_qt.cpp
@@ -36,6 +36,7 @@
#include "download_manager_delegate_qt.h"
+#include "content/public/browser/download_manager.h"
#include "content/public/browser/download_item.h"
#include "content/public/browser/save_page_type.h"
#include "content/public/browser/web_contents.h"
@@ -46,115 +47,21 @@
#include <QMap>
#include <QStandardPaths>
+#include "browser_context_adapter.h"
+#include "browser_context_adapter_client.h"
+#include "browser_context_qt.h"
#include "type_conversion.h"
#include "qtwebenginecoreglobal.h"
-// Helper class to track currently ongoing downloads to prevent file name
-// clashes / overwriting of files.
-class DownloadTargetHelper : public content::DownloadItem::Observer {
-public:
- DownloadTargetHelper()
- : m_defaultDownloadDirectory(QStandardPaths::writableLocation(QStandardPaths::DownloadLocation))
- {
-
- }
- virtual ~DownloadTargetHelper() {}
-
- bool determineDownloadTarget(content::DownloadItem *item, const content::DownloadTargetCallback &callback);
-
- virtual void OnDownloadUpdated(content::DownloadItem *download) Q_DECL_OVERRIDE;
- virtual void OnDownloadDestroyed(content::DownloadItem *download) Q_DECL_OVERRIDE;
-private:
- bool isPathAvailable(const QString& path);
-
- QDir m_defaultDownloadDirectory;
- QMap<content::DownloadItem*, QString> m_ongoingDownloads;
-};
-
-bool DownloadTargetHelper::isPathAvailable(const QString& path)
-{
- return !m_ongoingDownloads.values().contains(path) && !QFile::exists(path);
-}
-
-bool DownloadTargetHelper::determineDownloadTarget(content::DownloadItem *item, const content::DownloadTargetCallback &callback)
-{
- std::string suggestedFilename = item->GetSuggestedFilename();
-
- if (suggestedFilename.empty())
- suggestedFilename = item->GetTargetFilePath().AsUTF8Unsafe();
-
- if (suggestedFilename.empty())
- suggestedFilename = item->GetURL().ExtractFileName();
-
- if (suggestedFilename.empty())
- suggestedFilename = "qwe_download";
-
- if (!m_defaultDownloadDirectory.exists() && !m_defaultDownloadDirectory.mkpath(m_defaultDownloadDirectory.absolutePath()))
- return false;
-
- QString suggestedFilePath = m_defaultDownloadDirectory.absoluteFilePath(QString::fromStdString(suggestedFilename));
- if (!isPathAvailable(suggestedFilePath)) {
- int i = 1;
- for (; i < 99; i++) {
- QFileInfo tmpFile(suggestedFilePath);
- QString tmpFilePath = QString("%1%2%3(%4).%5").arg(tmpFile.absolutePath()).arg(QDir::separator()).arg(tmpFile.baseName()).arg(i).arg(tmpFile.completeSuffix());
- if (isPathAvailable(tmpFilePath)) {
- suggestedFilePath = tmpFilePath;
- break;
- }
- }
- if (i >= 99) {
- callback.Run(base::FilePath(), content::DownloadItem::TARGET_DISPOSITION_PROMPT, content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, base::FilePath());
- return false;
- }
- }
-
- m_ongoingDownloads.insert(item, suggestedFilePath);
- item->AddObserver(this);
-
- base::FilePath filePathForCallback(toFilePathString(suggestedFilePath));
- callback.Run(filePathForCallback, content::DownloadItem::TARGET_DISPOSITION_OVERWRITE,
- content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, filePathForCallback.AddExtension(toFilePathString("download")));
- return true;
-}
-
-void DownloadTargetHelper::OnDownloadUpdated(content::DownloadItem *download)
+DownloadManagerDelegateQt::DownloadManagerDelegateQt(BrowserContextAdapter *contextAdapter)
+ : m_currentId(0)
+ , m_contextAdapter(contextAdapter)
{
- switch (download->GetState()) {
- case content::DownloadItem::COMPLETE:
- case content::DownloadItem::CANCELLED:
- case content::DownloadItem::INTERRUPTED:
- download->RemoveObserver(this);
- m_ongoingDownloads.remove(download);
- break;
- case content::DownloadItem::IN_PROGRESS:
- default:
- break;
- }
-}
-
-void DownloadTargetHelper::OnDownloadDestroyed(content::DownloadItem *download)
-{
- download->RemoveObserver(this);
- m_ongoingDownloads.remove(download);
-}
-
-DownloadManagerDelegateQt::DownloadManagerDelegateQt()
- : m_targetHelper(new DownloadTargetHelper())
- , m_currentId(0)
-{
-
+ Q_ASSERT(m_contextAdapter);
}
DownloadManagerDelegateQt::~DownloadManagerDelegateQt()
{
- delete m_targetHelper;
-}
-
-
-void DownloadManagerDelegateQt::Shutdown()
-{
- QT_NOT_YET_IMPLEMENTED
}
void DownloadManagerDelegateQt::GetNextId(const content::DownloadIdCallback& callback)
@@ -162,24 +69,17 @@ void DownloadManagerDelegateQt::GetNextId(const content::DownloadIdCallback& cal
callback.Run(++m_currentId);
}
-bool DownloadManagerDelegateQt::ShouldOpenFileBasedOnExtension(const base::FilePath& path)
-{
- QT_NOT_YET_IMPLEMENTED
- return false;
-}
-
-bool DownloadManagerDelegateQt::ShouldCompleteDownload(content::DownloadItem* item,
- const base::Closure& complete_callback)
+void DownloadManagerDelegateQt::cancelDownload(const content::DownloadTargetCallback& callback)
{
- QT_NOT_YET_IMPLEMENTED
- return true;
+ callback.Run(base::FilePath(), content::DownloadItem::TARGET_DISPOSITION_PROMPT, content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, base::FilePath());
}
-bool DownloadManagerDelegateQt::ShouldOpenDownload(content::DownloadItem* item,
- const content::DownloadOpenDelayedCallback& callback)
+void DownloadManagerDelegateQt::cancelDownload(quint32 downloadId)
{
- QT_NOT_YET_IMPLEMENTED
- return false;
+ content::DownloadManager* dlm = content::BrowserContext::GetDownloadManager(m_contextAdapter->browserContext());
+ content::DownloadItem *download = dlm->GetDownload(downloadId);
+ if (download)
+ download->Cancel(/* user_cancel */ true);
}
bool DownloadManagerDelegateQt::DetermineDownloadTarget(content::DownloadItem* item,
@@ -194,41 +94,55 @@ bool DownloadManagerDelegateQt::DetermineDownloadTarget(content::DownloadItem* i
return true;
}
- // Let the target helper determine the download target path.
- return m_targetHelper->determineDownloadTarget(item, callback);
-}
+ std::string suggestedFilename = item->GetSuggestedFilename();
-bool DownloadManagerDelegateQt::GenerateFileHash()
-{
- QT_NOT_YET_IMPLEMENTED
- return false;
-}
+ if (suggestedFilename.empty())
+ suggestedFilename = item->GetTargetFilePath().AsUTF8Unsafe();
-void DownloadManagerDelegateQt::ChooseSavePath(
- content::WebContents* web_contents,
- const base::FilePath& suggested_path,
- const base::FilePath::StringType& default_extension,
- bool can_save_as_complete,
- const content::SavePackagePathPickedCallback& callback)
-{
- QT_NOT_YET_IMPLEMENTED
-}
+ if (suggestedFilename.empty())
+ suggestedFilename = item->GetURL().ExtractFileName();
-void DownloadManagerDelegateQt::OpenDownload(content::DownloadItem* download)
-{
- QT_NOT_YET_IMPLEMENTED
-}
+ if (suggestedFilename.empty())
+ suggestedFilename = "qwe_download";
-void DownloadManagerDelegateQt::ShowDownloadInShell(content::DownloadItem* download)
-{
- QT_NOT_YET_IMPLEMENTED
-}
+ QDir defaultDownloadDirectory = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
-void DownloadManagerDelegateQt::CheckForFileExistence(
- content::DownloadItem* download,
- const content::CheckForFileExistenceCallback& callback)
-{
- QT_NOT_YET_IMPLEMENTED
+ QFileInfo suggestedFile(defaultDownloadDirectory.absoluteFilePath(QString::fromStdString(suggestedFilename)));
+ QString suggestedFilePath = suggestedFile.absoluteFilePath();
+ QString tmpFileBase = QString("%1%2%3").arg(suggestedFile.absolutePath()).arg(QDir::separator()).arg(suggestedFile.baseName());
+
+ for (int i = 1; QFileInfo::exists(suggestedFilePath); ++i) {
+ suggestedFilePath = QString("%1(%2).%3").arg(tmpFileBase).arg(i).arg(suggestedFile.completeSuffix());
+ if (i >= 99) {
+ suggestedFilePath = suggestedFile.absoluteFilePath();
+ break;
+ }
+ }
+
+ item->AddObserver(this);
+ quint32 downloadId = item->GetId();
+ if (m_contextAdapter->client()) {
+ bool cancelled = false;
+ m_contextAdapter->client()->downloadRequested(downloadId, suggestedFilePath, cancelled);
+ suggestedFile.setFile(suggestedFilePath);
+
+ if (!cancelled && !suggestedFile.absoluteDir().mkpath(suggestedFile.absolutePath())) {
+ qWarning("Creating download path failed, download cancelled: %s", suggestedFile.absolutePath().toUtf8().data());
+ cancelled = true;
+ }
+
+ if (cancelled) {
+ cancelDownload(callback);
+ return true;
+ }
+
+ base::FilePath filePathForCallback(toFilePathString(suggestedFile.absoluteFilePath()));
+ callback.Run(filePathForCallback, content::DownloadItem::TARGET_DISPOSITION_OVERWRITE,
+ content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, filePathForCallback.AddExtension(toFilePathString("download")));
+ } else
+ cancelDownload(callback);
+
+ return true;
}
void DownloadManagerDelegateQt::GetSaveDir(content::BrowserContext* browser_context,
@@ -242,4 +156,16 @@ void DownloadManagerDelegateQt::GetSaveDir(content::BrowserContext* browser_cont
*skip_dir_check = true;
}
+void DownloadManagerDelegateQt::OnDownloadUpdated(content::DownloadItem *download)
+{
+ const quint32 downloadId = download->GetId();
+
+ if (m_contextAdapter->client())
+ m_contextAdapter->client()->downloadUpdated(downloadId, download->GetState(), download->PercentComplete());
+}
+void DownloadManagerDelegateQt::OnDownloadDestroyed(content::DownloadItem *download)
+{
+ download->RemoveObserver(this);
+ download->Cancel(/* user_cancel */ false);
+}
diff --git a/src/core/download_manager_delegate_qt.h b/src/core/download_manager_delegate_qt.h
index 4c838363f..007f2e580 100644
--- a/src/core/download_manager_delegate_qt.h
+++ b/src/core/download_manager_delegate_qt.h
@@ -39,7 +39,7 @@
#include "content/public/browser/download_manager_delegate.h"
-#include <qglobal.h>
+#include <QtCore/qcompilerdetection.h> // Needed for Q_DECL_OVERRIDE
namespace base {
class FilePath;
@@ -51,46 +51,38 @@ class DownloadItem;
class WebContents;
}
-class DownloadTargetHelper;
-
-class DownloadManagerDelegateQt : public content::DownloadManagerDelegate
+class BrowserContextAdapter;
+class DownloadManagerDelegateInstance;
+class DownloadManagerDelegateQt
+ : public content::DownloadManagerDelegate
+ , public content::DownloadItem::Observer
{
public:
- DownloadManagerDelegateQt();
- virtual ~DownloadManagerDelegateQt();
-
- void Shutdown() Q_DECL_OVERRIDE;
+ DownloadManagerDelegateQt(BrowserContextAdapter *contextAdapter);
+ ~DownloadManagerDelegateQt();
void GetNextId(const content::DownloadIdCallback& callback) Q_DECL_OVERRIDE;
- bool ShouldOpenFileBasedOnExtension(const base::FilePath& path) Q_DECL_OVERRIDE;
- bool ShouldCompleteDownload(content::DownloadItem* item,
- const base::Closure& complete_callback) Q_DECL_OVERRIDE;
-
- bool ShouldOpenDownload(content::DownloadItem* item,
- const content::DownloadOpenDelayedCallback& callback) Q_DECL_OVERRIDE;
bool DetermineDownloadTarget(content::DownloadItem* item,
const content::DownloadTargetCallback& callback) Q_DECL_OVERRIDE;
- bool GenerateFileHash() Q_DECL_OVERRIDE;
- void ChooseSavePath(content::WebContents* web_contents,
- const base::FilePath& suggested_path,
- const base::FilePath::StringType& default_extension,
- bool can_save_as_complete,
- const content::SavePackagePathPickedCallback& callback) Q_DECL_OVERRIDE;
-
- void OpenDownload(content::DownloadItem* download) Q_DECL_OVERRIDE;
- void ShowDownloadInShell(content::DownloadItem* download) Q_DECL_OVERRIDE;
- void CheckForFileExistence(content::DownloadItem* download,
- const content::CheckForFileExistenceCallback& callback) Q_DECL_OVERRIDE;
-
void GetSaveDir(content::BrowserContext* browser_context,
base::FilePath* website_save_dir,
base::FilePath* download_save_dir,
bool* skip_dir_check) Q_DECL_OVERRIDE;
+ void cancelDownload(quint32 downloadId);
+
+ // Inherited from content::DownloadItem::Observer
+ void OnDownloadUpdated(content::DownloadItem *download) Q_DECL_OVERRIDE;
+ void OnDownloadDestroyed(content::DownloadItem *download) Q_DECL_OVERRIDE;
+
private:
- DownloadTargetHelper* m_targetHelper;
+ void cancelDownload(const content::DownloadTargetCallback& callback);
+ BrowserContextAdapter *m_contextAdapter;
+
uint64 m_currentId;
+
+ friend class DownloadManagerDelegateInstance;
DISALLOW_COPY_AND_ASSIGN(DownloadManagerDelegateQt);
};
diff --git a/src/webengine/api/qquickwebenginedownloaditem.cpp b/src/webengine/api/qquickwebenginedownloaditem.cpp
new file mode 100644
index 000000000..729cb0d3f
--- /dev/null
+++ b/src/webengine/api/qquickwebenginedownloaditem.cpp
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickwebenginedownloaditem_p.h"
+#include "qquickwebenginedownloaditem_p_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QQuickWebEngineDownloadItemPrivate::QQuickWebEngineDownloadItemPrivate(QQuickWebEngineProfilePrivate *p)
+ : profile(p)
+ , downloadStarted(false)
+ , downloadId(-1)
+ , downloadState(QQuickWebEngineDownloadItem::DownloadCancelled)
+ , downloadProgress(0)
+{
+}
+
+QQuickWebEngineDownloadItemPrivate::~QQuickWebEngineDownloadItemPrivate()
+{
+ Q_Q(QQuickWebEngineDownloadItem);
+ q->cancel();
+}
+
+void QQuickWebEngineDownloadItemPrivate::update(QQuickWebEngineDownloadItem::DownloadState state, int progress)
+{
+ Q_Q(QQuickWebEngineDownloadItem);
+ if (state != downloadState) {
+ downloadState = state;
+ Q_EMIT q->stateChanged();
+ }
+ if (progress != downloadProgress) {
+ downloadProgress = progress;
+ Q_EMIT q->progressChanged();
+ }
+}
+
+void QQuickWebEngineDownloadItem::cancel()
+{
+ Q_D(QQuickWebEngineDownloadItem);
+
+ if (d->downloadState == QQuickWebEngineDownloadItem::DownloadCompleted
+ || d->downloadState == QQuickWebEngineDownloadItem::DownloadCancelled)
+ return;
+
+ d->update(QQuickWebEngineDownloadItem::DownloadCancelled, d->downloadProgress);
+
+ // We directly cancel the download if the user cancels before
+ // it even started, so no need to notify the profile here.
+ if (d->downloadStarted)
+ d->profile->cancelDownload(d->downloadId);
+}
+
+quint32 QQuickWebEngineDownloadItem::id()
+{
+ Q_D(QQuickWebEngineDownloadItem);
+ return d->downloadId;
+}
+
+QQuickWebEngineDownloadItem::DownloadState QQuickWebEngineDownloadItem::state()
+{
+ Q_D(QQuickWebEngineDownloadItem);
+ return d->downloadState;
+}
+
+int QQuickWebEngineDownloadItem::progress()
+{
+ Q_D(QQuickWebEngineDownloadItem);
+ return d->downloadProgress;
+}
+
+QString QQuickWebEngineDownloadItem::path()
+{
+ Q_D(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.");
+ return;
+ }
+ if (d->downloadPath != path) {
+ d->downloadPath = path;
+ Q_EMIT pathChanged();
+ }
+}
+
+QQuickWebEngineDownloadItem::QQuickWebEngineDownloadItem(QQuickWebEngineDownloadItemPrivate *p, QObject *parent)
+ : QObject(parent)
+ , d_ptr(p)
+{
+ p->q_ptr = this;
+}
+
+QQuickWebEngineDownloadItem::~QQuickWebEngineDownloadItem()
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/webengine/api/qquickwebenginedownloaditem_p.h b/src/webengine/api/qquickwebenginedownloaditem_p.h
new file mode 100644
index 000000000..8ea9f0850
--- /dev/null
+++ b/src/webengine/api/qquickwebenginedownloaditem_p.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKWEBENGINEDOWNLOADITEM_P_H
+#define QQUICKWEBENGINEDOWNLOADITEM_P_H
+
+#include <qtwebengineglobal_p.h>
+#include <QObject>
+#include <QScopedPointer>
+#include <QString>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickWebEngineDownloadItemPrivate;
+class QQuickWebEngineProfilePrivate;
+
+class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineDownloadItem: public QObject {
+ Q_OBJECT
+public:
+ ~QQuickWebEngineDownloadItem();
+ enum DownloadState {
+ DownloadInProgress,
+ DownloadCompleted,
+ DownloadCancelled,
+ DownloadInterrupted
+ };
+ Q_ENUMS(DownloadState)
+
+ 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(QString path READ path WRITE setPath NOTIFY pathChanged)
+
+ Q_INVOKABLE void cancel();
+
+ quint32 id();
+ DownloadState state();
+ int progress();
+ QString path();
+ void setPath(QString path);
+
+Q_SIGNALS:
+ void stateChanged();
+ void progressChanged();
+ void pathChanged();
+
+private:
+ QQuickWebEngineDownloadItem(QQuickWebEngineDownloadItemPrivate*, QObject *parent = 0);
+ Q_DISABLE_COPY(QQuickWebEngineDownloadItem)
+ Q_DECLARE_PRIVATE(QQuickWebEngineDownloadItem)
+ friend class QQuickWebEngineProfilePrivate;
+
+ QScopedPointer<QQuickWebEngineDownloadItemPrivate> d_ptr;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKWEBENGINEDOWNLOADITEM_P_H
diff --git a/src/webengine/api/qquickwebenginedownloaditem_p_p.h b/src/webengine/api/qquickwebenginedownloaditem_p_p.h
new file mode 100644
index 000000000..6b724b4c9
--- /dev/null
+++ b/src/webengine/api/qquickwebenginedownloaditem_p_p.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKWEBENGINEDOWNLOADITEM_P_P_H
+#define QQUICKWEBENGINEDOWNLOADITEM_P_P_H
+
+#include "qquickwebenginedownloaditem_p.h"
+#include "qquickwebengineprofile_p_p.h"
+#include <private/qtwebengineglobal_p.h>
+#include <QString>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickWebEngineDownloadItemPrivate {
+ QQuickWebEngineDownloadItem *q_ptr;
+ QQuickWebEngineProfilePrivate* profile;
+ friend class QQuickWebEngineProfilePrivate;
+public:
+ Q_DECLARE_PUBLIC(QQuickWebEngineDownloadItem)
+ QQuickWebEngineDownloadItemPrivate(QQuickWebEngineProfilePrivate *p);
+ ~QQuickWebEngineDownloadItemPrivate();
+
+ bool downloadStarted;
+ quint32 downloadId;
+ QQuickWebEngineDownloadItem::DownloadState downloadState;
+ int downloadProgress;
+ QString downloadPath;
+
+ void update(QQuickWebEngineDownloadItem::DownloadState state, int progress);
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKWEBENGINEDOWNLOADITEM_P_P_H
diff --git a/src/webengine/api/qquickwebengineprofile.cpp b/src/webengine/api/qquickwebengineprofile.cpp
index 64d9805d6..9eecae073 100644
--- a/src/webengine/api/qquickwebengineprofile.cpp
+++ b/src/webengine/api/qquickwebengineprofile.cpp
@@ -36,31 +36,114 @@
#include "qquickwebengineprofile_p.h"
+#include "qquickwebenginedownloaditem_p.h"
+#include "qquickwebenginedownloaditem_p_p.h"
#include "qquickwebengineprofile_p_p.h"
+#include <QQmlEngine>
#include "browser_context_adapter.h"
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_browserContext(browserContext)
{
if (ownsContext)
m_browserContextRef = browserContext;
+
+ m_browserContext->setClient(this);
}
QQuickWebEngineProfilePrivate::~QQuickWebEngineProfilePrivate()
{
+ m_browserContext->setClient(0);
+
+ Q_FOREACH (QQuickWebEngineDownloadItem* download, m_ongoingDownloads) {
+ if (download)
+ download->cancel();
+ }
+
+ m_ongoingDownloads.clear();
+}
+
+void QQuickWebEngineProfilePrivate::cancelDownload(quint32 downloadId)
+{
+ m_browserContext->cancelDownload(downloadId);
+}
+
+void QQuickWebEngineProfilePrivate::downloadDestroyed(quint32 downloadId)
+{
+ m_ongoingDownloads.remove(downloadId);
+}
+
+void QQuickWebEngineProfilePrivate::downloadRequested(quint32 downloadId, QString &downloadPath, bool &cancelled)
+{
+ Q_Q(QQuickWebEngineProfile);
+
+ Q_ASSERT(!m_ongoingDownloads.contains(downloadId));
+ QQuickWebEngineDownloadItemPrivate *itemPrivate = new QQuickWebEngineDownloadItemPrivate(this);
+ itemPrivate->downloadId = downloadId;
+ itemPrivate->downloadState = QQuickWebEngineDownloadItem::DownloadInProgress;
+ itemPrivate->downloadPath = downloadPath;
+
+ QQuickWebEngineDownloadItem *download = new QQuickWebEngineDownloadItem(itemPrivate, q);
+
+ m_ongoingDownloads.insert(downloadId, download);
+
+ QQmlEngine::setObjectOwnership(download, QQmlEngine::JavaScriptOwnership);
+ Q_EMIT q->downloadStarted(download);
+ download->d_func()->downloadStarted = true;
+
+ downloadPath = download->path();
+ cancelled = download->state() == QQuickWebEngineDownloadItem::DownloadCancelled;
+}
+
+void QQuickWebEngineProfilePrivate::downloadUpdated(quint32 downloadId, int downloadState, int percentComplete)
+{
+ Q_Q(QQuickWebEngineProfile);
+
+ Q_ASSERT(m_ongoingDownloads.contains(downloadId));
+ QQuickWebEngineDownloadItem* download = m_ongoingDownloads.value(downloadId).data();
+
+ if (!download) {
+ cancelDownload(downloadId);
+ return;
+ }
+
+ download->d_func()->update(toDownloadState(downloadState), percentComplete);
+
+ if (downloadState != BrowserContextAdapterClient::DownloadInProgress) {
+ Q_EMIT q->downloadFinished(download);
+ m_ongoingDownloads.remove(downloadId);
+ }
}
QQuickWebEngineProfile::QQuickWebEngineProfile()
: d_ptr(new QQuickWebEngineProfilePrivate(new BrowserContextAdapter(false), true))
{
+ d_ptr->q_ptr = this;
}
QQuickWebEngineProfile::QQuickWebEngineProfile(QQuickWebEngineProfilePrivate *privatePtr)
: d_ptr(privatePtr)
{
+ d_ptr->q_ptr = this;
}
QQuickWebEngineProfile::~QQuickWebEngineProfile()
diff --git a/src/webengine/api/qquickwebengineprofile_p.h b/src/webengine/api/qquickwebengineprofile_p.h
index 936573e8f..b8d7c8652 100644
--- a/src/webengine/api/qquickwebengineprofile_p.h
+++ b/src/webengine/api/qquickwebengineprofile_p.h
@@ -45,6 +45,7 @@
QT_BEGIN_NAMESPACE
+class QQuickWebEngineDownloadItem;
class QQuickWebEngineProfilePrivate;
class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineProfile : public QObject {
@@ -110,6 +111,9 @@ signals:
void persistentCookiesPolicyChanged();
void httpCacheMaxSizeChanged();
+ void downloadStarted(QQuickWebEngineDownloadItem *download);
+ void downloadFinished(QQuickWebEngineDownloadItem *download);
+
private:
Q_DECLARE_PRIVATE(QQuickWebEngineProfile);
QQuickWebEngineProfile(QQuickWebEngineProfilePrivate *);
diff --git a/src/webengine/api/qquickwebengineprofile_p_p.h b/src/webengine/api/qquickwebengineprofile_p_p.h
index d71dcfda9..18ccfc467 100644
--- a/src/webengine/api/qquickwebengineprofile_p_p.h
+++ b/src/webengine/api/qquickwebengineprofile_p_p.h
@@ -39,21 +39,37 @@
class BrowserContextAdapter;
+#include "browser_context_adapter_client.h"
+#include "qquickwebengineprofile_p.h"
+
#include <QExplicitlySharedDataPointer>
+#include <QMap>
+#include <QPointer>
QT_BEGIN_NAMESPACE
-
-class QQuickWebEngineProfilePrivate {
+class QQuickWebEngineDownloadItem;
+class QQuickWebEngineProfilePrivate
+ : public BrowserContextAdapterClient
+{
public:
+ Q_DECLARE_PUBLIC(QQuickWebEngineProfile)
QQuickWebEngineProfilePrivate(BrowserContextAdapter* browserContext, bool ownsContext);
~QQuickWebEngineProfilePrivate();
BrowserContextAdapter *browserContext() const { return m_browserContext; }
+ void cancelDownload(quint32 downloadId);
+ void downloadDestroyed(quint32 downloadId);
+
+ void downloadRequested(quint32 downloadId, QString &downloadPath, bool &cancelled) Q_DECL_OVERRIDE;
+ void downloadUpdated(quint32 downloadId, int downloadState, int percentComplete) Q_DECL_OVERRIDE;
+
private:
friend class QQuickWebEngineViewPrivate;
+ QQuickWebEngineProfile *q_ptr;
BrowserContextAdapter *m_browserContext;
QExplicitlySharedDataPointer<BrowserContextAdapter> m_browserContextRef;
+ QMap<quint32, QPointer<QQuickWebEngineDownloadItem> > m_ongoingDownloads;
};
QT_END_NAMESPACE
diff --git a/src/webengine/api/qquickwebenginesingleton_p.h b/src/webengine/api/qquickwebenginesingleton_p.h
index 3bc1a9700..f983d0ffb 100644
--- a/src/webengine/api/qquickwebenginesingleton_p.h
+++ b/src/webengine/api/qquickwebenginesingleton_p.h
@@ -43,7 +43,6 @@
QT_BEGIN_NAMESPACE
class QQuickWebEngineProfile;
class QQuickWebEngineSettings;
-
class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineSingleton : public QObject {
Q_OBJECT
Q_PROPERTY(QQuickWebEngineSettings* settings READ settings CONSTANT FINAL)
diff --git a/src/webengine/plugin/experimental/plugin.cpp b/src/webengine/plugin/experimental/plugin.cpp
index 883ebc598..f522478ab 100644
--- a/src/webengine/plugin/experimental/plugin.cpp
+++ b/src/webengine/plugin/experimental/plugin.cpp
@@ -36,6 +36,7 @@
#include <QtQml/qqmlextensionplugin.h>
+#include "qquickwebenginedownloaditem_p.h"
#include "qquickwebenginehistory_p.h"
#include "qquickwebenginesettings_p.h"
#include "qquickwebenginesingleton_p.h"
@@ -80,7 +81,9 @@ public:
QObject::tr("Cannot create a separate instance of NavigationHistory"));
qmlRegisterUncreatableType<QQuickWebEngineSettings>(uri, 1, 0, "WebEngineSettings",
QObject::tr("Cannot create a separate instance of WebEngineSettings"));
- qmlRegisterSingletonType<QQuickWebEngineSingleton>(uri, 1, 0, "WebEngine", webEngineSingletonProvider);
+ qmlRegisterUncreatableType<QQuickWebEngineDownloadItem>(uri, 1, 1, "WebEngineDownloadItem",
+ QObject::tr("Cannot create a separate instance of WebEngineDownloadItem"));
+ qmlRegisterSingletonType<QQuickWebEngineSingleton>(uri, 1, 1, "WebEngine", webEngineSingletonProvider);
}
};
diff --git a/src/webengine/webengine.pro b/src/webengine/webengine.pro
index 11ec95c05..6d17fd2eb 100644
--- a/src/webengine/webengine.pro
+++ b/src/webengine/webengine.pro
@@ -13,6 +13,7 @@ QMAKE_DOCS = $$PWD/doc/qtwebengine.qdocconf
INCLUDEPATH += $$PWD api ../core
SOURCES = \
+ api/qquickwebenginedownloaditem.cpp \
api/qquickwebenginehistory.cpp \
api/qquickwebengineloadrequest.cpp \
api/qquickwebenginenavigationrequest.cpp \
@@ -29,6 +30,8 @@ SOURCES = \
HEADERS = \
api/qtwebengineglobal.h \
api/qtwebengineglobal_p.h \
+ api/qquickwebenginedownloaditem_p.h \
+ api/qquickwebenginedownloaditem_p_p.h \
api/qquickwebenginehistory_p.h \
api/qquickwebengineloadrequest_p.h \
api/qquickwebenginenavigationrequest_p.h \