diff --git a/examples/webenginewidgets/simplebrowser/webpage.cpp b/examples/webenginewidgets/simplebrowser/webpage.cpp
index 99849c77d480ca3e14ab623c65eec95c41a13aa5..2e49f651f9db755e9dded06fbf4dd5f8eebc8e53 100644
--- a/examples/webenginewidgets/simplebrowser/webpage.cpp
+++ b/examples/webenginewidgets/simplebrowser/webpage.cpp
@@ -57,6 +57,7 @@
 #include <QAuthenticator>
 #include <QMessageBox>
 #include <QStyle>
+#include <QTimer>
 #include <QWebEngineCertificateError>
 
 WebPage::WebPage(QWebEngineProfile *profile, QObject *parent)
@@ -74,22 +75,33 @@ WebPage::WebPage(QWebEngineProfile *profile, QObject *parent)
 bool WebPage::certificateError(const QWebEngineCertificateError &error)
 {
     QWidget *mainWindow = view()->window();
-    if (error.isOverridable()) {
-        QDialog dialog(mainWindow);
-        dialog.setModal(true);
-        dialog.setWindowFlags(dialog.windowFlags() & ~Qt::WindowContextHelpButtonHint);
-        Ui::CertificateErrorDialog certificateDialog;
-        certificateDialog.setupUi(&dialog);
-        certificateDialog.m_iconLabel->setText(QString());
-        QIcon icon(mainWindow->style()->standardIcon(QStyle::SP_MessageBoxWarning, 0, mainWindow));
-        certificateDialog.m_iconLabel->setPixmap(icon.pixmap(32, 32));
-        certificateDialog.m_errorLabel->setText(error.errorDescription());
-        dialog.setWindowTitle(tr("Certificate Error"));
-        return dialog.exec() == QDialog::Accepted;
-    }
 
-    QMessageBox::critical(mainWindow, tr("Certificate Error"), error.errorDescription());
-    return false;
+    QWebEngineCertificateError deferredError = error;
+    deferredError.defer();
+
+    QTimer::singleShot(0, mainWindow, [mainWindow, error = std::move(deferredError)] () mutable {
+        if (!error.deferred()) {
+            QMessageBox::critical(mainWindow, tr("Certificate Error"), error.errorDescription());
+        } else {
+            QDialog dialog(mainWindow);
+            dialog.setModal(true);
+            dialog.setWindowFlags(dialog.windowFlags() & ~Qt::WindowContextHelpButtonHint);
+
+            Ui::CertificateErrorDialog certificateDialog;
+            certificateDialog.setupUi(&dialog);
+            certificateDialog.m_iconLabel->setText(QString());
+            QIcon icon(mainWindow->style()->standardIcon(QStyle::SP_MessageBoxWarning, 0, mainWindow));
+            certificateDialog.m_iconLabel->setPixmap(icon.pixmap(32, 32));
+            certificateDialog.m_errorLabel->setText(error.errorDescription());
+            dialog.setWindowTitle(tr("Certificate Error"));
+
+            if (dialog.exec() == QDialog::Accepted)
+                error.ignoreCertificateError();
+            else
+                error.rejectCertificate();
+        }
+    });
+    return true;
 }
 
 void WebPage::handleAuthenticationRequired(const QUrl &requestUrl, QAuthenticator *auth)
diff --git a/src/webenginewidgets/api/qwebenginecertificateerror.cpp b/src/webenginewidgets/api/qwebenginecertificateerror.cpp
index f04b7361537d11c92f22e9441a999ec7738e4446..e8c7a4245d8d2b49956186a0a05b1e7da18cc69c 100644
--- a/src/webenginewidgets/api/qwebenginecertificateerror.cpp
+++ b/src/webenginewidgets/api/qwebenginecertificateerror.cpp
@@ -39,6 +39,8 @@
 
 #include "qwebenginecertificateerror.h"
 
