From 4da1db8fb60b444dc112b41804a3ac7480197bd2 Mon Sep 17 00:00:00 2001
From: Pierre Rossi <pierre.rossi@digia.com>
Date: Fri, 11 Apr 2014 18:46:40 +0200
Subject: [PATCH] Add a way of using UI dialogs for authorization

We could use this to prompt the user for various feature permissions
that we are not ready to expose in our API.

Change-Id: If6e6a16aca4142b0564121dfc7677b7c4996f742
Reviewed-by: Zeno Albisser <zeno.albisser@digia.com>
---
 src/core/javascript_dialog_controller.cpp   | 10 +++++--
 src/core/javascript_dialog_controller.h     |  1 +
 src/core/javascript_dialog_controller_p.h   |  5 ++--
 src/core/javascript_dialog_manager_qt.cpp   | 33 ++++++++++++++-------
 src/core/javascript_dialog_manager_qt.h     |  6 ++++
 src/core/web_contents_adapter_client.h      |  4 ++-
 src/webengine/ui_delegates_manager.cpp      | 12 +++++---
 src/webenginewidgets/api/qwebenginepage.cpp |  3 ++
 8 files changed, 54 insertions(+), 20 deletions(-)

diff --git a/src/core/javascript_dialog_controller.cpp b/src/core/javascript_dialog_controller.cpp
index 973fa89b7..c3c133a0d 100644
--- a/src/core/javascript_dialog_controller.cpp
+++ b/src/core/javascript_dialog_controller.cpp
@@ -54,12 +54,13 @@ void JavaScriptDialogControllerPrivate::dialogFinished(bool accepted, const base
 }
 
 JavaScriptDialogControllerPrivate::JavaScriptDialogControllerPrivate(WebContentsAdapterClient::JavascriptDialogType t, const QString &msg, const QString &prompt
-                                                                     , const QUrl &securityOrigin, const content::JavaScriptDialogManager::DialogClosedCallback &cb
-                                                                     , content::WebContents *c)
+                                                                     , const QString &title, const QUrl &securityOrigin
+                                                                     , const content::JavaScriptDialogManager::DialogClosedCallback &cb, content::WebContents *c)
     : type(t)
     , message(msg)
     , defaultPrompt(prompt)
     , securityOrigin(securityOrigin)
+    , title(title)
     , callback(cb)
     , contents(c)
 {
@@ -79,6 +80,11 @@ QString JavaScriptDialogController::defaultPrompt() const
     return d->defaultPrompt;
 }
 
+QString JavaScriptDialogController::title() const
+{
+    return d->title;
+}
+
 WebContentsAdapterClient::JavascriptDialogType JavaScriptDialogController::type() const
 {
     return d->type;
diff --git a/src/core/javascript_dialog_controller.h b/src/core/javascript_dialog_controller.h
index 755a2712b..25e711cb7 100644
--- a/src/core/javascript_dialog_controller.h
+++ b/src/core/javascript_dialog_controller.h
@@ -54,6 +54,7 @@ public:
     ~JavaScriptDialogController();
     QString message() const;
     QString defaultPrompt() const;
+    QString title() const;
     WebContentsAdapterClient::JavascriptDialogType type() const;
     QUrl securityOrigin() const;
 
diff --git a/src/core/javascript_dialog_controller_p.h b/src/core/javascript_dialog_controller_p.h
index 0d7552ce2..ed51619d4 100644
--- a/src/core/javascript_dialog_controller_p.h
+++ b/src/core/javascript_dialog_controller_p.h
@@ -55,14 +55,15 @@ class JavaScriptDialogControllerPrivate {
 public:
     void dialogFinished(bool accepted, const base::string16 &promptValue);
     JavaScriptDialogControllerPrivate(WebContentsAdapterClient::JavascriptDialogType, const QString &message, const QString &prompt
-                                      , const QUrl &securityOrigin, const content::JavaScriptDialogManager::DialogClosedCallback &
-                                      , content::WebContents *);
+                                      , const QString& title, const QUrl &securityOrigin
+                                      , const content::JavaScriptDialogManager::DialogClosedCallback &, content::WebContents *);
 
     WebContentsAdapterClient::JavascriptDialogType type;
     QString message;
     QString defaultPrompt;
     QUrl securityOrigin;
     QString userInput;
+    QString title;
     content::JavaScriptDialogManager::DialogClosedCallback callback;
     content::WebContents *contents;
 };
