From 6f5850dd4f6c4cc253c48f41f59130aee5415591 Mon Sep 17 00:00:00 2001
From: Pierre Rossi <pierre.rossi@digia.com>
Date: Mon, 13 Jan 2014 15:01:54 +0100
Subject: [PATCH] JS dialogs in QtQuick

Refactor JavaScriptDialogManagerQt to support a Qt Quick dialogs
friendly approach.
Qt Quick dialogs are still missing a prompt, so we use a "handmade"
one. This should be solved before 5.3 though.

Change-Id: I965df66837b2e81d6e4618a8da1167a37661c26e
Reviewed-by: Jocelyn Turcotte <jocelyn.turcotte@digia.com>
---
 src/core/core_gyp_generator.pro             |   3 +
 src/core/javascript_dialog_controller.cpp   | 104 ++++++++++++++++++++
 src/core/javascript_dialog_controller.h     |  74 ++++++++++++++
 src/core/javascript_dialog_controller_p.h   |  68 +++++++++++++
 src/core/javascript_dialog_manager_qt.cpp   |  31 ++++--
 src/core/javascript_dialog_manager_qt.h     |  12 ++-
 src/core/web_contents_adapter.cpp           |   3 +-
 src/core/web_contents_adapter_client.h      |   4 +-
 src/core/web_contents_delegate_qt.cpp       |   1 +
 src/webengine/api/qquickwebengineview.cpp   |   6 +-
 src/webengine/api/qquickwebengineview_p_p.h |   2 +-
 src/webengine/ui/AlertDialog.qml            |  46 +++++++++
 src/webengine/ui/ConfirmDialog.qml          |  47 +++++++++
 src/webengine/ui/PromptDialog.qml           |  96 ++++++++++++++++++
 src/webengine/ui/qmldir                     |   3 +
 src/webengine/ui/ui.pro                     |   5 +
 src/webengine/ui_delegates_manager.cpp      |  77 ++++++++++++++-
 src/webengine/ui_delegates_manager.h        |  12 ++-
 src/webenginewidgets/api/qwebenginepage.cpp |  28 ++++--
 src/webenginewidgets/api/qwebenginepage_p.h |   2 +-
 20 files changed, 597 insertions(+), 27 deletions(-)
 create mode 100644 src/core/javascript_dialog_controller.cpp
 create mode 100644 src/core/javascript_dialog_controller.h
 create mode 100644 src/core/javascript_dialog_controller_p.h
 create mode 100644 src/webengine/ui/AlertDialog.qml
 create mode 100644 src/webengine/ui/ConfirmDialog.qml
 create mode 100644 src/webengine/ui/PromptDialog.qml

diff --git a/src/core/core_gyp_generator.pro b/src/core/core_gyp_generator.pro
index 4064324d0..a22b9126a 100644
--- a/src/core/core_gyp_generator.pro
+++ b/src/core/core_gyp_generator.pro
@@ -41,6 +41,7 @@ SOURCES = \
         dev_tools_http_handler_delegate_qt.cpp \
         download_manager_delegate_qt.cpp \
         chromium_gpu_helper.cpp \
+        javascript_dialog_controller.cpp \
         javascript_dialog_manager_qt.cpp \
         process_main.cpp \
         render_widget_host_view_qt.cpp \
@@ -69,6 +70,8 @@ HEADERS = \
         dev_tools_http_handler_delegate_qt.h \
         download_manager_delegate_qt.h \
         chromium_gpu_helper.h \
+        javascript_dialog_controller_p.h \
+        javascript_dialog_controller.h \
         javascript_dialog_manager_qt.h \
         process_main.h \
         render_widget_host_view_qt.h \
