From fba650c3d774c595b6726c7140ff12353f8c0a4c Mon Sep 17 00:00:00 2001
From: Allan Sandfeld Jensen <allan.jensen@theqtcompany.com>
Date: Fri, 18 Sep 2015 15:02:06 +0200
Subject: [PATCH] Make the MIME-type of downloads available

An application currently have to rely on suggested filename only to
guess the type of a download. This is often insufficient when the suffix
is misleading or missing.

This patch adds the mimetype to the reported metadata and also adds
a mimetype appropriate suffix to suggested filenames.

Task-number: QTBUG-48206
Change-Id: I4c70f076d6eb5ae820fd6b7f568515eeb7c18df5
Reviewed-by: Leena Miettinen <riitta-leena.miettinen@theqtcompany.com>
Reviewed-by: Joerg Bornemann <joerg.bornemann@theqtcompany.com>
---
 src/core/browser_context_adapter_client.h     |  1 +
 src/core/download_manager_delegate_qt.cpp     | 28 ++++++++++++-------
 .../api/qquickwebenginedownloaditem.cpp       | 12 ++++++++
 .../api/qquickwebenginedownloaditem_p.h       |  3 ++
 .../api/qquickwebenginedownloaditem_p_p.h     |  1 +
 src/webengine/api/qquickwebengineprofile.cpp  |  1 +
 src/webengine/plugin/plugin.cpp               |  2 ++
 .../api/qwebenginedownloaditem.cpp            | 12 ++++++++
 .../api/qwebenginedownloaditem.h              |  1 +
 .../api/qwebenginedownloaditem_p.h            |  1 +
 .../api/qwebengineprofile.cpp                 |  1 +
 11 files changed, 53 insertions(+), 10 deletions(-)

diff --git a/src/core/browser_context_adapter_client.h b/src/core/browser_context_adapter_client.h
index 4a57b75c4..efa889e75 100644
--- a/src/core/browser_context_adapter_client.h
+++ b/src/core/browser_context_adapter_client.h
@@ -64,6 +64,7 @@ public:
         const int state;
         const qint64 totalBytes;
         const qint64 receivedBytes;
+        const QString mimeType;
 
         QString path;
         bool accepted;
diff --git a/src/core/download_manager_delegate_qt.cpp b/src/core/download_manager_delegate_qt.cpp
index e9af98fd8..6d29af76a 100644
--- a/src/core/download_manager_delegate_qt.cpp
+++ b/src/core/download_manager_delegate_qt.cpp
@@ -46,6 +46,7 @@
 #include <QFile>
 #include <QFileInfo>
 #include <QMap>
+#include <QMimeDatabase>
 #include <QStandardPaths>
 
 #include "browser_context_adapter.h"
@@ -102,23 +103,28 @@ bool DownloadManagerDelegateQt::DetermineDownloadTarget(content::DownloadItem* i
         return true;
     }
 
-    std::string suggestedFilename = item->GetSuggestedFilename();
+    QString suggestedFilename = toQt(item->GetSuggestedFilename());
+    QString mimeTypeString = toQt(item->GetMimeType());
 
-    if (suggestedFilename.empty())
-        suggestedFilename = net::HttpContentDisposition(item->GetContentDisposition(), std::string()).filename();
+    if (suggestedFilename.isEmpty())
+        suggestedFilename = toQt(net::HttpContentDisposition(item->GetContentDisposition(), std::string()).filename());
 
-    if (suggestedFilename.empty())
-        suggestedFilename = item->GetTargetFilePath().AsUTF8Unsafe();
+    if (suggestedFilename.isEmpty())
+        suggestedFilename = toQt(item->GetTargetFilePath().AsUTF8Unsafe());
 
-    if (suggestedFilename.empty())
-        suggestedFilename = item->GetURL().ExtractFileName();
+    if (suggestedFilename.isEmpty())
+        suggestedFilename = toQt(item->GetURL().ExtractFileName());
 
-    if (suggestedFilename.empty())
-        suggestedFilename = "qwe_download";
+    if (suggestedFilename.isEmpty()) {
+        suggestedFilename = QStringLiteral("qwe_download");
+        QMimeType mimeType = QMimeDatabase().mimeTypeForName(mimeTypeString);
+        if (mimeType.isValid() && !mimeType.preferredSuffix().isEmpty())
+            suggestedFilename += QStringLiteral(".") + mimeType.preferredSuffix();
+    }
 
     QDir defaultDownloadDirectory = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
 
