290#if USE(GNOMEKEYRING)
291typedef struct _WebKitAuthData {
292 SoupMessage* msg;
293 SoupAuth* auth;
294 SoupSession* session;
295 GtkWidget* loginEntry;
296 GtkWidget* passwordEntry;
297 GtkWidget* checkButton;
298} WebKitAuthData;
299
300static void free_authData(WebKitAuthData* authData)
301{
302 g_object_unref(authData->msg);
303 g_slice_free(WebKitAuthData, authData);
304}
305
306static void set_password_callback(GnomeKeyringResult result, guint32 val, gpointer user_data)
307{
308 /* Dummy callback, gnome_keyring_set_network_password does not accept a NULL one */
309}
310
311static void response_callback(GtkDialog* dialog, gint response_id, WebKitAuthData* authData)
312{
313 const char* login;
314 const char* password;
315 gboolean storePassword;
316 SoupURI* uri;
317
318 switch(response_id) {
319 case GTK_RESPONSE_ACCEPT:
320 login = gtk_entry_get_text(GTK_ENTRY(authData->loginEntry));
321 password = gtk_entry_get_text(GTK_ENTRY(authData->passwordEntry));
322 storePassword = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(authData->checkButton));
323
324 soup_auth_authenticate(authData->auth, login, password);
325
326 if (storePassword) {
327 uri = soup_message_get_uri(authData->msg);
328 gnome_keyring_set_network_password(NULL,
329 login,
330 soup_auth_get_realm(authData->auth),
331 uri->host,
332 NULL,
333 uri->scheme,
334 soup_auth_get_scheme_name(authData->auth),
335 uri->port,
336 password,
337 reinterpret_cast<GnomeKeyringOperationGetIntCallback>(set_password_callback),
338 NULL,
339 NULL);
340 }
341 default:
342 break;
343 }
344
345 soup_session_unpause_message(authData->session, authData->msg);
346 free_authData(authData);
347 gtk_widget_destroy(GTK_WIDGET(dialog));
348}
349
350static void find_password_callback(GnomeKeyringResult result, GList* list, WebKitAuthData* authData)
351{
352 GList* p;
353 const char* login = NULL;
354 const char* password = NULL;
355
356 for (p = list; p; p = p->next) {
357 /* FIXME: support multiple logins/passwords ? */
358 GnomeKeyringNetworkPasswordData* data = static_cast<GnomeKeyringNetworkPasswordData*>(p->data);
359 login = data->user;
360 password = data->password;
361 break;
362 }
363
364 /* Mimic the UI from Gecko, EmbedPrompter.cpp, LGPL license */
365 GtkWidget* dialog;
366 dialog = gtk_dialog_new_with_buttons("",
367 NULL, // FIXME: how to get the current toplevel from here?
368 GTK_DIALOG_DESTROY_WITH_PARENT,
369 GTK_STOCK_CANCEL,
370 GTK_RESPONSE_REJECT,
371 GTK_STOCK_OK,
372 GTK_RESPONSE_ACCEPT,
373 NULL);
374 gtk_window_set_default_size(GTK_WINDOW(dialog), 100, 50);
375 gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT);
376
377 /* Main hbox for icon and controls */
378 GtkWidget* mainHBox = gtk_hbox_new(FALSE, 12);
379 gtk_container_set_border_width(GTK_CONTAINER(dialog), 6);
380 gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE);
381
382 GtkWidget* contentArea = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
383 gtk_box_set_spacing(GTK_BOX(contentArea), 12);
384 gtk_container_set_border_width(GTK_CONTAINER(mainHBox), 12);
385
386 /* VBox for labels and other controls */
387 GtkWidget* contentsVBox = gtk_vbox_new(FALSE, 12);
388 GtkWidget* icon = gtk_image_new_from_stock(GTK_STOCK_DIALOG_AUTHENTICATION,
389 GTK_ICON_SIZE_DIALOG);
390 gtk_misc_set_alignment(GTK_MISC(icon), 0.5, 0.0);
391 gtk_box_pack_start(GTK_BOX(mainHBox), icon, FALSE, FALSE, 0);
392
393 /* Pack the message label into the VBox */
394 SoupURI* uri = soup_message_get_uri(authData->msg);
395 char* message = g_strdup_printf("A username and password are being requested by %s",
396 uri->host);
397 GtkWidget* label = gtk_label_new(message);
398 g_free(message);
399 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
400 gtk_label_set_selectable(GTK_LABEL(label), TRUE);
401 gtk_box_pack_start(GTK_BOX(contentsVBox), label, FALSE, FALSE, 0);
402
403 /* Login/Password entries */
404 GtkWidget* userPassHBox = gtk_hbox_new(FALSE, 12);
405 GtkWidget* userPassLabels = gtk_vbox_new(TRUE, 6);
406 GtkWidget* userPassFields = gtk_vbox_new(TRUE, 6);
407
408 GtkWidget* userLabel = gtk_label_new("User Name:");
409 gtk_box_pack_start(GTK_BOX(userPassLabels), userLabel, FALSE, 0, 0);
410 GtkWidget* loginEntry = gtk_entry_new();
411 if (login)
412 gtk_entry_set_text(GTK_ENTRY(loginEntry), login);
413 gtk_entry_set_activates_default(GTK_ENTRY(loginEntry), TRUE);
414 gtk_box_pack_start(GTK_BOX(userPassFields), loginEntry, FALSE, 0, 0);
415
416 GtkWidget* passwordLabel = gtk_label_new("Password:");
417 gtk_box_pack_start(GTK_BOX(userPassLabels), passwordLabel, FALSE, 0, 0);
418 GtkWidget* passwordEntry = gtk_entry_new();
419 if (password)
420 gtk_entry_set_text(GTK_ENTRY(passwordEntry), password);
421 gtk_entry_set_visibility(GTK_ENTRY(passwordEntry), FALSE);
422 gtk_entry_set_activates_default(GTK_ENTRY(passwordEntry), TRUE);
423 gtk_box_pack_start(GTK_BOX(userPassFields), passwordEntry, FALSE, 0, 0);
424
425 gtk_box_pack_start(GTK_BOX(userPassHBox), userPassLabels, FALSE, 0, 0);
426 gtk_box_pack_start(GTK_BOX(userPassHBox), userPassFields, FALSE, 0, 0);
427 gtk_box_pack_start(GTK_BOX(contentsVBox), userPassHBox, FALSE, 0, 0);
428
429 /* Checkbutton */
430 GtkWidget* checkButton = gtk_check_button_new_with_label("Remember password");
431 if (login && password)
432 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkButton), TRUE);
433 gtk_label_set_line_wrap(GTK_LABEL(gtk_bin_get_child(GTK_BIN(checkButton))), TRUE);
434 gtk_box_pack_start(GTK_BOX(contentsVBox), checkButton, FALSE, 0, 0);
435
436 /* Pack and go */
437 gtk_box_pack_start(GTK_BOX(mainHBox), contentsVBox, FALSE, 0, 0);
438 gtk_box_pack_start(GTK_BOX(contentArea), mainHBox, FALSE, 0, 0);
439
440 authData->loginEntry = loginEntry;
441 authData->passwordEntry = passwordEntry;
442 authData->checkButton = checkButton;
443
444 g_signal_connect(dialog, "response", G_CALLBACK(response_callback), authData);
445 gtk_widget_show_all(dialog);
446}
447
448static void session_authenticate(SoupSession* session, SoupMessage* msg, SoupAuth* auth, gboolean retrying)
449{
450 SoupURI* uri;
451 WebKitAuthData* authData;
452
453 soup_session_pause_message(session, msg);
454 /* We need to make sure the message sticks around when pausing it */
455 g_object_ref(msg);
456
457 uri = soup_message_get_uri(msg);
458 authData = g_slice_new(WebKitAuthData);
459 authData->msg = msg;
460 authData->auth = auth;
461 authData->session = session;
462
463 gnome_keyring_find_network_password(NULL,
464 soup_auth_get_realm(auth),
465 uri->host,
466 NULL,
467 uri->scheme,
468 soup_auth_get_scheme_name(auth),
469 uri->port,
470 reinterpret_cast<GnomeKeyringOperationGetListCallback>(find_password_callback),
471 authData,
472 NULL);
473}
474#endif
475