diff --git a/src/core/javascript_dialog_controller.cpp b/src/core/javascript_dialog_controller.cpp
new file mode 100644
index 000000000..ed0431084
--- /dev/null
+++ b/src/core/javascript_dialog_controller.cpp
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "javascript_dialog_controller.h"
+#include "javascript_dialog_controller_p.h"
+
+#include"javascript_dialog_manager_qt.h"
+#include "type_conversion.h"
+
+void JavaScriptDialogControllerPrivate::dialogFinished(bool accepted, const base::string16 &promptValue)
+{
+    // Clear the queue first as this could result in the engine asking us to run another dialog.
+    JavaScriptDialogManagerQt::GetInstance()->removeDialogForContents(contents);
+
+    callback.Run(accepted, promptValue);
+}
+
+JavaScriptDialogControllerPrivate::JavaScriptDialogControllerPrivate(WebContentsAdapterClient::JavascriptDialogType t, const QString &msg, const QString &prompt
+                                                                     , const content::JavaScriptDialogManager::DialogClosedCallback &cb, content::WebContents *c)
+    : type(t)
+    , message(msg)
+    , defaultPrompt(prompt)
+    , callback(cb)
+    , contents(c)
+{
+}
+
+JavaScriptDialogController::~JavaScriptDialogController()
+{
+}
+
+QString JavaScriptDialogController::message() const
+{
+    return d->message;
+}
+
+QString JavaScriptDialogController::defaultPrompt() const
+{
+    return d->defaultPrompt;
+}
+
+WebContentsAdapterClient::JavascriptDialogType JavaScriptDialogController::type() const
+{
+    return d->type;
+}
+
+void JavaScriptDialogController::textProvided(const QString &text)
+{
+    d->userInput = text;
+}
+
+void JavaScriptDialogController::accept()
+{
+    d->dialogFinished(true, toString16(d->userInput));
+}
+
+void JavaScriptDialogController::reject()
+{
+    d->dialogFinished(false, toString16(d->defaultPrompt));
+}
+
+JavaScriptDialogController::JavaScriptDialogController(JavaScriptDialogControllerPrivate *dd)
+{
+    Q_ASSERT(dd);
+    d.reset(dd);
+}
diff --git a/src/core/javascript_dialog_controller.h b/src/core/javascript_dialog_controller.h
new file mode 100644
index 000000000..e92bc8067
--- /dev/null
+++ b/src/core/javascript_dialog_controller.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef JAVASCRIPT_DIALOG_CONTROLLER_H
+#define JAVASCRIPT_DIALOG_CONTROLLER_H
+
+#include "web_contents_adapter_client.h"
+
+QT_FORWARD_DECLARE_CLASS(QString)
+
+struct JavaScriptDialogControllerPrivate;
+
+class QWEBENGINE_EXPORT JavaScriptDialogController : public QObject {
+    Q_OBJECT
+public:
+    ~JavaScriptDialogController();
+    QString message() const;
+    QString defaultPrompt() const;
+    WebContentsAdapterClient::JavascriptDialogType type() const;
+
+public Q_SLOTS:
+    void textProvided(const QString &text);
+    void accept();
+    void reject();
+
+Q_SIGNALS:
+    void dialogCloseRequested();
+
+private:
+    JavaScriptDialogController(JavaScriptDialogControllerPrivate *);
+
+    QScopedPointer<JavaScriptDialogControllerPrivate> d;
+    friend class JavaScriptDialogManagerQt;
+};
+
+#endif // JAVASCRIPT_DIALOG_CONTROLLER_H
diff --git a/src/core/javascript_dialog_controller_p.h b/src/core/javascript_dialog_controller_p.h
new file mode 100644
index 000000000..9e84b31a0
--- /dev/null
+++ b/src/core/javascript_dialog_controller_p.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef JAVASCRIPT_DIALOG_CONTROLLER_P_H
+#define JAVASCRIPT_DIALOG_CONTROLLER_P_H
+
+#include "content/public/browser/javascript_dialog_manager.h"
+#include "web_contents_adapter_client.h"
+#include <QString>
+
+namespace content {
+class WebContents;
+}
+
+class JavaScriptDialogControllerPrivate {
+
+public:
+    void dialogFinished(bool accepted, const base::string16 &promptValue);
+    JavaScriptDialogControllerPrivate(WebContentsAdapterClient::JavascriptDialogType, const QString &message, const QString &prompt
+                                      , const content::JavaScriptDialogManager::DialogClosedCallback &, content::WebContents *);
+
+    WebContentsAdapterClient::JavascriptDialogType type;
+    QString message;
+    QString defaultPrompt;
+    QString userInput;
+    content::JavaScriptDialogManager::DialogClosedCallback callback;
+    content::WebContents *contents;
+};
+
+#endif // JAVASCRIPT_DIALOG_CONTROLLER_P_H
diff --git a/src/core/javascript_dialog_manager_qt.cpp b/src/core/javascript_dialog_manager_qt.cpp
index b2f6d86bc..f0b8c5485 100644
--- a/src/core/javascript_dialog_manager_qt.cpp
+++ b/src/core/javascript_dialog_manager_qt.cpp
@@ -41,6 +41,8 @@
 
 #include "javascript_dialog_manager_qt.h"
 
