From 378fbbcbc9c65d1462ea6994f1f680412531a043 Mon Sep 17 00:00:00 2001 From: Paulo Pinheiro Date: Wed, 25 Feb 2015 22:00:57 -0300 Subject: Quick: Fix handling of multiple certificate errors per request This patch enables Quick API to handle multiple certificate errors per requests and update the example projects. Chromium 40 branch raise an certificate error for every resource loaded in a request (.js, .css, .html) instead of only one (previous behavior), so requests with more than one certificate error were automatically rejected. Change-Id: Ibaa3027cd6e7f22b5dc51dcd52f76ccf5ea162d3 Reviewed-by: Pierre Rossi --- .../webengine/quicknanobrowser/BrowserWindow.qml | 37 ++++++++++---- .../api/qquickwebenginecertificateerror.cpp | 18 +++++-- .../api/qquickwebenginecertificateerror_p.h | 1 + src/webengine/api/qquickwebengineview.cpp | 6 ++- src/webengine/api/qquickwebengineview_p_p.h | 2 +- tests/quicktestbrowser/BrowserWindow.qml | 57 +++++++++++++++++----- tests/quicktestbrowser/utils.h | 6 +++ 7 files changed, 100 insertions(+), 27 deletions(-) diff --git a/examples/webengine/quicknanobrowser/BrowserWindow.qml b/examples/webengine/quicknanobrowser/BrowserWindow.qml index 3465e0da6..f451c8c07 100644 --- a/examples/webengine/quicknanobrowser/BrowserWindow.qml +++ b/examples/webengine/quicknanobrowser/BrowserWindow.qml @@ -290,10 +290,8 @@ ApplicationWindow { } onCertificateError: { - sslDialog.certError = error - sslDialog.text = "Certificate Error: " + error.description - sslDialog.visible = true error.defer() + sslDialog.enqueue(error) } onNewViewRequested: { @@ -316,14 +314,33 @@ ApplicationWindow { MessageDialog { id: sslDialog - property var certError - - standardButtons: StandardButton.Cancel | StandardButton.Ok - visible: false - title: "Do you want to accept this certificate?" + property var certErrors: [] + icon: StandardIcon.Warning + standardButtons: StandardButton.No | StandardButton.Yes + title: "Server's certificate not trusted" + text: "Do you wish to continue?" + detailedText: "If you wish so, you may continue with an unverified certificate. " + + "Accepting an unverified certificate means " + + "you may not be connected with the host you tried to connect to.\n" + + "Do you wish to override the security check and continue?" + onYes: { + certErrors.shift().ignoreCertificateError() + presentError() + } + onNo: reject() + onRejected: reject() - onAccepted: certError.ignoreCertificateError() - onRejected: certError.rejectCertificate() + function reject(){ + certErrors.shift().rejectCertificate() + presentError() + } + function enqueue(error){ + certErrors.push(error) + presentError() + } + function presentError(){ + visible = certErrors.length > 0 + } } DownloadView { id: downloadView diff --git a/src/webengine/api/qquickwebenginecertificateerror.cpp b/src/webengine/api/qquickwebenginecertificateerror.cpp index ba22bf1f0..a39bbfb84 100644 --- a/src/webengine/api/qquickwebenginecertificateerror.cpp +++ b/src/webengine/api/qquickwebenginecertificateerror.cpp @@ -45,7 +45,8 @@ public: error(static_cast(static_cast(controller->error()))), description(controller->errorString()), overridable(controller->overridable()), - async(false) + async(false), + answered(false) { } @@ -54,6 +55,7 @@ public: QString description; bool overridable; bool async; + bool answered; }; @@ -102,7 +104,9 @@ void QQuickWebEngineCertificateError::defer() */ void QQuickWebEngineCertificateError::ignoreCertificateError() { - Q_D(const QQuickWebEngineCertificateError); + Q_D(QQuickWebEngineCertificateError); + + d->answered = true; QSharedPointer strongRefCert = d->weakRefCertErrorController.toStrongRef(); if (strongRefCert) @@ -116,7 +120,9 @@ void QQuickWebEngineCertificateError::ignoreCertificateError() */ void QQuickWebEngineCertificateError::rejectCertificate() { - Q_D(const QQuickWebEngineCertificateError); + Q_D(QQuickWebEngineCertificateError); + + d->answered = true; QSharedPointer strongRefCert = d->weakRefCertErrorController.toStrongRef(); if (strongRefCert) @@ -169,5 +175,11 @@ bool QQuickWebEngineCertificateError::deferred() const return d->async; } +bool QQuickWebEngineCertificateError::answered() const +{ + Q_D(const QQuickWebEngineCertificateError); + return d->answered; +} + QT_END_NAMESPACE diff --git a/src/webengine/api/qquickwebenginecertificateerror_p.h b/src/webengine/api/qquickwebenginecertificateerror_p.h index 08ebc83b6..18a1f90e5 100644 --- a/src/webengine/api/qquickwebenginecertificateerror_p.h +++ b/src/webengine/api/qquickwebenginecertificateerror_p.h @@ -83,6 +83,7 @@ public: QString description() const; bool overridable() const; bool deferred() const; + bool answered() const; private: Q_DISABLE_COPY(QQuickWebEngineCertificateError) diff --git a/src/webengine/api/qquickwebengineview.cpp b/src/webengine/api/qquickwebengineview.cpp index 1430d72b3..c1d2ac2b6 100644 --- a/src/webengine/api/qquickwebengineview.cpp +++ b/src/webengine/api/qquickwebengineview.cpp @@ -228,12 +228,13 @@ void QQuickWebEngineViewPrivate::allowCertificateError(const QSharedPointercertificateError(quickController); - if (!quickController->deferred()) + if (!quickController->deferred() && !quickController->answered()) quickController->rejectCertificate(); + else + m_certificateErrorControllers.append(errorController); } void QQuickWebEngineViewPrivate::runGeolocationPermissionRequest(const QUrl &url) @@ -305,6 +306,7 @@ void QQuickWebEngineViewPrivate::loadStarted(const QUrl &provisionalUrl) Q_Q(QQuickWebEngineView); isLoading = true; m_history->reset(); + m_certificateErrorControllers.clear(); QQuickWebEngineLoadRequest loadRequest(provisionalUrl, QQuickWebEngineView::LoadStartedStatus); Q_EMIT q->loadingChanged(&loadRequest); } diff --git a/src/webengine/api/qquickwebengineview_p_p.h b/src/webengine/api/qquickwebengineview_p_p.h index 0111d4be4..377dcc91f 100644 --- a/src/webengine/api/qquickwebengineview_p_p.h +++ b/src/webengine/api/qquickwebengineview_p_p.h @@ -202,7 +202,7 @@ public: bool isLoading; qreal devicePixelRatio; QMap m_callbacks; - QSharedPointer m_certificateErrorController; + QList > m_certificateErrorControllers; private: QScopedPointer m_uIDelegatesManager; diff --git a/tests/quicktestbrowser/BrowserWindow.qml b/tests/quicktestbrowser/BrowserWindow.qml index 2c8e9e1ea..b111edb6c 100644 --- a/tests/quicktestbrowser/BrowserWindow.qml +++ b/tests/quicktestbrowser/BrowserWindow.qml @@ -357,10 +357,12 @@ ApplicationWindow { ] onCertificateError: { - sslDialog.certError = error - sslDialog.text = "Certificate Error: " + error.description - sslDialog.visible = true - error.defer() + if (!acceptedCertificates.shouldAutoAccept(error)){ + error.defer() + sslDialog.enqueue(error) + } else{ + error.ignoreCertificateError() + } } onNewViewRequested: { @@ -440,17 +442,50 @@ ApplicationWindow { } } + QtObject{ + id:acceptedCertificates + + property var acceptedUrls : [] + + function shouldAutoAccept(certificateError){ + var domain = utils.domainFromString(certificateError.url) + return acceptedUrls.indexOf(domain) >= 0 + } + } + MessageDialog { id: sslDialog - property var certError - - standardButtons: StandardButton.Cancel | StandardButton.Ok - visible: false - title: "Do you want to accept this certificate?" + property var certErrors: [] + icon: StandardIcon.Warning + standardButtons: StandardButton.No | StandardButton.Yes + title: "Server's certificate not trusted" + text: "Do you wish to continue?" + detailedText: "If you wish so, you may continue with an unverified certificate. " + + "Accepting an unverified certificate means " + + "you may not be connected with the host you tried to connect to.\n" + + "Do you wish to override the security check and continue?" + onYes: { + var cert = certErrors.shift() + var domain = utils.domainFromString(cert.url) + acceptedCertificates.acceptedUrls.push(domain) + cert.ignoreCertificateError() + presentError() + } + onNo: reject() + onRejected: reject() - onAccepted: certError.ignoreCertificateError() - onRejected: certError.rejectCertificate() + function reject(){ + certErrors.shift().rejectCertificate() + presentError() + } + function enqueue(error){ + certErrors.push(error) + presentError() + } + function presentError(){ + visible = certErrors.length > 0 + } } DownloadView { diff --git a/tests/quicktestbrowser/utils.h b/tests/quicktestbrowser/utils.h index 0f4460dfe..52025b7e4 100644 --- a/tests/quicktestbrowser/utils.h +++ b/tests/quicktestbrowser/utils.h @@ -48,6 +48,7 @@ class Utils : public QObject { Q_OBJECT public: Q_INVOKABLE static QUrl fromUserInput(const QString& userInput); + Q_INVOKABLE static QString domainFromString(const QString& urlString); }; inline QUrl Utils::fromUserInput(const QString& userInput) @@ -58,4 +59,9 @@ inline QUrl Utils::fromUserInput(const QString& userInput) return QUrl::fromUserInput(userInput); } +inline QString Utils::domainFromString(const QString& urlString) +{ + return QUrl::fromUserInput(urlString).host(); +} + #endif // UTILS_H -- cgit v1.2.3