[gnome-initial-setup] account: Do the same for the "enterprise login" section



commit 8cc86c5995325ade9e2c8960c342308a98e8a905
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Sat Nov 2 21:00:00 2013 -0400

    account: Do the same for the "enterprise login" section

 gnome-initial-setup/pages/account/Makefile.am      |   15 +-
 .../pages/account/account.gresource.xml            |    1 +
 .../pages/account/gis-account-page-enterprise.c    |  816 ++++++++++++++++++++
 .../pages/account/gis-account-page-enterprise.h    |   64 ++
 .../pages/account/gis-account-page-enterprise.ui   |  473 ++++++++++++
 .../pages/account/gis-account-page.c               |  736 +-----------------
 .../pages/account/gis-account-page.ui              |  467 +-----------
 7 files changed, 1387 insertions(+), 1185 deletions(-)
---
diff --git a/gnome-initial-setup/pages/account/Makefile.am b/gnome-initial-setup/pages/account/Makefile.am
index 9a6af50..3965376 100644
--- a/gnome-initial-setup/pages/account/Makefile.am
+++ b/gnome-initial-setup/pages/account/Makefile.am
@@ -22,13 +22,14 @@ account-resources.h: account.gresource.xml $(resource_files)
        $(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(srcdir) --generate-header $<
 BUILT_SOURCES += account-resources.c account-resources.h
 
-libgisaccount_la_SOURCES =                                     \
-       $(BUILT_SOURCES)                                        \
-       gis-account-page.c gis-account-page.h                   \
-       gis-account-page-local.c gis-account-page-local.h       \
-       um-realm-manager.c um-realm-manager.h                   \
-       um-utils.c um-utils.h                                   \
-       pw-utils.c pw-utils.h                                   \
+libgisaccount_la_SOURCES =                                             \
+       $(BUILT_SOURCES)                                                \
+       gis-account-page.c gis-account-page.h                           \
+       gis-account-page-local.c gis-account-page-local.h               \
+       gis-account-page-enterprise.c gis-account-page-enterprise.h     \
+       um-realm-manager.c um-realm-manager.h                           \
+       um-utils.c um-utils.h                                           \
+       pw-utils.c pw-utils.h                                           \
        $(NULL)
 
 libgisaccount_la_CFLAGS = $(INITIAL_SETUP_CFLAGS) -I "$(srcdir)/../.."
diff --git a/gnome-initial-setup/pages/account/account.gresource.xml 
b/gnome-initial-setup/pages/account/account.gresource.xml
index 7965408..2b3c470 100644
--- a/gnome-initial-setup/pages/account/account.gresource.xml
+++ b/gnome-initial-setup/pages/account/account.gresource.xml
@@ -3,5 +3,6 @@
   <gresource prefix="/org/gnome/initial-setup">
     <file preprocess="xml-stripblanks" alias="gis-account-page.ui">gis-account-page.ui</file>
     <file preprocess="xml-stripblanks" alias="gis-account-page-local.ui">gis-account-page-local.ui</file>
+    <file preprocess="xml-stripblanks" 
alias="gis-account-page-enterprise.ui">gis-account-page-enterprise.ui</file>
   </gresource>
 </gresources>
diff --git a/gnome-initial-setup/pages/account/gis-account-page-enterprise.c 
b/gnome-initial-setup/pages/account/gis-account-page-enterprise.c
new file mode 100644
index 0000000..f74a46a
--- /dev/null
+++ b/gnome-initial-setup/pages/account/gis-account-page-enterprise.c
@@ -0,0 +1,816 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright (C) 2013 Red Hat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Written by:
+ *     Jasper St. Pierre <jstpierre mecheye net>
+ */
+
+#include "config.h"
+
+#include "gis-account-page-enterprise.h"
+#include "gnome-initial-setup.h"
+
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+
+#include <act/act-user-manager.h>
+
+#include "um-realm-manager.h"
+#include "um-utils.h"
+#include "pw-utils.h"
+
+static void        join_show_prompt    (GisAccountPageEnterprise *page,
+                                        GError *error);
+
+static void        on_join_login       (GObject *source,
+                                        GAsyncResult *result,
+                                        gpointer user_data);
+
+static void        on_realm_joined     (GObject *source,
+                                        GAsyncResult *result,
+                                        gpointer user_data);
+
+struct _GisAccountPageEnterprisePrivate
+{
+  GtkWidget *login;
+  GtkWidget *password;
+  GtkWidget *domain;
+  GtkWidget *domain_entry;
+  GtkTreeModel *realms_model;
+
+  GtkWidget *join_dialog;
+  GtkWidget *join_name;
+  GtkWidget *join_password;
+  GtkWidget *join_domain;
+  GtkWidget *join_computer;
+
+  ActUserManager *act_client;
+  ActUser *act_user;
+
+  guint realmd_watch;
+  UmRealmManager *realm_manager;
+  gboolean domain_chosen;
+
+  /* Valid during apply */
+  UmRealmObject *realm;
+  GCancellable *cancellable;
+  gboolean join_prompted;
+
+  GisPageApplyCallback apply_complete_callback;
+  gpointer apply_complete_data;
+};
+typedef struct _GisAccountPageEnterprisePrivate GisAccountPageEnterprisePrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (GisAccountPageEnterprise, gis_account_page_enterprise, GTK_TYPE_BIN);
+
+enum {
+  VALIDATION_CHANGED,
+  LAST_SIGNAL,
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+static void
+validation_changed (GisAccountPageEnterprise *page)
+{
+  g_signal_emit (page, signals[VALIDATION_CHANGED], 0);
+}
+
+static void
+apply_complete (GisAccountPageEnterprise *page,
+                gboolean                  valid)
+{
+  GisAccountPageEnterprisePrivate *priv = gis_account_page_enterprise_get_instance_private (page);
+  priv->apply_complete_callback (NULL, valid, priv->apply_complete_data);
+}
+
+static void
+show_error_dialog (GisAccountPageEnterprise *page,
+                   const gchar *message,
+                   GError *error)
+{
+  GtkWidget *dialog;
+
+  if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+    return;
+
+  dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (page))),
+                                   GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+                                   GTK_MESSAGE_ERROR,
+                                   GTK_BUTTONS_CLOSE,
+                                   "%s", message);
+
+  if (error != NULL) {
+    g_dbus_error_strip_remote_error (error);
+    gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+                                              "%s", error->message);
+  }
+
+  g_signal_connect (dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL);
+  gtk_window_present (GTK_WINDOW (dialog));
+}
+
+gboolean
+gis_account_page_enterprise_validate (GisAccountPageEnterprise *page)
+{
+  const gchar *name;
+  gboolean valid_name;
+  gboolean valid_domain;
+  GtkTreeIter iter;
+  GisAccountPageEnterprisePrivate *priv = gis_account_page_enterprise_get_instance_private (page);
+
+  name = gtk_entry_get_text (GTK_ENTRY (priv->login));
+  valid_name = is_valid_name (name);
+
+  if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (priv->domain), &iter)) {
+    gtk_tree_model_get (gtk_combo_box_get_model (GTK_COMBO_BOX (priv->domain)),
+                        &iter, 0, &name, -1);
+  } else {
+    name = gtk_entry_get_text (GTK_ENTRY (priv->domain_entry));
+  }
+
+  valid_domain = is_valid_name (name);
+  return valid_name && valid_domain;
+}
+
+static void
+on_permit_user_login (GObject *source,
+                      GAsyncResult *result,
+                      gpointer user_data)
+{
+  GisAccountPageEnterprise *page = user_data;
+  GisAccountPageEnterprisePrivate *priv = gis_account_page_enterprise_get_instance_private (page);
+  UmRealmCommon *common;
+  GError *error = NULL;
+  gchar *login;
+
+  common = UM_REALM_COMMON (source);
+  um_realm_common_call_change_login_policy_finish (common, result, &error);
+  if (error == NULL) {
+
+    /*
+     * Now tell the account service about this user. The account service
+     * should also lookup information about this via the realm and make
+     * sure all that is functional.
+     */
+    login = um_realm_calculate_login (common, gtk_entry_get_text (GTK_ENTRY (priv->login)));
+    g_return_if_fail (login != NULL);
+
+    g_debug ("Caching remote user: %s", login);
+
+    priv->act_user = act_user_manager_cache_user (priv->act_client, login, NULL);
+    apply_complete (page, TRUE);
+
+    g_free (login);
+  } else {
+    show_error_dialog (page, _("Failed to register account"), error);
+    g_message ("Couldn't permit logins on account: %s", error->message);
+    g_error_free (error);
+    apply_complete (page, FALSE);
+  }
+}
+
+static void
+enterprise_permit_user_login (GisAccountPageEnterprise *page, UmRealmObject *realm)
+{
+  GisAccountPageEnterprisePrivate *priv = gis_account_page_enterprise_get_instance_private (page);
+  UmRealmCommon *common;
+  gchar *login;
+  const gchar *add[2];
+  const gchar *remove[1];
+  GVariant *options;
+
+  common = um_realm_object_get_common (realm);
+
+  login = um_realm_calculate_login (common, gtk_entry_get_text (GTK_ENTRY (priv->login)));
+  g_return_if_fail (login != NULL);
+
+  add[0] = login;
+  add[1] = NULL;
+  remove[0] = NULL;
+
+  g_debug ("Permitting login for: %s", login);
+  options = g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0);
+
+  um_realm_common_call_change_login_policy (common, "",
+                                            add, remove, options,
+                                            priv->cancellable,
+                                            on_permit_user_login,
+                                            page);
+
+  g_object_unref (common);
+  g_free (login);
+}
+
+static void
+on_set_static_hostname (GObject *source,
+                        GAsyncResult *result,
+                        gpointer user_data)
+{
+  GisAccountPageEnterprise *page = user_data;
+  GisAccountPageEnterprisePrivate *priv = gis_account_page_enterprise_get_instance_private (page);
+  GError *error = NULL;
+  GVariant *retval;
+
+  retval = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error);
+  if (error != NULL) {
+    join_show_prompt (page, error);
+    g_error_free (error);
+    return;
+  }
+
+  g_variant_unref (retval);
+
+  /* Prompted for some admin credentials, try to use them to log in */
+  um_realm_login (priv->realm,
+                  gtk_entry_get_text (GTK_ENTRY (priv->join_name)),
+                  gtk_entry_get_text (GTK_ENTRY (priv->join_password)),
+                  priv->cancellable, on_join_login, page);
+}
+
+static void
+on_join_response (GtkDialog *dialog,
+                  gint response,
+                  gpointer user_data)
+{
+  GisAccountPageEnterprise *page = user_data;
+  GisAccountPageEnterprisePrivate *priv = gis_account_page_enterprise_get_instance_private (page);
+  GDBusConnection *connection;
+  GError *error = NULL;
+  gchar hostname[128];
+  const gchar *name;
+
+  gtk_widget_hide (GTK_WIDGET (dialog));
+  if (response != GTK_RESPONSE_OK) {
+    apply_complete (page, FALSE);
+    return;
+  }
+
+  name = gtk_entry_get_text (GTK_ENTRY (priv->join_computer));
+  if (gethostname (hostname, sizeof (hostname)) == 0 &&
+      !g_str_equal (name, hostname)) {
+    g_debug ("Setting StaticHostname to '%s'", name);
+
+    connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, priv->cancellable, &error);
+    if (error != NULL) {
+      apply_complete (page, FALSE);
+      g_warning ("Could not get DBus connection: %s", error->message);
+      g_error_free (error);
+      return;
+    }
+
+    g_dbus_connection_call (connection, "org.freedesktop.hostname1",
+                            "/org/freedesktop/hostname1", "org.freedesktop.hostname1",
+                            "SetStaticHostname",
+                            g_variant_new ("(sb)", name, TRUE),
+                            G_VARIANT_TYPE ("()"),
+                            G_DBUS_CALL_FLAGS_NONE,
+                            G_MAXINT, NULL, on_set_static_hostname, page);
+
+  } else {
+    name = gtk_entry_get_text (GTK_ENTRY (priv->join_name));
+    g_debug ("Logging in as admin user: %s", name);
+
+    /* Prompted for some admin credentials, try to use them to log in */
+    um_realm_login (priv->realm, name,
+                    gtk_entry_get_text (GTK_ENTRY (priv->join_password)),
+                    NULL, on_join_login, page);
+  }
+}
+
+static void
+join_show_prompt (GisAccountPageEnterprise *page,
+                  GError *error)
+{
+  GisAccountPageEnterprisePrivate *priv = gis_account_page_enterprise_get_instance_private (page);
+  UmRealmKerberosMembership *membership;
+  UmRealmKerberos *kerberos;
+  gchar hostname[128];
+  const gchar *name;
+
+  gtk_entry_set_text (GTK_ENTRY (priv->join_password), "");
+  gtk_widget_grab_focus (GTK_WIDGET (priv->join_password));
+
+  kerberos = um_realm_object_get_kerberos (priv->realm);
+  membership = um_realm_object_get_kerberos_membership (priv->realm);
+
+  gtk_label_set_text (GTK_LABEL (priv->join_domain),
+                      um_realm_kerberos_get_domain_name (kerberos));
+
+  if (gethostname (hostname, sizeof (hostname)) == 0)
+    gtk_entry_set_text (GTK_ENTRY (priv->join_computer), hostname);
+
+  clear_entry_validation_error (GTK_ENTRY (priv->join_name));
+  clear_entry_validation_error (GTK_ENTRY (priv->join_password));
+
+  if (!priv->join_prompted) {
+    name = um_realm_kerberos_membership_get_suggested_administrator (membership);
+    if (name && !g_str_equal (name, "")) {
+      g_debug ("Suggesting admin user: %s", name);
+      gtk_entry_set_text (GTK_ENTRY (priv->join_name), name);
+    } else {
+      gtk_widget_grab_focus (GTK_WIDGET (priv->join_name));
+    }
+
+  } else if (g_error_matches (error, UM_REALM_ERROR, UM_REALM_ERROR_BAD_HOSTNAME)) {
+    g_debug ("Bad host name: %s", error->message);
+    set_entry_validation_error (GTK_ENTRY (priv->join_computer), error->message);
+
+  } else if (g_error_matches (error, UM_REALM_ERROR, UM_REALM_ERROR_BAD_PASSWORD)) {
+    g_debug ("Bad admin password: %s", error->message);
+    set_entry_validation_error (GTK_ENTRY (priv->join_password), error->message);
+
+  } else {
+    g_debug ("Admin login failure: %s", error->message);
+    g_dbus_error_strip_remote_error (error);
+    set_entry_validation_error (GTK_ENTRY (priv->join_name), error->message);
+  }
+
+  g_debug ("Showing admin password dialog");
+  gtk_window_set_transient_for (GTK_WINDOW (priv->join_dialog),
+                                GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (page))));
+  gtk_window_set_modal (GTK_WINDOW (priv->join_dialog), TRUE);
+  gtk_window_present (GTK_WINDOW (priv->join_dialog));
+
+  priv->join_prompted = TRUE;
+  g_object_unref (kerberos);
+  g_object_unref (membership);
+
+  /* And now we wait for on_join_response() */
+}
+
+static void
+on_join_login (GObject *source,
+               GAsyncResult *result,
+               gpointer user_data)
+{
+  GisAccountPageEnterprise *page = user_data;
+  GisAccountPageEnterprisePrivate *priv = gis_account_page_enterprise_get_instance_private (page);
+  GError *error = NULL;
+  GBytes *creds;
+
+  um_realm_login_finish (priv->realm, result, &creds, &error);
+
+  /* Logged in as admin successfully, use creds to join domain */
+  if (error == NULL) {
+    if (!um_realm_join_as_admin (priv->realm,
+                                 gtk_entry_get_text (GTK_ENTRY (priv->join_name)),
+                                 gtk_entry_get_text (GTK_ENTRY (priv->join_password)),
+                                 creds, NULL, on_realm_joined, page)) {
+      show_error_dialog (page, _("No supported way to authenticate with this domain"), NULL);
+      g_message ("Authenticating as admin is not supported by the realm");
+    }
+
+    g_bytes_unref (creds);
+
+  /* Couldn't login as admin, show prompt again */
+  } else {
+    join_show_prompt (page, error);
+    g_message ("Couldn't log in as admin to join domain: %s", error->message);
+    g_error_free (error);
+  }
+}
+
+static void
+on_realm_joined (GObject *source,
+                 GAsyncResult *result,
+                 gpointer user_data)
+{
+  GisAccountPageEnterprise *page = user_data;
+  GisAccountPageEnterprisePrivate *priv = gis_account_page_enterprise_get_instance_private (page);
+  GError *error = NULL;
+
+  um_realm_join_finish (priv->realm, result, &error);
+
+  /* Yay, joined the domain, register the user locally */
+  if (error == NULL) {
+    g_debug ("Joining realm completed successfully");
+    enterprise_permit_user_login (page, priv->realm);
+
+    /* Credential failure while joining domain, prompt for admin creds */
+  } else if (g_error_matches (error, UM_REALM_ERROR, UM_REALM_ERROR_BAD_LOGIN) ||
+             g_error_matches (error, UM_REALM_ERROR, UM_REALM_ERROR_BAD_PASSWORD) ||
+             g_error_matches (error, UM_REALM_ERROR, UM_REALM_ERROR_BAD_HOSTNAME)) {
+    g_debug ("Joining realm failed due to credentials or host name");
+
+    join_show_prompt (page, error);
+
+    /* Other failure */
+  } else {
+    show_error_dialog (page, _("Failed to join domain"), error);
+    g_message ("Failed to join the domain: %s", error->message);
+    apply_complete (page, FALSE);
+  }
+
+  g_clear_error (&error);
+}
+
+static void
+on_realm_login (GObject *source,
+                GAsyncResult *result,
+                gpointer user_data)
+{
+  GisAccountPageEnterprise *page = user_data;
+  GisAccountPageEnterprisePrivate *priv = gis_account_page_enterprise_get_instance_private (page);
+  GError *error = NULL;
+  GBytes *creds = NULL;
+
+  um_realm_login_finish (priv->realm, result, &creds, &error);
+
+  /*
+   * User login is valid, but cannot authenticate right now (eg: user needs
+   * to change password at next login etc.)
+   */
+  if (g_error_matches (error, UM_REALM_ERROR, UM_REALM_ERROR_CANNOT_AUTH)) {
+    g_clear_error (&error);
+    creds = NULL;
+  }
+
+  if (error == NULL) {
+
+    /* Already joined to the domain, just register this user */
+    if (um_realm_is_configured (priv->realm)) {
+      g_debug ("Already joined to this realm");
+      enterprise_permit_user_login (page, priv->realm);
+
+      /* Join the domain, try using the user's creds */
+    } else if (creds == NULL ||
+               !um_realm_join_as_user (priv->realm,
+                                       gtk_entry_get_text (GTK_ENTRY (priv->login)),
+                                       gtk_entry_get_text (GTK_ENTRY (priv->password)),
+                                       creds, priv->cancellable,
+                                       on_realm_joined,
+                                       page)) {
+
+      /* If we can't do user auth, try to authenticate as admin */
+      g_debug ("Cannot join with user credentials");
+
+      join_show_prompt (page, error);
+    }
+
+    g_bytes_unref (creds);
+
+    /* A problem with the user's login name or password */
+  } else if (g_error_matches (error, UM_REALM_ERROR, UM_REALM_ERROR_BAD_LOGIN)) {
+    g_debug ("Problem with the user's login: %s", error->message);
+    set_entry_validation_error (GTK_ENTRY (priv->login), error->message);
+    gtk_widget_grab_focus (priv->login);
+    apply_complete (page, FALSE);
+
+  } else if (g_error_matches (error, UM_REALM_ERROR, UM_REALM_ERROR_BAD_PASSWORD)) {
+    g_debug ("Problem with the user's password: %s", error->message);
+    set_entry_validation_error (GTK_ENTRY (priv->password), error->message);
+    gtk_widget_grab_focus (priv->password);
+    apply_complete (page, FALSE);
+
+    /* Other login failure */
+  } else {
+    show_error_dialog (page, _("Failed to log into domain"), error);
+    g_message ("Couldn't log in as user: %s", error->message);
+    apply_complete (page, FALSE);
+  }
+
+  g_clear_error (&error);
+}
+
+static void
+enterprise_check_login (GisAccountPageEnterprise *page)
+{
+  GisAccountPageEnterprisePrivate *priv = gis_account_page_enterprise_get_instance_private (page);
+
+  g_assert (priv->realm);
+
+  um_realm_login (priv->realm,
+                  gtk_entry_get_text (GTK_ENTRY (priv->login)),
+                  gtk_entry_get_text (GTK_ENTRY (priv->password)),
+                  priv->cancellable,
+                  on_realm_login,
+                  page);
+}
+
+static void
+on_realm_discover_input (GObject *source,
+                         GAsyncResult *result,
+                         gpointer user_data)
+{
+  GisAccountPageEnterprise *page = user_data;
+  GisAccountPageEnterprisePrivate *priv = gis_account_page_enterprise_get_instance_private (page);
+  GError *error = NULL;
+  GList *realms;
+
+  realms = um_realm_manager_discover_finish (priv->realm_manager,
+                                             result, &error);
+
+  /* Found a realm, log user into domain */
+  if (error == NULL) {
+    g_assert (realms != NULL);
+    priv->realm = g_object_ref (realms->data);
+    enterprise_check_login (page);
+    g_list_free_full (realms, g_object_unref);
+
+  } else {
+    /* The domain is likely invalid */
+    g_dbus_error_strip_remote_error (error);
+    g_message ("Couldn't discover domain: %s", error->message);
+    gtk_widget_grab_focus (priv->domain_entry);
+    set_entry_validation_error (GTK_ENTRY (priv->domain_entry), error->message);
+    apply_complete (page, FALSE);
+    g_error_free (error);
+  }
+}
+
+static void
+enterprise_add_user (GisAccountPageEnterprise *page)
+{
+  GisAccountPageEnterprisePrivate *priv = gis_account_page_enterprise_get_instance_private (page);
+  GtkTreeIter iter;
+
+  priv->join_prompted = FALSE;
+  g_clear_object (&priv->realm);
+
+  /* Already know about this realm, try to login as user */
+  if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (priv->domain), &iter)) {
+    gtk_tree_model_get (gtk_combo_box_get_model (GTK_COMBO_BOX (priv->domain)),
+                        &iter, 1, &priv->realm, -1);
+    enterprise_check_login (page);
+
+    /* Something the user typed, we need to discover realm */
+  } else {
+    um_realm_manager_discover (priv->realm_manager,
+                               gtk_entry_get_text (GTK_ENTRY (priv->domain_entry)),
+                               priv->cancellable,
+                               on_realm_discover_input,
+                               page);
+  }
+}
+
+gboolean
+gis_account_page_enterprise_apply (GisAccountPageEnterprise *page,
+                                   GCancellable             *cancellable,
+                                   GisPageApplyCallback      callback,
+                                   gpointer                  data)
+{
+  GisAccountPageEnterprisePrivate *priv = gis_account_page_enterprise_get_instance_private (page);
+
+  priv->apply_complete_callback = callback;
+  priv->apply_complete_data = data;
+  priv->cancellable = g_object_ref (cancellable);
+  enterprise_add_user (page);
+  return TRUE;
+}
+
+static gchar *
+realm_get_name (UmRealmObject *realm)
+{
+  UmRealmCommon *common;
+  gchar *name;
+
+  common = um_realm_object_get_common (realm);
+  name = g_strdup (um_realm_common_get_name (common));
+  g_object_unref (common);
+
+  return name;
+}
+
+static gboolean
+model_contains_realm (GtkTreeModel *model,
+                      const gchar *realm_name)
+{
+  gboolean contains = FALSE;
+  GtkTreeIter iter;
+  gboolean match;
+  gchar *name;
+  gboolean ret;
+
+  ret = gtk_tree_model_get_iter_first (model, &iter);
+  while (ret) {
+    gtk_tree_model_get (model, &iter, 0, &name, -1);
+    match = (g_strcmp0 (name, realm_name) == 0);
+    g_free (name);
+    if (match) {
+      g_debug ("ignoring duplicate realm: %s", realm_name);
+      contains = TRUE;
+      break;
+    }
+    ret = gtk_tree_model_iter_next (model, &iter);
+  }
+
+  return contains;
+}
+
+static void
+enterprise_add_realm (GisAccountPageEnterprise *page,
+                      UmRealmObject  *realm)
+{
+  GisAccountPageEnterprisePrivate *priv = gis_account_page_enterprise_get_instance_private (page);
+  GtkTreeIter iter;
+  gchar *name;
+
+  name = realm_get_name (realm);
+
+  /*
+   * Don't add a second realm if we already have one with this name.
+   * Sometimes realmd returns two realms for the same name, if it has
+   * different ways to use that realm. The first one that realmd
+   * returns is the one it prefers.
+   */
+
+  if (!model_contains_realm (GTK_TREE_MODEL (priv->realms_model), name)) {
+    gtk_list_store_append (GTK_LIST_STORE (priv->realms_model), &iter);
+    gtk_list_store_set (GTK_LIST_STORE (priv->realms_model), &iter,
+                        0, name,
+                        1, realm,
+                        -1);
+
+    if (!priv->domain_chosen && um_realm_is_configured (realm))
+      gtk_combo_box_set_active_iter (GTK_COMBO_BOX (priv->domain), &iter);
+
+    g_debug ("added realm to drop down: %s %s", name,
+             g_dbus_object_get_object_path (G_DBUS_OBJECT (realm)));
+  }
+
+  g_free (name);
+}
+
+static void
+on_manager_realm_added (UmRealmManager  *manager,
+                        UmRealmObject   *realm,
+                        gpointer         user_data)
+{
+  GisAccountPageEnterprise *page = user_data;
+  enterprise_add_realm (page, realm);
+}
+
+static void
+on_realm_manager_created (GObject *source,
+                          GAsyncResult *result,
+                          gpointer user_data)
+{
+  GisAccountPageEnterprise *page = user_data;
+  GisAccountPageEnterprisePrivate *priv = gis_account_page_enterprise_get_instance_private (page);
+  GError *error = NULL;
+  GList *realms, *l;
+
+  g_clear_object (&priv->realm_manager);
+  priv->realm_manager = um_realm_manager_new_finish (result, &error);
+
+  if (error != NULL) {
+    g_warning ("Couldn't contact realmd service: %s", error->message);
+    g_error_free (error);
+    return;
+  }
+
+  /* Lookup all the realm objects */
+  realms = um_realm_manager_get_realms (priv->realm_manager);
+  for (l = realms; l != NULL; l = g_list_next (l))
+    enterprise_add_realm (page, l->data);
+
+  g_list_free (realms);
+  g_signal_connect (priv->realm_manager, "realm-added",
+                    G_CALLBACK (on_manager_realm_added), page);
+
+  /* When no realms try to discover a sensible default, triggers realm-added signal */
+  um_realm_manager_discover (priv->realm_manager, "", NULL, NULL, NULL);
+  gtk_widget_set_visible (GTK_WIDGET (page), TRUE);
+}
+
+static void
+on_realmd_appeared (GDBusConnection *connection,
+                    const gchar *name,
+                    const gchar *name_owner,
+                    gpointer user_data)
+{
+  GisAccountPageEnterprise *page = user_data;
+  um_realm_manager_new (NULL, on_realm_manager_created, page);
+}
+
+static void
+on_realmd_disappeared (GDBusConnection *unused1,
+                       const gchar *unused2,
+                       gpointer user_data)
+{
+  GisAccountPageEnterprise *page = user_data;
+  GisAccountPageEnterprisePrivate *priv = gis_account_page_enterprise_get_instance_private (page);
+
+  if (priv->realm_manager != NULL) {
+    g_signal_handlers_disconnect_by_func (priv->realm_manager,
+                                          on_manager_realm_added,
+                                          page);
+    g_clear_object (&priv->realm_manager);
+  }
+
+  gtk_widget_set_visible (GTK_WIDGET (page), FALSE);
+}
+
+static void
+on_domain_changed (GtkComboBox *widget,
+                   gpointer user_data)
+{
+  GisAccountPageEnterprise *page = user_data;
+  GisAccountPageEnterprisePrivate *priv = gis_account_page_enterprise_get_instance_private (page);
+
+  priv->domain_chosen = TRUE;
+  validation_changed (page);
+  clear_entry_validation_error (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (widget))));
+}
+
+static void
+on_entry_changed (GtkEditable *editable,
+                  gpointer user_data)
+{
+  GisAccountPageEnterprise *page = user_data;
+  validation_changed (page);
+  clear_entry_validation_error (GTK_ENTRY (editable));
+}
+
+static void
+gis_account_page_enterprise_constructed (GObject *object)
+{
+  GisAccountPageEnterprise *page = GIS_ACCOUNT_PAGE_ENTERPRISE (object);
+  GisAccountPageEnterprisePrivate *priv = gis_account_page_enterprise_get_instance_private (page);
+
+  G_OBJECT_CLASS (gis_account_page_enterprise_parent_class)->constructed (object);
+
+  priv->act_client = act_user_manager_get_default ();
+
+  priv->realmd_watch = g_bus_watch_name (G_BUS_TYPE_SYSTEM, "org.freedesktop.realmd",
+                                         G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
+                                         on_realmd_appeared, on_realmd_disappeared,
+                                         page, NULL);
+
+  g_signal_connect (priv->join_dialog, "response",
+                    G_CALLBACK (on_join_response), page);
+  g_signal_connect (priv->domain, "changed",
+                    G_CALLBACK (on_domain_changed), page);
+  g_signal_connect (priv->login, "changed",
+                    G_CALLBACK (on_entry_changed), page);
+}
+
+static void
+gis_account_page_enterprise_dispose (GObject *object)
+{
+  GisAccountPageEnterprise *page = GIS_ACCOUNT_PAGE_ENTERPRISE (object);
+  GisAccountPageEnterprisePrivate *priv = gis_account_page_enterprise_get_instance_private (page);
+
+  if (priv->realmd_watch)
+    g_bus_unwatch_name (priv->realmd_watch);
+
+  priv->realmd_watch = 0;
+
+  g_cancellable_cancel (priv->cancellable);
+
+  g_clear_object (&priv->realm_manager);
+  g_clear_object (&priv->realm);
+  g_clear_object (&priv->cancellable);
+
+  G_OBJECT_CLASS (gis_account_page_enterprise_parent_class)->dispose (object);
+}
+
+static void
+gis_account_page_enterprise_class_init (GisAccountPageEnterpriseClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->constructed = gis_account_page_enterprise_constructed;
+  object_class->dispose = gis_account_page_enterprise_dispose;
+
+  gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (klass), 
"/org/gnome/initial-setup/gis-account-page-enterprise.ui");
+
+  gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPageEnterprise, login);
+  gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPageEnterprise, 
password);
+  gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPageEnterprise, domain);
+  gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPageEnterprise, 
domain_entry);
+  gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPageEnterprise, 
realms_model);
+
+  gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPageEnterprise, 
join_dialog);
+  gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPageEnterprise, 
join_name);
+  gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPageEnterprise, 
join_password);
+  gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPageEnterprise, 
join_domain);
+  gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPageEnterprise, 
join_computer);
+
+  signals[VALIDATION_CHANGED] = g_signal_new ("validation-changed", GIS_TYPE_ACCOUNT_PAGE_ENTERPRISE,
+                                              G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL,
+                                              G_TYPE_NONE, 0);
+}
+
+static void
+gis_account_page_enterprise_init (GisAccountPageEnterprise *page)
+{
+  gtk_widget_init_template (GTK_WIDGET (page));
+}
diff --git a/gnome-initial-setup/pages/account/gis-account-page-enterprise.h 
b/gnome-initial-setup/pages/account/gis-account-page-enterprise.h
new file mode 100644
index 0000000..2c7d14f
--- /dev/null
+++ b/gnome-initial-setup/pages/account/gis-account-page-enterprise.h
@@ -0,0 +1,64 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright (C) 2013 Red Hat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Written by:
+ *     Jasper St. Pierre <jstpierre mecheye net>
+ */
+
+#ifndef __GIS_ACCOUNT_PAGE_ENTERPRISE_H__
+#define __GIS_ACCOUNT_PAGE_ENTERPRISE_H__
+
+#include <gtk/gtk.h>
+
+/* For GisPageApplyCallback */
+#include "gis-page.h"
+
+G_BEGIN_DECLS
+
+#define GIS_TYPE_ACCOUNT_PAGE_ENTERPRISE               (gis_account_page_enterprise_get_type ())
+#define GIS_ACCOUNT_PAGE_ENTERPRISE(obj)                           (G_TYPE_CHECK_INSTANCE_CAST ((obj), 
GIS_TYPE_ACCOUNT_PAGE_ENTERPRISE, GisAccountPageEnterprise))
+#define GIS_ACCOUNT_PAGE_ENTERPRISE_CLASS(klass)                   (G_TYPE_CHECK_CLASS_CAST ((klass),  
GIS_TYPE_ACCOUNT_PAGE_ENTERPRISE, GisAccountPageEnterpriseClass))
+#define GIS_IS_ACCOUNT_PAGE_ENTERPRISE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), 
GIS_TYPE_ACCOUNT_PAGE_ENTERPRISE))
+#define GIS_IS_ACCOUNT_PAGE_ENTERPRISE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  
GIS_TYPE_ACCOUNT_PAGE_ENTERPRISE))
+#define GIS_ACCOUNT_PAGE_ENTERPRISE_GET_CLASS(obj)                 (G_TYPE_INSTANCE_GET_CLASS ((obj),  
GIS_TYPE_ACCOUNT_PAGE_ENTERPRISE, GisAccountPageEnterpriseClass))
+
+typedef struct _GisAccountPageEnterprise        GisAccountPageEnterprise;
+typedef struct _GisAccountPageEnterpriseClass   GisAccountPageEnterpriseClass;
+
+struct _GisAccountPageEnterprise
+{
+    GtkBin parent;
+};
+
+struct _GisAccountPageEnterpriseClass
+{
+    GtkBinClass parent_class;
+};
+
+GType gis_account_page_enterprise_get_type (void);
+
+gboolean gis_account_page_enterprise_validate (GisAccountPageEnterprise *enterprise);
+gboolean gis_account_page_enterprise_apply (GisAccountPageEnterprise *enterprise,
+                                            GCancellable             *cancellable,
+                                            GisPageApplyCallback      callback,
+                                            gpointer                  data);
+
+G_END_DECLS
+
+#endif /* __GIS_ACCOUNT_PAGE_ENTERPRISE_H__ */
diff --git a/gnome-initial-setup/pages/account/gis-account-page-enterprise.ui 
b/gnome-initial-setup/pages/account/gis-account-page-enterprise.ui
new file mode 100644
index 0000000..723a6d8
--- /dev/null
+++ b/gnome-initial-setup/pages/account/gis-account-page-enterprise.ui
@@ -0,0 +1,473 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <template class="GisAccountPageEnterprise" parent="GtkBin">
+    <child>
+      <object class="GtkGrid" id="area">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="hexpand">True</property>
+        <property name="row_spacing">6</property>
+        <property name="column_spacing">12</property>
+        <child>
+          <object class="GtkFrame" id="sizer3">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="label_xalign">0</property>
+            <property name="shadow_type">none</property>
+          </object>
+          <packing>
+            <property name="left_attach">0</property>
+            <property name="top_attach">0</property>
+            <property name="width">1</property>
+            <property name="height">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="title">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="halign">start</property>
+            <property name="valign">start</property>
+            <property name="margin_bottom">8</property>
+            <property name="hexpand">True</property>
+            <property name="label" translatable="yes">Create an Enterprise Account</property>
+            <attributes>
+              <attribute name="weight" value="bold"/>
+              <attribute name="scale" value="1.2"/>
+            </attributes>
+          </object>
+          <packing>
+            <property name="left_attach">0</property>
+            <property name="top_attach">0</property>
+            <property name="width">2</property>
+            <property name="height">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="label4">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="halign">end</property>
+            <property name="xalign">1</property>
+            <property name="label" translatable="yes">_Domain</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">domain</property>
+          </object>
+          <packing>
+            <property name="left_attach">0</property>
+            <property name="top_attach">1</property>
+            <property name="width">1</property>
+            <property name="height">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="label8">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="halign">end</property>
+            <property name="xalign">1</property>
+            <property name="label" translatable="yes">_Username</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">login</property>
+          </object>
+          <packing>
+            <property name="left_attach">0</property>
+            <property name="top_attach">3</property>
+            <property name="width">1</property>
+            <property name="height">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="label9">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="halign">end</property>
+            <property name="xalign">1</property>
+            <property name="label" translatable="yes">_Password</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">password</property>
+          </object>
+          <packing>
+            <property name="left_attach">0</property>
+            <property name="top_attach">4</property>
+            <property name="width">1</property>
+            <property name="height">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkEntry" id="login">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="hexpand">True</property>
+            <property name="invisible_char">●</property>
+            <property name="invisible_char_set">True</property>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="top_attach">3</property>
+            <property name="width">1</property>
+            <property name="height">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkEntry" id="password">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="hexpand">True</property>
+            <property name="visibility">False</property>
+            <property name="invisible_char">●</property>
+            <property name="activates_default">True</property>
+            <property name="invisible_char_set">True</property>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="top_attach">4</property>
+            <property name="width">1</property>
+            <property name="height">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkComboBox" id="domain">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="hexpand">True</property>
+            <property name="model">realms_model</property>
+            <property name="has_entry">True</property>
+            <property name="entry_text_column">0</property>
+            <child internal-child="entry">
+              <object class="GtkEntry" id="domain_entry">
+                <property name="can_focus">True</property>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="top_attach">1</property>
+            <property name="width">1</property>
+            <property name="height">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="label10">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="margin_bottom">12</property>
+            <property name="xalign">0</property>
+            <property name="label" translatable="yes">Enterprise domain or realm name</property>
+            <attributes>
+              <attribute name="scale" value="0.8"/>
+            </attributes>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="top_attach">2</property>
+            <property name="width">1</property>
+            <property name="height">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="filler">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+          </object>
+          <packing>
+            <property name="left_attach">2</property>
+            <property name="top_attach">4</property>
+            <property name="width">1</property>
+            <property name="height">1</property>
+          </packing>
+        </child>
+        <child>
+          <placeholder/>
+        </child>
+        <child>
+          <placeholder/>
+        </child>
+        <child>
+          <placeholder/>
+        </child>
+        <child>
+          <placeholder/>
+        </child>
+        <child>
+          <placeholder/>
+        </child>
+      </object>
+    </child>
+  </template>
+
+  <object class="GtkDialog" id="join_dialog">
+    <property name="can_focus">False</property>
+    <property name="border_width">10</property>
+    <property name="resizable">False</property>
+    <property name="modal">True</property>
+    <property name="destroy_with_parent">True</property>
+    <property name="type_hint">dialog</property>
+    <child internal-child="vbox">
+      <object class="GtkBox" id="dialog-vbox1">
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">2</property>
+        <child internal-child="action_area">
+          <object class="GtkButtonBox" id="dialog-action_area1">
+            <property name="can_focus">False</property>
+            <property name="layout_style">end</property>
+            <child>
+              <object class="GtkButton" id="button1">
+                <property name="label">gtk-cancel</property>
+                <property name="use_action_appearance">False</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="can_default">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_action_appearance">False</property>
+                <property name="use_stock">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="button2">
+                <property name="label" translatable="yes">C_ontinue</property>
+                <property name="use_action_appearance">False</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="can_default">True</property>
+                <property name="has_default">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_action_appearance">False</property>
+                <property name="use_underline">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkBox" id="box2">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="border_width">5</property>
+            <property name="orientation">vertical</property>
+            <property name="spacing">10</property>
+            <child>
+              <object class="GtkLabel" id="label71">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="label" translatable="yes">Domain Administrator Login</property>
+                <attributes>
+                  <attribute name="weight" value="bold"/>
+                  <attribute name="scale" value="1.2"/>
+                </attributes>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="label12">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="xalign">0</property>
+                <property name="yalign">0</property>
+                <property name="label" translatable="yes">In order to use enterprise logins, this computer 
needs to be
+                enrolled in the domain. Please have your network administrator
+                type their domain password here, and choose a unique computer
+                name for your computer.</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkGrid" id="grid1">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="margin_left">12</property>
+                <property name="hexpand">True</property>
+                <property name="row_spacing">6</property>
+                <property name="column_spacing">12</property>
+                <child>
+                  <object class="GtkLabel" id="label13">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="xalign">1</property>
+                    <property name="label" translatable="yes">_Domain</property>
+                    <property name="use_underline">True</property>
+                    <property name="mnemonic_widget">join_domain</property>
+                    <style>
+                      <class name="dim-label"/>
+                    </style>
+                  </object>
+                  <packing>
+                    <property name="left_attach">0</property>
+                    <property name="top_attach">0</property>
+                    <property name="width">1</property>
+                    <property name="height">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="join_domain">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="margin_top">5</property>
+                    <property name="margin_bottom">5</property>
+                    <property name="xalign">0</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="top_attach">0</property>
+                    <property name="width">1</property>
+                    <property name="height">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="label18">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="xalign">1</property>
+                    <property name="label" translatable="yes">_Computer</property>
+                    <property name="use_underline">True</property>
+                    <property name="mnemonic_widget">join_computer</property>
+                    <style>
+                      <class name="dim-label"/>
+                    </style>
+                  </object>
+                  <packing>
+                    <property name="left_attach">0</property>
+                    <property name="top_attach">1</property>
+                    <property name="width">1</property>
+                    <property name="height">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkEntry" id="join_computer">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="hexpand">True</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="top_attach">1</property>
+                    <property name="width">1</property>
+                    <property name="height">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="label14">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="xalign">1</property>
+                    <property name="label" translatable="yes">Administrator _Name</property>
+                    <property name="use_underline">True</property>
+                    <property name="mnemonic_widget">join_name</property>
+                    <style>
+                      <class name="dim-label"/>
+                    </style>
+                  </object>
+                  <packing>
+                    <property name="left_attach">0</property>
+                    <property name="top_attach">2</property>
+                    <property name="width">1</property>
+                    <property name="height">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkEntry" id="join_name">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="hexpand">True</property>
+                    <property name="invisible_char">●</property>
+                    <property name="invisible_char_set">True</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="top_attach">2</property>
+                    <property name="width">1</property>
+                    <property name="height">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="label15">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="xalign">1</property>
+                    <property name="label" translatable="yes">Administrator Password</property>
+                    <property name="use_underline">True</property>
+                    <property name="mnemonic_widget">join_password</property>
+                    <style>
+                      <class name="dim-label"/>
+                    </style>
+                  </object>
+                  <packing>
+                    <property name="left_attach">0</property>
+                    <property name="top_attach">3</property>
+                    <property name="width">1</property>
+                    <property name="height">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkEntry" id="join_password">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="hexpand">True</property>
+                    <property name="visibility">False</property>
+                    <property name="invisible_char">●</property>
+                    <property name="activates_default">True</property>
+                    <property name="invisible_char_set">True</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="top_attach">3</property>
+                    <property name="width">1</property>
+                    <property name="height">1</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">2</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <action-widgets>
+      <action-widget response="-6">button1</action-widget>
+      <action-widget response="-5">button2</action-widget>
+    </action-widgets>
+  </object>
+
+  <object class="GtkListStore" id="realms_model">
+    <columns>
+      <!-- column-name gchararray -->
+      <column type="gchararray"/>
+      <!-- column-name gobject -->
+      <column type="GObject"/>
+    </columns>
+  </object>
+</interface>
diff --git a/gnome-initial-setup/pages/account/gis-account-page.c 
b/gnome-initial-setup/pages/account/gis-account-page.c
index 4ee6711..bf4a287 100644
--- a/gnome-initial-setup/pages/account/gis-account-page.c
+++ b/gnome-initial-setup/pages/account/gis-account-page.c
@@ -29,27 +29,11 @@
 #include "account-resources.h"
 #include "gis-account-page.h"
 #include "gis-account-page-local.h"