+#include "javascript_dialog_controller.h"
+#include "javascript_dialog_controller_p.h"
 #include "web_contents_adapter_client.h"
 #include "web_contents_view_qt.h"
 #include "type_conversion.h"
@@ -65,14 +67,31 @@ void JavaScriptDialogManagerQt::RunJavaScriptDialog(content::WebContents *webCon
         return;
     }
 
-    QString promptInput;
     WebContentsAdapterClient::JavascriptDialogType dialogType = static_cast<WebContentsAdapterClient::JavascriptDialogType>(javascriptMessageType);
-    bool res = client->javascriptDialog(dialogType, toQt(messageText).toHtmlEscaped(), toQt(defaultPromptText).toHtmlEscaped(), &promptInput);
-    callback.Run(res, toString16(promptInput));
+    JavaScriptDialogControllerPrivate *dialogData = new JavaScriptDialogControllerPrivate(dialogType, toQt(messageText).toHtmlEscaped()
+                                                                                          , toQt(defaultPromptText).toHtmlEscaped(), callback, webContents);
+    QSharedPointer<JavaScriptDialogController> dialog(new JavaScriptDialogController(dialogData));
+
+    // We shouldn't get new dialogs for a given WebContents until we gave back a result.
+    Q_ASSERT(!m_activeDialogs.contains(webContents));
+    m_activeDialogs.insert(webContents, dialog);
+
+    client->javascriptDialog(dialog);
+}
+
+bool JavaScriptDialogManagerQt::HandleJavaScriptDialog(content::WebContents *contents, bool accept, const base::string16 *promptOverride)
+{
+    if (!m_activeDialogs.contains(contents))
+        return false;
+    QSharedPointer<JavaScriptDialogController> dialog = m_activeDialogs.value(contents);
+    Q_EMIT dialog->dialogCloseRequested();
+    dialog->d->dialogFinished(accept, promptOverride ? *promptOverride : base::string16());
+    return true;
 }
 
-bool JavaScriptDialogManagerQt::HandleJavaScriptDialog(content::WebContents *, bool accept, const base::string16 *promptOverride)
+
+void JavaScriptDialogManagerQt::removeDialogForContents(content::WebContents *contents)
 {
-    // FIXME: We might need to keep a queue of modal dialogs in there and unqueue them...
-    return false;
+    QSharedPointer<JavaScriptDialogController> dialog = m_activeDialogs.take(contents);
+    Q_EMIT dialog->dialogCloseRequested();
 }
diff --git a/src/core/javascript_dialog_manager_qt.h b/src/core/javascript_dialog_manager_qt.h
index de416e03e..69eaf94b1 100644
--- a/src/core/javascript_dialog_manager_qt.h
+++ b/src/core/javascript_dialog_manager_qt.h
@@ -45,7 +45,10 @@
 #include "content/public/common/javascript_message_type.h"
 
 #include "qglobal.h"
+#include <QMap>
+#include <QSharedPointer>
 
+class JavaScriptDialogController;
 namespace content {
 class WebContents;
 }
@@ -62,8 +65,13 @@ public:
     virtual void RunBeforeUnloadDialog(content::WebContents *, const base::string16 &messageText, bool isReload,
                                          const content::JavaScriptDialogManager::DialogClosedCallback &callback) Q_DECL_OVERRIDE { Q_UNUSED(messageText); Q_UNUSED(isReload); Q_UNUSED(callback); }
     virtual bool HandleJavaScriptDialog(content::WebContents *, bool accept, const base::string16 *promptOverride) Q_DECL_OVERRIDE;
