diff --git a/include/QCefView.h b/include/QCefView.h index 7256ed1c..3469d1d8 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 + { + CefJsDialogTypeAlert = 0, + CefJsDialogTypeConfirm, + CefJsDialogTypePrompt + }; + 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..b7e7cbbc 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::CefJsDialogTypeAlert) { + button = QMessageBox::warning(this, "Alert", messageText); + callbackResult.first = true; + callbackResult.second = ""; + } 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::CefJsDialogTypePrompt) { + 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();