From: commit-queue@webkit.org Date: Tue, 17 Jan 2012 13:17:51 +0000 (+0000) Subject: [Qt] Implement HTTP authentication QML API X-Git-Tag: 070512121124~15197 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=1eab810c91ad51f5525a5f510042393c151720f9;p=profile%2Fivi%2Fwebkit-efl.git [Qt] Implement HTTP authentication QML API https://bugs.webkit.org/show_bug.cgi?id=75535 Patch by Alexander Færøy 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 --- diff --git a/Source/WebKit2/ChangeLog b/Source/WebKit2/ChangeLog index 743b93a..f6d0f1c4 100644 --- a/Source/WebKit2/ChangeLog +++ b/Source/WebKit2/ChangeLog @@ -1,3 +1,49 @@ +2012-01-17 Alexander Færøy + + [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 REGRESSION: Every Safari Reader WKView leaks diff --git a/Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp b/Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp index 43d40b9..d3dac5d 100644 --- a/Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp +++ b/Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp @@ -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); diff --git a/Source/WebKit2/UIProcess/API/qt/qquickwebview_p.h b/Source/WebKit2/UIProcess/API/qt/qquickwebview_p.h index 0fa0791..155e960 100644 --- a/Source/WebKit2/UIProcess/API/qt/qquickwebview_p.h +++ b/Source/WebKit2/UIProcess/API/qt/qquickwebview_p.h @@ -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); diff --git a/Source/WebKit2/UIProcess/API/qt/qquickwebview_p_p.h b/Source/WebKit2/UIProcess/API/qt/qquickwebview_p_p.h index 4be7170..e8e6bf7 100644 --- a/Source/WebKit2/UIProcess/API/qt/qquickwebview_p_p.h +++ b/Source/WebKit2/UIProcess/API/qt/qquickwebview_p_p.h @@ -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; diff --git a/Source/WebKit2/UIProcess/PageClient.h b/Source/WebKit2/UIProcess/PageClient.h index c94ea1a..deabbd0 100644 --- a/Source/WebKit2/UIProcess/PageClient.h +++ b/Source/WebKit2/UIProcess/PageClient.h @@ -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) diff --git a/Source/WebKit2/UIProcess/WebPageProxy.cpp b/Source/WebKit2/UIProcess/WebPageProxy.cpp index 7e08cec..b253daa 100644 --- a/Source/WebKit2/UIProcess/WebPageProxy.cpp +++ b/Source/WebKit2/UIProcess/WebPageProxy.cpp @@ -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) diff --git a/Source/WebKit2/UIProcess/WebPageProxy.h b/Source/WebKit2/UIProcess/WebPageProxy.h index 43e53b1..926502f 100644 --- a/Source/WebKit2/UIProcess/WebPageProxy.h +++ b/Source/WebKit2/UIProcess/WebPageProxy.h @@ -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) diff --git a/Source/WebKit2/UIProcess/WebPageProxy.messages.in b/Source/WebKit2/UIProcess/WebPageProxy.messages.in index 5c2133a..875f5b9 100644 --- a/Source/WebKit2/UIProcess/WebPageProxy.messages.in +++ b/Source/WebKit2/UIProcess/WebPageProxy.messages.in @@ -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) diff --git a/Source/WebKit2/UIProcess/qt/QtDialogRunner.cpp b/Source/WebKit2/UIProcess/qt/QtDialogRunner.cpp index 32de21a..f731ca4 100644 --- a/Source/WebKit2/UIProcess/qt/QtDialogRunner.cpp +++ b/Source/WebKit2/UIProcess/qt/QtDialogRunner.cpp @@ -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(); diff --git a/Source/WebKit2/UIProcess/qt/QtDialogRunner.h b/Source/WebKit2/UIProcess/qt/QtDialogRunner.h index bfa5302..eb41070 100644 --- a/Source/WebKit2/UIProcess/qt/QtDialogRunner.h +++ b/Source/WebKit2/UIProcess/qt/QtDialogRunner.h @@ -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 m_dialog; QString m_result; bool m_wasAccepted; + + QString m_username; + QString m_password; }; #endif // QtDialogRunner_h diff --git a/Source/WebKit2/UIProcess/qt/QtPageClient.cpp b/Source/WebKit2/UIProcess/qt/QtPageClient.cpp index cc96876..a1063b9 100644 --- a/Source/WebKit2/UIProcess/qt/QtPageClient.cpp +++ b/Source/WebKit2/UIProcess/qt/QtPageClient.cpp @@ -107,6 +107,17 @@ void QtPageClient::handleApplicationSchemeRequest(PassRefPtrexperimental()->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. diff --git a/Source/WebKit2/UIProcess/qt/QtPageClient.h b/Source/WebKit2/UIProcess/qt/QtPageClient.h index 7715026..81dfddf 100644 --- a/Source/WebKit2/UIProcess/qt/QtPageClient.h +++ b/Source/WebKit2/UIProcess/qt/QtPageClient.h @@ -54,6 +54,7 @@ public: virtual PassOwnPtr createDrawingAreaProxy(); virtual void handleDownloadRequest(DownloadProxy*); virtual void handleApplicationSchemeRequest(PassRefPtr); + 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); diff --git a/Source/WebKit2/WebProcess/qt/QtNetworkAccessManager.cpp b/Source/WebKit2/WebProcess/qt/QtNetworkAccessManager.cpp index 178a565..bb85d9a 100644 --- a/Source/WebKit2/WebProcess/qt/QtNetworkAccessManager.cpp +++ b/Source/WebKit2/WebProcess/qt/QtNetworkAccessManager.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2011 Zeno Albisser + * 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 #include #include @@ -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" diff --git a/Source/WebKit2/WebProcess/qt/QtNetworkAccessManager.h b/Source/WebKit2/WebProcess/qt/QtNetworkAccessManager.h index 1af6fc2..b224c13 100644 --- a/Source/WebKit2/WebProcess/qt/QtNetworkAccessManager.h +++ b/Source/WebKit2/WebProcess/qt/QtNetworkAccessManager.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2011 Zeno Albisser + * 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&);