-    virtual void CancelActiveAndPendingDialogs(content::WebContents *) Q_DECL_OVERRIDE {}
-    virtual void WebContentsDestroyed(content::WebContents *) Q_DECL_OVERRIDE {}
+    virtual void CancelActiveAndPendingDialogs(content::WebContents *contents) Q_DECL_OVERRIDE { removeDialogForContents(contents); }
+    virtual void WebContentsDestroyed(content::WebContents *contents) Q_DECL_OVERRIDE { removeDialogForContents(contents); }
+
+    void removeDialogForContents(content::WebContents *);
+
+private:
+    QMap<content::WebContents *, QSharedPointer<JavaScriptDialogController> > m_activeDialogs;
 
 };
 
diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp
index 7542f35bd..bb2ac36f4 100644
--- a/src/core/web_contents_adapter.cpp
+++ b/src/core/web_contents_adapter.cpp
@@ -40,8 +40,9 @@
 ****************************************************************************/
 #include "web_contents_adapter.h"
 
-#include "content_browser_client_qt.h"
 #include "browser_context_qt.h"
+#include "content_browser_client_qt.h"
+#include "javascript_dialog_manager_qt.h"
 #include "type_conversion.h"
 #include "web_contents_adapter_client.h"
 #include "web_contents_delegate_qt.h"
diff --git a/src/core/web_contents_adapter_client.h b/src/core/web_contents_adapter_client.h
index 2231fd46b..28cd3c4d8 100644
--- a/src/core/web_contents_adapter_client.h
+++ b/src/core/web_contents_adapter_client.h
@@ -44,10 +44,12 @@
 #include "qtwebenginecoreglobal.h"
 
 #include <QRect>
+#include <QSharedPointer>
 #include <QString>
 #include <QStringList>
 #include <QUrl>
 
+class JavaScriptDialogController;
 class RenderWidgetHostViewQt;
 class RenderWidgetHostViewQtDelegate;
 class RenderWidgetHostViewQtDelegateClient;
@@ -123,7 +125,7 @@ public:
     virtual void adoptNewWindow(WebContentsAdapter *newWebContents, WindowOpenDisposition disposition, const QRect & initialGeometry) = 0;
     virtual void close() = 0;
     virtual bool contextMenuRequested(const WebEngineContextMenuData&) = 0;
-    virtual bool javascriptDialog(JavascriptDialogType type, const QString &message, const QString &defaultValue = QString(), QString *result = 0) = 0;
+    virtual void javascriptDialog(QSharedPointer<JavaScriptDialogController>) = 0;
     virtual void runFileChooser(FileChooserMode, const QString &defaultFileName, const QStringList &acceptedMimeTypes) = 0;
 };
 
