[Qt] Implement HTTP authentication QML API
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 17 Jan 2012 13:17:51 +0000 (13:17 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 17 Jan 2012 13:17:51 +0000 (13:17 +0000)
https://bugs.webkit.org/show_bug.cgi?id=75535

Patch by Alexander Færøy <alexander.faeroy@nokia.com> on 2012-01-17
Reviewed by Kenneth Rohde Christiansen.

This patch implements the QML API for handling HTTP authentication.
The implementation uses a syncronous message between the WebProcess
and the UIProcess which is called when the authenticationRequired
signal is emitted from QNAM.

Based in part upon patch by Peter Hartmann.

* UIProcess/API/qt/qquickwebview.cpp:
(QQuickWebViewPrivate::QQuickWebViewPrivate):
(QQuickWebViewPrivate::handleAuthenticationRequiredRequest):
(QQuickWebViewExperimental::authenticationDialog):
(QQuickWebViewExperimental::setAuthenticationDialog):
* UIProcess/API/qt/qquickwebview_p.h:
* UIProcess/API/qt/qquickwebview_p_p.h:
* UIProcess/PageClient.h:
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::authenticationRequiredRequest):
* UIProcess/WebPageProxy.h:
* UIProcess/WebPageProxy.messages.in:
* UIProcess/qt/QtDialogRunner.cpp:
(AuthenticationDialogContextObject::AuthenticationDialogContextObject):
(AuthenticationDialogContextObject::hostname):
(AuthenticationDialogContextObject::realm):
(AuthenticationDialogContextObject::prefilledUsername):
(AuthenticationDialogContextObject::accept):
(AuthenticationDialogContextObject::reject):
(QtDialogRunner::initForAuthentication):
* UIProcess/qt/QtDialogRunner.h:
(QtDialogRunner::username):
(QtDialogRunner::password):
(QtDialogRunner::onAuthenticationAccepted):
* UIProcess/qt/QtPageClient.cpp:
(QtPageClient::handleAuthenticationRequiredRequest):
* UIProcess/qt/QtPageClient.h:
* WebProcess/qt/QtNetworkAccessManager.cpp:
(WebKit::QtNetworkAccessManager::QtNetworkAccessManager):
(WebKit::QtNetworkAccessManager::onAuthenticationRequired):
* WebProcess/qt/QtNetworkAccessManager.h:

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@105146 268f45cc-cd09-0410-ab3c-d52691b4dbfc

14 files changed:
Source/WebKit2/ChangeLog
Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp
Source/WebKit2/UIProcess/API/qt/qquickwebview_p.h
Source/WebKit2/UIProcess/API/qt/qquickwebview_p_p.h
Source/WebKit2/UIProcess/PageClient.h
Source/WebKit2/UIProcess/WebPageProxy.cpp
Source/WebKit2/UIProcess/WebPageProxy.h
Source/WebKit2/UIProcess/WebPageProxy.messages.in
Source/WebKit2/UIProcess/qt/QtDialogRunner.cpp
Source/WebKit2/UIProcess/qt/QtDialogRunner.h
Source/WebKit2/UIProcess/qt/QtPageClient.cpp
Source/WebKit2/UIProcess/qt/QtPageClient.h
Source/WebKit2/WebProcess/qt/QtNetworkAccessManager.cpp
Source/WebKit2/WebProcess/qt/QtNetworkAccessManager.h

