summaryrefslogtreecommitdiffstats
path: root/tests/manual/widgets
diff options
context:
space:
mode:
Diffstat (limited to 'tests/manual/widgets')
-rw-r--r--tests/manual/widgets/CMakeLists.txt3
-rw-r--r--tests/manual/widgets/extensions/CMakeLists.txt24
-rw-r--r--tests/manual/widgets/extensions/main.cpp287
3 files changed, 314 insertions, 0 deletions
diff --git a/tests/manual/widgets/CMakeLists.txt b/tests/manual/widgets/CMakeLists.txt
index 94ee1c138..6d6555d83 100644
--- a/tests/manual/widgets/CMakeLists.txt
+++ b/tests/manual/widgets/CMakeLists.txt
@@ -8,3 +8,6 @@ endif()
if(TARGET Qt6::HttpServer)
add_subdirectory(webrtc)
endif()
+if(QT_FEATURE_webengine_extensions)
+ add_subdirectory(extensions)
+endif()
diff --git a/tests/manual/widgets/extensions/CMakeLists.txt b/tests/manual/widgets/extensions/CMakeLists.txt
new file mode 100644
index 000000000..a2d916f1f
--- /dev/null
+++ b/tests/manual/widgets/extensions/CMakeLists.txt
@@ -0,0 +1,24 @@
+# Copyright (C) 2025 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(extensions LANGUAGES CXX)
+ find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ endif()
+
+qt_internal_add_manual_test(extensions
+ SOURCES
+ main.cpp
+)
+
+set_target_properties(extensions PROPERTIES
+ WIN32_EXECUTABLE TRUE
+ MACOSX_BUNDLE TRUE
+)
+
+target_link_libraries(extensions PUBLIC
+ Qt::Core
+ Qt::Gui
+ Qt::WebEngineWidgets
+)
diff --git a/tests/manual/widgets/extensions/main.cpp b/tests/manual/widgets/extensions/main.cpp
new file mode 100644
index 000000000..938bf1fab
--- /dev/null
+++ b/tests/manual/widgets/extensions/main.cpp
@@ -0,0 +1,287 @@
+// Copyright (C) 2025 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <QAbstractListModel>
+#include <QApplication>
+#include <QDirListing>
+#include <QFileDialog>
+#include <QHBoxLayout>
+#include <QListView>
+#include <QMainWindow>
+#include <QMessageBox>
+#include <QPushButton>
+#include <QTemporaryDir>
+#include <QTimer>
+#include <QWebEngineProfileBuilder>
+#include <QWebEngineView>
+#include <QWebEngineProfile>
+#include <QWidget>
+
+#include <QWebEngineExtensionManager>
+#include <QWebEngineExtensionInfo>
+
+// Test for extension management APIs using QWebEngineExtensionManager
+// and QWebEngineExtensionInfo
+
+class ExtensionsListModel : public QAbstractListModel
+{
+public:
+ ExtensionsListModel(const QList<QWebEngineExtensionInfo> &extensions)
+ : m_extensionsList(std::move(extensions))
+ {
+ }
+
+ int rowCount(const QModelIndex &parent = QModelIndex()) const override
+ {
+ Q_UNUSED(parent)
+ return m_extensionsList.count();
+ }
+
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override
+ {
+ if (!index.isValid())
+ return QVariant();
+ switch (role) {
+ case Qt::DisplayRole: {
+ auto extension = m_extensionsList.at(index.row());
+ QString enabled = extension.isEnabled() ? " enabled" : " disabled";
+ return extension.name() + enabled + "\nId: " + extension.id()
+ + "\npath: " + extension.path();
+ }
+ case Qt::UserRole: {
+ QWebEngineExtensionInfo extension = m_extensionsList.at(index.row());
+ return QVariant::fromValue(extension);
+ }
+ default:
+ break;
+ }
+ return QVariant();
+ }
+
+private:
+ QList<QWebEngineExtensionInfo> m_extensionsList;
+};
+
+class ExtensionsWidget : public QWidget
+{
+public:
+ ExtensionsWidget(QWebEngineProfile *profile, QWebEngineExtensionManager *manager)
+ : m_profile(profile), m_extensionManager(manager)
+ {
+ update();
+
+ setLayout(new QVBoxLayout);
+ m_extensionsView.setSpacing(2);
+ m_extensionsView.setWrapping(true);
+ layout()->addWidget(&m_extensionsView);
+
+ auto *actionsBtn = new QPushButton("open actions menu");
+ QObject::connect(actionsBtn, &QPushButton::clicked, this,
+ &ExtensionsWidget::openActionsMenu);
+ layout()->addWidget(actionsBtn);
+
+ auto *enabeBtn = new QPushButton("enable selected");
+ QObject::connect(enabeBtn, &QPushButton::clicked, this, &ExtensionsWidget::enable);
+ layout()->addWidget(enabeBtn);
+
+ auto *disableBtn = new QPushButton("disable selected");
+ QObject::connect(disableBtn, &QPushButton::clicked, this, &ExtensionsWidget::disable);
+ layout()->addWidget(disableBtn);
+
+ auto *loadBtn = new QPushButton("load unpacked");
+ QObject::connect(loadBtn, &QPushButton::clicked, this, &ExtensionsWidget::loadUnpacked);
+ layout()->addWidget(loadBtn);
+
+ auto *installBtn = new QPushButton("install packed");
+ QObject::connect(installBtn, &QPushButton::clicked, this, [this]() { install(true); });
+ layout()->addWidget(installBtn);
+
+ auto *installUnpackedBtn = new QPushButton("install unpacked");
+ QObject::connect(installUnpackedBtn, &QPushButton::clicked, this,
+ [this]() { install(false); });
+ layout()->addWidget(installUnpackedBtn);
+
+ auto *unLoadBtn = new QPushButton("unload");
+ QObject::connect(unLoadBtn, &QPushButton::clicked, this, &ExtensionsWidget::unload);
+ layout()->addWidget(unLoadBtn);
+
+ auto *uninstallBtn = new QPushButton("uninstall");
+ QObject::connect(uninstallBtn, &QPushButton::clicked, this, &ExtensionsWidget::uninstall);
+ layout()->addWidget(uninstallBtn);
+
+ QObject::connect(m_extensionManager, &QWebEngineExtensionManager::extensionLoadFinished,
+ [this](QWebEngineExtensionInfo extension) {
+ if (!extension.isLoaded()) {
+ showInfoDialog("Failed to load extension\n\nFile:"
+ + extension.path()
+ + "\nError: " + extension.error());
+ return;
+ }
+ m_extensionManager->setExtensionEnabled(extension, true);
+ showInfoDialog("Extension loaded\n\nName:" + extension.name()
+ + "\nFile: " + extension.path());
+ update();
+ });
+
+ QObject::connect(m_extensionManager, &QWebEngineExtensionManager::extensionInstallFinished,
+ [this](QWebEngineExtensionInfo extension) {
+ if (!extension.isInstalled()) {
+ showInfoDialog("Failed to install extension\n\nFile: "
+ + extension.path()
+ + "\nError: " + extension.error());
+ return;
+ }
+ showInfoDialog("Extension installed\n\nName:" + extension.name()
+ + "\nFile: " + extension.path());
+ m_extensionManager->setExtensionEnabled(extension, true);
+ update();
+ });
+ QObject::connect(m_extensionManager, &QWebEngineExtensionManager::extensionUnloadFinished,
+ [this](QWebEngineExtensionInfo extension) {
+ if (!extension.error().isEmpty()) {
+ showInfoDialog("Failed to unload " + extension.name()
+ + "\n\nFile: " + extension.path()
+ + "\nError: " + extension.error());
+ return;
+ }
+ showInfoDialog("Extension unloaded\n\nName: " + extension.name()
+ + "\nFile: " + extension.path());
+ update();
+ });
+ QObject::connect(
+ m_extensionManager, &QWebEngineExtensionManager::extensionUninstallFinished,
+ [this](QWebEngineExtensionInfo extension) {
+ if (!extension.error().isEmpty()) {
+ showInfoDialog("Failed to uninstall " + extension.name() + "\n\nFile: "
+ + extension.path() + "\nError: " + extension.error());
+ return;
+ }
+ showInfoDialog("Extension uninstalled\n\nName: " + extension.name()
+ + "\nFile: " + extension.path());
+ update();
+ });
+ }
+
+private:
+ void update()
+ {
+ auto *oldModel = m_extensionsView.selectionModel();
+ m_extensionsView.setModel(
+ new ExtensionsListModel(std::move(m_extensionManager->extensions())));
+ if (oldModel)
+ delete oldModel;
+ }
+
+ QWebEngineExtensionInfo getSelectedExtension()
+ {
+ QModelIndex idx = m_extensionsView.currentIndex();
+ QVariant var = m_extensionsView.model()->data(idx, Qt::UserRole);
+ QWebEngineExtensionInfo extension = var.value<QWebEngineExtensionInfo>();
+ return extension;
+ }
+
+ void enable()
+ {
+ m_extensionManager->setExtensionEnabled(getSelectedExtension(), true);
+ update();
+ }
+
+ void disable()
+ {
+ m_extensionManager->setExtensionEnabled(getSelectedExtension(), false);
+ update();
+ }
+
+ void loadUnpacked()
+ {
+ QFileDialog dialog(this);
+ dialog.setFileMode(QFileDialog::Directory);
+ if (dialog.exec())
+ m_extensionManager->loadExtension(dialog.selectedFiles()[0]);
+ }
+
+ void install(bool packed)
+ {
+ QFileDialog dialog(this);
+ if (packed) {
+ dialog.setFileMode(QFileDialog::ExistingFile);
+ dialog.setNameFilter("Extensions(*.zip)");
+ } else {
+ dialog.setFileMode(QFileDialog::Directory);
+ }
+ if (dialog.exec())
+ m_extensionManager->installExtension(dialog.selectedFiles()[0]);
+ }
+
+ void unload()
+ {
+ m_extensionManager->unloadExtension(getSelectedExtension());
+ update();
+ }
+
+ void uninstall()
+ {
+ m_extensionManager->uninstallExtension(getSelectedExtension());
+ update();
+ }
+
+ void openActionsMenu()
+ {
+ const auto url = getSelectedExtension().actionPopupUrl();
+ if (url.isEmpty()) {
+ showInfoDialog("No popup page set for this extension");
+ return;
+ }
+
+ auto *view = new QWebEngineView(m_profile);
+ view->setAttribute(Qt::WA_DeleteOnClose, true);
+ view->load(url);
+ view->show();
+ }
+
+ void showInfoDialog(const QString &msg)
+ {
+ QMessageBox *msgBox = new QMessageBox;
+ msgBox->setWindowModality(Qt::NonModal);
+ msgBox->setWindowFlags(Qt::FramelessWindowHint | Qt::Dialog);
+ msgBox->setAttribute(Qt::WA_DeleteOnClose, true);
+ msgBox->resize(400, 100);
+ msgBox->setText(msg);
+ QTimer::singleShot(4000, msgBox, &QMessageBox::close);
+ msgBox->show();
+ }
+
+ QWebEngineProfile *m_profile;
+ QWebEngineExtensionManager *m_extensionManager;
+ QListView m_extensionsView;
+};
+
+int main(int argc, char *argv[])
+{
+ QCoreApplication::setOrganizationName("QtExamples");
+ QApplication app(argc, argv);
+ QMainWindow window;
+ window.setCentralWidget(new QWidget);
+
+ auto *layout = new QHBoxLayout;
+ window.centralWidget()->setLayout(layout);
+
+ QTemporaryDir tempDir;
+ QWebEngineProfileBuilder profileBuilder;
+ QWebEngineProfile *profile = profileBuilder.createProfile("ExtensionsManualTest");
+
+ auto *extensionManager = profile->extensionManager();
+ qDebug() << "installDir" << extensionManager->installDirectory();
+
+ QWebEngineView view(profile);
+ view.setUrl(QUrl(QStringLiteral("https://www.google.com/")));
+ view.resize(1024, 750);
+
+ window.centralWidget()->layout()->addWidget(&view);
+ window.centralWidget()->layout()->addWidget(
+ new ExtensionsWidget(profile, extensionManager));
+
+ window.show();
+
+ return app.exec();
+}