+#include "certificate_error_controller.h"
+
 QT_BEGIN_NAMESPACE
 
 /*!
@@ -51,14 +53,37 @@ QT_BEGIN_NAMESPACE
     QWebEnginePage::certificateError().
 */
 
-class QWebEngineCertificateErrorPrivate {
+class QWebEngineCertificateErrorPrivate : public QSharedData {
 public:
     QWebEngineCertificateErrorPrivate(int error, QUrl url, bool overridable, QString errorDescription);
 
+    ~QWebEngineCertificateErrorPrivate() {
+        if (deferred && !answered)
+            rejectCertificate();
+    }
+
+    void resolveError(bool accept) {
+        if (answered)
+            return;
+        answered = true;
+        if (overridable) {
+            if (auto ctl = controller.lock())
+                ctl->accept(accept);
+        }
+    }
+
+    void ignoreCertificateError() { resolveError(true); }
+    void rejectCertificate() { resolveError(false); }
+
     QWebEngineCertificateError::Error error;
     QUrl url;
     bool overridable;
     QString errorDescription;
+
+    bool answered = false, deferred = false;
+    QWeakPointer<CertificateErrorController> controller;
+
+    Q_DISABLE_COPY(QWebEngineCertificateErrorPrivate)
 };
 
 QWebEngineCertificateErrorPrivate::QWebEngineCertificateErrorPrivate(int error, QUrl url, bool overridable, QString errorDescription)
@@ -68,17 +93,30 @@ QWebEngineCertificateErrorPrivate::QWebEngineCertificateErrorPrivate(int error,
     , errorDescription(errorDescription)
 { }
 
-
 /*! \internal
 */
 QWebEngineCertificateError::QWebEngineCertificateError(int error, QUrl url, bool overridable, QString errorDescription)
-    : d_ptr(new QWebEngineCertificateErrorPrivate(error, url, overridable, errorDescription))
+    : d(new QWebEngineCertificateErrorPrivate(error, url, overridable, errorDescription))
 { }
 
+/*! \internal
+*/
+QWebEngineCertificateError::QWebEngineCertificateError(const QSharedPointer<CertificateErrorController> &controller)
+    : d(new QWebEngineCertificateErrorPrivate(controller->error(), controller->url(),
+                                              controller->overridable(), controller->errorString()))
+{
+    d->controller = controller;
+}
+
+QWebEngineCertificateError::QWebEngineCertificateError(const QWebEngineCertificateError &other) = default;
+
+QWebEngineCertificateError& QWebEngineCertificateError::operator=(const QWebEngineCertificateError &other) = default;
+
 /*! \internal
 */
 QWebEngineCertificateError::~QWebEngineCertificateError()
 {
+
 }
 
 /*!
@@ -116,7 +154,6 @@ QWebEngineCertificateError::~QWebEngineCertificateError()
 */
 bool QWebEngineCertificateError::isOverridable() const
 {
-    const Q_D(QWebEngineCertificateError);
     return d->overridable;
 }
 
@@ -127,7 +164,6 @@ bool QWebEngineCertificateError::isOverridable() const
 */
 QUrl QWebEngineCertificateError::url() const
 {
-    const Q_D(QWebEngineCertificateError);
     return d->url;
 }
 
@@ -138,7 +174,6 @@ QUrl QWebEngineCertificateError::url() const
 */
 QWebEngineCertificateError::Error QWebEngineCertificateError::error() const
 {
-    const Q_D(QWebEngineCertificateError);
     return d->error;
 }
 
@@ -149,8 +184,56 @@ QWebEngineCertificateError::Error QWebEngineCertificateError::error() const
 */
 QString QWebEngineCertificateError::errorDescription() const
 {
-    const Q_D(QWebEngineCertificateError);
     return d->errorDescription;
 }
 
+/*!
+    Marks the certificate error for delayed handling.
+
+    This function should be called when there is a need to postpone the decision whether to ignore a
+    certificate error, for example, while waiting for user input. When called, the function pauses the
+    URL request until ignoreCertificateError() or rejectCertificate() is called.
+
+    \note It is only possible to defer overridable certificate errors.
+
+    \sa isOverridable(), deferred()
+*/
+void QWebEngineCertificateError::defer()
+{
+    if (isOverridable())
+        d->deferred = true;
+}
+
+/*!
+    Returns whether the decision for error handling was delayed and the URL load was halted.
+*/
+bool QWebEngineCertificateError::deferred() const
+{
+    return d->deferred;
+}
+
+/*!
+    Ignores the certificate error and continues the loading of the requested URL.
+*/
+void QWebEngineCertificateError::ignoreCertificateError()
+{
+    d->ignoreCertificateError();
+}
+
+/*!
+    Rejects the certificate and aborts the loading of the requested URL.
+*/
+void QWebEngineCertificateError::rejectCertificate()
+{
+    d->rejectCertificate();
+}
+
+/*!
+    Returns \c true if the error was explicitly rejected or accepted.
+*/
+bool QWebEngineCertificateError::answered() const
+{
+    return d->answered;
+}
+
 QT_END_NAMESPACE
diff --git a/src/webenginewidgets/api/qwebenginecertificateerror.h b/src/webenginewidgets/api/qwebenginecertificateerror.h
index 82ac281be04c62978f80b746045762dd19ff975c..f8805e8a761fe5d7426c254f68aa8b345cc4c2a4 100644
--- a/src/webenginewidgets/api/qwebenginecertificateerror.h
+++ b/src/webenginewidgets/api/qwebenginecertificateerror.h
@@ -42,11 +42,12 @@
 
 #include <QtWebEngineWidgets/qtwebenginewidgetsglobal.h>
 
-#include <QtCore/qscopedpointer.h>
+#include <QtCore/qsharedpointer.h>
 #include <QtCore/qurl.h>
 
 QT_BEGIN_NAMESPACE
 
+class CertificateErrorController;
 class QWebEngineCertificateErrorPrivate;
 
 class QWEBENGINEWIDGETS_EXPORT QWebEngineCertificateError {
@@ -78,10 +79,20 @@ public:
     bool isOverridable() const;
     QString errorDescription() const;
 
+    QWebEngineCertificateError(const QWebEngineCertificateError &other);
+    QWebEngineCertificateError& operator=(const QWebEngineCertificateError &other);
+
+    void defer();
+    bool deferred() const;
+
+    void rejectCertificate();
+    void ignoreCertificateError();
+    bool answered() const;
+
 private:
-    Q_DISABLE_COPY(QWebEngineCertificateError)
-    Q_DECLARE_PRIVATE(QWebEngineCertificateError)
-    QScopedPointer<QWebEngineCertificateErrorPrivate> d_ptr;
+    friend class QWebEnginePagePrivate;
+    QWebEngineCertificateError(const QSharedPointer<CertificateErrorController> &controller);
+    QExplicitlySharedDataPointer<QWebEngineCertificateErrorPrivate> d;
 };
 
 QT_END_NAMESPACE
diff --git a/src/webenginewidgets/api/qwebenginepage.cpp b/src/webenginewidgets/api/qwebenginepage.cpp
index c9e9177b7ab99e59a51da87fe88cf01a5a5ce0af..b22d4791688793fe80fb274eae316b0c6c9b19fd 100644
--- a/src/webenginewidgets/api/qwebenginepage.cpp
+++ b/src/webenginewidgets/api/qwebenginepage.cpp
@@ -294,6 +294,7 @@ void QWebEnginePagePrivate::loadStarted(const QUrl &provisionalUrl, bool isError
         return;
 
     isLoading = true;
+    m_certificateErrorControllers.clear();
     QTimer::singleShot(0, q, &QWebEnginePage::loadStarted);
 }
 
@@ -1715,10 +1716,11 @@ void QWebEnginePagePrivate::allowCertificateError(const QSharedPointer<Certifica
     Q_Q(QWebEnginePage);
     bool accepted = false;
 
-    QWebEngineCertificateError error(controller->error(), controller->url(), controller->overridable() && !controller->strictEnforcement(), controller->errorString());
+    QWebEngineCertificateError error(controller);
     accepted = q->certificateError(error);
-
-    if (error.isOverridable())
+    if (error.deferred() && !error.answered())
+        m_certificateErrorControllers.append(controller);
+    else if (!error.answered() && error.isOverridable())
         controller->accept(accepted);
 }
 
diff --git a/src/webenginewidgets/api/qwebenginepage_p.h b/src/webenginewidgets/api/qwebenginepage_p.h
index fae97b9fabd91d4cd75ae84a7808ff888b4bb8a9..2843f69c485876f79a792936ad230d001ec18289 100644
--- a/src/webenginewidgets/api/qwebenginepage_p.h
+++ b/src/webenginewidgets/api/qwebenginepage_p.h
@@ -210,6 +210,8 @@ public:
 #if QT_CONFIG(webengine_printing_and_pdf)
     QPrinter *currentPrinter;
 #endif
+
+    QList<QSharedPointer<CertificateErrorController>> m_certificateErrorControllers;
 };
 
 class QContextMenuBuilder : public QtWebEngineCore::RenderViewContextMenuQt
diff --git a/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc b/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc
index 64fe4c9cd7e6561c16694676e91e79393ac630ff..5536c005828075e5128044eedbdeffa692c494b7 100644
--- a/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc
+++ b/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc
@@ -522,6 +522,8 @@
     Return \c true to ignore the error and complete the request. Return \c false to stop loading
     the request.
 
+    \note If the error was successfully deferred then the returned value will be ignored.
+
     \sa QWebEngineCertificateError
 */
 
diff --git a/tests/auto/shared/https.pri b/tests/auto/shared/https.pri
new file mode 100644
index 0000000000000000000000000000000000000000..ce4c147f7b8bf5418c6b126b446a95699e00f3a1
--- /dev/null
+++ b/tests/auto/shared/https.pri
@@ -0,0 +1,4 @@
+include($$PWD/http.pri)
+
+HEADERS += $$PWD/httpsserver.h
+RESOURCES += $$PWD/httpsserver.qrc
diff --git a/tests/auto/shared/httpserver.cpp b/tests/auto/shared/httpserver.cpp
index b85af99014e5127c23b749d228af86c79bf26ae2..e282fc8b893427ee5b9b3b955cd678ac5e2849c5 100644
--- a/tests/auto/shared/httpserver.cpp
+++ b/tests/auto/shared/httpserver.cpp
@@ -31,9 +31,21 @@
 
 Q_LOGGING_CATEGORY(gHttpServerLog, "HttpServer")
 
-HttpServer::HttpServer(QObject *parent) : QObject(parent)
+HttpServer::HttpServer(QObject *parent) : HttpServer(new QTcpServer, "http", parent)
 {
-    connect(&m_tcpServer, &QTcpServer::newConnection, this, &HttpServer::handleNewConnection);
+}
+
+HttpServer::HttpServer(QTcpServer *tcpServer, const QString &protocol, QObject *parent)
+    : QObject(parent), m_tcpServer(tcpServer)
+{
+    m_url.setHost(QStringLiteral("127.0.0.1"));
+    m_url.setScheme(protocol);
+    connect(tcpServer, &QTcpServer::newConnection, this, &HttpServer::handleNewConnection);
+}
+
+HttpServer::~HttpServer()
+{
+    delete m_tcpServer;
 }
 
 bool HttpServer::start()
@@ -41,21 +53,18 @@ bool HttpServer::start()
     m_error = false;
     m_expectingError = false;
 
-    if (!m_tcpServer.listen()) {
-        qCWarning(gHttpServerLog).noquote() << m_tcpServer.errorString();
+    if (!m_tcpServer->listen()) {
+        qCWarning(gHttpServerLog).noquote() << m_tcpServer->errorString();
         return false;
     }
 
-    m_url.setScheme(QStringLiteral("http"));
-    m_url.setHost(QStringLiteral("127.0.0.1"));
-    m_url.setPort(m_tcpServer.serverPort());
-
+    m_url.setPort(m_tcpServer->serverPort());
     return true;
 }
 
 bool HttpServer::stop()
 {
-    m_tcpServer.close();
+    m_tcpServer->close();
     return m_error == m_expectingError;
 }
 
@@ -73,12 +82,12 @@ QUrl HttpServer::url(const QString &path) const
 
 void HttpServer::handleNewConnection()
 {
-    auto rr = new HttpReqRep(m_tcpServer.nextPendingConnection(), this);
+    auto rr = new HttpReqRep(m_tcpServer->nextPendingConnection(), this);
     connect(rr, &HttpReqRep::requestReceived, [this, rr]() {
         Q_EMIT newRequest(rr);
         rr->close();
     });
-    connect(rr, &HttpReqRep::responseSent, [this, rr]() {
+    connect(rr, &HttpReqRep::responseSent, [rr]() {
         qCInfo(gHttpServerLog).noquote() << rr->requestMethod() << rr->requestPath()
                                          << rr->responseStatus() << rr->responseBody().size();
     });
diff --git a/tests/auto/shared/httpserver.h b/tests/auto/shared/httpserver.h
index b4649244ef858a621f21f06444e3f7d2688b2e94..57f824bb549ccf5a3a36f53dffa8196a05309825 100644
--- a/tests/auto/shared/httpserver.h
+++ b/tests/auto/shared/httpserver.h
@@ -59,19 +59,22 @@ class HttpServer : public QObject
     Q_OBJECT
 public:
     explicit HttpServer(QObject *parent = nullptr);
+    explicit HttpServer(QTcpServer *server, const QString &protocol, QObject *parent = nullptr);
+
+    ~HttpServer() override;
 
     // Must be called to start listening.
     //
     // Returns true if a TCP port has been successfully bound.
-    Q_REQUIRED_RESULT bool start();
+    Q_INVOKABLE Q_REQUIRED_RESULT bool start();
 
     // Stops listening and performs final error checks.
-    Q_REQUIRED_RESULT bool stop();
+    Q_INVOKABLE Q_REQUIRED_RESULT bool stop();
 
-    void setExpectError(bool b);
+    Q_INVOKABLE void setExpectError(bool b);
 
     // Full URL for given relative path
-    QUrl url(const QString &path = QStringLiteral("/")) const;
+    Q_INVOKABLE QUrl url(const QString &path = QStringLiteral("/")) const;
 
 Q_SIGNALS:
     // Emitted after a HTTP request has been successfully parsed.
@@ -81,7 +84,7 @@ private Q_SLOTS:
     void handleNewConnection();
 
 private:
-    QTcpServer m_tcpServer;
+    QTcpServer *m_tcpServer;
     QUrl m_url;
     bool m_error = false;
     bool m_expectingError = false;
diff --git a/tests/auto/shared/httpsserver.h b/tests/auto/shared/httpsserver.h
new file mode 100644
index 0000000000000000000000000000000000000000..76287a7e5abfbd8c3b63869b19d19e549d392088
--- /dev/null
+++ b/tests/auto/shared/httpsserver.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef HTTPSSERVER_H
+#define HTTPSSERVER_H
+
+#include "httpreqrep.h"
+#include "httpserver.h"
+
+#include <QDebug>
+#include <QFile>
+#include <QSslKey>
+#include <QSslSocket>
+#include <QSslConfiguration>
+#include <QTcpServer>
+
+struct SslTcpServer : QTcpServer
+{
+    SslTcpServer() {
+        sslconf.setLocalCertificate(QSslCertificate::fromPath(":/resources/cert.pem").first());
+        sslconf.setPrivateKey(readKey(":/resources/key.pem"));
+    }
+
+    void incomingConnection(qintptr d) override {
+        auto socket = new QSslSocket(this);
+        socket->setSslConfiguration(sslconf);
+
+        if (!socket->setSocketDescriptor(d)) {
+            qWarning() << "Failed to setup ssl socket!";
+            delete socket;
+            return;
+        }
+
+        connect(socket, QOverload<QSslSocket::SocketError>::of(&QSslSocket::error),
+                [] (QSslSocket::SocketError e) { qWarning() << "! Socket Error:" << e; });
+        connect(socket, QOverload<const QList<QSslError> &>::of(&QSslSocket::sslErrors),
+                [] (const QList<QSslError> &le) { qWarning() << "! SSL Errors:\n" << le; });
+
+        addPendingConnection(socket);
+        socket->startServerEncryption();
+    }
+
+    QSslKey readKey(const QString &path) const {
+        QFile file(path);
+        file.open(QIODevice::ReadOnly);
+        return QSslKey(file.readAll(), QSsl::Rsa, QSsl::Pem);
+    }
+
+    QSslConfiguration sslconf;
+};
+
+struct HttpsServer : HttpServer
+{
+    HttpsServer(QObject *parent = nullptr) : HttpServer(new SslTcpServer, "https", parent) { }
+};
+
+#endif
diff --git a/tests/auto/shared/httpsserver.qrc b/tests/auto/shared/httpsserver.qrc
new file mode 100644
index 0000000000000000000000000000000000000000..ec57a1983fb68f4e682e0a7bf7abab2466e65982
--- /dev/null
+++ b/tests/auto/shared/httpsserver.qrc
@@ -0,0 +1,6 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+    <file>resources/cert.pem</file>
+    <file>resources/key.pem</file>
+</qresource>
+</RCC>
diff --git a/tests/auto/shared/resources/cert.pem b/tests/auto/shared/resources/cert.pem
new file mode 100644
index 0000000000000000000000000000000000000000..518642d1d1559b7836b8d0991a16be2df3daefda
--- /dev/null
+++ b/tests/auto/shared/resources/cert.pem
@@ -0,0 +1,34 @@
+-----BEGIN CERTIFICATE-----
+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
+K+MCKRECBkh4ZvMxd3yEJAym0w==
+-----END CERTIFICATE-----
diff --git a/tests/auto/shared/resources/key.pem b/tests/auto/shared/resources/key.pem
new file mode 100644
index 0000000000000000000000000000000000000000..bd350d7fbff1dd83cd45a88a03e56bd8dff2c9af
--- /dev/null
+++ b/tests/auto/shared/resources/key.pem
@@ -0,0 +1,52 @@
+-----BEGIN PRIVATE KEY-----
+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
+zB9TRbOML1RSOJ+z+mbv7ONymoUI/Jf5
+-----END PRIVATE KEY-----
diff --git a/tests/auto/widgets/certificateerror/certificateerror.pro b/tests/auto/widgets/certificateerror/certificateerror.pro
new file mode 100644
index 0000000000000000000000000000000000000000..73ba7515bc974e9dbebcbc446cf110c9946a1a19
--- /dev/null
+++ b/tests/auto/widgets/certificateerror/certificateerror.pro
@@ -0,0 +1,3 @@
+include(../tests.pri)
+include(../../shared/https.pri)
+QT *= core-private
diff --git a/tests/auto/widgets/certificateerror/tst_certificateerror.cpp b/tests/auto/widgets/certificateerror/tst_certificateerror.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b002dc363f2185db5a44d93a74e13c3823e6f13f
--- /dev/null
+++ b/tests/auto/widgets/certificateerror/tst_certificateerror.cpp
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <httpsserver.h>
+#include <util.h>
+
+#include <QWebEngineCertificateError>
+#include <QWebEnginePage>
+#include <QWebEngineSettings>
+
+#include <QtTest/QtTest>
+
+class tst_CertificateError : public QObject
+{
+    Q_OBJECT
+public:
+    tst_CertificateError() { }
+
+private Q_SLOTS:
+    void handleError_data();
+    void handleError();
+};
+
+struct PageWithCertificateErrorHandler : QWebEnginePage
+{
+    PageWithCertificateErrorHandler(bool defer, bool accept, QObject *p = nullptr)
+        : QWebEnginePage(p), deferError(defer), acceptCertificate(accept) {
+        connect(this, &QWebEnginePage::loadFinished, [&] (bool result) { spyLoad(result); });
+    }
+
+    bool deferError, acceptCertificate;
+
+    CallbackSpy<bool> spyLoad;
+    QScopedPointer<QWebEngineCertificateError> error;
+
+    bool certificateError(const QWebEngineCertificateError &e) override {
+        error.reset(new QWebEngineCertificateError(e));
+        if (deferError)
+            error->defer();
+        return acceptCertificate;
+    }
+};
+
+void tst_CertificateError::handleError_data()
+{
+    QTest::addColumn<bool>("deferError");
+    QTest::addColumn<bool>("acceptCertificate");
+    QTest::addColumn<QString>("expectedContent");
+    QTest::addRow("Reject") << false << false << QString();
+    QTest::addRow("DeferReject") << true << false << QString();
+    QTest::addRow("DeferAccept") << true << true << "TEST";
+}
+
+void tst_CertificateError::handleError()
+{
+    HttpsServer server;
+    server.setExpectError(true);
+    QVERIFY(server.start());
+
+    connect(&server, &HttpsServer::newRequest, [&] (HttpReqRep *rr) {
+        rr->setResponseBody(QByteArrayLiteral("<html><body>TEST</body></html>"));
+        rr->sendResponse();
+    });
+
+    QFETCH(bool, deferError);
+    QFETCH(bool, acceptCertificate);
+    QFETCH(QString, expectedContent);
+
+    PageWithCertificateErrorHandler page(deferError, acceptCertificate);
+    page.settings()->setAttribute(QWebEngineSettings::ErrorPageEnabled, false);
+
+    page.setUrl(server.url());
+    QTRY_VERIFY(page.error);
+    QVERIFY(page.error->isOverridable());
+
+    if (deferError) {
+        QVERIFY(page.error->deferred());
+        QVERIFY(!page.error->answered());
+        QVERIFY(!page.spyLoad.wasCalled());
+        QCOMPARE(toPlainTextSync(&page), QString());
+
+        if (acceptCertificate)
+            page.error->ignoreCertificateError();
+        else
+            page.error->rejectCertificate();
+
+        QVERIFY(page.error->answered());
+        page.error.reset();
+    }
+
+    bool loadResult = page.spyLoad.waitForResult();
+    QVERIFY(page.spyLoad.wasCalled());
+    QCOMPARE(loadResult, acceptCertificate);
+    QCOMPARE(toPlainTextSync(&page), expectedContent);
+}
+
+QTEST_MAIN(tst_CertificateError)
+#include <tst_certificateerror.moc>
diff --git a/tests/auto/widgets/widgets.pro b/tests/auto/widgets/widgets.pro
index 92159bf83dce08821bff538f5ce8dd8ea2cb36e3..df553df55315975b0408e3dc8c3b09882fceccc4 100644
--- a/tests/auto/widgets/widgets.pro
+++ b/tests/auto/widgets/widgets.pro
@@ -4,6 +4,7 @@ QT_FOR_CONFIG += webenginecore webenginecore-private
 TEMPLATE = subdirs
 
 SUBDIRS += \
+    certificateerror \
     defaultsurfaceformat \
     devtools \
     faviconmanager \