index 743b93a..f6d0f1c 100644 (file)
@@ -1,3 +1,49 @@
+2012-01-17  Alexander Færøy  <alexander.faeroy@nokia.com>
+
+        [Qt] Implement HTTP authentication QML API
+        https://bugs.webkit.org/show_bug.cgi?id=75535
+
+        Reviewed by Kenneth Rohde Christiansen.
+
+        This patch implements the QML API for handling HTTP authentication.
+        The implementation uses a syncronous message between the WebProcess
+        and the UIProcess which is called when the authenticationRequired
+        signal is emitted from QNAM.
+
+        Based in part upon patch by Peter Hartmann.
+
+        * UIProcess/API/qt/qquickwebview.cpp:
+        (QQuickWebViewPrivate::QQuickWebViewPrivate):
+        (QQuickWebViewPrivate::handleAuthenticationRequiredRequest):
+        (QQuickWebViewExperimental::authenticationDialog):
+        (QQuickWebViewExperimental::setAuthenticationDialog):
+        * UIProcess/API/qt/qquickwebview_p.h:
+        * UIProcess/API/qt/qquickwebview_p_p.h:
+        * UIProcess/PageClient.h:
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::authenticationRequiredRequest):
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/WebPageProxy.messages.in:
+        * UIProcess/qt/QtDialogRunner.cpp:
+        (AuthenticationDialogContextObject::AuthenticationDialogContextObject):
+        (AuthenticationDialogContextObject::hostname):
+        (AuthenticationDialogContextObject::realm):
+        (AuthenticationDialogContextObject::prefilledUsername):
+        (AuthenticationDialogContextObject::accept):
+        (AuthenticationDialogContextObject::reject):
+        (QtDialogRunner::initForAuthentication):
+        * UIProcess/qt/QtDialogRunner.h:
+        (QtDialogRunner::username):
+        (QtDialogRunner::password):
+        (QtDialogRunner::onAuthenticationAccepted):
+        * UIProcess/qt/QtPageClient.cpp:
+        (QtPageClient::handleAuthenticationRequiredRequest):
+        * UIProcess/qt/QtPageClient.h:
+        * WebProcess/qt/QtNetworkAccessManager.cpp:
+        (WebKit::QtNetworkAccessManager::QtNetworkAccessManager):
+        (WebKit::QtNetworkAccessManager::onAuthenticationRequired):
+        * WebProcess/qt/QtNetworkAccessManager.h:
+
 2012-01-16  Dan Bernstein  <mitz@apple.com>
 
         <rdar://problem/10702758> REGRESSION: Every Safari Reader WKView leaks
index 43d40b9..d3dac5d 100644 (file)
@@ -55,6 +55,7 @@ QQuickWebViewPrivate::QQuickWebViewPrivate(QQuickWebView* viewport)
     , alertDialog(0)
     , confirmDialog(0)
     , promptDialog(0)
+    , authenticationDialog(0)
     , itemSelector(0)
     , postTransitionState(adoptPtr(new PostTransitionState(this)))
     , isTransitioningToNewPage(false)
@@ -440,6 +441,26 @@ QString QQuickWebViewPrivate::runJavaScriptPrompt(const QString& message, const
     return dialogRunner.result();
 }
 
