Index: GNUmakefile.am =================================================================== --- GNUmakefile.am (revision 30475) +++ GNUmakefile.am (working copy) @@ -251,6 +251,7 @@ webkitgtk_h_api += \ WebKit/gtk/webkit/webkit.h \ WebKit/gtk/webkit/webkitdefines.h \ WebKit/gtk/webkit/webkitnetworkrequest.h \ + WebKit/gtk/webkit/webkitwebauthchallenge.h \ WebKit/gtk/webkit/webkitwebbackforwardlist.h \ WebKit/gtk/webkit/webkitwebframe.h \ WebKit/gtk/webkit/webkitwebhistoryitem.h \ @@ -274,6 +275,7 @@ webkitgtk_headers += \ webkitgtk_sources += \ WebKit/gtk/webkit/webkitnetworkrequest.cpp \ WebKit/gtk/webkit/webkitprivate.cpp \ + WebKit/gtk/webkit/webkitwebauthchallenge.cpp \ WebKit/gtk/webkit/webkitwebbackforwardlist.cpp \ WebKit/gtk/webkit/webkitwebframe.cpp \ WebKit/gtk/webkit/webkitwebhistoryitem.cpp \ Index: WebCore/WebCore.pro =================================================================== --- WebCore/WebCore.pro (revision 30475) +++ WebCore/WebCore.pro (working copy) @@ -995,6 +995,7 @@ gtk-port { ../WebKit/gtk/webkit/webkitdefines.h \ ../WebKit/gtk/webkit/webkitnetworkrequest.h \ ../WebKit/gtk/webkit/webkitprivate.h \ + ../WebKit/gtk/webkit/webkitwebauthchallenge.h \ ../WebKit/gtk/webkit/webkitwebbackforwardlist.h \ ../WebKit/gtk/webkit/webkitwebframe.h \ ../WebKit/gtk/webkit/webkitwebhistoryitem.h \ @@ -1075,6 +1076,7 @@ gtk-port { platform/image-decoders/xbm/XBMImageDecoder.cpp \ ../WebKit/gtk/webkit/webkitnetworkrequest.cpp \ ../WebKit/gtk/webkit/webkitprivate.cpp \ + ../WebKit/gtk/webkit/webkitwebauthchallenge.cpp \ ../WebKit/gtk/webkit/webkitwebbackforwardlist.cpp \ ../WebKit/gtk/webkit/webkitwebframe.cpp \ ../WebKit/gtk/webkit/webkitwebhistoryitem.cpp \ Index: WebCore/platform/network/ResourceHandle.h =================================================================== --- WebCore/platform/network/ResourceHandle.h (revision 30475) +++ WebCore/platform/network/ResourceHandle.h (working copy) @@ -97,7 +97,7 @@ public: ~ResourceHandle(); -#if PLATFORM(MAC) || USE(CFNETWORK) +#if PLATFORM(MAC) || USE(CFNETWORK) || USE(CURL) void didReceiveAuthenticationChallenge(const AuthenticationChallenge&); void receivedCredential(const AuthenticationChallenge&, const Credential&); void receivedRequestToContinueWithoutCredential(const AuthenticationChallenge&); Index: WebCore/platform/network/ResourceHandleInternal.h =================================================================== --- WebCore/platform/network/ResourceHandleInternal.h (revision 30475) +++ WebCore/platform/network/ResourceHandleInternal.h (working copy) @@ -101,6 +101,8 @@ namespace WebCore { , m_file(0) , m_formDataElementIndex(0) , m_formDataElementDataOffset(0) + , m_webChallenge() + , m_continueWithoutCredential(false) #endif #if PLATFORM(QT) , m_job(0) @@ -159,6 +161,9 @@ namespace WebCore { size_t m_formDataElementIndex; size_t m_formDataElementDataOffset; Vector m_postBytes; + + AuthenticationChallenge m_webChallenge; + bool m_continueWithoutCredential; #endif #if PLATFORM(QT) #if QT_VERSION < 0x040400 Index: WebCore/platform/network/curl/ResourceHandleCurl.cpp =================================================================== --- WebCore/platform/network/curl/ResourceHandleCurl.cpp (revision 30475) +++ WebCore/platform/network/curl/ResourceHandleCurl.cpp (working copy) @@ -95,4 +95,69 @@ void ResourceHandle::loadResourceSynchro notImplemented(); } +void ResourceHandle::didReceiveAuthenticationChallenge(const AuthenticationChallenge& challenge) +{ + /* FIXME: add support for FTP, HTTPS, and FTPS authentication, + * get the right port, server and authentication scheme + */ + ResourceHandleInternal* d = getInternal(); + if (d->m_continueWithoutCredential) + return; + cancel(); + + ProtectionSpace protectionSpace; + unsigned previousFailureCount = 0; + if (challenge.isNull()) { + protectionSpace = ProtectionSpace(d->m_response.httpHeaderField("Host"), + 80, + ProtectionSpaceServerHTTP, + d->m_response.httpHeaderField("Realm"), + ProtectionSpaceAuthenticationSchemeDefault); + } else { + protectionSpace = d->m_webChallenge.protectionSpace(); + previousFailureCount = d->m_webChallenge.previousFailureCount()+1; + } + + d->m_webChallenge = AuthenticationChallenge(protectionSpace, + challenge.proposedCredential(), + previousFailureCount, + d->m_response, + challenge.error()); + + if (d->client()) + d->client()->didReceiveAuthenticationChallenge(this, d->m_webChallenge); +} + +void ResourceHandle::receivedCredential(const AuthenticationChallenge& challenge, const Credential& credential) +{ + ASSERT(!challenge.isNull()); + ResourceHandleInternal* d = getInternal(); + if (challenge != d->m_webChallenge) + return; + + d->m_webChallenge = AuthenticationChallenge(challenge.protectionSpace(), + credential, + challenge.previousFailureCount(), + challenge.failureResponse(), + challenge.error()); + + ResourceHandleManager::sharedInstance()->add(this); +} + +void ResourceHandle::receivedRequestToContinueWithoutCredential(const AuthenticationChallenge& challenge) +{ + ASSERT(!challenge.isNull()); + ResourceHandleInternal* d = getInternal(); + if (challenge != d->m_webChallenge) + return; + + d->m_continueWithoutCredential = true; + ResourceHandleManager::sharedInstance()->add(this); +} + +void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challenge) +{ + notImplemented(); +} + } // namespace WebCore Index: WebCore/platform/network/curl/ResourceHandleManager.cpp =================================================================== --- WebCore/platform/network/curl/ResourceHandleManager.cpp (revision 30475) +++ WebCore/platform/network/curl/ResourceHandleManager.cpp (working copy) @@ -170,6 +170,10 @@ static size_t headerCallback(char* ptr, d->m_response.setTextEncodingName(extractCharsetFromMediaType(d->m_response.httpHeaderField("Content-Type"))); d->m_response.setSuggestedFilename(filenameFromHTTPContentDisposition(d->m_response.httpHeaderField("Content-Disposition"))); + // HTTP authentication + if (httpCode == 401 && d->m_response.isHTTP()) + job->didReceiveAuthenticationChallenge(d->m_webChallenge); + // HTTP redirection if (httpCode >= 300 && httpCode < 400) { String location = d->m_response.httpHeaderField("location"); @@ -557,6 +561,9 @@ void ResourceHandleManager::startJob(Res } d->m_handle = curl_easy_init(); + // HTTP Authentication cancels the job so be sure the new job is not cancelled + d->m_cancelled = false; + #ifndef NDEBUG if (getenv("DEBUG_CURL")) curl_easy_setopt(d->m_handle, CURLOPT_VERBOSE, 1); @@ -590,6 +597,23 @@ void ResourceHandleManager::startJob(Res curl_easy_setopt(d->m_handle, CURLOPT_COOKIEJAR, m_cookieJarFileName); } + if (!d->m_webChallenge.isNull() && !d->m_continueWithoutCredential) { + long curlAuth; + switch(d->m_webChallenge.protectionSpace().authenticationScheme()) { + case ProtectionSpaceAuthenticationSchemeHTTPBasic: + case ProtectionSpaceAuthenticationSchemeDefault: + default: + curlAuth = CURLAUTH_BASIC; + break; + } + + Credential credential = d->m_webChallenge.proposedCredential(); + String userpwd = credential.user() + ":" + credential.password(); + + curl_easy_setopt(d->m_handle, CURLOPT_HTTPAUTH, curlAuth); + curl_easy_setopt(d->m_handle, CURLOPT_USERPWD, strdup(userpwd.utf8().data())); + } + struct curl_slist* headers = 0; if (job->request().httpHeaderFields().size() > 0) { HTTPHeaderMap customHeaders = job->request().httpHeaderFields(); Index: WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.cpp =================================================================== --- WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.cpp (revision 30475) +++ WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.cpp (working copy) @@ -30,6 +30,7 @@ #include "HTMLFrameOwnerElement.h" #include "HTMLNames.h" #include "Language.h" +#include "MainResourceLoader.h" #include "MIMETypeRegistry.h" #include "NotImplemented.h" #include "PlatformString.h" @@ -39,6 +40,7 @@ #include "kjs_binding.h" #include "kjs_proxy.h" #include "kjs_window.h" +#include "webkitwebauthchallenge.h" #include "webkitwebview.h" #include "webkitwebframe.h" #include "webkitprivate.h" @@ -165,9 +167,24 @@ void FrameLoaderClient::committedLoad(Do fl->addData(data, length); } -void FrameLoaderClient::dispatchDidReceiveAuthenticationChallenge(DocumentLoader*, unsigned long identifier, const AuthenticationChallenge&) +void FrameLoaderClient::dispatchDidReceiveAuthenticationChallenge(DocumentLoader* documentLoader, unsigned long identifier, const AuthenticationChallenge& webChallenge) { - notImplemented(); + ResourceHandle* handle = documentLoader->mainResourceLoader()->handle(); + ASSERT(handle); + if (!handle) + return; + + WebKitWebAuthChallenge* challenge = webkit_web_auth_challenge_new(); + WebKitWebAuthChallengePrivate* challengePrivate = WEBKIT_WEB_AUTH_CHALLENGE_GET_PRIVATE(challenge); + *challengePrivate->webChallenge = webChallenge; + challengePrivate->webHandle = handle; + + Credential credential = webChallenge.proposedCredential(); + webkit_web_auth_challenge_set_user(challenge, credential.user().utf8().data()); + webkit_web_auth_challenge_set_password(challenge, credential.password().utf8().data()); + + WebKitWebView* webView = getViewFromFrame(m_frame); + g_signal_emit_by_name(webView, "authentication-requested", m_frame, challenge, NULL); } void FrameLoaderClient::dispatchDidCancelAuthenticationChallenge(DocumentLoader*, unsigned long identifier, const AuthenticationChallenge&) Index: WebKit/gtk/webkit/webkitdefines.h =================================================================== --- WebKit/gtk/webkit/webkitdefines.h (revision 30475) +++ WebKit/gtk/webkit/webkitdefines.h (working copy) @@ -46,6 +46,9 @@ typedef struct _WebKitNetworkRequestClas typedef struct _WebKitWebBackForwardList WebKitWebBackForwardList; typedef struct _WebKitWebBackForwardListClass WebKitWebBackForwardListClass; +typedef struct _WebKitWebAuthChallenge WebKitWebAuthChallenge; +typedef struct _WebKitWebAuthChallengeClass WebKitWebAuthChallengeClass; + typedef struct _WebKitWebHistoryItem WebKitWebHistoryItem; typedef struct _WebKitWebHistoryItemClass WebKitWebHistoryItemClass; Index: WebKit/gtk/webkit/webkitprivate.h =================================================================== --- WebKit/gtk/webkit/webkitprivate.h (revision 30475) +++ WebKit/gtk/webkit/webkitprivate.h (working copy) @@ -27,12 +27,14 @@ */ #include +#include #include #include #include #include #include +#include "AuthenticationChallenge.h" #include "BackForwardList.h" #include "HistoryItem.h" #include "Settings.h" @@ -105,6 +107,17 @@ extern "C" { struct _WebKitNetworkRequestPrivate { gchar* uri; }; + + #define WEBKIT_WEB_AUTH_CHALLENGE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), WEBKIT_TYPE_WEB_AUTH_CHALLENGE, WebKitWebAuthChallengePrivate)) + typedef struct _WebKitWebAuthChallengePrivate WebKitWebAuthChallengePrivate; + struct _WebKitWebAuthChallengePrivate { + WebCore::AuthenticationChallenge* webChallenge; + WebCore::ResourceHandle* webHandle; + gchar* user; + gchar* password; + + gboolean response_fired; + }; WebKitWebFrame* webkit_web_frame_init_with_web_view(WebKitWebView*, WebCore::HTMLFrameOwnerElement*); Index: WebKit/gtk/webkit/webkitwebauthchallenge.cpp =================================================================== --- WebKit/gtk/webkit/webkitwebauthchallenge.cpp (revision 0) +++ WebKit/gtk/webkit/webkitwebauthchallenge.cpp (revision 0) @@ -0,0 +1,260 @@ +/* + * Copyright (C) 2008 Luca Bruno + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" + +#include "webkitprivate.h" +#include "webkitwebauthchallenge.h" + +#include "AuthenticationChallenge.h" +#include "Credential.h" +#include "ResourceHandle.h" + +using namespace WebKit; +using namespace WebCore; + +extern "C" { + +enum { + PROP_0, + + PROP_USER, + PROP_PASSWORD, +}; + +G_DEFINE_TYPE(WebKitWebAuthChallenge, webkit_web_auth_challenge, G_TYPE_OBJECT); + +static void webkit_web_auth_challenge_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) +{ + WebKitWebAuthChallenge* challenge = WEBKIT_WEB_AUTH_CHALLENGE(object); + + switch(prop_id) { + case PROP_USER: + g_value_set_string(value, webkit_web_auth_challenge_get_user(challenge)); + break; + case PROP_PASSWORD: + g_value_set_string(value, webkit_web_auth_challenge_get_password(challenge)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void webkit_web_auth_challenge_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec *pspec) +{ + WebKitWebAuthChallenge* challenge = WEBKIT_WEB_AUTH_CHALLENGE(object); + + switch(prop_id) { + case PROP_USER: + webkit_web_auth_challenge_set_user(challenge, g_value_get_string(value)); + break; + case PROP_PASSWORD: + webkit_web_auth_challenge_set_password(challenge, g_value_get_string(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + } +} + +static void webkit_web_auth_challenge_finalize(GObject* object) +{ + WebKitWebAuthChallenge* challenge = WEBKIT_WEB_AUTH_CHALLENGE(object); + WebKitWebAuthChallengePrivate* priv = challenge->priv; + + delete priv->webChallenge; + g_free(priv->user); + g_free(priv->password); + + G_OBJECT_CLASS(webkit_web_auth_challenge_parent_class)->finalize(object); +} + +static void webkit_web_auth_challenge_class_init(WebKitWebAuthChallengeClass* challengeClass) +{ + g_type_class_add_private(challengeClass, sizeof(WebKitWebAuthChallengePrivate)); + + GObjectClass* objectClass = G_OBJECT_CLASS(challengeClass); + objectClass->finalize = webkit_web_auth_challenge_finalize; + objectClass->get_property = webkit_web_auth_challenge_get_property; + objectClass->set_property = webkit_web_auth_challenge_set_property; +} + +static void webkit_web_auth_challenge_init(WebKitWebAuthChallenge* challenge) +{ + WebKitWebAuthChallengePrivate* priv = WEBKIT_WEB_AUTH_CHALLENGE_GET_PRIVATE(challenge); + challenge->priv = priv; + + priv->webChallenge = new AuthenticationChallenge(); + priv->webHandle = NULL; + priv->user = NULL; + priv->password = NULL; + priv->response_fired = FALSE; +} + +/** + * webkit_web_auth_challenge_new: + * + * This function returns a new WebKitWebAuthChallenge object. + * The purpose of this class is to response to authentication requested to access protected web resources. + * + * Usually the application doesn't need to create this object. + * + * Return value: the #WebKitWebAuthChallenge + **/ +WebKitWebAuthChallenge* webkit_web_auth_challenge_new() +{ + WebKitWebAuthChallenge* challenge = WEBKIT_WEB_AUTH_CHALLENGE(g_object_new(WEBKIT_TYPE_WEB_AUTH_CHALLENGE, NULL)); + + return challenge; +} + +/** + * webkit_web_auth_challenge_set_user: + * @challenge: a #WebKitWebAuthChallenge + * @user: a string with the username + * + * Set the username for the authentication @challenge. + */ +void webkit_web_auth_challenge_set_user(WebKitWebAuthChallenge* challenge, const gchar* user) +{ + g_return_if_fail(WEBKIT_IS_WEB_AUTH_CHALLENGE(challenge)); + g_return_if_fail(user); + + WebKitWebAuthChallengePrivate* priv = challenge->priv; + + g_free(priv->user); + priv->user = g_strdup(user); +} + +/** + * webkit_web_auth_challenge_get_user + * @challenge: a #WebKitWebAuthChallenge + * + * Returns the current username used by the authentication @challenge. + * + * Return value: the username + */ +const gchar* webkit_web_auth_challenge_get_user(WebKitWebAuthChallenge* challenge) +{ + g_return_val_if_fail(WEBKIT_IS_WEB_AUTH_CHALLENGE(challenge), NULL); + + WebKitWebAuthChallengePrivate* priv = challenge->priv; + + return priv->user; +} + +/** + * webkit_web_auth_challenge_set_password: + * @challenge: a #WebKitWebAuthChallenge + * @password: a string with the password + * + * Set the password for the authentication @challenge. + */ +void webkit_web_auth_challenge_set_password(WebKitWebAuthChallenge* challenge, const gchar* password) +{ + g_return_if_fail(WEBKIT_IS_WEB_AUTH_CHALLENGE(challenge)); + g_return_if_fail(password); + + WebKitWebAuthChallengePrivate* priv = challenge->priv; + + g_free(priv->password); + priv->password = g_strdup(password); +} + +/** + * webkit_web_auth_challenge_get_password + * @challenge: a #WebKitWebAuthChallenge + * + * Returns the current password used by the authentication @challenge. + * + * Return value: the password + */ +const gchar* webkit_web_auth_challenge_get_password(WebKitWebAuthChallenge* challenge) +{ + g_return_val_if_fail(WEBKIT_IS_WEB_AUTH_CHALLENGE(challenge), NULL); + + WebKitWebAuthChallengePrivate* priv = challenge->priv; + + return priv->password; +} + +/** + * webkit_web_auth_challenge_use_credential + * @challenge: a #WebKitWebAuthChallenge + * + * Response the credential of @challenge to be used for the requested authentication. + * + * After this response, the @challenge can't be used for any further responses on the + * same authentication request. + */ +void webkit_web_auth_challenge_use_credential(WebKitWebAuthChallenge* challenge) +{ + g_return_if_fail(WEBKIT_IS_WEB_AUTH_CHALLENGE(challenge)); + + WebKitWebAuthChallengePrivate* priv = challenge->priv; + g_return_if_fail(!priv->response_fired); + + Credential credential = Credential(String::fromUTF8(priv->user), + String::fromUTF8(priv->password), + CredentialPersistenceForSession); + priv->webHandle->receivedCredential(*priv->webChallenge, credential); + priv->response_fired = TRUE; +} + +/** + * webkit_web_auth_challenge_continue_without_credential + * @challenge: a #WebKitWebAuthChallenge + * + * Response to continue loading the requested resource without any credential. + * + * After this response, the @challenge can't be used for any further responses on the + * same authentication request. + */ +void webkit_web_auth_challenge_continue_without_credential(WebKitWebAuthChallenge* challenge) +{ + g_return_if_fail(WEBKIT_IS_WEB_AUTH_CHALLENGE(challenge)); + + WebKitWebAuthChallengePrivate* priv = challenge->priv; + g_return_if_fail(!priv->response_fired); + + priv->webHandle->receivedRequestToContinueWithoutCredential(*priv->webChallenge); + priv->response_fired = TRUE; +} + +/** + * webkit_web_auth_challenge_cancel + * @challenge: a #WebKitWebAuthChallenge + * + * Response to cancel the current authentication @challenge for the requested resource. + * + * After this response, the @challenge can't be used for any further responses on the + * same authentication request. + */ +void webkit_web_auth_challenge_cancel(WebKitWebAuthChallenge* challenge) +{ + g_return_if_fail(WEBKIT_IS_WEB_AUTH_CHALLENGE(challenge)); + + WebKitWebAuthChallengePrivate* priv = challenge->priv; + g_return_if_fail(!priv->response_fired); + + priv->webHandle->receivedCancellation(*priv->webChallenge); + priv->response_fired = TRUE; +} + +} Index: WebKit/gtk/webkit/webkitwebauthchallenge.h =================================================================== --- WebKit/gtk/webkit/webkitwebauthchallenge.h (revision 0) +++ WebKit/gtk/webkit/webkitwebauthchallenge.h (revision 0) @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2008 Luca Bruno + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef WEBKIT_WEB_AUTH_CHALLENGE_H +#define WEBKIT_WEB_AUTH_CHALLENGE_H + +#include + +#include "webkitdefines.h" + +G_BEGIN_DECLS + +#define WEBKIT_TYPE_WEB_AUTH_CHALLENGE (webkit_web_auth_challenge_get_type()) +#define WEBKIT_WEB_AUTH_CHALLENGE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_WEB_AUTH_CHALLENGE, WebKitWebAuthChallenge)) +#define WEBKIT_WEB_AUTH_CHALLENGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WEBKIT_TYPE_WEB_AUTH_CHALLENGE, WebKitWebAuthChallengeClass)) +#define WEBKIT_IS_WEB_AUTH_CHALLENGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_WEB_AUTH_CHALLENGE)) +#define WEBKIT_IS_WEB_AUTH_CHALLENGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WEBKIT_TYPE_WEB_AUTH_CHALLENGE)) +#define WEBKIT_WEB_AUTH_CHALLENGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WEBKIT_TYPE_WEB_AUTH_CHALLENGE, WebKitWebAuthChallengeClass)) + +typedef struct _WebKitWebAuthChallengePrivate WebKitWebAuthChallengePrivate; + +struct _WebKitWebAuthChallenge { + GObject parent; + + WebKitWebAuthChallengePrivate* priv; +}; + +struct _WebKitWebAuthChallengeClass { + GObjectClass parent; +}; + +WEBKIT_API GType +webkit_web_auth_challenge_get_type (void); + +WEBKIT_API WebKitWebAuthChallenge* +webkit_web_auth_challenge_new (); + +WEBKIT_API void +webkit_web_auth_challenge_set_user (WebKitWebAuthChallenge* challenge, const gchar* user); + +WEBKIT_API const gchar* +webkit_web_auth_challenge_get_user (WebKitWebAuthChallenge* challenge); + +WEBKIT_API void +webkit_web_auth_challenge_set_password (WebKitWebAuthChallenge* challenge, const gchar* password); + +WEBKIT_API const gchar* +webkit_web_auth_challenge_get_password (WebKitWebAuthChallenge* challenge); + +WEBKIT_API void +webkit_web_auth_challenge_use_credential (WebKitWebAuthChallenge* challenge); + +WEBKIT_API void +webkit_web_auth_challenge_continue_without_credential (WebKitWebAuthChallenge* challenge); + +WEBKIT_API void +webkit_web_auth_challenge_cancel (WebKitWebAuthChallenge* challenge); + +G_END_DECLS + +#endif Index: WebKit/gtk/webkit/webkitwebview.cpp =================================================================== --- WebKit/gtk/webkit/webkitwebview.cpp (revision 30475) +++ WebKit/gtk/webkit/webkitwebview.cpp (working copy) @@ -85,6 +85,7 @@ enum { COPY_CLIPBOARD, PASTE_CLIPBOARD, CUT_CLIPBOARD, + AUTHENTICATION_REQUESTED, LAST_SIGNAL }; @@ -395,7 +396,7 @@ static gboolean webkit_web_view_focus_in GtkWidget* toplevel = gtk_widget_get_toplevel(widget); if (GTK_WIDGET_TOPLEVEL(toplevel) && gtk_window_has_toplevel_focus(GTK_WINDOW(toplevel))) { WebKitWebView* webView = WEBKIT_WEB_VIEW(widget); - + Frame* frame = core(webView)->mainFrame(); core(webView)->focusController()->setActive(frame); } @@ -621,6 +622,82 @@ static void webkit_web_view_real_paste_c frame->editor()->command("Paste").execute(); } +typedef struct +{ + GtkWidget* user_entry; + GtkWidget* password_entry; + WebKitWebAuthChallenge* challenge; +} AuthDialogData; + +static void webkit_web_view_web_auth_dialog_response_cb(GtkWidget* dialog, gint response, gpointer user_data) +{ + AuthDialogData* data = reinterpret_cast(user_data); + + switch (response) { + case GTK_RESPONSE_NONE: + case GTK_RESPONSE_DELETE_EVENT: + case GTK_RESPONSE_REJECT: + webkit_web_auth_challenge_continue_without_credential(data->challenge); + break; + case GTK_RESPONSE_ACCEPT: + webkit_web_auth_challenge_set_user(data->challenge, + gtk_entry_get_text(GTK_ENTRY(data->user_entry))); + webkit_web_auth_challenge_set_password(data->challenge, + gtk_entry_get_text(GTK_ENTRY(data->password_entry))); + webkit_web_auth_challenge_use_credential(data->challenge); + break; + default: + g_assert_not_reached (); + break; + } + + gtk_widget_destroy(dialog); + g_object_unref(data->challenge); +} + +static void webkit_web_view_real_authentication_requested(WebKitWebView* webView, WebKitWebFrame* webFrame, + WebKitWebAuthChallenge* challenge) +{ + GtkWidget* window; + GtkWidget* dialog; + GtkWidget* table; + GtkWidget* label; + AuthDialogData* data; + + window = gtk_widget_get_toplevel(GTK_WIDGET(webView)); + gchar* title = g_strconcat("Authentication - ", webkit_web_frame_get_uri(webFrame), NULL); + dialog = gtk_dialog_new_with_buttons(title, GTK_WIDGET_TOPLEVEL(window) ? GTK_WINDOW(window) : 0, + (GtkDialogFlags)(GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT), + GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, + GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, + NULL); + g_free(title); + gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_REJECT); + + data = g_new(AuthDialogData, 1); + data->user_entry = gtk_entry_new(); + data->password_entry = gtk_entry_new(); + gtk_entry_set_visibility(GTK_ENTRY(data->password_entry), FALSE); + data->challenge = challenge; + g_signal_connect(dialog, "response", G_CALLBACK(webkit_web_view_web_auth_dialog_response_cb), data); + + table = gtk_table_new(2, 2, FALSE); + gtk_table_set_col_spacings(GTK_TABLE(table), 3); + gtk_table_set_row_spacings(GTK_TABLE(table), 3); + + label = gtk_label_new("Username:"); + gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 0, 1); + gtk_table_attach_defaults(GTK_TABLE(table), data->user_entry, 1, 2, 0, 1); + + label = gtk_label_new("Password:"); + gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 1, 2); + gtk_table_attach_defaults(GTK_TABLE(table), data->password_entry, 1, 2, 1, 2); + + gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), table); + gtk_widget_show_all(table); + gtk_widget_show(dialog); +} + static void webkit_web_view_finalize(GObject* object) { WebKitWebView* webView = WEBKIT_WEB_VIEW(object); @@ -987,6 +1064,25 @@ static void webkit_web_view_class_init(W g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + /** + * WebKitWebView::authentication-requested: + * @web_view: the object which received the signal + * + * The ::authentication-requested signal is emitted when an authentication is + * requested from the server to access a resource. + * + * The default behavior for this signal is creating an input dialog to get a suitable credential. + */ + webkit_web_view_signals[AUTHENTICATION_REQUESTED] = g_signal_new("authentication-requested", + G_TYPE_FROM_CLASS(webViewClass), + (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), + G_STRUCT_OFFSET(WebKitWebViewClass, authentication_requested), + NULL, NULL, + webkit_marshal_VOID__OBJECT_OBJECT, + G_TYPE_NONE, 2, + WEBKIT_TYPE_WEB_FRAME, + WEBKIT_TYPE_WEB_AUTH_CHALLENGE); + /* * implementations of virtual methods */ @@ -1002,6 +1098,7 @@ static void webkit_web_view_class_init(W webViewClass->cut_clipboard = webkit_web_view_real_cut_clipboard; webViewClass->copy_clipboard = webkit_web_view_real_copy_clipboard; webViewClass->paste_clipboard = webkit_web_view_real_paste_clipboard; + webViewClass->authentication_requested = webkit_web_view_real_authentication_requested; GObjectClass* objectClass = G_OBJECT_CLASS(webViewClass); objectClass->finalize = webkit_web_view_finalize; Index: WebKit/gtk/webkit/webkitwebview.h =================================================================== --- WebKit/gtk/webkit/webkitwebview.h (revision 30475) +++ WebKit/gtk/webkit/webkitwebview.h (working copy) @@ -84,6 +84,7 @@ struct _WebKitWebViewClass { void (*cut_clipboard) (WebKitWebView* web_view); void (*copy_clipboard) (WebKitWebView* web_view); void (*paste_clipboard) (WebKitWebView* web_view); + void (*authentication_requested) (WebKitWebView* web_view, WebKitWebFrame* web_frame, WebKitWebAuthChallenge* web_auth_challenge); /* * internal