1/*
2 * Copyright (C) 2012 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 "WebKitAuthenticationDialog.h"
22
23#include "AuthenticationDecisionListener.h"
24#include "WebCredential.h"
25#include "WebKitPrivate.h"
26
27using namespace WebKit;
28
29struct _WebKitAuthenticationDialogPrivate {
30    RefPtr<AuthenticationChallengeProxy> authenticationChallenge;
31
32    GtkWidget* authWidget;
33    GtkWidget* defaultButton;
34    GRefPtr<GtkStyleContext> styleContext;
35};
36
37WEBKIT_DEFINE_TYPE(WebKitAuthenticationDialog, webkit_authentication_dialog, GTK_TYPE_EVENT_BOX)
38
39static void webkitAuthenticationDialogAuthenticate(WebKitAuthenticationDialog* authDialog, WebCredential* credential)
40{
41    WebKitAuthenticationDialogPrivate* priv = authDialog->priv;
42    priv->authenticationChallenge->listener()->useCredential(credential);
43    gtk_widget_destroy(GTK_WIDGET(authDialog));
44}
45
46static void okButtonClicked(GtkButton*, WebKitAuthenticationDialog* authDialog)
47{
48    WebKitAuthenticationDialogPrivate* priv = authDialog->priv;
49    RefPtr<WebCredential> webCredential = WebCredential::create(webkitAuthenticationWidgetCreateCredential(WEBKIT_AUTHENTICATION_WIDGET(priv->authWidget)));
50    webkitAuthenticationDialogAuthenticate(authDialog, webCredential.get());
51}
52
53static void cancelButtonClicked(GtkButton*, WebKitAuthenticationDialog* authDialog)
54{
55    webkitAuthenticationDialogAuthenticate(authDialog, 0);
56}
57
58static void webkitAuthenticationDialogInitialize(WebKitAuthenticationDialog* authDialog, CredentialStorageMode credentialStorageMode)
59{
60    GtkWidget* frame = gtk_frame_new(0);
61    gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
62
63    GtkWidget* vBox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6);
64    gtk_container_set_border_width(GTK_CONTAINER(vBox), 5);
65
66    GtkWidget* buttonBox = gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL);
67    gtk_button_box_set_layout(GTK_BUTTON_BOX(buttonBox), GTK_BUTTONBOX_END);
68    gtk_container_set_border_width(GTK_CONTAINER(buttonBox), 5);
69    gtk_box_set_spacing(GTK_BOX(buttonBox), 6);
70
71    GtkWidget* button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
72    g_signal_connect(button, "clicked", G_CALLBACK(cancelButtonClicked), authDialog);
73    gtk_box_pack_end(GTK_BOX(buttonBox), button, FALSE, TRUE, 0);
74    gtk_widget_show(button);
75
76    button = gtk_button_new_from_stock(GTK_STOCK_OK);
77    authDialog->priv->defaultButton = button;
78    g_signal_connect(button, "clicked", G_CALLBACK(okButtonClicked), authDialog);
79    gtk_widget_set_can_default(button, TRUE);
80    gtk_box_pack_end(GTK_BOX(buttonBox), button, FALSE, TRUE, 0);
81    gtk_widget_show(button);
82
83    authDialog->priv->authWidget = webkitAuthenticationWidgetNew(authDialog->priv->authenticationChallenge->core(), credentialStorageMode);
84    gtk_box_pack_start(GTK_BOX(vBox), authDialog->priv->authWidget, TRUE, TRUE, 0);
85    gtk_widget_show(authDialog->priv->authWidget);
86
87    gtk_box_pack_end(GTK_BOX(vBox), buttonBox, FALSE, TRUE, 0);
88    gtk_widget_show(buttonBox);
89
90    gtk_container_add(GTK_CONTAINER(frame), vBox);
91    gtk_widget_show(vBox);
92
93    gtk_container_add(GTK_CONTAINER(authDialog), frame);
94    gtk_widget_show(frame);
95}
96
97static gboolean webkitAuthenticationDialogDraw(GtkWidget* widget, cairo_t* cr)
98{
99    WebKitAuthenticationDialogPrivate* priv = WEBKIT_AUTHENTICATION_DIALOG(widget)->priv;
100
101    gtk_style_context_save(priv->styleContext.get());
102    gtk_style_context_add_class(priv->styleContext.get(), GTK_STYLE_CLASS_BACKGROUND);
103    gtk_render_background(priv->styleContext.get(), cr, 0, 0, gtk_widget_get_allocated_width(widget), gtk_widget_get_allocated_height(widget));
104    gtk_style_context_restore(priv->styleContext.get());
105
106    GTK_WIDGET_CLASS(webkit_authentication_dialog_parent_class)->draw(widget, cr);
107
108    return FALSE;
109}
110
111static void webkitAuthenticationDialogMap(GtkWidget* widget)
112{
113    WebKitAuthenticationDialogPrivate* priv = WEBKIT_AUTHENTICATION_DIALOG(widget)->priv;
114    gtk_widget_grab_default(priv->defaultButton);
115
116    GTK_WIDGET_CLASS(webkit_authentication_dialog_parent_class)->map(widget);
117}
118
119static void webkitAuthenticationDialogConstructed(GObject* object)
120{
121    G_OBJECT_CLASS(webkit_authentication_dialog_parent_class)->constructed(object);
122
123    WebKitAuthenticationDialogPrivate* priv = WEBKIT_AUTHENTICATION_DIALOG(object)->priv;
124    priv->styleContext = adoptGRef(gtk_style_context_new());
125    GtkWidgetPath* path = gtk_widget_path_new();
126    gtk_widget_path_append_type(path, GTK_TYPE_WINDOW);
127    gtk_style_context_set_path(priv->styleContext.get(), path);
128    gtk_widget_path_free(path);
129}
130
131static void webkit_authentication_dialog_class_init(WebKitAuthenticationDialogClass* klass)
132{
133    GObjectClass* objectClass = G_OBJECT_CLASS(klass);
134    objectClass->constructed = webkitAuthenticationDialogConstructed;
135
136    GtkWidgetClass* widgetClass = GTK_WIDGET_CLASS(klass);
137    widgetClass->draw = webkitAuthenticationDialogDraw;
138    widgetClass->map = webkitAuthenticationDialogMap;
139}
140
141GtkWidget* webkitAuthenticationDialogNew(AuthenticationChallengeProxy* authenticationChallenge, CredentialStorageMode mode)
142{
143    WebKitAuthenticationDialog* authDialog = WEBKIT_AUTHENTICATION_DIALOG(g_object_new(WEBKIT_TYPE_AUTHENTICATION_DIALOG, NULL));
144    authDialog->priv->authenticationChallenge = authenticationChallenge;
145    webkitAuthenticationDialogInitialize(authDialog, mode);
146    return GTK_WIDGET(authDialog);
147}
148