-    QFileInfo suggestedFile(defaultDownloadDirectory.absoluteFilePath(QString::fromStdString(suggestedFilename)));
+    QFileInfo suggestedFile(defaultDownloadDirectory.absoluteFilePath(suggestedFilename));
     QString suggestedFilePath = suggestedFile.absoluteFilePath();
     QString tmpFileBase = QString("%1%2%3").arg(suggestedFile.absolutePath()).arg(QDir::separator()).arg(suggestedFile.baseName());
 
@@ -139,6 +145,7 @@ bool DownloadManagerDelegateQt::DetermineDownloadTarget(content::DownloadItem* i
             item->GetState(),
             item->GetTotalBytes(),
             item->GetReceivedBytes(),
+            mimeTypeString,
             suggestedFilePath,
             false /* accepted */
         };
@@ -191,6 +198,7 @@ void DownloadManagerDelegateQt::OnDownloadUpdated(content::DownloadItem *downloa
             download->GetState(),
             download->GetTotalBytes(),
             download->GetReceivedBytes(),
+            toQt(download->GetMimeType()),
             QString(),
             true /* accepted */
         };
diff --git a/src/webengine/api/qquickwebenginedownloaditem.cpp b/src/webengine/api/qquickwebenginedownloaditem.cpp
index da47388ee..7290dba2b 100644
--- a/src/webengine/api/qquickwebenginedownloaditem.cpp
+++ b/src/webengine/api/qquickwebenginedownloaditem.cpp
@@ -216,6 +216,18 @@ qint64 QQuickWebEngineDownloadItem::receivedBytes() const
     return d->receivedBytes;
 }
 