+#include "gis-account-page-enterprise.h"
 
 #include <glib/gi18n.h>
 #include <gio/gio.h>
 
-#include <act/act-user-manager.h>
-
-#include "um-realm-manager.h"
-#include "um-utils.h"
-#include "pw-utils.h"
-
-static void        join_show_prompt    (GisAccountPage *page,
-                                        GError *error);
-
-static void        on_join_login       (GObject *source,
-                                        GAsyncResult *result,
-                                        gpointer user_data);
-
-static void        on_realm_joined     (GObject *source,
-                                        GAsyncResult *result,
-                                        gpointer user_data);
-
 typedef enum {
   UM_LOCAL,
   UM_ENTERPRISE,
@@ -59,88 +43,26 @@ typedef enum {
 struct _GisAccountPagePrivate
 {
   GtkWidget *page_local;
-
-  GtkWidget *enterprise_login;
-  GtkWidget *enterprise_password;
-  GtkWidget *enterprise_domain;
-  GtkWidget *enterprise_domain_entry;
-  GtkTreeModel *enterprise_realms_model;
-
-  GtkWidget *join_dialog;
-  GtkWidget *join_name;
-  GtkWidget *join_password;
-  GtkWidget *join_domain;
-  GtkWidget *join_computer;
+  GtkWidget *page_enterprise;
 
   GtkWidget *page_toggle;
   GtkWidget *notebook;
 
-  ActUserManager *act_client;
-  ActUser *act_user;
-
   UmAccountMode mode;
 
   gboolean has_enterprise;
-  guint realmd_watch;
-  UmRealmManager *realm_manager;
-  gboolean domain_chosen;
-
-  /* Valid during apply */
-  UmRealmObject *realm;
-  GCancellable *cancellable;
-  gboolean join_prompted;
 };
 typedef struct _GisAccountPagePrivate GisAccountPagePrivate;
 
 G_DEFINE_TYPE_WITH_PRIVATE (GisAccountPage, gis_account_page, GIS_TYPE_PAGE);
 
 static void
-show_error_dialog (GisAccountPage *page,
-                   const gchar *message,
-                   GError *error)
-{
-  GtkWidget *dialog;
-
-  if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
-    return;
-
-  dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (page))),
-                                   GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
-                                   GTK_MESSAGE_ERROR,
-                                   GTK_BUTTONS_CLOSE,
-                                   "%s", message);
-
-  if (error != NULL) {
-    g_dbus_error_strip_remote_error (error);
-    gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
-                                              "%s", error->message);
-  }
-
-  g_signal_connect (dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL);
-  gtk_window_present (GTK_WINDOW (dialog));
-}
-
-static gboolean
-enterprise_validate (GisAccountPage *page)
+enterprise_apply_complete (GisPage  *dummy,
+                           gboolean  valid,
+                           gpointer  user_data)
 {
-  const gchar *name;
-  gboolean valid_name;
-  gboolean valid_domain;
-  GtkTreeIter iter;
-  GisAccountPagePrivate *priv = gis_account_page_get_instance_private (page);
-
-  name = gtk_entry_get_text (GTK_ENTRY (priv->enterprise_login));
-  valid_name = is_valid_name (name);
-
-  if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (priv->enterprise_domain), &iter)) {
-    gtk_tree_model_get (gtk_combo_box_get_model (GTK_COMBO_BOX (priv->enterprise_domain)),
-                        &iter, 0, &name, -1);
-  } else {
-    name = gtk_entry_get_text (GTK_ENTRY (priv->enterprise_domain_entry));
-  }
-
-  valid_domain = is_valid_name (name);
-  return valid_name && valid_domain;
+  GisAccountPage *page = GIS_ACCOUNT_PAGE (user_data);
+  gis_page_apply_complete (GIS_PAGE (page), valid);
 }
 
 static gboolean