+void QQuickWebViewPrivate::handleAuthenticationRequiredRequest(const QString& hostname, const QString& realm, const QString& prefilledUsername, QString& username, QString& password)
+{
+    if (!authenticationDialog)
+        return;
+
+    Q_Q(QQuickWebView);
+    QtDialogRunner dialogRunner;
+    if (!dialogRunner.initForAuthentication(authenticationDialog, q, hostname, realm, prefilledUsername))
+        return;
+
+    setViewInAttachedProperties(dialogRunner.dialog());
+
+    disableMouseEvents();
+    dialogRunner.exec();
+    enableMouseEvents();
+
+    username = dialogRunner.username();
+    password = dialogRunner.password();
+}
+
 void QQuickWebViewPrivate::chooseFiles(WKOpenPanelResultListenerRef listenerRef, const QStringList& selectedFileNames, QtWebPageUIClient::FileChooserType type)
 {
 #ifndef QT_NO_FILEDIALOG
@@ -671,6 +692,21 @@ void QQuickWebViewExperimental::setPromptDialog(QDeclarativeComponent* promptDia
     emit promptDialogChanged();
 }
 
+QDeclarativeComponent* QQuickWebViewExperimental::authenticationDialog() const
+{
+    Q_D(const QQuickWebView);
+    return d->authenticationDialog;
+}
+
+void QQuickWebViewExperimental::setAuthenticationDialog(QDeclarativeComponent* authenticationDialog)
+{
+    Q_D(QQuickWebView);
+    if (d->authenticationDialog == authenticationDialog)
+        return;
+    d->authenticationDialog = authenticationDialog;
+    emit authenticationDialogChanged();
+}
+
 QDeclarativeComponent* QQuickWebViewExperimental::itemSelector() const
 {
     Q_D(const QQuickWebView);
index 0fa0791..155e960 100644 (file)
@@ -208,6 +208,7 @@ class QWEBKIT_EXPORT QQuickWebViewExperimental : public QObject {
     Q_PROPERTY(QDeclarativeComponent* alertDialog READ alertDialog WRITE setAlertDialog NOTIFY alertDialogChanged)
     Q_PROPERTY(QDeclarativeComponent* confirmDialog READ confirmDialog WRITE setConfirmDialog NOTIFY confirmDialogChanged)
     Q_PROPERTY(QDeclarativeComponent* promptDialog READ promptDialog WRITE setPromptDialog NOTIFY promptDialogChanged)
+    Q_PROPERTY(QDeclarativeComponent* authenticationDialog READ authenticationDialog WRITE setAuthenticationDialog NOTIFY authenticationDialogChanged)
     Q_PROPERTY(QDeclarativeComponent* itemSelector READ itemSelector WRITE setItemSelector NOTIFY itemSelectorChanged)
     Q_PROPERTY(QWebPreferences* preferences READ preferences CONSTANT FINAL)
     Q_PROPERTY(bool useTraditionalDesktopBehaviour READ useTraditionalDesktopBehaviour WRITE setUseTraditionalDesktopBehaviour)
@@ -229,6 +230,8 @@ public:
     void setConfirmDialog(QDeclarativeComponent*);
     QDeclarativeComponent* promptDialog() const;
     void setPromptDialog(QDeclarativeComponent*);
+    QDeclarativeComponent* authenticationDialog() const;
+    void setAuthenticationDialog(QDeclarativeComponent*);
     QDeclarativeComponent* itemSelector() const;
     void setItemSelector(QDeclarativeComponent*);
     
@@ -257,6 +260,7 @@ Q_SIGNALS:
     void alertDialogChanged();
     void confirmDialogChanged();
     void promptDialogChanged();
+    void authenticationDialogChanged();
     void itemSelectorChanged();
     void downloadRequested(QWebDownloadItem* downloadItem);
     void permissionRequested(QWebPermissionRequest* permission);
index 4be7170..e8e6bf7 100644 (file)
@@ -96,6 +96,8 @@ public:
     bool runJavaScriptConfirm(const QString&);
     QString runJavaScriptPrompt(const QString&, const QString& defaultValue, bool& ok);
 
+    void handleAuthenticationRequiredRequest(const QString& hostname, const QString& realm, const QString& prefilledUsername, QString& username, QString& password);
+
     void setUseTraditionalDesktopBehaviour(bool enable);
     void setViewInAttachedProperties(QObject*);
     void setIcon(const QUrl&);
@@ -150,6 +152,7 @@ private:
     QDeclarativeComponent* alertDialog;
     QDeclarativeComponent* confirmDialog;
     QDeclarativeComponent* promptDialog;
+    QDeclarativeComponent* authenticationDialog;
     QDeclarativeComponent* itemSelector;
 
     WebCore::ViewportArguments viewportArguments;
index c94ea1a..deabbd0 100644 (file)
@@ -110,6 +110,7 @@ public:
     virtual void didReceiveMessageFromNavigatorQtObject(const String&) = 0;
     virtual void handleDownloadRequest(DownloadProxy*) = 0;
     virtual void updateTextInputState() = 0;
+    virtual void handleAuthenticationRequiredRequest(const String& hostname, const String& realm, const String& prefilledUsername, String& username, String& password) = 0;
 #endif
 
 #if PLATFORM(QT) || PLATFORM(GTK)
index 7e08cec..b253daa 100644 (file)
@@ -2353,7 +2353,12 @@ void WebPageProxy::handleDownloadRequest(DownloadProxy* download)
 {
     m_pageClient->handleDownloadRequest(download);
 }
-#endif
+
+void WebPageProxy::authenticationRequiredRequest(const String& hostname, const String& realm, const String& prefilledUsername, String& username, String& password)
+{
+    m_pageClient->handleAuthenticationRequiredRequest(hostname, realm, prefilledUsername, username, password);
+}
+#endif // PLATFORM(QT).
 
 #if ENABLE(TOUCH_EVENTS)
 void WebPageProxy::needTouchEvents(bool needTouchEvents)
index 43e53b1..926502f 100644 (file)
@@ -320,6 +320,7 @@ public:
     void registerApplicationScheme(const String& scheme);
     void resolveApplicationSchemeRequest(QtNetworkRequestData);
     void sendApplicationSchemeReply(const QQuickNetworkReply*);
+    void authenticationRequiredRequest(const String& hostname, const String& realm, const String& prefilledUsername, String& username, String& password);
 #endif
 
 #if PLATFORM(QT)
index 5c2133a..875f5b9 100644 (file)
@@ -75,6 +75,7 @@ messages -> WebPageProxy {
     DidChangeContentsSize(WebCore::IntSize newSize)
     DidFindZoomableArea(WebCore::IntPoint target, WebCore::IntRect area)
     FocusEditableArea(WebCore::IntRect caret, WebCore::IntRect area)
+    AuthenticationRequiredRequest(WTF::String hostname, WTF::String realm, WTF::String prefilledUsername) -> (WTF::String username, WTF::String password)
 #endif
 #if ENABLE(TOUCH_EVENTS)
     NeedTouchEvents(bool needTouchEvents)
index 32de21a..f731ca4 100644 (file)
@@ -69,6 +69,39 @@ private:
     QString m_defaultValue;
 };
 
+class AuthenticationDialogContextObject : public QObject {
+    Q_OBJECT
+    Q_PROPERTY(QString hostname READ hostname CONSTANT)
+    Q_PROPERTY(QString realm READ realm CONSTANT)
+    Q_PROPERTY(QString prefilledUsername READ prefilledUsername CONSTANT)
+
+public:
+    AuthenticationDialogContextObject(const QString& hostname, const QString& realm, const QString& prefilledUsername)
+        : QObject()
+        , m_hostname(hostname)
+        , m_realm(realm)
+        , m_prefilledUsername(prefilledUsername)
+    {
+    }
+
+    QString hostname() const { return m_hostname; }
+    QString realm() const { return m_realm; }
+    QString prefilledUsername() const { return m_prefilledUsername; }
+
+public slots:
+    void accept(const QString& username, const QString& password) { emit accepted(username, password); }
+    void reject() { emit rejected(); }
+
+signals:
+    void accepted(const QString& username, const QString& password);
+    void rejected();
+
+private:
+    QString m_hostname;
+    QString m_realm;
+    QString m_prefilledUsername;
+};
+
 bool QtDialogRunner::initForAlert(QDeclarativeComponent* component, QQuickItem* dialogParent, const QString& message)
 {
     DialogContextObject* contextObject = new DialogContextObject(message);
@@ -103,6 +136,19 @@ bool QtDialogRunner::initForPrompt(QDeclarativeComponent* component, QQuickItem*
     return true;
 }
 
+bool QtDialogRunner::initForAuthentication(QDeclarativeComponent* component, QQuickItem* dialogParent, const QString& hostname, const QString& realm, const QString& prefilledUsername)
+{
+    AuthenticationDialogContextObject* contextObject = new AuthenticationDialogContextObject(hostname, realm, prefilledUsername);
+    if (!createDialog(component, dialogParent, contextObject))
+        return false;
+
+    connect(contextObject, SIGNAL(accepted(QString, QString)), SLOT(onAuthenticationAccepted(QString, QString)));
+    connect(contextObject, SIGNAL(accepted(QString, QString)), SLOT(quit()));
+    connect(contextObject, SIGNAL(rejected()), SLOT(quit()));
+
+    return true;
+}
+
 bool QtDialogRunner::createDialog(QDeclarativeComponent* component, QQuickItem* dialogParent, QObject* contextObject)
 {
     QDeclarativeContext* baseContext = component->creationContext();
index bfa5302..eb41070 100644 (file)
@@ -38,12 +38,16 @@ public:
     bool initForAlert(QDeclarativeComponent*, QQuickItem* dialogParent, const QString& message);
     bool initForConfirm(QDeclarativeComponent*, QQuickItem* dialogParent, const QString& message);
     bool initForPrompt(QDeclarativeComponent*, QQuickItem* dialogParent, const QString& message, const QString& defaultValue);
+    bool initForAuthentication(QDeclarativeComponent*, QQuickItem* dialogParent, const QString& hostname, const QString& realm, const QString& prefilledUsername);
 
     QQuickItem* dialog() const { return m_dialog.get(); }
 
     bool wasAccepted() const { return m_wasAccepted; }
     QString result() const { return m_result; }
 
+    QString username() const { return m_username; }
+    QString password() const { return m_password; }
+
 public slots:
     void onAccepted(const QString& result = QString())
     {
@@ -51,6 +55,12 @@ public slots:
         m_result = result;
     }
 
+    void onAuthenticationAccepted(const QString& username, const QString& password)
+    {
+        m_username = username;
+        m_password = password;
+    }
+
 private:
     bool createDialog(QDeclarativeComponent*, QQuickItem* dialogParent, QObject* contextObject);
 
@@ -58,6 +68,9 @@ private:
     OwnPtr<QQuickItem> m_dialog;
     QString m_result;
     bool m_wasAccepted;
+
+    QString m_username;
+    QString m_password;
 };
 
 #endif // QtDialogRunner_h
index cc96876..a1063b9 100644 (file)
@@ -107,6 +107,17 @@ void QtPageClient::handleApplicationSchemeRequest(PassRefPtr<QtNetworkRequestDat
     m_webView->experimental()->invokeApplicationSchemeHandler(requestData.get());
 }
 
+void QtPageClient::handleAuthenticationRequiredRequest(const String& hostname, const String& realm, const String& prefilledUsername, String& username, String& password)
+{
+    QString qUsername;
+    QString qPassword;
+
+    QQuickWebViewPrivate::get(m_webView)->handleAuthenticationRequiredRequest(hostname, realm, prefilledUsername, qUsername, qPassword);
+
+    username = qUsername;
+    password = qPassword;
+}
+
 void QtPageClient::setCursor(const WebCore::Cursor& cursor)
 {
     // FIXME: This is a temporary fix until we get cursor support in QML items.
index 7715026..81dfddf 100644 (file)
@@ -54,6 +54,7 @@ public:
     virtual PassOwnPtr<DrawingAreaProxy> createDrawingAreaProxy();
     virtual void handleDownloadRequest(DownloadProxy*);
     virtual void handleApplicationSchemeRequest(PassRefPtr<QtNetworkRequestData>);
+    virtual void handleAuthenticationRequiredRequest(const String& hostname, const String& realm, const String& prefilledUsername, String& username, String& password);
 
     virtual void displayView();
     virtual void scrollView(const WebCore::IntRect& scrollRect, const WebCore::IntSize& scrollOffset);
index 178a565..bb85d9a 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2011 Zeno Albisser <zeno@webkit.org>
+ * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -29,7 +30,9 @@
 #include "SharedMemory.h"
 #include "WebFrameNetworkingContext.h"
 #include "WebPage.h"
+#include "WebPageProxyMessages.h"
 #include "WebProcess.h"
+#include <QAuthenticator>
 #include <QNetworkReply>
 #include <QNetworkRequest>
 
@@ -39,6 +42,7 @@ QtNetworkAccessManager::QtNetworkAccessManager(WebProcess* webProcess)
     : QNetworkAccessManager()
     , m_webProcess(webProcess)
 {
+    connect(this, SIGNAL(authenticationRequired(QNetworkReply*, QAuthenticator*)), SLOT(onAuthenticationRequired(QNetworkReply*, QAuthenticator*)));
 }
 
 WebPage* QtNetworkAccessManager::obtainOriginatingWebPage(const QNetworkRequest& request)
@@ -68,6 +72,30 @@ void QtNetworkAccessManager::registerApplicationScheme(const WebPage* page, cons
     m_applicationSchemes.insert(page, scheme.toLower());
 }
 
+void QtNetworkAccessManager::onAuthenticationRequired(QNetworkReply* reply, QAuthenticator* authenticator)
+{
+    WebPage* webPage = obtainOriginatingWebPage(reply->request());
+
+    // FIXME: This check can go away once our Qt version is up-to-date. See: QTBUG-23512.
+    if (!webPage)
+        return;
+
+    String hostname = reply->url().toString(QUrl::RemovePath | QUrl::RemoveQuery | QUrl::RemoveFragment | QUrl::StripTrailingSlash);
+    String realm = authenticator->realm();
+    String prefilledUsername = authenticator->user();
+    String username;
+    String password;
+
+    if (webPage->sendSync(
+        Messages::WebPageProxy::AuthenticationRequiredRequest(hostname, realm, prefilledUsername),
+        Messages::WebPageProxy::AuthenticationRequiredRequest::Reply(username, password))) {
+        if (!username.isEmpty())
+            authenticator->setUser(username);
+        if (!password.isEmpty())
+            authenticator->setPassword(password);
+    }
+}
+
 }
 
 #include "moc_QtNetworkAccessManager.cpp"
index 1af6fc2..b224c13 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2011 Zeno Albisser <zeno@webkit.org>
+ * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -44,6 +45,9 @@ public:
 protected:
     virtual QNetworkReply* createRequest(Operation, const QNetworkRequest&, QIODevice* outgoingData = 0) OVERRIDE;
 
+private Q_SLOTS:
+    void onAuthenticationRequired(QNetworkReply *, QAuthenticator *);
+
 private:
     WebPage* obtainOriginatingWebPage(const QNetworkRequest&);