summaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
authorJoerg Bornemann <joerg.bornemann@qt.io>2017-08-17 14:59:51 +0200
committerSimon Hausmann <simon.hausmann@qt.io>2017-08-18 20:59:02 +0000
commit99f84ffd2c0c78014a24534a863aa1c755abd51c (patch)
tree9858801c9ed2c7743e7190b339fc40692baf8fe5 /src/core
parent8df8a253b13e866dc23fa6f874d23b7150dc1b05 (diff)
Handle content::DropData::file_contents
DropData::file_contents and DropData::file_description_filename are filled by Chromium if the user drags an image from a web page. Write the file's content into a file with the suggested file name in a temporary directory, and set the drop action to "move". This enables users to drag images from the browser to the desktop or a file browser. The file is moved by the client to the target location. The temporary directory is removed when the page is closed. Note that Chrome doesn't use this temporary directory trick, but employs techniques like XDS [1] on Linux to transfer the data via the native clipboard/DnD MIME object. Unfortunately QDrag doesn't support this. Support could be added, but I consider this solution as good enough. [1] https://www.freedesktop.org/wiki/Specifications/XDS/ Task-number: QTBUG-60790 Change-Id: I44f2b3170a124e861ed4131c421903d895b70715 Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'src/core')
-rw-r--r--src/core/web_contents_adapter.cpp36
-rw-r--r--src/core/web_contents_adapter.h2
-rw-r--r--src/core/web_contents_adapter_p.h2
3 files changed, 39 insertions, 1 deletions
diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp
index 8273b247f..9c78d67a0 100644
--- a/src/core/web_contents_adapter.cpp
+++ b/src/core/web_contents_adapter.cpp
@@ -93,6 +93,7 @@
#include <QVariant>
#include <QtCore/qelapsedtimer.h>
#include <QtCore/qmimedata.h>
+#include <QtCore/qtemporarydir.h>
#include <QtGui/qaccessible.h>
#include <QtGui/qdrag.h>
#include <QtGui/qpixmap.h>
@@ -1206,7 +1207,11 @@ void WebContentsAdapter::startDragging(QObject *dragSource, const content::DropD
#endif
});
- drag->setMimeData(mimeDataFromDropData(*d->currentDropData));
+ QMimeData *mimeData = mimeDataFromDropData(*d->currentDropData);
+ if (handleDropDataFileContents(dropData, mimeData))
+ allowedActions = Qt::MoveAction;
+
+ drag->setMimeData(mimeData);
if (!pixmap.isNull()) {
drag->setPixmap(pixmap);
drag->setHotSpot(offset);
@@ -1232,6 +1237,35 @@ void WebContentsAdapter::startDragging(QObject *dragSource, const content::DropD
}
}
+bool WebContentsAdapter::handleDropDataFileContents(const content::DropData &dropData,
+ QMimeData *mimeData)
+{
+ if (dropData.file_contents.empty())
+ return false;
+
+ Q_D(WebContentsAdapter);
+ if (!d->dndTmpDir) {
+ d->dndTmpDir.reset(new QTemporaryDir);
+ if (!d->dndTmpDir->isValid()) {
+ d->dndTmpDir.reset();
+ return false;
+ }
+ }
+
+ const QString &fileName = toQt(dropData.file_description_filename);
+ const QString &filePath = d->dndTmpDir->filePath(fileName);
+ QFile file(filePath);
+ if (!file.open(QIODevice::WriteOnly)) {
+ qWarning("Cannot write temporary file %s.", qUtf8Printable(filePath));
+ return false;
+ }
+ file.write(QByteArray::fromStdString(dropData.file_contents));
+
+ const QUrl &targetUrl = QUrl::fromLocalFile(filePath);
+ mimeData->setUrls(QList<QUrl>{targetUrl});
+ return true;
+}
+
static void fillDropDataFromMimeData(content::DropData *dropData, const QMimeData *mimeData)
{
Q_ASSERT(dropData->filenames.empty());
diff --git a/src/core/web_contents_adapter.h b/src/core/web_contents_adapter.h
index 10c65a6cb..46c8d2604 100644
--- a/src/core/web_contents_adapter.h
+++ b/src/core/web_contents_adapter.h
@@ -58,6 +58,7 @@ QT_BEGIN_NAMESPACE
class QAccessibleInterface;
class QDragEnterEvent;
class QDragMoveEvent;
+class QMimeData;
class QPageLayout;
class QString;
class QWebChannel;
@@ -187,6 +188,7 @@ private:
Q_DISABLE_COPY(WebContentsAdapter)
Q_DECLARE_PRIVATE(WebContentsAdapter)
void waitForUpdateDragActionCalled();
+ bool handleDropDataFileContents(const content::DropData &dropData, QMimeData *mimeData);
QScopedPointer<WebContentsAdapterPrivate> d_ptr;
};
diff --git a/src/core/web_contents_adapter_p.h b/src/core/web_contents_adapter_p.h
index f24070523..94f3ca08b 100644
--- a/src/core/web_contents_adapter_p.h
+++ b/src/core/web_contents_adapter_p.h
@@ -61,6 +61,7 @@
#include <QScopedPointer>
#include <QSharedPointer>
+QT_FORWARD_DECLARE_CLASS(QTemporaryDir)
QT_FORWARD_DECLARE_CLASS(QWebChannel)
class WebEngineContext;
@@ -98,6 +99,7 @@ public:
bool updateDragActionCalled;
gfx::Point lastDragClientPos;
gfx::Point lastDragScreenPos;
+ std::unique_ptr<QTemporaryDir> dndTmpDir;
};
} // namespace QtWebEngineCore