1/* 2 * Copyright (C) 2009 Igalia S.L. 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Library General Public 6 * License as published by the Free Software Foundation; either 7 * version 2 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Library General Public License for more details. 13 * 14 * You should have received a copy of the GNU Library General Public License 15 * along with this library; see the file COPYING.LIB. If not, write to 16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 * Boston, MA 02110-1301, USA. 18 */ 19 20#include "config.h" 21#include "webkitsoupauthdialog.h" 22 23#include "AuthenticationClient.h" 24#include "ResourceHandle.h" 25#include "webkitauthenticationdialog.h" 26#include "webkitmarshal.h" 27#include <wtf/text/CString.h> 28 29using namespace WebCore; 30 31/** 32 * SECTION:webkitsoupauthdialog 33 * @short_description: A #SoupSessionFeature to provide a simple 34 * authentication dialog for HTTP basic auth support. 35 * 36 * #WebKitSoupAuthDialog is a #SoupSessionFeature that you can attach to your 37 * #SoupSession to provide a simple authentication dialog while 38 * handling HTTP basic auth. 39 */ 40 41 42// This class exists only for API compatibility reasons. WebKitSoupAuthDialog was exposed 43// in the public API, so we must provide this "fake" AuthenticationClient in order to 44// continue using GtkAuthenticationDialog with the new authentication architecture. 45class WebKitSoupAuthDialogAuthenticationClient : public WebCore::AuthenticationClient, public RefCounted<WebKitSoupAuthDialogAuthenticationClient> { 46using RefCounted<WebKitSoupAuthDialogAuthenticationClient>::ref; 47using RefCounted<WebKitSoupAuthDialogAuthenticationClient>::deref; 48public: 49 virtual void didReceiveAuthenticationChallenge(const AuthenticationChallenge& challenge) 50 { 51 } 52 53 virtual void receivedRequestToContinueWithoutCredential(const AuthenticationChallenge& challenge) 54 { 55 soup_session_unpause_message(challenge.soupSession(), challenge.soupMessage()); 56 } 57 58 virtual void receivedCredential(const AuthenticationChallenge& challenge, const Credential& credential) 59 { 60 soup_auth_authenticate(challenge.soupAuth(), credential.user().utf8().data(), credential.password().utf8().data()); 61 soup_session_unpause_message(challenge.soupSession(), challenge.soupMessage()); 62 } 63 64 virtual void receivedCancellation(const AuthenticationChallenge& challenge) 65 { 66 soup_session_unpause_message(challenge.soupSession(), challenge.soupMessage()); 67 } 68 69 // This seems necessary to make the compiler happy. Both AuthenticationClient and 70 // RefCounted<T> expose a ref/deref method, which interferes with the use of a RefPtr. 71 void derefWebKitSoupAuthDialogAuthenticationClient() 72 { 73 deref(); 74 } 75 76private: 77 virtual void refAuthenticationClient() { ref(); } 78 virtual void derefAuthenticationClient() { deref(); } 79}; 80 81static void webkit_soup_auth_dialog_session_feature_init(SoupSessionFeatureInterface*, gpointer); 82static void attach(SoupSessionFeature*, SoupSession*); 83static void detach(SoupSessionFeature*, SoupSession*); 84 85enum { 86 CURRENT_TOPLEVEL, 87 LAST_SIGNAL 88}; 89 90static guint signals[LAST_SIGNAL] = { 0 }; 91 92G_DEFINE_TYPE_WITH_CODE(WebKitSoupAuthDialog, webkit_soup_auth_dialog, G_TYPE_OBJECT, 93 G_IMPLEMENT_INTERFACE(SOUP_TYPE_SESSION_FEATURE, 94 webkit_soup_auth_dialog_session_feature_init)) 95 96static void webkit_soup_auth_dialog_class_init(WebKitSoupAuthDialogClass* klass) 97{ 98 GObjectClass* objectClass = G_OBJECT_CLASS(klass); 99 100 /** 101 * WebKitSoupAuthDialog::current-toplevel: 102 * @authDialog: the object on which the signal is emitted 103 * @message: the #SoupMessage being used in the authentication process 104 * 105 * This signal is emitted by the @authDialog when it needs to know 106 * the current toplevel widget in order to correctly set the 107 * transiency for the authentication dialog. 108 * 109 * Return value: (transfer none): the current toplevel #GtkWidget or %NULL if there's none 110 * 111 * Since: 1.1.1 112 */ 113 signals[CURRENT_TOPLEVEL] = g_signal_new("current-toplevel", 114 G_OBJECT_CLASS_TYPE(objectClass), 115 G_SIGNAL_RUN_LAST, 116 G_STRUCT_OFFSET(WebKitSoupAuthDialogClass, current_toplevel), 117 0, 0, 118 webkit_marshal_OBJECT__OBJECT, 119 GTK_TYPE_WIDGET, 1, 120 SOUP_TYPE_MESSAGE); 121} 122 123static void webkit_soup_auth_dialog_init(WebKitSoupAuthDialog*) 124{ 125} 126 127static void webkit_soup_auth_dialog_session_feature_init(SoupSessionFeatureInterface *featureInterface, gpointer) 128{ 129 featureInterface->attach = attach; 130 featureInterface->detach = detach; 131} 132 133static void sessionAuthenticate(SoupSession* session, SoupMessage* message, SoupAuth* auth, gboolean retrying, SoupSessionFeature* manager) 134{ 135 GtkWindow* toplevel = 0; 136 g_signal_emit(manager, signals[CURRENT_TOPLEVEL], 0, message, &toplevel); 137 138 WebKitSoupAuthDialogAuthenticationClient* client = new WebKitSoupAuthDialogAuthenticationClient(); 139 AuthenticationChallenge challenge(session, message, auth, retrying, client); 140 soup_session_unpause_message(session, message); 141 142 // A RefPtr would be better here, but it seems that accessing RefCounted::deref from this context is 143 // impossible with gcc, due to WebKitSoupAuthDialogAuthenticationClient's two superclasses. 144 client->derefWebKitSoupAuthDialogAuthenticationClient(); 145 146 GtkWidget* authDialog = createAuthenticationDialog(toplevel, challenge, DisallowPersistentStorage); 147 gtk_widget_show(authDialog); 148} 149 150static void attach(SoupSessionFeature* manager, SoupSession* session) 151{ 152 g_signal_connect(session, "authenticate", G_CALLBACK(sessionAuthenticate), manager); 153} 154 155static void detach(SoupSessionFeature* manager, SoupSession* session) 156{ 157 g_signal_handlers_disconnect_by_func(session, reinterpret_cast<gpointer>(sessionAuthenticate), manager); 158} 159 160 161