summaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
authorSzabolcs David <davidsz@inf.u-szeged.hu>2021-06-11 16:25:20 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2021-07-01 09:53:14 +0000
commitc1b07a71bf594054a014f533153a8d112009c63e (patch)
tree54f9a314124dee669ee35f450beb4341402a8f56 /src/core
parentcaf912cfa4bb5401c26ccd7b56a1126bd7d16d39 (diff)
Implement dialogs of File System Access API
Dialogs triggered by window.showOpenFilePicker() or window.showDirectoryPicker() needed different implementation than regular file picker dialogs. Since the end-users can't distinguish between HTML file picker dialogs and these file system access dialogs, we can just use the existing file picker WebEngine API and UI delegates. Task-number: QTBUG-92519 Change-Id: Ib1624f80603c4042803303274ba45d864ecb371c Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io> (cherry picked from commit 46a2f0f3137dcb46f2752130bbee6438742c27ac) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Diffstat (limited to 'src/core')
-rw-r--r--src/core/CMakeLists.txt1
-rw-r--r--src/core/browser_main_parts_qt.cpp3
-rw-r--r--src/core/content_browser_client_qt.cpp7
-rw-r--r--src/core/content_browser_client_qt.h2
-rw-r--r--src/core/file_picker_controller.cpp66
-rw-r--r--src/core/select_file_dialog_factory_qt.cpp185
-rw-r--r--src/core/select_file_dialog_factory_qt.h87
7 files changed, 331 insertions, 20 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 6c73e694f..e9d34adfb 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -155,6 +155,7 @@ foreach(config ${configs})
request_controller.h
resource_bundle_qt.cpp
resource_context_qt.cpp resource_context_qt.h
+ select_file_dialog_factory_qt.cpp select_file_dialog_factory_qt.h
touch_handle_drawable_client.h
touch_handle_drawable_qt.cpp touch_handle_drawable_qt.h
touch_selection_controller_client_qt.cpp touch_selection_controller_client_qt.h
diff --git a/src/core/browser_main_parts_qt.cpp b/src/core/browser_main_parts_qt.cpp
index bc0499bca..864e96c89 100644
--- a/src/core/browser_main_parts_qt.cpp
+++ b/src/core/browser_main_parts_qt.cpp
@@ -67,6 +67,7 @@
#include "extensions/plugin_service_filter_qt.h"
#include "common/extensions/extensions_client_qt.h"
#endif //BUILDFLAG(ENABLE_EXTENSIONS)
+#include "select_file_dialog_factory_qt.h"
#include "services/service_manager/public/cpp/connector.h"
#include "services/service_manager/public/cpp/service.h"
#include "ui/display/screen.h"
@@ -248,6 +249,8 @@ void BrowserMainPartsQt::PreMainMessageLoopStart()
void BrowserMainPartsQt::PreMainMessageLoopRun()
{
+ ui::SelectFileDialog::SetFactory(new SelectFileDialogFactoryQt());
+
#if BUILDFLAG(ENABLE_EXTENSIONS)
extensions::ExtensionsClient::Set(new extensions::ExtensionsClientQt());
extensions::ExtensionsBrowserClient::Set(new extensions::ExtensionsBrowserClientQt());
diff --git a/src/core/content_browser_client_qt.cpp b/src/core/content_browser_client_qt.cpp
index fdcd98024..f17bc5025 100644
--- a/src/core/content_browser_client_qt.cpp
+++ b/src/core/content_browser_client_qt.cpp
@@ -106,6 +106,7 @@
#include "profile_io_data_qt.h"
#include "quota_permission_context_qt.h"
#include "renderer_host/user_resource_controller_host.h"
+#include "select_file_dialog_factory_qt.h"
#include "type_conversion.h"
#include "web_contents_adapter_client.h"
#include "web_contents_adapter.h"
@@ -391,6 +392,12 @@ void ContentBrowserClientQt::GetAdditionalAllowedSchemesForFileSystem(std::vecto
additional_schemes->push_back(content::kChromeUIScheme);
}
+std::unique_ptr<ui::SelectFilePolicy>
+ContentBrowserClientQt::CreateSelectFilePolicy(content::WebContents *web_contents)
+{
+ return std::make_unique<SelectFilePolicyQt>(web_contents);
+}
+
#if defined(Q_OS_LINUX)
void ContentBrowserClientQt::GetAdditionalMappedFilesForChildProcess(const base::CommandLine& command_line, int child_process_id, content::PosixFileDescriptorInfo* mappings)
{
diff --git a/src/core/content_browser_client_qt.h b/src/core/content_browser_client_qt.h
index bac155c8c..1abb4a69f 100644
--- a/src/core/content_browser_client_qt.h
+++ b/src/core/content_browser_client_qt.h
@@ -103,6 +103,8 @@ public:
void GetAdditionalWebUISchemes(std::vector<std::string>* additional_schemes) override;
void GetAdditionalAllowedSchemesForFileSystem(std::vector<std::string>* additional_schemes) override;
+ std::unique_ptr<ui::SelectFilePolicy>
+ CreateSelectFilePolicy(content::WebContents *web_contents) override;
void BindHostReceiverForRenderer(content::RenderProcessHost *render_process_host,
mojo::GenericPendingReceiver receiver) override;
void RegisterBrowserInterfaceBindersForFrame(content::RenderFrameHost *render_frame_host,
diff --git a/src/core/file_picker_controller.cpp b/src/core/file_picker_controller.cpp
index 1494d8aae..537a01508 100644
--- a/src/core/file_picker_controller.cpp
+++ b/src/core/file_picker_controller.cpp
@@ -44,6 +44,7 @@
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/file_select_listener.h"
+#include "ui/shell_dialogs/select_file_dialog.h"
#include <QtCore/qcoreapplication.h>
#include <QDir>
@@ -57,7 +58,8 @@ namespace QtWebEngineCore {
class FilePickerControllerPrivate {
public:
FilePickerController::FileChooserMode mode;
- scoped_refptr<content::FileSelectListener> listener;
+ scoped_refptr<content::FileSelectListener> fileDialogListener;
+ ui::SelectFileDialog::Listener *fileSystemAccessDialogListener;
QString defaultFileName;
QStringList acceptedMimeTypes;
};
@@ -66,7 +68,19 @@ FilePickerController *createFilePickerController(
FilePickerController::FileChooserMode mode, scoped_refptr<content::FileSelectListener> listener,
const QString &defaultFileName, const QStringList &acceptedMimeTypes, QObject *parent = nullptr)
{
- auto priv = new FilePickerControllerPrivate{mode, listener, defaultFileName, acceptedMimeTypes};
+ auto priv = new FilePickerControllerPrivate { mode, listener, nullptr, defaultFileName,
+ acceptedMimeTypes };
+ return new FilePickerController(priv, parent);
+}
+
+FilePickerController *createFilePickerController(FilePickerController::FileChooserMode mode,
+ ui::SelectFileDialog::Listener *listener,
+ const QString &defaultFileName,
+ const QStringList &acceptedMimeTypes,
+ QObject *parent = nullptr)
+{
+ auto priv = new FilePickerControllerPrivate { mode, nullptr, listener, defaultFileName,
+ acceptedMimeTypes };
return new FilePickerController(priv, parent);
}
@@ -194,27 +208,39 @@ ASSERT_ENUMS_MATCH(FilePickerController::Save, blink::mojom::FileChooserParams_M
void FilePickerController::filesSelectedInChooser(const QStringList &filesList)
{
- QStringList files(filesList);
- base::FilePath baseDir;
- if (d_ptr->mode == UploadFolder && !filesList.isEmpty()
+ if (d_ptr->fileDialogListener) {
+ QStringList files(filesList);
+ base::FilePath baseDir;
+ if (d_ptr->mode == UploadFolder && !filesList.isEmpty()
&& QFileInfo(filesList.first()).isDir()) {
- // Enumerate the directory
- files = listRecursively(QDir(filesList.first()));
- baseDir = toFilePath(filesList.first());
- }
+ // Enumerate the directory
+ files = listRecursively(QDir(filesList.first()));
+ baseDir = toFilePath(filesList.first());
+ }
- std::vector<blink::mojom::FileChooserFileInfoPtr> chooser_files;
- for (const auto &file : qAsConst(files)) {
- chooser_files.push_back(blink::mojom::FileChooserFileInfo::NewNativeFile(
- blink::mojom::NativeFileInfo::New(toFilePath(file), base::string16())));
- }
+ std::vector<blink::mojom::FileChooserFileInfoPtr> chooser_files;
+ for (const auto &file : qAsConst(files)) {
+ chooser_files.push_back(blink::mojom::FileChooserFileInfo::NewNativeFile(
+ blink::mojom::NativeFileInfo::New(toFilePath(file), base::string16())));
+ }
- if (files.isEmpty())
- d_ptr->listener->FileSelectionCanceled();
- else
- d_ptr->listener->FileSelected(std::move(chooser_files),
- baseDir,
- static_cast<blink::mojom::FileChooserParams::Mode>(d_ptr->mode));
+ if (files.isEmpty())
+ d_ptr->fileDialogListener->FileSelectionCanceled();
+ else
+ d_ptr->fileDialogListener->FileSelected(
+ std::move(chooser_files), baseDir,
+ static_cast<blink::mojom::FileChooserParams::Mode>(d_ptr->mode));
+ } else if (d_ptr->fileSystemAccessDialogListener) {
+ std::vector<base::FilePath> files;
+ for (const auto &file : qAsConst(filesList)) {
+ files.push_back(toFilePath(file));
+ }
+
+ if (files.empty())
+ d_ptr->fileSystemAccessDialogListener->FileSelectionCanceled(nullptr);
+ else
+ d_ptr->fileSystemAccessDialogListener->MultiFilesSelected(files, nullptr);
+ }
}
QStringList FilePickerController::acceptedMimeTypes() const
diff --git a/src/core/select_file_dialog_factory_qt.cpp b/src/core/select_file_dialog_factory_qt.cpp
new file mode 100644
index 000000000..baad07b24
--- /dev/null
+++ b/src/core/select_file_dialog_factory_qt.cpp
@@ -0,0 +1,185 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/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.LGPL3 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-3.0.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 (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "select_file_dialog_factory_qt.h"
+
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "file_picker_controller.h"
+#include "type_conversion.h"
+#include "ui/shell_dialogs/select_file_dialog.h"
+#include "web_contents_adapter_client.h"
+#include "web_contents_view_qt.h"
+
+#include <QSharedPointer>
+#include <QTimer>
+
+namespace QtWebEngineCore {
+
+SelectFilePolicyQt::SelectFilePolicyQt(content::WebContents *source_contents)
+ : m_webContents(source_contents)
+{
+}
+
+SelectFilePolicyQt::~SelectFilePolicyQt() { }
+
+bool SelectFilePolicyQt::CanOpenSelectFileDialog()
+{
+ return true;
+}
+
+void SelectFilePolicyQt::SelectFileDenied() { }
+
+content::WebContents *SelectFilePolicyQt::webContents()
+{
+ return m_webContents;
+}
+
+static FilePickerController::FileChooserMode toFileChooserMode(ui::SelectFileDialog::Type type)
+{
+ switch (type) {
+ case ui::SelectFileDialog::Type::SELECT_FOLDER:
+ case ui::SelectFileDialog::Type::SELECT_UPLOAD_FOLDER:
+ case ui::SelectFileDialog::Type::SELECT_EXISTING_FOLDER:
+ return FilePickerController::FileChooserMode::UploadFolder;
+ case ui::SelectFileDialog::Type::SELECT_SAVEAS_FILE:
+ return FilePickerController::FileChooserMode::Save;
+ case ui::SelectFileDialog::Type::SELECT_OPEN_FILE:
+ return FilePickerController::FileChooserMode::Open;
+ case ui::SelectFileDialog::Type::SELECT_OPEN_MULTI_FILE:
+ case ui::SelectFileDialog::Type::SELECT_NONE:
+ default:
+ return FilePickerController::FileChooserMode::OpenMultiple;
+ break;
+ }
+}
+
+class SelectFileDialogQt : public ui::SelectFileDialog
+{
+public:
+ SelectFileDialogQt(Listener *, std::unique_ptr<ui::SelectFilePolicy>,
+ WebContentsAdapterClient *);
+
+ // ui::SelectFileDialog implementation:
+ bool IsRunning(gfx::NativeWindow) const override;
+ void ListenerDestroyed() override;
+ void SelectFileImpl(Type type, const base::string16 &title, const base::FilePath &default_path,
+ const FileTypeInfo *file_types, int file_type_index,
+ const base::FilePath::StringType &default_extension,
+ gfx::NativeWindow owning_window, void *params) override;
+ bool HasMultipleFileTypeChoicesImpl() override;
+
+private:
+ WebContentsAdapterClient *m_client;
+ QSharedPointer<FilePickerController> m_filePickerController;
+
+ DISALLOW_COPY_AND_ASSIGN(SelectFileDialogQt);
+};
+
+SelectFileDialogQt::SelectFileDialogQt(Listener *listener,
+ std::unique_ptr<ui::SelectFilePolicy> policy,
+ WebContentsAdapterClient *client)
+ : SelectFileDialog(listener, std::move(policy)), m_client(client)
+{
+}
+
+bool SelectFileDialogQt::IsRunning(gfx::NativeWindow) const
+{
+ return listener_;
+}
+
+void SelectFileDialogQt::ListenerDestroyed()
+{
+ listener_ = nullptr;
+}
+
+bool SelectFileDialogQt::HasMultipleFileTypeChoicesImpl()
+{
+ return false;
+}
+
+extern FilePickerController *createFilePickerController(FilePickerController::FileChooserMode mode,
+ ui::SelectFileDialog::Listener *listener,
+ const QString &defaultFileName,
+ const QStringList &acceptedMimeTypes,
+ QObject *parent = nullptr);
+
+void SelectFileDialogQt::SelectFileImpl(Type type, const base::string16 &title,
+ const base::FilePath &default_path,
+ const FileTypeInfo *file_types, int file_type_index,
+ const base::FilePath::StringType &default_extension,
+ gfx::NativeWindow owning_window, void *params)
+{
+ Q_UNUSED(title);
+ Q_UNUSED(file_type_index);
+ Q_UNUSED(default_extension);
+ Q_UNUSED(owning_window);
+ Q_UNUSED(params);
+
+ QStringList acceptedSuffixes;
+ if (file_types) {
+ for (const auto &type : file_types->extensions) {
+ for (const auto &extension : type)
+ acceptedSuffixes.append("." + toQt(extension));
+ }
+ }
+
+ m_filePickerController.reset(createFilePickerController(
+ toFileChooserMode(type), listener_, toQt(default_path.value()), acceptedSuffixes));
+ QTimer::singleShot(0, [this]() { m_client->runFileChooser(m_filePickerController); });
+}
+
+SelectFileDialogFactoryQt::SelectFileDialogFactoryQt() = default;
+
+SelectFileDialogFactoryQt::~SelectFileDialogFactoryQt() = default;
+
+ui::SelectFileDialog *
+SelectFileDialogFactoryQt::Create(ui::SelectFileDialog::Listener *listener,
+ std::unique_ptr<ui::SelectFilePolicy> policy)
+{
+ content::WebContents *webContents =
+ static_cast<SelectFilePolicyQt *>(policy.get())->webContents();
+ WebContentsAdapterClient *client =
+ WebContentsViewQt::from(static_cast<content::WebContentsImpl *>(webContents)->GetView())
+ ->client();
+ if (!client)
+ return nullptr;
+ return new SelectFileDialogQt(listener, std::move(policy), client);
+}
+
+} // namespace QtWebEngineCore
diff --git a/src/core/select_file_dialog_factory_qt.h b/src/core/select_file_dialog_factory_qt.h
new file mode 100644
index 000000000..572bf217f
--- /dev/null
+++ b/src/core/select_file_dialog_factory_qt.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/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.LGPL3 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-3.0.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 (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SELECT_FILE_DIALOG_FACTORY_QT_H_
+#define SELECT_FILE_DIALOG_FACTORY_QT_H_
+
+#include "ui/shell_dialogs/select_file_dialog_factory.h"
+#include "ui/shell_dialogs/select_file_policy.h"
+
+namespace content {
+class WebContents;
+}
+
+namespace QtWebEngineCore {
+
+class SelectFilePolicyQt : public ui::SelectFilePolicy
+{
+public:
+ explicit SelectFilePolicyQt(content::WebContents *source_contents);
+ ~SelectFilePolicyQt() override;
+
+ // Overridden from ui::SelectFilePolicy:
+ bool CanOpenSelectFileDialog() override;
+ void SelectFileDenied() override;
+
+ content::WebContents *webContents();
+
+private:
+ content::WebContents *m_webContents;
+
+ DISALLOW_COPY_AND_ASSIGN(SelectFilePolicyQt);
+};
+
+// Implements a file Open / Save dialog for File System Access API.
+class SelectFileDialogFactoryQt : public ui::SelectFileDialogFactory
+{
+public:
+ SelectFileDialogFactoryQt();
+ ~SelectFileDialogFactoryQt() override;
+
+ // Overridden from ui::SelectFileDialogFactory:
+ ui::SelectFileDialog *Create(ui::SelectFileDialog::Listener *listener,
+ std::unique_ptr<ui::SelectFilePolicy> policy) override;
+
+private:
+ DISALLOW_COPY_AND_ASSIGN(SelectFileDialogFactoryQt);
+};
+
+} // namespace QtWebEngineCore
+
+#endif // SELECT_FILE_DIALOG_FACTORY_QT_H_