@@ -152,7 +74,7 @@ page_validate (GisAccountPage *page)
   case UM_LOCAL:
     return gis_account_page_local_validate (GIS_ACCOUNT_PAGE_LOCAL (priv->page_local));
   case UM_ENTERPRISE:
-    return enterprise_validate (page);
+    return gis_account_page_enterprise_validate (GIS_ACCOUNT_PAGE_ENTERPRISE (priv->page_enterprise));
   default:
     g_assert_not_reached ();
   }
@@ -188,10 +110,15 @@ set_mode (GisAccountPage *page,
 }
 
 static void
-set_has_enterprise (GisAccountPage *page,
-                    gboolean        has_enterprise)
+on_enterprise_visible_changed (GObject    *object,
+                               GParamSpec *param,
+                               gpointer    user_data)
 {
+  GisAccountPage *page = GIS_ACCOUNT_PAGE (user_data);
   GisAccountPagePrivate *priv = gis_account_page_get_instance_private (page);
+  gboolean has_enterprise;
+
+  has_enterprise = gtk_widget_get_visible (priv->page_enterprise);
 
   if (priv->has_enterprise == has_enterprise)
     return;
@@ -205,581 +132,6 @@ set_has_enterprise (GisAccountPage *page,
 }
 
 static void
-on_permit_user_login (GObject *source,
-                      GAsyncResult *result,
-                      gpointer user_data)
-{
-  GisAccountPage *page = user_data;
-  GisAccountPagePrivate *priv = gis_account_page_get_instance_private (page);
-  UmRealmCommon *common;
-  GError *error = NULL;
-  gchar *login;
-
-  common = UM_REALM_COMMON (source);
-  um_realm_common_call_change_login_policy_finish (common, result, &error);
-  if (error == NULL) {
-
-    /*
-     * Now tell the account service about this user. The account service
-     * should also lookup information about this via the realm and make
-     * sure all that is functional.
-     */
-    login = um_realm_calculate_login (common, gtk_entry_get_text (GTK_ENTRY (priv->enterprise_login)));
-    g_return_if_fail (login != NULL);
-
-    g_debug ("Caching remote user: %s", login);
-
-    priv->act_user = act_user_manager_cache_user (priv->act_client, login, NULL);
-    gis_page_apply_complete (GIS_PAGE (page), TRUE);
-
-    g_free (login);
-  } else {
-    show_error_dialog (page, _("Failed to register account"), error);
-    g_message ("Couldn't permit logins on account: %s", error->message);
-    g_error_free (error);
-    gis_page_apply_complete (GIS_PAGE (page), FALSE);
-  }
-}
-
-static void
-enterprise_permit_user_login (GisAccountPage *page, UmRealmObject *realm)
-{
-  GisAccountPagePrivate *priv = gis_account_page_get_instance_private (page);
-  UmRealmCommon *common;
-  gchar *login;
-  const gchar *add[2];
-  const gchar *remove[1];
-  GVariant *options;
-
-  common = um_realm_object_get_common (realm);
-
-  login = um_realm_calculate_login (common, gtk_entry_get_text (GTK_ENTRY (priv->enterprise_login)));
-  g_return_if_fail (login != NULL);
-
-  add[0] = login;
-  add[1] = NULL;
-  remove[0] = NULL;
-
-  g_debug ("Permitting login for: %s", login);
-  options = g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0);
-
-  um_realm_common_call_change_login_policy (common, "",
-                                            add, remove, options,
-                                            priv->cancellable,
-                                            on_permit_user_login,
-                                            page);
-
-  g_object_unref (common);
-  g_free (login);
-}
-
-static void
-on_set_static_hostname (GObject *source,
-                        GAsyncResult *result,
-                        gpointer user_data)
-{
-  GisAccountPage *page = user_data;
-  GisAccountPagePrivate *priv = gis_account_page_get_instance_private (page);
-  GError *error = NULL;
-  GVariant *retval;
-
-  retval = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error);
-  if (error != NULL) {
-    join_show_prompt (page, error);
-    g_error_free (error);
-    return;
-  }
-
-  g_variant_unref (retval);
-
-  /* Prompted for some admin credentials, try to use them to log in */
-  um_realm_login (priv->realm,
-                  gtk_entry_get_text (GTK_ENTRY (priv->join_name)),
-                  gtk_entry_get_text (GTK_ENTRY (priv->join_password)),
-                  priv->cancellable, on_join_login, page);
-}
-
-static void
-on_join_response (GtkDialog *dialog,
-                  gint response,
-                  gpointer user_data)
-{
-  GisAccountPage *page = user_data;
-  GisAccountPagePrivate *priv = gis_account_page_get_instance_private (page);
-  GDBusConnection *connection;
-  GError *error = NULL;
-  gchar hostname[128];
-  const gchar *name;
-
-  gtk_widget_hide (GTK_WIDGET (dialog));
-  if (response != GTK_RESPONSE_OK) {
-    gis_page_apply_complete (GIS_PAGE (page), FALSE);
-    return;
-  }
-
-  name = gtk_entry_get_text (GTK_ENTRY (priv->join_computer));
-  if (gethostname (hostname, sizeof (hostname)) == 0 &&
-      !g_str_equal (name, hostname)) {
-    g_debug ("Setting StaticHostname to '%s'", name);
-
-    connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, priv->cancellable, &error);
-    if (error != NULL) {
-      gis_page_apply_complete (GIS_PAGE (page), FALSE);
-      g_warning ("Could not get DBus connection: %s", error->message);
-      g_error_free (error);
-      return;
-    }
-
-    g_dbus_connection_call (connection, "org.freedesktop.hostname1",
-                            "/org/freedesktop/hostname1", "org.freedesktop.hostname1",
-                            "SetStaticHostname",
-                            g_variant_new ("(sb)", name, TRUE),
-                            G_VARIANT_TYPE ("()"),
-                            G_DBUS_CALL_FLAGS_NONE,
-                            G_MAXINT, NULL, on_set_static_hostname, page);
-
-  } else {
-    name = gtk_entry_get_text (GTK_ENTRY (priv->join_name));
-    g_debug ("Logging in as admin user: %s", name);
-
-    /* Prompted for some admin credentials, try to use them to log in */
-    um_realm_login (priv->realm, name,
-                    gtk_entry_get_text (GTK_ENTRY (priv->join_password)),
-                    NULL, on_join_login, page);
-  }
-}
-
-static void
-join_show_prompt (GisAccountPage *page,
-                  GError *error)
-{
-  GisAccountPagePrivate *priv = gis_account_page_get_instance_private (page);
-  UmRealmKerberosMembership *membership;
-  UmRealmKerberos *kerberos;
-  gchar hostname[128];
-  const gchar *name;
-
-  gtk_entry_set_text (GTK_ENTRY (priv->join_password), "");
-  gtk_widget_grab_focus (GTK_WIDGET (priv->join_password));
-
-  kerberos = um_realm_object_get_kerberos (priv->realm);
-  membership = um_realm_object_get_kerberos_membership (priv->realm);
-
-  gtk_label_set_text (GTK_LABEL (priv->join_domain),
-                      um_realm_kerberos_get_domain_name (kerberos));
-
-  if (gethostname (hostname, sizeof (hostname)) == 0)
-    gtk_entry_set_text (GTK_ENTRY (priv->join_computer), hostname);
-
-  clear_entry_validation_error (GTK_ENTRY (priv->join_name));
-  clear_entry_validation_error (GTK_ENTRY (priv->join_password));
-
-  if (!priv->join_prompted) {
-    name = um_realm_kerberos_membership_get_suggested_administrator (membership);
-    if (name && !g_str_equal (name, "")) {
-      g_debug ("Suggesting admin user: %s", name);
-      gtk_entry_set_text (GTK_ENTRY (priv->join_name), name);
-    } else {
-      gtk_widget_grab_focus (GTK_WIDGET (priv->join_name));
-    }
-
-  } else if (g_error_matches (error, UM_REALM_ERROR, UM_REALM_ERROR_BAD_HOSTNAME)) {
-    g_debug ("Bad host name: %s", error->message);
-    set_entry_validation_error (GTK_ENTRY (priv->join_computer), error->message);
-
-  } else if (g_error_matches (error, UM_REALM_ERROR, UM_REALM_ERROR_BAD_PASSWORD)) {
-    g_debug ("Bad admin password: %s", error->message);
-    set_entry_validation_error (GTK_ENTRY (priv->join_password), error->message);
-
-  } else {
-    g_debug ("Admin login failure: %s", error->message);
-    g_dbus_error_strip_remote_error (error);
-    set_entry_validation_error (GTK_ENTRY (priv->join_name), error->message);
-  }
-
-  g_debug ("Showing admin password dialog");
-  gtk_window_set_transient_for (GTK_WINDOW (priv->join_dialog),
-                                GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (page))));
-  gtk_window_set_modal (GTK_WINDOW (priv->join_dialog), TRUE);
-  gtk_window_present (GTK_WINDOW (priv->join_dialog));
-
-  priv->join_prompted = TRUE;
-  g_object_unref (kerberos);
-  g_object_unref (membership);
-
-  /* And now we wait for on_join_response() */
-}
-
-static void
-on_join_login (GObject *source,
-               GAsyncResult *result,
-               gpointer user_data)
-{
-  GisAccountPage *page = user_data;
-  GisAccountPagePrivate *priv = gis_account_page_get_instance_private (page);
-  GError *error = NULL;
-  GBytes *creds;
-
-  um_realm_login_finish (priv->realm, result, &creds, &error);
-
-  /* Logged in as admin successfully, use creds to join domain */
-  if (error == NULL) {
-    if (!um_realm_join_as_admin (priv->realm,
-                                 gtk_entry_get_text (GTK_ENTRY (priv->join_name)),
-                                 gtk_entry_get_text (GTK_ENTRY (priv->join_password)),
-                                 creds, NULL, on_realm_joined, page)) {
-      show_error_dialog (page, _("No supported way to authenticate with this domain"), NULL);
-      g_message ("Authenticating as admin is not supported by the realm");
-    }
-
-    g_bytes_unref (creds);
-
-  /* Couldn't login as admin, show prompt again */
-  } else {
-    join_show_prompt (page, error);
-    g_message ("Couldn't log in as admin to join domain: %s", error->message);
-    g_error_free (error);
-  }
-}
-
-static void
-on_realm_joined (GObject *source,
-                 GAsyncResult *result,
-                 gpointer user_data)
-{
-  GisAccountPage *page = user_data;
-  GisAccountPagePrivate *priv = gis_account_page_get_instance_private (page);
-  GError *error = NULL;
-
-  um_realm_join_finish (priv->realm, result, &error);
-
-  /* Yay, joined the domain, register the user locally */
-  if (error == NULL) {
-    g_debug ("Joining realm completed successfully");
-    enterprise_permit_user_login (page, priv->realm);
-
-    /* Credential failure while joining domain, prompt for admin creds */
-  } else if (g_error_matches (error, UM_REALM_ERROR, UM_REALM_ERROR_BAD_LOGIN) ||
-             g_error_matches (error, UM_REALM_ERROR, UM_REALM_ERROR_BAD_PASSWORD) ||
-             g_error_matches (error, UM_REALM_ERROR, UM_REALM_ERROR_BAD_HOSTNAME)) {
-    g_debug ("Joining realm failed due to credentials or host name");
-
-    join_show_prompt (page, error);
-
-    /* Other failure */
-  } else {
-    show_error_dialog (page, _("Failed to join domain"), error);
-    g_message ("Failed to join the domain: %s", error->message);
-    gis_page_apply_complete (GIS_PAGE (page), FALSE);
-  }
-
-  g_clear_error (&error);
-}
-
-static void
-on_realm_login (GObject *source,
-                GAsyncResult *result,
-                gpointer user_data)
-{
-  GisAccountPage *page = user_data;
-  GisAccountPagePrivate *priv = gis_account_page_get_instance_private (page);
-  GError *error = NULL;
-  GBytes *creds = NULL;
-
-  um_realm_login_finish (priv->realm, result, &creds, &error);
-
-  /*
-   * User login is valid, but cannot authenticate right now (eg: user needs
-   * to change password at next login etc.)
-   */
-  if (g_error_matches (error, UM_REALM_ERROR, UM_REALM_ERROR_CANNOT_AUTH)) {
-    g_clear_error (&error);
-    creds = NULL;
-  }
-
-  if (error == NULL) {
-
-    /* Already joined to the domain, just register this user */
-    if (um_realm_is_configured (priv->realm)) {
-      g_debug ("Already joined to this realm");
-      enterprise_permit_user_login (page, priv->realm);
-
-      /* Join the domain, try using the user's creds */
-    } else if (creds == NULL ||
-               !um_realm_join_as_user (priv->realm,
-                                       gtk_entry_get_text (GTK_ENTRY (priv->enterprise_login)),
-                                       gtk_entry_get_text (GTK_ENTRY (priv->enterprise_password)),
-                                       creds, priv->cancellable,
-                                       on_realm_joined,
-                                       page)) {
-
-      /* If we can't do user auth, try to authenticate as admin */
-      g_debug ("Cannot join with user credentials");
-
-      join_show_prompt (page, error);
-    }
-
-    g_bytes_unref (creds);
-
-    /* A problem with the user's login name or password */
-  } else if (g_error_matches (error, UM_REALM_ERROR, UM_REALM_ERROR_BAD_LOGIN)) {
-    g_debug ("Problem with the user's login: %s", error->message);
-    set_entry_validation_error (GTK_ENTRY (priv->enterprise_login), error->message);
-    gtk_widget_grab_focus (priv->enterprise_login);
-    gis_page_apply_complete (GIS_PAGE (page), FALSE);
-
-  } else if (g_error_matches (error, UM_REALM_ERROR, UM_REALM_ERROR_BAD_PASSWORD)) {
-    g_debug ("Problem with the user's password: %s", error->message);
-    set_entry_validation_error (GTK_ENTRY (priv->enterprise_password), error->message);
-    gtk_widget_grab_focus (priv->enterprise_password);
-    gis_page_apply_complete (GIS_PAGE (page), FALSE);
-
-    /* Other login failure */
-  } else {
-    show_error_dialog (page, _("Failed to log into domain"), error);
-    g_message ("Couldn't log in as user: %s", error->message);
-    gis_page_apply_complete (GIS_PAGE (page), FALSE);
-  }
-
-  g_clear_error (&error);
-}
-
-static void
-enterprise_check_login (GisAccountPage *page)
-{
-  GisAccountPagePrivate *priv = gis_account_page_get_instance_private (page);
-
-  g_assert (priv->realm);
-
-  um_realm_login (priv->realm,
-                  gtk_entry_get_text (GTK_ENTRY (priv->enterprise_login)),
-                  gtk_entry_get_text (GTK_ENTRY (priv->enterprise_password)),
-                  priv->cancellable,
-                  on_realm_login,
-                  page);
-}
-
-static void
-on_realm_discover_input (GObject *source,
-                         GAsyncResult *result,
-                         gpointer user_data)
-{
-  GisAccountPage *page = user_data;
-  GisAccountPagePrivate *priv = gis_account_page_get_instance_private (page);
-  GError *error = NULL;
-  GList *realms;
-
-  realms = um_realm_manager_discover_finish (priv->realm_manager,
-                                             result, &error);
-
-  /* Found a realm, log user into domain */
-  if (error == NULL) {
-    g_assert (realms != NULL);
-    priv->realm = g_object_ref (realms->data);
-    enterprise_check_login (page);
-    g_list_free_full (realms, g_object_unref);
-
-  } else {
-    /* The domain is likely invalid */
-    g_dbus_error_strip_remote_error (error);
-    g_message ("Couldn't discover domain: %s", error->message);
-    gtk_widget_grab_focus (priv->enterprise_domain_entry);
-    set_entry_validation_error (GTK_ENTRY (priv->enterprise_domain_entry), error->message);
-    gis_page_apply_complete (GIS_PAGE (page), FALSE);
-    g_error_free (error);
-  }
-}
-
-static void
-enterprise_add_user (GisAccountPage *page)
-{
-  GisAccountPagePrivate *priv = gis_account_page_get_instance_private (page);
-  GtkTreeIter iter;
-
-  priv->join_prompted = FALSE;
-  g_clear_object (&priv->realm);
-
-  /* Already know about this realm, try to login as user */
-  if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (priv->enterprise_domain), &iter)) {
-    gtk_tree_model_get (gtk_combo_box_get_model (GTK_COMBO_BOX (priv->enterprise_domain)),
-                        &iter, 1, &priv->realm, -1);
-    enterprise_check_login (page);
-
-    /* Something the user typed, we need to discover realm */
-  } else {
-    um_realm_manager_discover (priv->realm_manager,
-                               gtk_entry_get_text (GTK_ENTRY (priv->enterprise_domain_entry)),
-                               priv->cancellable,
-                               on_realm_discover_input,
-                               page);
-  }
-}
-
-static gchar *
-realm_get_name (UmRealmObject *realm)
-{
-  UmRealmCommon *common;
-  gchar *name;
-
-  common = um_realm_object_get_common (realm);
-  name = g_strdup (um_realm_common_get_name (common));
-  g_object_unref (common);
-
-  return name;
-}
-
-static gboolean
-model_contains_realm (GtkTreeModel *model,
-                      const gchar *realm_name)
-{
-  gboolean contains = FALSE;
-  GtkTreeIter iter;
-  gboolean match;
-  gchar *name;
-  gboolean ret;
-
-  ret = gtk_tree_model_get_iter_first (model, &iter);
-  while (ret) {
-    gtk_tree_model_get (model, &iter, 0, &name, -1);
-    match = (g_strcmp0 (name, realm_name) == 0);
-    g_free (name);
-    if (match) {
-      g_debug ("ignoring duplicate realm: %s", realm_name);
-      contains = TRUE;
-      break;
-    }
-    ret = gtk_tree_model_iter_next (model, &iter);
-  }
-
-  return contains;
-}
-
-static void
-enterprise_add_realm (GisAccountPage *page,
-                      UmRealmObject  *realm)
-{
-  GisAccountPagePrivate *priv = gis_account_page_get_instance_private (page);
-  GtkTreeIter iter;
-  gchar *name;
-
-  name = realm_get_name (realm);
-
-  /*
-   * Don't add a second realm if we already have one with this name.
-   * Sometimes realmd returns two realms for the same name, if it has
-   * different ways to use that realm. The first one that realmd
-   * returns is the one it prefers.
-   */
-
-  if (!model_contains_realm (GTK_TREE_MODEL (priv->enterprise_realms_model), name)) {
-    gtk_list_store_append (GTK_LIST_STORE (priv->enterprise_realms_model), &iter);
-    gtk_list_store_set (GTK_LIST_STORE (priv->enterprise_realms_model), &iter,
-                        0, name,
-                        1, realm,
-                        -1);
-
-    if (!priv->domain_chosen && um_realm_is_configured (realm))
-      gtk_combo_box_set_active_iter (GTK_COMBO_BOX (priv->enterprise_domain), &iter);
-
-    g_debug ("added realm to drop down: %s %s", name,
-             g_dbus_object_get_object_path (G_DBUS_OBJECT (realm)));
-  }
-
-  g_free (name);
-}
-
-static void
-on_manager_realm_added (UmRealmManager  *manager,
-                        UmRealmObject   *realm,
-                        gpointer         user_data)
-{
-  GisAccountPage *page = user_data;
-  enterprise_add_realm (page, realm);
-}
-
-static void
-on_realm_manager_created (GObject *source,
-                          GAsyncResult *result,
-                          gpointer user_data)
-{
-  GisAccountPage *page = user_data;
-  GisAccountPagePrivate *priv = gis_account_page_get_instance_private (page);
-  GError *error = NULL;
-  GList *realms, *l;
-
-  g_clear_object (&priv->realm_manager);
-  priv->realm_manager = um_realm_manager_new_finish (result, &error);
-
-  if (error != NULL) {
-    g_warning ("Couldn't contact realmd service: %s", error->message);
-    g_error_free (error);
-    return;
-  }
-
-  /* Lookup all the realm objects */
-  realms = um_realm_manager_get_realms (priv->realm_manager);
-  for (l = realms; l != NULL; l = g_list_next (l))
-    enterprise_add_realm (page, l->data);
-
-  g_list_free (realms);
-  g_signal_connect (priv->realm_manager, "realm-added",
-                    G_CALLBACK (on_manager_realm_added), page);
-
-  /* When no realms try to discover a sensible default, triggers realm-added signal */
-  um_realm_manager_discover (priv->realm_manager, "", NULL, NULL, NULL);
-  set_has_enterprise (page, TRUE);
-}
-
-static void
-on_realmd_appeared (GDBusConnection *connection,
-                    const gchar *name,
-                    const gchar *name_owner,
-                    gpointer user_data)
-{
-  GisAccountPage *page = user_data;
-  um_realm_manager_new (NULL, on_realm_manager_created, page);
-}
-
-static void
-on_realmd_disappeared (GDBusConnection *unused1,
-                       const gchar *unused2,
-                       gpointer user_data)
-{
-  GisAccountPage *page = user_data;
-  GisAccountPagePrivate *priv = gis_account_page_get_instance_private (page);
-
-  if (priv->realm_manager != NULL) {
-    g_signal_handlers_disconnect_by_func (priv->realm_manager,
-                                          on_manager_realm_added,
-                                          page);
-    g_clear_object (&priv->realm_manager);
-  }
-
-  set_has_enterprise (page, FALSE);
-}
-
-static void
-on_domain_changed (GtkComboBox *widget,
-                   gpointer user_data)
-{
-  GisAccountPage *page = user_data;
-  GisAccountPagePrivate *priv = gis_account_page_get_instance_private (page);
-
-  priv->domain_chosen = TRUE;
-  update_page_validation (page);
-  clear_entry_validation_error (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (widget))));
-}
-
-static void
-on_entry_changed (GtkEditable *editable,
-                  gpointer user_data)
-{
-  GisAccountPage *page = user_data;
-  update_page_validation (page);
-  clear_entry_validation_error (GTK_ENTRY (editable));
-}
-
-static void
 toggle_mode (GtkToggleButton *button,
              gpointer         user_data)
 {
@@ -798,8 +150,8 @@ gis_account_page_apply (GisPage *gis_page,
   case UM_LOCAL:
     return FALSE;
   case UM_ENTERPRISE:
-    priv->cancellable = g_object_ref (cancellable);
-    enterprise_add_user (page);
+    return gis_account_page_enterprise_apply (GIS_ACCOUNT_PAGE_ENTERPRISE (priv->page_enterprise), 
cancellable,
+                                              enterprise_apply_complete, page);
     return TRUE;
   default:
     g_assert_not_reached ();
@@ -846,25 +198,16 @@ gis_account_page_constructed (GObject *object)
 
   G_OBJECT_CLASS (gis_account_page_parent_class)->constructed (object);
 
-  priv->realmd_watch = g_bus_watch_name (G_BUS_TYPE_SYSTEM, "org.freedesktop.realmd",
-                                         G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
-                                         on_realmd_appeared, on_realmd_disappeared,
-                                         page, NULL);
-
-  g_signal_connect (priv->join_dialog, "response",
-                    G_CALLBACK (on_join_response), page);
-  g_signal_connect (priv->enterprise_domain, "changed",
-                    G_CALLBACK (on_domain_changed), page);
-  g_signal_connect (priv->enterprise_login, "changed",
-                    G_CALLBACK (on_entry_changed), page);
-
-  priv->act_client = act_user_manager_get_default ();
-
   g_signal_connect (priv->page_local, "validation-changed",
                     G_CALLBACK (on_validation_changed), page);
   g_signal_connect (priv->page_local, "user-created",
                     G_CALLBACK (on_local_user_created), page);
 
+  g_signal_connect (priv->page_enterprise, "validation-changed",
+                    G_CALLBACK (on_validation_changed), page);
+  g_signal_connect (priv->page_enterprise, "notify::visible",
+                    G_CALLBACK (on_enterprise_visible_changed), page);
+
   update_page_validation (page);
 
   priv->has_enterprise = FALSE;
@@ -880,26 +223,6 @@ gis_account_page_constructed (GObject *object)
 }
 
 static void
-gis_account_page_dispose (GObject *object)
-{
-  GisAccountPage *page = GIS_ACCOUNT_PAGE (object);
-  GisAccountPagePrivate *priv = gis_account_page_get_instance_private (page);
-
-  if (priv->realmd_watch)
-    g_bus_unwatch_name (priv->realmd_watch);
-
-  priv->realmd_watch = 0;
-
-  g_cancellable_cancel (priv->cancellable);
-
-  g_clear_object (&priv->realm_manager);
-  g_clear_object (&priv->realm);
-  g_clear_object (&priv->cancellable);
-
-  G_OBJECT_CLASS (gis_account_page_parent_class)->dispose (object);
-}
-
-static void
 gis_account_page_locale_changed (GisPage *page)
 {
   gis_page_set_title (GIS_PAGE (page), _("Login"));
@@ -914,18 +237,7 @@ gis_account_page_class_init (GisAccountPageClass *klass)
   gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (klass), 
"/org/gnome/initial-setup/gis-account-page.ui");
 
   gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPage, page_local);
