From d0035fea1417c49239549e759f132e8f512d3c44 Mon Sep 17 00:00:00 2001 From: trafalgar Date: Sun, 18 Aug 2024 21:29:04 +0800 Subject: [PATCH 1/2] feat: expose onJsDialog --- include/QCefView.h | 31 ++++++++++++++++ src/QCefView.cpp | 36 ++++++++++++++++++ src/details/CCefClientDelegate.h | 8 ++++ .../CCefClientDelegate_JSDialogHandler.cpp | 37 +++++++++++++++++++ src/details/QCefViewPrivate.cpp | 26 +++++++++++++ src/details/QCefViewPrivate.h | 7 ++++ 6 files changed, 145 insertions(+) create mode 100644 src/details/CCefClientDelegate_JSDialogHandler.cpp diff --git a/include/QCefView.h b/include/QCefView.h index 7256ed1c..6a406d10 100644 --- a/include/QCefView.h +++ b/include/QCefView.h @@ -59,6 +59,17 @@ class QCEFVIEW_EXPORT QCefView : public QWidget }; Q_ENUM(CefWindowOpenDisposition) + /// + /// Represents the CEF javascript dialog type + /// + enum CefJsDialogType + { + JSDIALOGTYPE_ALERT = 0, + JSDIALOGTYPE_CONFIRM, + JSDIALOGTYPE_PROMPT, + }; + Q_ENUM(CefJsDialogType) + public: /// /// Constructs a QCefView instance @@ -269,6 +280,26 @@ class QCEFVIEW_EXPORT QCefView : public QWidget /// True to enable; otherwise false bool isDragAndDropEnabled() const; + /// + /// Handles custom JavaScript dialogs + /// + /// The URL of the page that triggered the dialog + /// The type of the JavaScript dialog (alert, confirm, prompt) + /// The message to be displayed in the dialog + /// The default text for the prompt dialog + /// Set to true to suppress the dialog + /// A pair containing the result of the dialog and the user input + /// + /// This function is called when a JavaScript dialog is triggered. It allows for custom handling of the dialog, + /// including modifying the message, suppressing the dialog, and providing a custom result. + /// + bool onJsDialog(const QString& originUrl, + QCefView::CefJsDialogType dialogType, + const QString& messageText, + const QString& defaultPromptText, + bool& suppressMessage, + QPair& callbackResult); + signals: /// /// Gets called on loading state changed diff --git a/src/QCefView.cpp b/src/QCefView.cpp index c815ff27..a4fd0f7f 100644 --- a/src/QCefView.cpp +++ b/src/QCefView.cpp @@ -1,6 +1,8 @@ #include #pragma region qt_headers +#include +#include #include #include #include @@ -327,6 +329,40 @@ QCefView::onRequestCloseFromWeb() return true; } +bool +QCefView::onJsDialog(const QString& originUrl, + QCefView::CefJsDialogType dialogType, + const QString& messageText, + const QString& defaultPromptText, + bool& suppressMessage, + QPair& callbackResult) +{ + suppressMessage = false; + + QMessageBox::StandardButton button = QMessageBox::NoButton; + if (dialogType == QCefView::CefJsDialogType::JSDIALOGTYPE_ALERT) { + button = QMessageBox::warning(this, "Alert", messageText); + callbackResult.first = true; + callbackResult.second = ""; + } else if (dialogType == QCefView::CefJsDialogType::JSDIALOGTYPE_CONFIRM) { + button = QMessageBox::question(this, "Confirm", messageText, QMessageBox::Yes | QMessageBox::No); + callbackResult.first = button == QMessageBox::Yes; + callbackResult.second = ""; + } else if (dialogType == QCefView::CefJsDialogType::JSDIALOGTYPE_PROMPT) { + bool ok = false; + QString text = QInputDialog::getText(this, "Prompt", messageText, QLineEdit::Normal, defaultPromptText, &ok); + if (ok) { + callbackResult.first = true; + callbackResult.second = text; + } else { + callbackResult.first = false; + callbackResult.second = ""; + } + } + + return true; +} + void QCefView::leaveEvent(QEvent* event) { diff --git a/src/details/CCefClientDelegate.h b/src/details/CCefClientDelegate.h index 77c6ece0..a8d9e6ae 100644 --- a/src/details/CCefClientDelegate.h +++ b/src/details/CCefClientDelegate.h @@ -94,6 +94,14 @@ class CCefClientDelegate #endif CefRefPtr callback) override; + virtual bool OnJSDialog(CefRefPtr browser, + const CefString& origin_url, + CefJSDialogHandler::JSDialogType dialog_type, + const CefString& message_text, + const CefString& default_prompt_text, + CefRefPtr callback, + bool& suppress_message) override; + // DisplayHandler virtual void addressChanged(CefRefPtr& browser, int64_t frameId, const std::string& url) override; virtual void titleChanged(CefRefPtr& browser, const std::string& title) override; diff --git a/src/details/CCefClientDelegate_JSDialogHandler.cpp b/src/details/CCefClientDelegate_JSDialogHandler.cpp new file mode 100644 index 00000000..16def437 --- /dev/null +++ b/src/details/CCefClientDelegate_JSDialogHandler.cpp @@ -0,0 +1,37 @@ +#include "CCefClientDelegate.h" + +#include +#include +#include + +#include "QCefViewPrivate.h" +#include "utils/CommonUtils.h" +#include "utils/ValueConvertor.h" + +bool +CCefClientDelegate::OnJSDialog(CefRefPtr browser, + const CefString& origin_url, + CefJSDialogHandler::JSDialogType dialog_type, + const CefString& message_text, + const CefString& default_prompt_text, + CefRefPtr callback, + bool& suppress_message) + +{ + bool ret = false; + + QString originUrl = QString::fromStdString(origin_url.ToString()); + QString messageText = QString::fromStdString(message_text.ToString()); + QString defaultPromptText = QString::fromStdString(default_prompt_text.ToString()); + + Qt::ConnectionType c = + pCefViewPrivate_->q_ptr->thread() == QThread::currentThread() ? Qt::DirectConnection : Qt::BlockingQueuedConnection; + QMetaObject::invokeMethod( + pCefViewPrivate_, + [&]() { + ret = pCefViewPrivate_->onJsDialog( + originUrl, dialog_type, messageText, defaultPromptText, callback, suppress_message); + }, + c); + return ret; +} diff --git a/src/details/QCefViewPrivate.cpp b/src/details/QCefViewPrivate.cpp index 18804104..38873faa 100644 --- a/src/details/QCefViewPrivate.cpp +++ b/src/details/QCefViewPrivate.cpp @@ -615,6 +615,32 @@ QCefViewPrivate::onCefContextMenuDismissed() osr.contextMenuCallback_ = nullptr; } +bool +QCefViewPrivate::onJsDialog(const QString& origin_url, + int dialog_type, + const QString& message_text, + const QString& default_prompt_text, + CefRefPtr callback, + bool& suppress_message) +{ + Q_Q(QCefView); + + bool ret = false; + + QPair callbackResult; + + ret = q->onJsDialog(origin_url, + (QCefView::CefJsDialogType)dialog_type, + message_text, + default_prompt_text, + suppress_message, + callbackResult); + + callback->Continue(callbackResult.first, callbackResult.second.toStdString()); + + return ret; +} + void QCefViewPrivate::onFileDialog(CefBrowserHost::FileDialogMode mode, const CefString& title, diff --git a/src/details/QCefViewPrivate.h b/src/details/QCefViewPrivate.h index e09b88e2..b5837ab5 100644 --- a/src/details/QCefViewPrivate.h +++ b/src/details/QCefViewPrivate.h @@ -236,6 +236,13 @@ public slots: void onContextMenuDestroyed(QObject* obj); + bool onJsDialog(const QString& origin_url, + int dialog_type, + const QString& message_text, + const QString& default_prompt_text, + CefRefPtr callback, + bool& suppress_message); + signals: void updateOsrFrame(); From 8cbd09afd564a550bee8a641caf6b8ca3e3417c9 Mon Sep 17 00:00:00 2001 From: trafalgar Date: Thu, 22 Aug 2024 02:09:11 +0800 Subject: [PATCH 2/2] rename CefJsDialogType enum value --- include/QCefView.h | 6 +++--- src/QCefView.cpp | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/QCefView.h b/include/QCefView.h index 6a406d10..3469d1d8 100644 --- a/include/QCefView.h +++ b/include/QCefView.h @@ -64,9 +64,9 @@ class QCEFVIEW_EXPORT QCefView : public QWidget /// enum CefJsDialogType { - JSDIALOGTYPE_ALERT = 0, - JSDIALOGTYPE_CONFIRM, - JSDIALOGTYPE_PROMPT, + CefJsDialogTypeAlert = 0, + CefJsDialogTypeConfirm, + CefJsDialogTypePrompt }; Q_ENUM(CefJsDialogType) diff --git a/src/QCefView.cpp b/src/QCefView.cpp index a4fd0f7f..b7e7cbbc 100644 --- a/src/QCefView.cpp +++ b/src/QCefView.cpp @@ -340,15 +340,15 @@ QCefView::onJsDialog(const QString& originUrl, suppressMessage = false; QMessageBox::StandardButton button = QMessageBox::NoButton; - if (dialogType == QCefView::CefJsDialogType::JSDIALOGTYPE_ALERT) { + if (dialogType == QCefView::CefJsDialogType::CefJsDialogTypeAlert) { button = QMessageBox::warning(this, "Alert", messageText); callbackResult.first = true; callbackResult.second = ""; - } else if (dialogType == QCefView::CefJsDialogType::JSDIALOGTYPE_CONFIRM) { + } else if (dialogType == QCefView::CefJsDialogType::CefJsDialogTypeConfirm) { button = QMessageBox::question(this, "Confirm", messageText, QMessageBox::Yes | QMessageBox::No); callbackResult.first = button == QMessageBox::Yes; callbackResult.second = ""; - } else if (dialogType == QCefView::CefJsDialogType::JSDIALOGTYPE_PROMPT) { + } else if (dialogType == QCefView::CefJsDialogType::CefJsDialogTypePrompt) { bool ok = false; QString text = QInputDialog::getText(this, "Prompt", messageText, QLineEdit::Normal, defaultPromptText, &ok); if (ok) {