diff --git a/src/core/javascript_dialog_manager_qt.cpp b/src/core/javascript_dialog_manager_qt.cpp
index 1e37481b6..bd528af95 100644
--- a/src/core/javascript_dialog_manager_qt.cpp
+++ b/src/core/javascript_dialog_manager_qt.cpp
@@ -43,7 +43,6 @@
 
 #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"
 
@@ -62,20 +61,13 @@ void JavaScriptDialogManagerQt::RunJavaScriptDialog(content::WebContents *webCon
 
     WebContentsAdapterClient *client = WebContentsViewQt::from(webContents->GetView())->client();
     if (!client) {
-        *didSuppressMessage = true;
+        if (didSuppressMessage)
+            *didSuppressMessage = true;
         return;
     }
 
     WebContentsAdapterClient::JavascriptDialogType dialogType = static_cast<WebContentsAdapterClient::JavascriptDialogType>(javascriptMessageType);
-    JavaScriptDialogControllerPrivate *dialogData = new JavaScriptDialogControllerPrivate(dialogType, toQt(messageText).toHtmlEscaped()
-                                                                                          , toQt(defaultPromptText).toHtmlEscaped(), toQt(originUrl), 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);
+    runDialogForContents(webContents, dialogType, toQt(messageText).toHtmlEscaped(), toQt(defaultPromptText).toHtmlEscaped(), toQt(originUrl), callback);
 }
 
 bool JavaScriptDialogManagerQt::HandleJavaScriptDialog(content::WebContents *contents, bool accept, const base::string16 *promptOverride)
@@ -88,6 +80,25 @@ bool JavaScriptDialogManagerQt::HandleJavaScriptDialog(content::WebContents *con
     return true;
 }
 
+void JavaScriptDialogManagerQt::runDialogForContents(content::WebContents *webContents, WebContentsAdapterClient::JavascriptDialogType type
+                                                     , const QString &messageText, const QString &defaultPrompt, const QUrl &origin
+                                                     , const content::JavaScriptDialogManager::DialogClosedCallback &callback, const QString &title)
+{
+    WebContentsAdapterClient *client = WebContentsViewQt::from(webContents->GetView())->client();
+    if (!client)
+        return;
+
+    JavaScriptDialogControllerPrivate *dialogData = new JavaScriptDialogControllerPrivate(type, messageText, defaultPrompt, title, origin, 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);
+
+}
+
 
 void JavaScriptDialogManagerQt::removeDialogForContents(content::WebContents *contents)
 {
diff --git a/src/core/javascript_dialog_manager_qt.h b/src/core/javascript_dialog_manager_qt.h
index 69eaf94b1..518ceca53 100644
--- a/src/core/javascript_dialog_manager_qt.h
+++ b/src/core/javascript_dialog_manager_qt.h
@@ -44,6 +44,8 @@
 #include "content/public/browser/javascript_dialog_manager.h"
 #include "content/public/common/javascript_message_type.h"
 
+#include "web_contents_adapter_client.h"
+
 #include "qglobal.h"
 #include <QMap>
 #include <QSharedPointer>
@@ -62,12 +64,16 @@ public:
     virtual void RunJavaScriptDialog(content::WebContents *, const GURL &, const std::string &acceptLang, content::JavaScriptMessageType javascriptMessageType,
                                        const base::string16 &messageText, const base::string16 &defaultPromptText,
                                        const content::JavaScriptDialogManager::DialogClosedCallback &callback, bool *didSuppressMessage) Q_DECL_OVERRIDE;
+
     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 *contents) Q_DECL_OVERRIDE { removeDialogForContents(contents); }
     virtual void WebContentsDestroyed(content::WebContents *contents) Q_DECL_OVERRIDE { removeDialogForContents(contents); }
 