+/*!
+    \qmlproperty QString WebEngineDownloadItem::mimeType
+
+    Holds the MIME type of the download.
+*/
+
+QString QQuickWebEngineDownloadItem::mimeType() const
+{
+    Q_D(const QQuickWebEngineDownloadItem);
+    return d->mimeType;
+}
+
 /*!
     \qmlproperty QString WebEngineDownloadItem::path
 
diff --git a/src/webengine/api/qquickwebenginedownloaditem_p.h b/src/webengine/api/qquickwebenginedownloaditem_p.h
index d0be2f99a..124cea1a5 100644
--- a/src/webengine/api/qquickwebenginedownloaditem_p.h
+++ b/src/webengine/api/qquickwebenginedownloaditem_p.h
@@ -75,6 +75,7 @@ public:
     Q_PROPERTY(DownloadState state READ state NOTIFY stateChanged)
     Q_PROPERTY(qint64 totalBytes READ totalBytes NOTIFY totalBytesChanged)
     Q_PROPERTY(qint64 receivedBytes READ receivedBytes NOTIFY receivedBytesChanged)
+    Q_PROPERTY(QString mimeType READ mimeType NOTIFY mimeTypeChanged REVISION 1)
     Q_PROPERTY(QString path READ path WRITE setPath NOTIFY pathChanged)
 
     Q_INVOKABLE void accept();
@@ -84,6 +85,7 @@ public:
     DownloadState state() const;
     qint64 totalBytes() const;
     qint64 receivedBytes() const;
+    QString mimeType() const;
     QString path() const;
     void setPath(QString path);
 
@@ -91,6 +93,7 @@ Q_SIGNALS:
     void stateChanged();
     void receivedBytesChanged();
     void totalBytesChanged();
+    void mimeTypeChanged();
     void pathChanged();
 
 private:
diff --git a/src/webengine/api/qquickwebenginedownloaditem_p_p.h b/src/webengine/api/qquickwebenginedownloaditem_p_p.h
index 230f322b5..4e36fec43 100644
--- a/src/webengine/api/qquickwebenginedownloaditem_p_p.h
+++ b/src/webengine/api/qquickwebenginedownloaditem_p_p.h
@@ -71,6 +71,7 @@ public:
     QQuickWebEngineDownloadItem::DownloadState downloadState;
     qint64 totalBytes;
     qint64 receivedBytes;
+    QString mimeType;
     QString downloadPath;
 
     void update(const QtWebEngineCore::BrowserContextAdapterClient::DownloadItemInfo &info);
diff --git a/src/webengine/api/qquickwebengineprofile.cpp b/src/webengine/api/qquickwebengineprofile.cpp
index 303f038a8..a8f61dfcd 100644
--- a/src/webengine/api/qquickwebengineprofile.cpp
+++ b/src/webengine/api/qquickwebengineprofile.cpp
@@ -93,6 +93,7 @@ void QQuickWebEngineProfilePrivate::downloadRequested(DownloadItemInfo &info)
     itemPrivate->downloadId = info.id;
     itemPrivate->downloadState = QQuickWebEngineDownloadItem::DownloadRequested;
     itemPrivate->totalBytes = info.totalBytes;
+    itemPrivate->mimeType = info.mimeType;
     itemPrivate->downloadPath = info.path;
 
     QQuickWebEngineDownloadItem *download = new QQuickWebEngineDownloadItem(itemPrivate, q);
diff --git a/src/webengine/plugin/plugin.cpp b/src/webengine/plugin/plugin.cpp
index 16d36b190..fa84c9f5a 100644
--- a/src/webengine/plugin/plugin.cpp
+++ b/src/webengine/plugin/plugin.cpp
@@ -76,6 +76,8 @@ public:
         qmlRegisterUncreatableType<QQuickWebEngineCertificateError>(uri, 1, 1, "WebEngineCertificateError", tr("Cannot create separate instance of WebEngineCertificateError"));
         qmlRegisterUncreatableType<QQuickWebEngineDownloadItem>(uri, 1, 1, "WebEngineDownloadItem",
             tr("Cannot create a separate instance of WebEngineDownloadItem"));
+        qmlRegisterUncreatableType<QQuickWebEngineDownloadItem, 1>(uri, 1, 2, "WebEngineDownloadItem",
+            tr("Cannot create a separate instance of WebEngineDownloadItem"));
         qmlRegisterUncreatableType<QQuickWebEngineNewViewRequest>(uri, 1, 1, "WebEngineNewViewRequest", tr("Cannot create separate instance of WebEngineNewViewRequest"));
         qmlRegisterUncreatableType<QQuickWebEngineSettings>(uri, 1, 1, "WebEngineSettings", tr("Cannot create a separate instance of WebEngineSettings"));
         // FIXME(QTBUG-40043): qmlRegisterUncreatableType<QQuickWebEngineSettings, 1>(uri, 1, 2, "WebEngineSettings", tr("Cannot create a separate instance of WebEngineSettings"));
diff --git a/src/webenginewidgets/api/qwebenginedownloaditem.cpp b/src/webenginewidgets/api/qwebenginedownloaditem.cpp
index 6c9413280..9fdab3367 100644
--- a/src/webenginewidgets/api/qwebenginedownloaditem.cpp
+++ b/src/webenginewidgets/api/qwebenginedownloaditem.cpp
@@ -246,6 +246,18 @@ QUrl QWebEngineDownloadItem::url() const
     return d->downloadUrl;
 }
 
+/*!
+    \since 5.6
+
+    Returns the MIME type of the download.
+*/
+
+QString QWebEngineDownloadItem::mimeType() const
+{
+    Q_D(const QWebEngineDownloadItem);
+    return d->mimeType;
+}
+
 /*!
     Returns the full target path where data is being downloaded to.
 
diff --git a/src/webenginewidgets/api/qwebenginedownloaditem.h b/src/webenginewidgets/api/qwebenginedownloaditem.h
index 38b9a4ad8..886d9ab9a 100644
--- a/src/webenginewidgets/api/qwebenginedownloaditem.h
+++ b/src/webenginewidgets/api/qwebenginedownloaditem.h
@@ -66,6 +66,7 @@ public:
     qint64 totalBytes() const;
     qint64 receivedBytes() const;
     QUrl url() const;
+    QString mimeType() const;
     QString path() const;
     void setPath(QString path);
     bool isFinished() const;
diff --git a/src/webenginewidgets/api/qwebenginedownloaditem_p.h b/src/webenginewidgets/api/qwebenginedownloaditem_p.h
index 87dc4114a..2c7bbf985 100644
--- a/src/webenginewidgets/api/qwebenginedownloaditem_p.h
+++ b/src/webenginewidgets/api/qwebenginedownloaditem_p.h
@@ -70,6 +70,7 @@ public:
     QWebEngineDownloadItem::DownloadState downloadState;
     QString downloadPath;
     const QUrl downloadUrl;
+    QString mimeType;
 
     qint64 totalBytes;
     qint64 receivedBytes;
diff --git a/src/webenginewidgets/api/qwebengineprofile.cpp b/src/webenginewidgets/api/qwebengineprofile.cpp
index e1cde4f08..7f63b312f 100644
--- a/src/webenginewidgets/api/qwebengineprofile.cpp
+++ b/src/webenginewidgets/api/qwebengineprofile.cpp
@@ -150,6 +150,7 @@ void QWebEngineProfilePrivate::downloadRequested(DownloadItemInfo &info)
     itemPrivate->downloadId = info.id;
     itemPrivate->downloadState = QWebEngineDownloadItem::DownloadRequested;
     itemPrivate->downloadPath = info.path;
+    itemPrivate->mimeType = info.mimeType;
 
     QWebEngineDownloadItem *download = new QWebEngineDownloadItem(itemPrivate, q);
 
-- 
GitLab