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
+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
, alertDialog(0)
, confirmDialog(0)
, promptDialog(0)
+ , authenticationDialog(0)
, itemSelector(0)
, postTransitionState(adoptPtr(new PostTransitionState(this)))
, isTransitioningToNewPage(false)
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
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);
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)
void setConfirmDialog(QDeclarativeComponent*);
QDeclarativeComponent* promptDialog() const;
void setPromptDialog(QDeclarativeComponent*);
+ QDeclarativeComponent* authenticationDialog() const;
+ void setAuthenticationDialog(QDeclarativeComponent*);
QDeclarativeComponent* itemSelector() const;
void setItemSelector(QDeclarativeComponent*);
void alertDialogChanged();
void confirmDialogChanged();
void promptDialogChanged();
+ void authenticationDialogChanged();
void itemSelectorChanged();
void downloadRequested(QWebDownloadItem* downloadItem);
void permissionRequested(QWebPermissionRequest* permission);
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&);
QDeclarativeComponent* alertDialog;
QDeclarativeComponent* confirmDialog;
QDeclarativeComponent* promptDialog;
+ QDeclarativeComponent* authenticationDialog;
QDeclarativeComponent* itemSelector;
WebCore::ViewportArguments viewportArguments;
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)
{
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)
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)
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)
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);
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();
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())
{
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);
OwnPtr<QQuickItem> m_dialog;
QString m_result;
bool m_wasAccepted;
+
+ QString m_username;
+ QString m_password;
};
#endif // QtDialogRunner_h
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.
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);
/*
* 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
#include "SharedMemory.h"
#include "WebFrameNetworkingContext.h"
#include "WebPage.h"
+#include "WebPageProxyMessages.h"
#include "WebProcess.h"
+#include <QAuthenticator>
#include <QNetworkReply>
#include <QNetworkRequest>
: QNetworkAccessManager()
, m_webProcess(webProcess)
{
+ connect(this, SIGNAL(authenticationRequired(QNetworkReply*, QAuthenticator*)), SLOT(onAuthenticationRequired(QNetworkReply*, QAuthenticator*)));
}
WebPage* QtNetworkAccessManager::obtainOriginatingWebPage(const QNetworkRequest& request)
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"
/*
* 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
protected:
virtual QNetworkReply* createRequest(Operation, const QNetworkRequest&, QIODevice* outgoingData = 0) OVERRIDE;
+private Q_SLOTS:
+ void onAuthenticationRequired(QNetworkReply *, QAuthenticator *);
+
private:
WebPage* obtainOriginatingWebPage(const QNetworkRequest&);