+
+    void runDialogForContents(content::WebContents *, WebContentsAdapterClient::JavascriptDialogType, const QString &messageText, const QString &defaultPrompt
+                              , const QUrl &,const content::JavaScriptDialogManager::DialogClosedCallback &callback, const QString &title = QString());
     void removeDialogForContents(content::WebContents *);
 
 private:
diff --git a/src/core/web_contents_adapter_client.h b/src/core/web_contents_adapter_client.h
index 7deb55686..64b5fca38 100644
--- a/src/core/web_contents_adapter_client.h
+++ b/src/core/web_contents_adapter_client.h
@@ -96,7 +96,9 @@ public:
     enum JavascriptDialogType {
         AlertDialog,
         ConfirmDialog,
-        PromptDialog
+        PromptDialog,
+        // Leave room for potential new specs
+        InternalAuthorizationDialog = 0x10,
     };
 
     // Must match the ones in file_chooser_params.h
diff --git a/src/webengine/ui_delegates_manager.cpp b/src/webengine/ui_delegates_manager.cpp
index 5fb5ef475..919b3f622 100644
--- a/src/webengine/ui_delegates_manager.cpp
+++ b/src/webengine/ui_delegates_manager.cpp
@@ -257,15 +257,19 @@ void UIDelegatesManager::showDialog(QSharedPointer<JavaScriptDialogController> d
     switch (dialogController->type()) {
     case WebContentsAdapterClient::AlertDialog:
         dialogComponentType = AlertDialog;
-        title = QObject::tr("Javascript Alert - %1");
+        title = QObject::tr("Javascript Alert - %1").arg(m_view->url().toString());
         break;
     case WebContentsAdapterClient::ConfirmDialog:
         dialogComponentType = ConfirmDialog;
-        title = QObject::tr("Javascript Confirm - %1");
+        title = QObject::tr("Javascript Confirm - %1").arg(m_view->url().toString());
         break;
     case WebContentsAdapterClient::PromptDialog:
         dialogComponentType = PromptDialog;
-        title = QObject::tr("Javascript Prompt - %1");
+        title = QObject::tr("Javascript Prompt - %1").arg(m_view->url().toString());
+        break;
+    case WebContentsAdapterClient::InternalAuthorizationDialog:
+        dialogComponentType = ConfirmDialog;
+        title = dialogController->title();
         break;
     default:
         Q_UNREACHABLE();
@@ -288,7 +292,7 @@ void UIDelegatesManager::showDialog(QSharedPointer<JavaScriptDialogController> d
     textProp.write(dialogController->message());
 
     QQmlProperty titleProp(dialog, QStringLiteral("title"));
-    titleProp.write(title.arg(m_view->url().toString()));
+    titleProp.write(title);
 
     if (dialogComponentType == PromptDialog) {
         QQmlProperty promptProp(dialog, QStringLiteral("prompt"));
diff --git a/src/webenginewidgets/api/qwebenginepage.cpp b/src/webenginewidgets/api/qwebenginepage.cpp
index 6fcababbf..ec0c0224d 100644
--- a/src/webenginewidgets/api/qwebenginepage.cpp
+++ b/src/webenginewidgets/api/qwebenginepage.cpp
@@ -594,6 +594,9 @@ void QWebEnginePagePrivate::javascriptDialog(QSharedPointer<JavaScriptDialogCont
         if (accepted)
             controller->textProvided(promptResult);
         break;
+    case InternalAuthorizationDialog:
+        accepted = (QMessageBox::question(view, controller->title(), controller->message(), QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes);
+        break;
     default:
         Q_UNREACHABLE();
     }
-- 
GitLab