From 43eb77cb0d93020ce7db27fa2ac8dc7ef7738709 Mon Sep 17 00:00:00 2001
From: Tamas Zakor <ztamas@inf.u-szeged.hu>
Date: Tue, 12 Mar 2019 15:59:09 +0100
Subject: [PATCH] Fix qmltests::WebEngineViewSingleFileUpload auto tests

Add scheme checks for FilePickerController::accepted().
A file:// prefix to a file selected here causes chromium to terminate
the render process due to an illegal ipc message.

Extend auto tests with custom Dialog.

Also fix directory upload test.

Change-Id: I8d672e435129d62d268b48c3471b924c0161b44b
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
---
 src/core/file_picker_controller.cpp           |  31 +++--
 tests/auto/quick/qmltests/BLACKLIST           |   9 --
 .../quick/qmltests/data/multifileupload.html  |   2 +-
 .../quick/qmltests/data/singlefileupload.html |   2 +-
 .../quick/qmltests/data/tst_filePicker.qml    | 106 ++++++++++++++++--
 5 files changed, 119 insertions(+), 31 deletions(-)

diff --git a/src/core/file_picker_controller.cpp b/src/core/file_picker_controller.cpp
index 05aed8d2b..3e64afd20 100644
--- a/src/core/file_picker_controller.cpp
+++ b/src/core/file_picker_controller.cpp
@@ -63,24 +63,35 @@ FilePickerController::~FilePickerController() = default;
 
 void FilePickerController::accepted(const QStringList &files)
 {
-    FilePickerController::filesSelectedInChooser(files);
+    QStringList stringList;
+
+    for (const QString &file : files) {
+        if (QDir(file).isAbsolute())
+            stringList.append(file);
+        else
+            qWarning("Ignore invalid item in FilePickerController::accepted(QStringList): %s", qPrintable(file));
+    }
+
+    FilePickerController::filesSelectedInChooser(stringList);
 }
 
 void FilePickerController::accepted(const QVariant &files)
 {
     QStringList stringList;
+    QList<QUrl> urlList = QUrl::fromStringList(files.toStringList());
 
-    if (files.canConvert(QVariant::StringList)) {
-        stringList = files.toStringList();
-    } else if (files.canConvert<QList<QUrl> >()) {
-        const QList<QUrl> urls = files.value<QList<QUrl>>();
-        for (const QUrl &url : urls)
-            stringList.append(url.toLocalFile());
+    if (urlList.isEmpty()) {
+        FilePickerController::accepted(stringList);
     } else {
-        qWarning("An unhandled type '%s' was provided in FilePickerController::accepted(QVariant)", files.typeName());
+        for (const QUrl &url : qAsConst(urlList)) {
+            if (url.isValid() && url.scheme() == "file" && !url.path().isEmpty())
+                stringList.append(url.path());
+            else
+                qWarning("Ignore invalid item in FilePickerController::accepted(QVariant): %s", qPrintable(url.toString()));
+        }
+
+        FilePickerController::accepted(stringList);
     }
-
-    FilePickerController::filesSelectedInChooser(stringList);
 }
 
 void FilePickerController::rejected()
diff --git a/tests/auto/quick/qmltests/BLACKLIST b/tests/auto/quick/qmltests/BLACKLIST
index dfafbaea4..957911c3b 100644
--- a/tests/auto/quick/qmltests/BLACKLIST
+++ b/tests/auto/quick/qmltests/BLACKLIST
@@ -4,15 +4,6 @@ osx
 [WebViewGeopermission::test_geoPermissionRequest]
 osx
 
-[WebEngineViewSingleFileUpload::test_acceptDirectory]
-*
-
-[WebEngineViewSingleFileUpload::test_acceptMultipleFilesSelection]
-*
-
-[WebEngineViewSingleFileUpload::test_acceptSingleFileSelection]
-*
-
 [WebViewFindText::test_findTextInterruptedByLoad]
 *
 
diff --git a/tests/auto/quick/qmltests/data/multifileupload.html b/tests/auto/quick/qmltests/data/multifileupload.html
index 1f788a377..d41ea15c0 100644
--- a/tests/auto/quick/qmltests/data/multifileupload.html
+++ b/tests/auto/quick/qmltests/data/multifileupload.html
@@ -1,7 +1,7 @@
 <html>
 <head>
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
-<title> Mutli-file Upload </title>
+<title> Failed to Upload </title>
 <script src = "./titleupdate.js">
 </script>
 </head>
diff --git a/tests/auto/quick/qmltests/data/singlefileupload.html b/tests/auto/quick/qmltests/data/singlefileupload.html
index 6cfef7ade..ac91c2c0d 100644
--- a/tests/auto/quick/qmltests/data/singlefileupload.html
+++ b/tests/auto/quick/qmltests/data/singlefileupload.html
@@ -1,7 +1,7 @@
 <html>
 <head>
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
-<title> Single File Upload </title>
+<title> Failed to Upload </title>
 <script src = "./titleupdate.js">
 </script>
 </head>
diff --git a/tests/auto/quick/qmltests/data/tst_filePicker.qml b/tests/auto/quick/qmltests/data/tst_filePicker.qml
index 655789bb3..2f813b966 100644
--- a/tests/auto/quick/qmltests/data/tst_filePicker.qml
+++ b/tests/auto/quick/qmltests/data/tst_filePicker.qml
@@ -70,16 +70,61 @@ TestWebEngineView {
             webEngineView.waitForLoadSucceeded()
         }
 
-        function test_acceptSingleFileSelection() {
-            webEngineView.url = Qt.resolvedUrl("singlefileupload.html")
-            verify(webEngineView.waitForLoadSucceeded())
+        function test_acceptSingleFileSelection_data() {
+            return [
+                   { tag: "/test.txt)", input: "/test.txt", passDefaultDialog: false, passCustomDialog: true },
+                   { tag: "/tést.txt", input: "/tést.txt", passDefaultDialog: false, passCustomDialog: true },
+                   { tag: "file:///test.txt", input: "file:///test.txt", passDefaultDialog: true, passCustomDialog: false },
+                   { tag: "file:///tést.txt", input: "file:///tést.txt", passDefaultDialog: true, passCustomDialog: false  },
+                   { tag: "file:///t%C3%A9st.txt", input: "file:///t%C3%A9st.txt", passDefaultDialog: true, passCustomDialog: false },
+                   { tag: "file://test.txt", input: "file://test.txt", passDefaultDialog: false, passCustomDialog: false },
+                   { tag: "file:/test.txt", input: "file:/test.txt", passDefaultDialog: true, passCustomDialog: false },
+                   { tag: "file:test//test.txt", input: "file:test//test.txt", passDefaultDialog: false, passCustomDialog: false },
+                   { tag: "http://test.txt", input: "http://test.txt", passDefaultDialog: false, passCustomDialog: false },
+                   { tag: "qrc:/test.txt", input: "qrc:/test.txt", passDefaultDialog: false, passCustomDialog: false },
+            ];
+        }
 
-            FilePickerParams.selectFiles = true
-            FilePickerParams.selectedFilesUrl.push(Qt.resolvedUrl("test1.html"))
+        function test_acceptSingleFileSelection(row) {
+            var expectedFileName;
 
-            keyPress(Qt.Key_Enter) // Focus is on the button. Open FileDialog.
-            tryCompare(FilePickerParams, "filePickerOpened", true)
-            tryCompare(webEngineView, "title", "test1.html")
+            // Default dialog (expects URL).
+            expectedFileName = "Failed to Upload";
+            if (row.passDefaultDialog)
+                expectedFileName = row.input.slice(row.input.lastIndexOf('/') + 1);
+
+            webEngineView.url = Qt.resolvedUrl("singlefileupload.html");
+            verify(webEngineView.waitForLoadSucceeded());
+
+            FilePickerParams.selectFiles = true;
+            FilePickerParams.selectedFilesUrl.push(row.input);
+
+            keyClick(Qt.Key_Enter); // Focus is on the button. Open FileDialog.
+            tryCompare(FilePickerParams, "filePickerOpened", true);
+            tryCompare(webEngineView, "title", decodeURIComponent(expectedFileName));
+
+
+            // Custom dialog (expects absolute path).
+            var finished = false;
+
+            expectedFileName = "Failed to Upload";
+            if (row.passCustomDialog)
+                expectedFileName = row.input.slice(row.input.lastIndexOf('/') + 1);
+
+            function acceptedFileHandler(request) {
+                request.accepted = true;
+                request.dialogAccept(row.input);
+                finished = true;
+            }
+
+            webEngineView.fileDialogRequested.connect(acceptedFileHandler);
+            webEngineView.url = Qt.resolvedUrl("singlefileupload.html");
+            verify(webEngineView.waitForLoadSucceeded());
+
+            keyClick(Qt.Key_Enter); // Focus is on the button. Open FileDialog.
+            tryVerify(function() { return finished; });
+            tryCompare(webEngineView, "title", expectedFileName);
+            webEngineView.fileDialogRequested.disconnect(acceptedFileHandler);
         }
 
         function test_acceptMultipleFilesSelection() {
@@ -102,9 +147,10 @@ TestWebEngineView {
             FilePickerParams.selectFiles = true
             FilePickerParams.selectedFilesUrl.push(Qt.resolvedUrl("../data"))
 
-            keyPress(Qt.Key_Enter) // Focus is on the button. Open FileDialog.
+            keyClick(Qt.Key_Enter) // Focus is on the button. Open FileDialog.
             tryCompare(FilePickerParams, "filePickerOpened", true)
-            tryCompare(webEngineView, "title", "data")
+            // Check that the title is a file list (eg. "test1.html,test2.html")
+            tryVerify(function() { return webEngineView.title.match("^([^,]+,)+[^,]+$"); })
         }
 
         function test_reject() {
@@ -116,5 +162,45 @@ TestWebEngineView {
             wait(100)
             compare(titleSpy.count, 0)
         }
+
+        function test_acceptMultipleFilesWithCustomDialog_data() {
+            return [
+                   { tag: "path", input: ["/test1.txt", "/test2.txt"], expectedValueForDefaultDialog: "Failed to Upload", expectedValueForCustomDialog: "test1.txt,test2.txt" },
+                   { tag: "file", input: ["file:///test1.txt", "file:///test2.txt"], expectedValueForDefaultDialog: "test1.txt,test2.txt", expectedValueForCustomDialog: "Failed to Upload" },
+                   { tag: "mixed", input: ["file:///test1.txt", "/test2.txt"], expectedValueForDefaultDialog: "test1.txt", expectedValueForCustomDialog: "test2.txt" },
+            ];
+        }
+
+        function test_acceptMultipleFilesWithCustomDialog(row) {
+            // Default dialog (expects URL).
+            webEngineView.url = Qt.resolvedUrl("multifileupload.html");
+            verify(webEngineView.waitForLoadSucceeded());
+
+            FilePickerParams.selectFiles = true;
+            FilePickerParams.selectedFilesUrl = row.input;
+
+            keyClick(Qt.Key_Enter); // Focus is on the button. Open FileDialog.
+            tryCompare(FilePickerParams, "filePickerOpened", true);
+            tryCompare(webEngineView, "title", row.expectedValueForDefaultDialog);
+
+
+            // Custom dialog (expects absolute path).
+            var finished = false;
+
+            function acceptedFileHandler(request) {
+                request.accepted = true;
+                request.dialogAccept(row.input);
+                finished = true;
+            }
+
+            webEngineView.fileDialogRequested.connect(acceptedFileHandler);
+            webEngineView.url = Qt.resolvedUrl("multifileupload.html");
+            verify(webEngineView.waitForLoadSucceeded());
+
+            keyClick(Qt.Key_Enter); // Focus is on the button. Open FileDialog.
+            tryVerify(function() { return finished; });
+            tryCompare(webEngineView, "title", row.expectedValueForCustomDialog);
+            webEngineView.fileDialogRequested.disconnect(acceptedFileHandler);
+        }
     }
 }
-- 
GitLab