-
-  gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPage, enterprise_login);
-  gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPage, 
enterprise_password);
-  gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPage, enterprise_domain);
-  gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPage, 
enterprise_domain_entry);
-  gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPage, 
enterprise_realms_model);
-
-  gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPage, join_dialog);
-  gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPage, join_name);
-  gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPage, join_password);
-  gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPage, join_domain);
-  gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPage, join_computer);
+  gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPage, page_enterprise);
 
   gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPage, page_toggle);
   gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPage, notebook);
@@ -935,7 +247,6 @@ gis_account_page_class_init (GisAccountPageClass *klass)
   page_class->apply = gis_account_page_apply;
   page_class->save_data = gis_account_page_save_data;
   object_class->constructed = gis_account_page_constructed;
-  object_class->dispose = gis_account_page_dispose;
 }
 
 static void
@@ -943,6 +254,7 @@ gis_account_page_init (GisAccountPage *page)
 {
   g_resources_register (account_get_resource ());
   g_type_ensure (GIS_TYPE_ACCOUNT_PAGE_LOCAL);
+  g_type_ensure (GIS_TYPE_ACCOUNT_PAGE_ENTERPRISE);
 
   gtk_widget_init_template (GTK_WIDGET (page));
 }
diff --git a/gnome-initial-setup/pages/account/gis-account-page.ui 
b/gnome-initial-setup/pages/account/gis-account-page.ui
index 12dbdd5..d6781bb 100644
--- a/gnome-initial-setup/pages/account/gis-account-page.ui
+++ b/gnome-initial-setup/pages/account/gis-account-page.ui
@@ -24,200 +24,9 @@
               </object>
             </child>
             <child>