diff --git a/src/core/web_contents_delegate_qt.cpp b/src/core/web_contents_delegate_qt.cpp
index 6dd8121dd..c3648bccf 100644
--- a/src/core/web_contents_delegate_qt.cpp
+++ b/src/core/web_contents_delegate_qt.cpp
@@ -86,6 +86,7 @@ void WebContentsDelegateQt::AddNewContents(content::WebContents* source, content
 void WebContentsDelegateQt::CloseContents(content::WebContents *source)
 {
     m_viewClient->close();
+    GetJavaScriptDialogManager()->CancelActiveAndPendingDialogs(source);
 }
 
 void WebContentsDelegateQt::LoadingStateChanged(content::WebContents* source)
diff --git a/src/webengine/api/qquickwebengineview.cpp b/src/webengine/api/qquickwebengineview.cpp
index 1dcc2acd0..c06a4af48 100644
--- a/src/webengine/api/qquickwebengineview.cpp
+++ b/src/webengine/api/qquickwebengineview.cpp
@@ -43,6 +43,7 @@
 #include "qquickwebengineview_p_p.h"
 
 #include "net/base/net_errors.h"
+#include "javascript_dialog_controller.h"
 #include "qquickwebengineloadrequest_p.h"
 #include "render_widget_host_view_qt_delegate_quick.h"
 #include "ui_delegates_manager.h"
@@ -171,10 +172,9 @@ bool QQuickWebEngineViewPrivate::contextMenuRequested(const WebEngineContextMenu
     return true;
 }
 
-bool QQuickWebEngineViewPrivate::javascriptDialog(JavascriptDialogType type, const QString &message, const QString &defaultValue, QString *result)
+void QQuickWebEngineViewPrivate::javascriptDialog(QSharedPointer<JavaScriptDialogController> dialog)
 {
-    Q_UNUSED(message); Q_UNUSED(defaultValue); Q_UNUSED(result);
-    return false;
+    ui()->showDialog(dialog);
 }
 
 void QQuickWebEngineViewPrivate::titleChanged(const QString &title)
diff --git a/src/webengine/api/qquickwebengineview_p_p.h b/src/webengine/api/qquickwebengineview_p_p.h
index 67337baeb..45622d308 100644
--- a/src/webengine/api/qquickwebengineview_p_p.h
+++ b/src/webengine/api/qquickwebengineview_p_p.h
@@ -136,7 +136,7 @@ public:
     virtual void adoptNewWindow(WebContentsAdapter *newWebContents, WindowOpenDisposition disposition, const QRect &) Q_DECL_OVERRIDE;
     virtual void close() Q_DECL_OVERRIDE;
     virtual bool contextMenuRequested(const WebEngineContextMenuData &) Q_DECL_OVERRIDE;
-    virtual bool javascriptDialog(JavascriptDialogType, const QString &message, const QString &defaultValue = QString(), QString *result = 0) Q_DECL_OVERRIDE { Q_UNUSED(message); Q_UNUSED(defaultValue); Q_UNUSED(result); return false; }
+    virtual void javascriptDialog(QSharedPointer<JavaScriptDialogController>) Q_DECL_OVERRIDE;
     virtual void runFileChooser(FileChooserMode, const QString &defaultFileName, const QStringList &acceptedMimeTypes) { Q_UNUSED(defaultFileName); Q_UNUSED(acceptedMimeTypes);}
 
     void setDevicePixelRatio(qreal);
diff --git a/src/webengine/ui/AlertDialog.qml b/src/webengine/ui/AlertDialog.qml
new file mode 100644
index 000000000..bc494a080
--- /dev/null
+++ b/src/webengine/ui/AlertDialog.qml
@@ -0,0 +1,46 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the demonstration applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick.Dialogs 1.1
+
+MessageDialog {
+    icon: StandardIcon.Information
+}
diff --git a/src/webengine/ui/ConfirmDialog.qml b/src/webengine/ui/ConfirmDialog.qml
new file mode 100644
index 000000000..108497d3d
--- /dev/null
+++ b/src/webengine/ui/ConfirmDialog.qml
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the demonstration applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick.Dialogs 1.1
+
+MessageDialog {
+    icon: StandardIcon.Question
+    standardButtons: StandardButton.Ok | StandardButton.Cancel
+}
diff --git a/src/webengine/ui/PromptDialog.qml b/src/webengine/ui/PromptDialog.qml
new file mode 100644
index 000000000..534c9dd9b
--- /dev/null
+++ b/src/webengine/ui/PromptDialog.qml
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the demonstration applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// FIXME: prompt missing in Qt Quick Dialogs atm. Make our own for now.
+import QtQuick.Controls 1.1
+import QtQuick.Layouts 1.0
+import QtQuick 2.0
+
+ApplicationWindow {
+    signal input(string text);
+    signal accepted;
+    signal rejected;
+    property alias text: message.text;
+    property alias prompt: field.text;
+
+    width: 350
+    height: 100
+    flags: Qt.Dialog
+
+    function open() {
+        show();
+    }
+
+    ColumnLayout {
+        anchors.fill: parent;
+        anchors.margins: 4;
+        Text {
+            id: message;
+            Layout.fillWidth: true;
+        }
+        TextField {
+            id:field;
+            Layout.fillWidth: true;
+        }
+        RowLayout {
+            Layout.alignment: Qt.AlignRight
+            spacing: 8;
+            Button {
+                text: "OK"
+                onClicked: {
+                    input(field.text)
+                    accepted();
+                    close();
+                    destroy();
+                }
+            }
+            Button {
+                text: "Cancel"
+                onClicked: {
+                    rejected();
+                    close();
+                    destroy();
+                }
+            }
+        }
+    }
+
+}
diff --git a/src/webengine/ui/qmldir b/src/webengine/ui/qmldir
index bc0e2e300..bb942a81a 100644
--- a/src/webengine/ui/qmldir
+++ b/src/webengine/ui/qmldir
@@ -1,4 +1,7 @@
 module QtWebEngine.UIDelegates
+AlertDialog 1.0 AlertDialog.qml
+ConfirmDialog 1.0 ConfirmDialog.qml
+PromptDialog 1.0 PromptDialog.qml
 Menu 1.0 Menu.qml
 MenuItem 1.0 MenuItem.qml
 MenuSeparator 1.0 MenuSeparator.qml
diff --git a/src/webengine/ui/ui.pro b/src/webengine/ui/ui.pro
index 42a5777dc..049b428f5 100644
--- a/src/webengine/ui/ui.pro
+++ b/src/webengine/ui/ui.pro
@@ -1,6 +1,11 @@
 TARGETPATH = QtWebEngine/UIDelegates
 
 QML_FILES += \
+    # JS Dialogs
+    AlertDialog.qml \
+    ConfirmDialog.qml \
+    PromptDialog.qml \
+    # Menus. Based on Qt Quick Controls
     Menu.qml \
     MenuItem.qml \
     MenuSeparator.qml
diff --git a/src/webengine/ui_delegates_manager.cpp b/src/webengine/ui_delegates_manager.cpp
index 34edbd479..6ee3ea360 100644
--- a/src/webengine/ui_delegates_manager.cpp
+++ b/src/webengine/ui_delegates_manager.cpp
@@ -40,7 +40,9 @@
 ****************************************************************************/
 
 #include "ui_delegates_manager.h"
+
 #include "api/qquickwebengineview_p.h"
+#include "javascript_dialog_controller.h"
 
 #include <QAbstractListModel>
 #include <QClipboard>
@@ -158,9 +160,9 @@ QQmlContext *UIDelegatesManager::creationContextForComponent(QQmlComponent *comp
     return baseContext;
 }
 
-#define CHECK_QML_SIGNAL_PROPERTY(prop, type, location) \
+#define CHECK_QML_SIGNAL_PROPERTY(prop, location) \
     if (!prop.isSignalProperty()) \
-        qWarning(#type "component (Loaded from %s) is missing %s signal property.\n", qPrintable(location.toString()), qPrintable(prop.name()));
+        qWarning("%s is missing %s signal property.\n", qPrintable(location.toString()), qPrintable(prop.name()));
 
 void UIDelegatesManager::addMenuItem(MenuItemHandler *menuItemHandler, const QString &text, const QString &iconName, bool enabled)
 {
@@ -231,3 +233,74 @@ QObject *UIDelegatesManager::addMenu(QObject *parentMenu, const QString &title,
     return menu;
 }
 
+#define ASSIGN_DIALOG_COMPONENT_DATA_CASE_STATEMENT(TYPE, COMPONENT) \
+    case TYPE:\
+        dialogComponent = COMPONENT##Component.data(); \
+        break;
+
+
+void UIDelegatesManager::showDialog(QSharedPointer<JavaScriptDialogController> dialogController)
+{
+    Q_ASSERT(!dialogController.isNull());
+    ComponentType dialogComponentType = Invalid;
+    QString title;
+    switch (dialogController->type()) {
+    case WebContentsAdapterClient::AlertDialog:
+        dialogComponentType = AlertDialog;
+        title = QObject::tr("Javascript Alert - %1");
+        break;
+    case WebContentsAdapterClient::ConfirmDialog:
+        dialogComponentType = ConfirmDialog;
+        title = QObject::tr("Javascript Confirm - %1");
+        break;
+    case WebContentsAdapterClient::PromptDialog:
+        dialogComponentType = PromptDialog;
+        title = QObject::tr("Javascript Prompt - %1");
+        break;
+    default:
+        Q_UNREACHABLE();
+    }
+
+    if (!ensureComponentLoaded(dialogComponentType))
+        return;
+
+    QQmlComponent *dialogComponent = Q_NULLPTR;
+    switch (dialogComponentType) {
+    FOR_EACH_COMPONENT_TYPE(ASSIGN_DIALOG_COMPONENT_DATA_CASE_STATEMENT, NO_SEPARATOR)
+    default:
+        Q_UNREACHABLE();
+    }
+
+    QQmlContext *context(creationContextForComponent(dialogComponent));
+    QObject *dialog = dialogComponent->beginCreate(context);
+    dialog->setParent(m_view);
+    QQmlProperty textProp(dialog, QStringLiteral("text"));
+    textProp.write(dialogController->message());
+
+    QQmlProperty titleProp(dialog, QStringLiteral("title"));
+    titleProp.write(title.arg(m_view->url().toString()));
+
+    if (dialogComponentType == PromptDialog) {
+        QQmlProperty promptProp(dialog, QStringLiteral("prompt"));
+        promptProp.write(dialogController->defaultPrompt());
+        QQmlProperty inputSignal(dialog, QStringLiteral("onInput"));
+        CHECK_QML_SIGNAL_PROPERTY(inputSignal, dialogComponent->url());
+        static int setTextIndex = dialogController->metaObject()->indexOfSlot("textProvided(QString)");
+        QObject::connect(dialog, inputSignal.method(), dialogController.data(), dialogController->metaObject()->method(setTextIndex));
+    }
+
+    QQmlProperty acceptSignal(dialog, QStringLiteral("onAccepted"));
+    QQmlProperty rejectSignal(dialog, QStringLiteral("onRejected"));
+    CHECK_QML_SIGNAL_PROPERTY(acceptSignal, dialogComponent->url());
+    CHECK_QML_SIGNAL_PROPERTY(rejectSignal, dialogComponent->url());
+
+    static int acceptIndex = dialogController->metaObject()->indexOfSlot("accept()");
+    QObject::connect(dialog, acceptSignal.method(), dialogController.data(), dialogController->metaObject()->method(acceptIndex));
+    static int rejectIndex = dialogController->metaObject()->indexOfSlot("reject()");
+    QObject::connect(dialog, rejectSignal.method(), dialogController.data(), dialogController->metaObject()->method(rejectIndex));
+    dialogComponent->completeCreate();
+
+    QObject::connect(dialogController.data(), &JavaScriptDialogController::dialogCloseRequested, dialog, &QObject::deleteLater);
+
+    QMetaObject::invokeMethod(dialog, "open");
+}
diff --git a/src/webengine/ui_delegates_manager.h b/src/webengine/ui_delegates_manager.h
index 65f994b93..eeece895c 100644
--- a/src/webengine/ui_delegates_manager.h
+++ b/src/webengine/ui_delegates_manager.h
@@ -47,14 +47,18 @@
 
 #include <QExplicitlySharedDataPointer>
 #include <QPoint>
-#include <QPointer>
 #include <QQmlComponent>
+#include <QScopedPointer>
+#include <QSharedPointer>
 #include <QUrl>
 
 #define FOR_EACH_COMPONENT_TYPE(F, SEPARATOR) \
     F(Menu, menu) SEPARATOR \
     F(MenuItem, menuItem) SEPARATOR \
-    F(MenuSeparator, menuSeparator) SEPARATOR
+    F(MenuSeparator, menuSeparator) SEPARATOR \
+    F(AlertDialog, alertDialog) SEPARATOR \
+    F(ConfirmDialog, confirmDialog) SEPARATOR \
+    F(PromptDialog, promptDialog) SEPARATOR
 
 #define COMMA_SEPARATOR ,
 #define SEMICOLON_SEPARATOR ;
@@ -63,6 +67,7 @@
 #define MEMBER_DECLARATION(TYPE, COMPONENT) \
     QScopedPointer<QQmlComponent> COMPONENT##Component
 
+class JavaScriptDialogController;
 QT_BEGIN_NAMESPACE
 class QObject;
 class QQmlContext;
@@ -106,7 +111,9 @@ class UIDelegatesManager {
 
 public:
     enum ComponentType {
+        Invalid = -1,
         FOR_EACH_COMPONENT_TYPE(ENUM_DECLARATION, COMMA_SEPARATOR)
+        ComponentTypeCount
     };
 
     UIDelegatesManager(QQuickWebEngineView *);
@@ -115,6 +122,7 @@ public:
     void addMenuSeparator(QObject *menu);
     QObject *addMenu(QObject *parentMenu, const QString &title, const QPoint &pos = QPoint());
     QQmlContext *creationContextForComponent(QQmlComponent *);
+    void showDialog(QSharedPointer<JavaScriptDialogController>);
 
 private:
     bool ensureComponentLoaded(ComponentType);
diff --git a/src/webenginewidgets/api/qwebenginepage.cpp b/src/webenginewidgets/api/qwebenginepage.cpp
index 3f4287a02..0178c1118 100644
--- a/src/webenginewidgets/api/qwebenginepage.cpp
+++ b/src/webenginewidgets/api/qwebenginepage.cpp
@@ -23,6 +23,7 @@
 #include "qwebenginepage.h"
 #include "qwebenginepage_p.h"
 
+#include "javascript_dialog_controller.h"
 #include "qwebenginehistory.h"
 #include "qwebenginehistory_p.h"
 #include "qwebengineview.h"
@@ -326,20 +327,31 @@ bool QWebEnginePagePrivate::contextMenuRequested(const WebEngineContextMenuData
     return true;
 }
 
-bool QWebEnginePagePrivate::javascriptDialog(JavascriptDialogType type, const QString &message, const QString &defaultValue, QString *result)
+void QWebEnginePagePrivate::javascriptDialog(QSharedPointer<JavaScriptDialogController> controller)
 {
     Q_Q(QWebEnginePage);
-    switch (type) {
+    bool accepted = false;
+    QString promptResult;
+    switch (controller->type()) {
     case AlertDialog:
-        q->javaScriptAlert(0, message);
-        return true;
+        q->javaScriptAlert(0, controller->message());
+        accepted = true;
+        break;
     case ConfirmDialog:
-        return q->javaScriptConfirm(0, message);
+        accepted = q->javaScriptConfirm(0, controller->message());
+        break;
     case PromptDialog:
-        return q->javaScriptPrompt(0, message, defaultValue, result);
+        accepted = q->javaScriptPrompt(0, controller->message(), controller->defaultPrompt(), &promptResult);
+        if (accepted)
+            controller->textProvided(promptResult);
+        break;
+    default:
+        Q_UNREACHABLE();
     }
-    Q_UNREACHABLE();
-    return false;
+    if (accepted)
+        controller->accept();
+    else
+        controller->reject();
 }
 
 namespace {
diff --git a/src/webenginewidgets/api/qwebenginepage_p.h b/src/webenginewidgets/api/qwebenginepage_p.h
index 8901f5ec4..c8dd63daa 100644
--- a/src/webenginewidgets/api/qwebenginepage_p.h
+++ b/src/webenginewidgets/api/qwebenginepage_p.h
@@ -78,7 +78,7 @@ public:
     virtual void adoptNewWindow(WebContentsAdapter *newWebContents, WindowOpenDisposition disposition, const QRect &initialGeometry) Q_DECL_OVERRIDE;
     virtual void close() Q_DECL_OVERRIDE;
     virtual bool contextMenuRequested(const WebEngineContextMenuData &data) Q_DECL_OVERRIDE;
-    virtual bool javascriptDialog(JavascriptDialogType type, const QString &message, const QString &defaultValue = QString(), QString *result = 0) Q_DECL_OVERRIDE;
+    virtual void javascriptDialog(QSharedPointer<JavaScriptDialogController>) Q_DECL_OVERRIDE;
     virtual void runFileChooser(FileChooserMode, const QString &defaultFileName, const QStringList &acceptedMimeTypes) Q_DECL_OVERRIDE;
 
     void updateAction(QWebEnginePage::WebAction) const;
-- 
GitLab