/* * This file is part of smolbote. It's copyrighted by the contributors recorded * in the version control history of the file, available from its original * location: https://neueland.iserlohn-fortress.net/gitea/aqua/smolbote * * SPDX-License-Identifier: GPL-3.0 */ #include "webpage.h" #include <QLayout> #include <QMessageBox> #include <QTimer> #include <QWebEngineFullScreenRequest> #include <QWebEngineCertificateError> [[nodiscard]] inline QString tr_terminationStatus(QWebEnginePage::RenderProcessTerminationStatus status) { switch(status) { case QWebEnginePage::NormalTerminationStatus: return QObject::tr("The render process terminated normally."); case QWebEnginePage::AbnormalTerminationStatus: return QObject::tr("The render process terminated with with a non-zero exit status."); case QWebEnginePage::CrashedTerminationStatus: return QObject::tr("The render process crashed, for example because of a segmentation fault."); case QWebEnginePage::KilledTerminationStatus: return QObject::tr("The render process was killed, for example by SIGKILL or task manager kill."); } return QObject::tr("The render process was terminated with an unknown status."); } [[nodiscard]] inline QString feature_toString(QWebEnginePage::Feature feature) { switch(feature) { case QWebEnginePage::Notifications: return QObject::tr("Notifications"); case QWebEnginePage::Geolocation: return QObject::tr("Geolocation"); case QWebEnginePage::MediaAudioCapture: return QObject::tr("Audio Capture"); case QWebEnginePage::MediaVideoCapture: return QObject::tr("Video Capture"); case QWebEnginePage::MediaAudioVideoCapture: return QObject::tr("Audio and Video Capture"); case QWebEnginePage::MouseLock: return QObject::tr("Mouse Lock"); case QWebEnginePage::DesktopVideoCapture: return QObject::tr("Desktop Video Capture"); case QWebEnginePage::DesktopAudioVideoCapture: return QObject::tr("Desktop Audio and Video Capture"); } return QObject::tr("Unknown feature"); } WebPage::WebPage(QWebEngineProfile *profile, QObject *parent) : QWebEnginePage(profile, parent) { connect(this, &WebPage::fullScreenRequested, this, [](QWebEngineFullScreenRequest request) { request.accept(); }); connect(this, &QWebEnginePage::featurePermissionRequested, this, &WebPage::featurePermissionDialog); connect(this, &QWebEnginePage::renderProcessTerminated, this, &WebPage::renderProcessCrashed); } bool WebPage::certificateError(const QWebEngineCertificateError &certificateError) { QMessageBox messageBox; messageBox.setWindowTitle(tr("SSL Error")); if(certificateError.isOverridable()) messageBox.setIcon(QMessageBox::Warning); else messageBox.setIcon(QMessageBox::Critical); messageBox.setText(tr("An SSL error has occurred on <strong>%1</strong>").arg(certificateError.url().toString())); messageBox.setInformativeText(tr("<p>%1</p>" "<p>This error %2 be overridden.</p>") .arg(certificateError.errorDescription(), certificateError.isOverridable() ? tr("can") : tr("cannot"))); messageBox.setDetailedText(tr("Error code: %1").arg(certificateError.error())); if(certificateError.isOverridable()) { messageBox.setStandardButtons(QMessageBox::Ignore | QMessageBox::Abort); messageBox.setDefaultButton(QMessageBox::Ignore); } else messageBox.setStandardButtons(QMessageBox::Abort); auto resp = messageBox.exec(); return resp == QMessageBox::Ignore; } void WebPage::featurePermissionDialog(const QUrl &securityOrigin, QWebEnginePage::Feature feature) { QMessageBox messageBox; messageBox.setWindowTitle(tr("Feature permission request")); messageBox.setIcon(QMessageBox::Question); messageBox.setText(tr("<p>The webpage <strong>%1</strong> has requested permission to access: %2</p>" "<p>Allow this feature?</p>") .arg(securityOrigin.toString(), feature_toString(feature))); messageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); messageBox.setDefaultButton(QMessageBox::No); if(messageBox.exec() == QMessageBox::Yes) { setFeaturePermission(securityOrigin, feature, QWebEnginePage::PermissionGrantedByUser); } else { setFeaturePermission(securityOrigin, feature, QWebEnginePage::PermissionDeniedByUser); } } void WebPage::renderProcessCrashed(QWebEnginePage::RenderProcessTerminationStatus terminationStatus, int exitCode) { if(terminationStatus != QWebEnginePage::NormalTerminationStatus) { QString page = "<html><body><h1>This tab has crashed!</h1>%message%</body></html>"; page.replace(QLatin1String("%message%"), QString("<p>%1<br>Exit code is %2.</p>" "<p>Press <a href='%3'>here</a> to reload this tab.</p>") .arg(tr_terminationStatus(terminationStatus), QString::number(exitCode), this->url().toEncoded())); QTimer::singleShot(0, this, [this, page]() { setHtml(page.toUtf8(), url()); }); } }