-              <object class="GtkGrid" id="enterprise_area">
+              <object class="GisAccountPageEnterprise" id="page_enterprise">
                 <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="hexpand">True</property>
-                <property name="row_spacing">6</property>
-                <property name="column_spacing">12</property>
-                <child>
-                  <object class="GtkFrame" id="sizer3">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="label_xalign">0</property>
-                    <property name="shadow_type">none</property>
-                  </object>
-                  <packing>
-                    <property name="left_attach">0</property>
-                    <property name="top_attach">0</property>
-                    <property name="width">1</property>
-                    <property name="height">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="enterprise_title">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="halign">start</property>
-                    <property name="valign">start</property>
-                    <property name="margin_bottom">8</property>
-                    <property name="hexpand">True</property>
-                    <property name="label" translatable="yes">Create an Enterprise Account</property>
-                    <attributes>
-                      <attribute name="weight" value="bold"/>
-                      <attribute name="scale" value="1.2"/>
-                    </attributes>
-                  </object>
-                  <packing>
-                    <property name="left_attach">0</property>
-                    <property name="top_attach">0</property>
-                    <property name="width">2</property>
-                    <property name="height">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="label4">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="halign">end</property>
-                    <property name="xalign">1</property>
-                    <property name="label" translatable="yes">_Domain</property>
-                    <property name="use_underline">True</property>
-                    <property name="mnemonic_widget">enterprise_domain</property>
-                  </object>
-                  <packing>
-                    <property name="left_attach">0</property>
-                    <property name="top_attach">1</property>
-                    <property name="width">1</property>
-                    <property name="height">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="label8">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="halign">end</property>
-                    <property name="xalign">1</property>
-                    <property name="label" translatable="yes">_Username</property>
-                    <property name="use_underline">True</property>
-                    <property name="mnemonic_widget">enterprise_login</property>
-                  </object>
-                  <packing>
-                    <property name="left_attach">0</property>
-                    <property name="top_attach">3</property>
-                    <property name="width">1</property>
-                    <property name="height">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="label9">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="halign">end</property>
-                    <property name="xalign">1</property>
-                    <property name="label" translatable="yes">_Password</property>
-                    <property name="use_underline">True</property>
-                    <property name="mnemonic_widget">enterprise_password</property>
-                  </object>
-                  <packing>
-                    <property name="left_attach">0</property>
-                    <property name="top_attach">4</property>
-                    <property name="width">1</property>
-                    <property name="height">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkEntry" id="enterprise_login">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="hexpand">True</property>
-                    <property name="invisible_char">●</property>
-                    <property name="invisible_char_set">True</property>
-                  </object>
-                  <packing>
-                    <property name="left_attach">1</property>
-                    <property name="top_attach">3</property>
-                    <property name="width">1</property>
-                    <property name="height">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkEntry" id="enterprise_password">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="hexpand">True</property>
-                    <property name="visibility">False</property>
-                    <property name="invisible_char">●</property>
-                    <property name="activates_default">True</property>
-                    <property name="invisible_char_set">True</property>
-                  </object>
-                  <packing>
-                    <property name="left_attach">1</property>
-                    <property name="top_attach">4</property>
-                    <property name="width">1</property>
-                    <property name="height">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkComboBox" id="enterprise_domain">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="hexpand">True</property>
-                    <property name="model">enterprise_realms_model</property>
-                    <property name="has_entry">True</property>
-                    <property name="entry_text_column">0</property>
-                    <child internal-child="entry">
-                      <object class="GtkEntry" id="enterprise_domain_entry">
-                        <property name="can_focus">True</property>
-                      </object>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="left_attach">1</property>
-                    <property name="top_attach">1</property>
-                    <property name="width">1</property>
-                    <property name="height">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="label10">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="margin_bottom">12</property>
-                    <property name="xalign">0</property>
-                    <property name="label" translatable="yes">Enterprise domain or realm name</property>
-                    <attributes>
-                      <attribute name="scale" value="0.8"/>
-                    </attributes>
-                  </object>
-                  <packing>
-                    <property name="left_attach">1</property>
-                    <property name="top_attach">2</property>
-                    <property name="width">1</property>
-                    <property name="height">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="filler">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                  </object>
-                  <packing>
-                    <property name="left_attach">2</property>
-                    <property name="top_attach">4</property>
-                    <property name="width">1</property>
-                    <property name="height">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <placeholder/>
-                </child>
-                <child>
-                  <placeholder/>
-                </child>
-                <child>
-                  <placeholder/>
-                </child>
-                <child>
-                  <placeholder/>
-                </child>
-                <child>
-                  <placeholder/>
-                </child>
               </object>
-              <packing>
-                <property name="position">1</property>
-              </packing>
             </child>
           </object>
           <packing>
@@ -238,278 +47,4 @@
       </object>
     </child>
   </template>
-
-  <object class="GtkDialog" id="join_dialog">
-    <property name="can_focus">False</property>
-    <property name="border_width">10</property>
-    <property name="resizable">False</property>
-    <property name="modal">True</property>
-    <property name="destroy_with_parent">True</property>
-    <property name="type_hint">dialog</property>
-    <child internal-child="vbox">
-      <object class="GtkBox" id="dialog-vbox1">
-        <property name="can_focus">False</property>
-        <property name="orientation">vertical</property>
-        <property name="spacing">2</property>
-        <child internal-child="action_area">
-          <object class="GtkButtonBox" id="dialog-action_area1">
-            <property name="can_focus">False</property>
-            <property name="layout_style">end</property>
-            <child>
-              <object class="GtkButton" id="button1">
-                <property name="label">gtk-cancel</property>
-                <property name="use_action_appearance">False</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="can_default">True</property>
-                <property name="receives_default">True</property>
-                <property name="use_action_appearance">False</property>
-                <property name="use_stock">True</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkButton" id="button2">
-                <property name="label" translatable="yes">C_ontinue</property>
-                <property name="use_action_appearance">False</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="can_default">True</property>
-                <property name="has_default">True</property>
-                <property name="receives_default">True</property>
-                <property name="use_action_appearance">False</property>
-                <property name="use_underline">True</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">1</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">True</property>
-            <property name="pack_type">end</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkBox" id="box2">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="border_width">5</property>
-            <property name="orientation">vertical</property>
-            <property name="spacing">10</property>
-            <child>
-              <object class="GtkLabel" id="label71">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="label" translatable="yes">Domain Administrator Login</property>
-                <attributes>
-                  <attribute name="weight" value="bold"/>
-                  <attribute name="scale" value="1.2"/>
-                </attributes>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkLabel" id="label12">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="xalign">0</property>
-                <property name="yalign">0</property>
-                <property name="label" translatable="yes">In order to use enterprise logins, this computer 
needs to be
-                enrolled in the domain. Please have your network administrator
-                type their domain password here, and choose a unique computer
-                name for your computer.</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">1</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkGrid" id="grid1">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="margin_left">12</property>
-                <property name="hexpand">True</property>
-                <property name="row_spacing">6</property>
-                <property name="column_spacing">12</property>
-                <child>
-                  <object class="GtkLabel" id="label13">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="xalign">1</property>
-                    <property name="label" translatable="yes">_Domain</property>
-                    <property name="use_underline">True</property>
-                    <property name="mnemonic_widget">join_domain</property>
-                    <style>
-                      <class name="dim-label"/>
-                    </style>
-                  </object>
-                  <packing>
-                    <property name="left_attach">0</property>
-                    <property name="top_attach">0</property>
-                    <property name="width">1</property>
-                    <property name="height">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="join_domain">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="margin_top">5</property>
-                    <property name="margin_bottom">5</property>
-                    <property name="xalign">0</property>
-                  </object>
-                  <packing>
-                    <property name="left_attach">1</property>
-                    <property name="top_attach">0</property>
-                    <property name="width">1</property>
-                    <property name="height">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="label18">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="xalign">1</property>
-                    <property name="label" translatable="yes">_Computer</property>
-                    <property name="use_underline">True</property>
-                    <property name="mnemonic_widget">join_computer</property>
-                    <style>
-                      <class name="dim-label"/>
-                    </style>
-                  </object>
-                  <packing>
-                    <property name="left_attach">0</property>
-                    <property name="top_attach">1</property>
-                    <property name="width">1</property>
-                    <property name="height">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkEntry" id="join_computer">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="hexpand">True</property>
-                  </object>
-                  <packing>
-                    <property name="left_attach">1</property>
-                    <property name="top_attach">1</property>
-                    <property name="width">1</property>
-                    <property name="height">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="label14">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="xalign">1</property>
-                    <property name="label" translatable="yes">Administrator _Name</property>
-                    <property name="use_underline">True</property>
-                    <property name="mnemonic_widget">join_name</property>
-                    <style>
-                      <class name="dim-label"/>
-                    </style>
-                  </object>
-                  <packing>
-                    <property name="left_attach">0</property>
-                    <property name="top_attach">2</property>
-                    <property name="width">1</property>
-                    <property name="height">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkEntry" id="join_name">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="hexpand">True</property>
-                    <property name="invisible_char">●</property>
-                    <property name="invisible_char_set">True</property>
-                  </object>
-                  <packing>
-                    <property name="left_attach">1</property>
-                    <property name="top_attach">2</property>
-                    <property name="width">1</property>
-                    <property name="height">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="label15">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="xalign">1</property>
-                    <property name="label" translatable="yes">Administrator Password</property>
-                    <property name="use_underline">True</property>
-                    <property name="mnemonic_widget">join_password</property>
-                    <style>
-                      <class name="dim-label"/>
-                    </style>
-                  </object>
-                  <packing>
-                    <property name="left_attach">0</property>
-                    <property name="top_attach">3</property>
-                    <property name="width">1</property>
-                    <property name="height">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkEntry" id="join_password">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="hexpand">True</property>
-                    <property name="visibility">False</property>
-                    <property name="invisible_char">●</property>
-                    <property name="activates_default">True</property>
-                    <property name="invisible_char_set">True</property>
-                  </object>
-                  <packing>
-                    <property name="left_attach">1</property>
-                    <property name="top_attach">3</property>
-                    <property name="width">1</property>
-                    <property name="height">1</property>
-                  </packing>
-                </child>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">2</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">True</property>
-            <property name="position">1</property>
-          </packing>
-        </child>
-      </object>
-    </child>
-    <action-widgets>
-      <action-widget response="-6">button1</action-widget>
-      <action-widget response="-5">button2</action-widget>
-    </action-widgets>
-  </object>
-
-  <object class="GtkListStore" id="enterprise_realms_model">
-    <columns>
-      <!-- column-name gchararray -->
-      <column type="gchararray"/>
-      <!-- column-name gobject -->
-      <column type="GObject"/>
-    </columns>
-  </object>
 </interface>


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]