Blob Blame History Raw
diff --git a/Makefile b/Makefile
index fb0d2eb..ee36a1f 100644
--- a/Makefile
+++ b/Makefile
@@ -487,12 +487,19 @@ coverage-jenkins:
 #
 # gettext, po files, etc
 #
-
 po/POTFILES.in:
 	# generate the POTFILES.in file expected by intltool. it wants one
 	# file per line, but we're lazy.
 	find $(SRC_DIR)/ $(RCT_SRC_DIR) $(RD_SRC_DIR) $(DAEMONS_SRC_DIR) $(YUM_PLUGINS_SRC_DIR) -name "*.py" > po/POTFILES.in
-	find $(SRC_DIR)/gui/data/ -name "*.glade" >> po/POTFILES.in
+	find $(SRC_DIR)/gui/data/glade/ -name "*.glade" >> po/POTFILES.in
+	# intltool-update doesn't recognize .ui as glade files, so
+	# build a dir of .glade symlinks to the .ui files and add to POTFILES.in
+	mkdir -p po/tmp_ui_links
+	for ui_file in ./$(SRC_DIR)/gui/data/ui/*.ui ; do \
+		ui_base=$$(basename "$$ui_file") ; \
+		ln -f -s "../../$$ui_file" "po/tmp_ui_links/$$ui_base.glade" ; \
+	done ;
+	find po/tmp_ui_links/ -name "*.glade"  >> po/POTFILES.in
 	find $(BIN_DIR) -name "*-to-rhsm" >> po/POTFILES.in
 	find $(BIN_DIR) -name "subscription-manager*" >> po/POTFILES.in
 	find $(BIN_DIR) -name "rct" >> po/POTFILES.in
diff --git a/man/rhsm.conf.5 b/man/rhsm.conf.5
index 04e9aca..29349b2 100644
--- a/man/rhsm.conf.5
+++ b/man/rhsm.conf.5
@@ -51,7 +51,7 @@ The port which the subscription service is listening on\&.
 .PP
 insecure
 .RS 4
-This flag enables or disables certification verification using the certificate authorities which are installed in /etc/rhsm/ca\&.
+This flag enables or disables entitlement server certification verification using the certificate authorities which are installed in /etc/rhsm/ca\&.
 .RE
 .PP
 ssl_verify_depth
diff --git a/rel-eng/packages/subscription-manager b/rel-eng/packages/subscription-manager
index 6f399f3..9f6984a 100644
--- a/rel-eng/packages/subscription-manager
+++ b/rel-eng/packages/subscription-manager
@@ -1 +1 @@
-1.15.9-7 ./
+1.15.9-8 ./
diff --git a/src/initial-setup/com_redhat_subscription_manager/gui/spokes/rhsm_gui.py b/src/initial-setup/com_redhat_subscription_manager/gui/spokes/rhsm_gui.py
index 09ca0b6..43b6947 100644
--- a/src/initial-setup/com_redhat_subscription_manager/gui/spokes/rhsm_gui.py
+++ b/src/initial-setup/com_redhat_subscription_manager/gui/spokes/rhsm_gui.py
@@ -22,6 +22,7 @@ import sys
 from pyanaconda.ui.gui.spokes import NormalSpoke
 from pyanaconda.ui.common import FirstbootOnlySpokeMixIn
 from pyanaconda.ui.categories.system import SystemCategory
+from pyanaconda.ui.gui.utils import really_hide
 
 log = logging.getLogger(__name__)
 
@@ -38,6 +39,7 @@ from subscription_manager.gui import managergui
 from subscription_manager.injectioninit import init_dep_injection
 from subscription_manager import injection as inj
 from subscription_manager.gui import registergui
+from subscription_manager.gui import utils
 
 ga_GObject.threads_init()
 
@@ -45,7 +47,7 @@ __all__ = ["RHSMSpoke"]
 
 
 class RHSMSpoke(FirstbootOnlySpokeMixIn, NormalSpoke):
-    buildrObjects = ["RHSMSpokeWindow", "RHSMSpokeWindow-action_area1"]
+    buildrObjects = ["RHSMSpokeWindow"]
 
     mainWidgetName = "RHSMSpokeWindow"
 
@@ -67,68 +69,113 @@ class RHSMSpoke(FirstbootOnlySpokeMixIn, NormalSpoke):
         init_dep_injection()
 
         facts = inj.require(inj.FACTS)
+
         backend = managergui.Backend()
 
-        self._registergui = registergui.RegisterScreen(backend, facts,
-                                                       callbacks=[self.finished])
-        self._action_area = self.builder.get_object("RHSMSpokeWindow-action_area1")
-        self._register_box = self._registergui.dialog_vbox6
-
-        # FIXME: close_window handling is kind of a mess. Standlone subman gui,
-        # the firstboot screens, and initial-setup need it to do different
-        # things. Potentially a 'Im done with this window now' signal, with
-        # each attaching different handlers.
-        self._registergui.close_window_callback = self._close_window_callback
-
-        self._registergui._error_screen = registergui.CHOOSE_SERVER_PAGE
-
-        # we have a ref to _register_box, but need to remove it from
-        # the regustergui.window (a GtkDialog), and add it to the main
-        # box in the action area of our initial-setup screen.
-        self._registergui.window.remove(self._register_box)
-        self._action_area.pack_end(self._register_box, True, True, 0)
-        self._action_area.show()
-        self._register_box.show_all()
-        self._registergui.initialize()
-
-    def _close_window_callback(self):
-        self._registergui.goto_error_screen()
-
-    def finished(self):
-        self._registergui.done()
-        self._registergui.cancel_button.hide()
-        self._registergui.register_button.hide()
+        self.register_widget = registergui.RegisterWidget(backend, facts,
+                                                          parent_window=self.main_window)
+
+        self.register_box = self.builder.get_object("register_box")
+        self.button_box = self.builder.get_object('navigation_button_box')
+        self.proceed_button = self.builder.get_object('proceed_button')
+        self.cancel_button = self.builder.get_object('cancel_button')
+
+        self.register_box.pack_start(self.register_widget.register_widget,
+                                     True, True, 0)
+
+        # Hook up the nav buttons in the gui
+        # TODO: add a 'start over'?
+        self.proceed_button.connect('clicked', self._on_register_button_clicked)
+        self.cancel_button.connect('clicked', self.cancel)
+
+        # initial-setup will likely
+        self.register_widget.connect('finished', self.finished)
+        self.register_widget.connect('register-finished', self.register_finished)
+        self.register_widget.connect('register-error', self._on_register_error)
+
+        # update the 'next/register button on page change'
+        self.register_widget.connect('notify::register-button-label',
+                                       self._on_register_button_label_change)
+
+        self.register_box.show_all()
+        self.register_widget.initialize()
+
+    # handler for RegisterWidgets 'finished' signal
+    def finished(self, obj):
+        self._done = True
+        really_hide(self.button_box)
+
+    # If we completed registration, that's close enough to consider
+    # completed.
+    def register_finished(self, obj):
         self._done = True
 
     # Update gui widgets to reflect state of self.data
+    # This could also be used to pre populate partial answers from a ks
+    # or answer file
     def refresh(self):
         log.debug("data.addons.com_redhat_subscription_manager %s",
                   self.data.addons.com_redhat_subscription_manager)
-
         pass
 
+    # take info from the gui widgets and set into the self.data
     def apply(self):
         self.data.addons.com_redhat_subscription_manager.text = \
             "System is registered to Red Hat Subscription Management."
 
+    # when the spoke is left, this can run anything that happens
     def execute(self):
         pass
 
+    def cancel(self, button):
+        # TODO: clear out settings and restart?
+        # TODO: attempt to undo the REST api calls we've made?
+        self.register_widget.set_initial_screen()
+        self.register_widget.clear_screens()
+
+    # A property indicating the spoke is ready to be visited. This
+    # could depend on other modules or waiting for internal state to be setup.
     @property
     def ready(self):
         return True
 
+    # Indicate if all the mandatory actions are completed
     @property
     def completed(self):
+        # TODO: tie into register_widget.info.register-state
         return self._done
 
+    # indicate if the module has to be completed before initial-setup is done.
     @property
     def mandatory(self):
         return False
 
+    # A user facing string showing a summary of the status. This is displayed
+    # under the spokes name on it's hub.
     @property
     def status(self):
         if self._done:
+            # TODO: add consumer uuid, products, etc?
             return "System is registered to RHSM."
         else:
             return "System is not registered to RHSM."
+
+    def _on_register_button_clicked(self, button):
+        # unset any error info
+        self.clear_info()
+
+        self.register_widget.emit('proceed')
+
+    def _on_register_error(self, widget, msg, exc_info):
+        if exc_info:
+            formatted_msg = utils.format_exception(exc_info, msg)
+            self.set_error(formatted_msg)
+        else:
+            log.error(msg)
+            self.set_error(msg)
+
+    def _on_register_button_label_change(self, obj, value):
+        register_label = obj.get_property('register-button-label')
+
+        if register_label:
+            self.proceed_button.set_label(register_label)
diff --git a/src/initial-setup/com_redhat_subscription_manager/gui/spokes/rhsm_gui.ui b/src/initial-setup/com_redhat_subscription_manager/gui/spokes/rhsm_gui.ui
index ea465a3..3a5f64f 100644
--- a/src/initial-setup/com_redhat_subscription_manager/gui/spokes/rhsm_gui.ui
+++ b/src/initial-setup/com_redhat_subscription_manager/gui/spokes/rhsm_gui.ui
@@ -39,10 +39,60 @@
             <child internal-child="action_area">
               <object class="GtkBox" id="RHSMSpokeWindow-action_area1">
                 <property name="can_focus">False</property>
+                <property name="valign">start</property>
                 <property name="orientation">vertical</property>
                 <property name="spacing">6</property>
                 <child>
-                  <placeholder/>
+                  <object class="GtkButtonBox" id="navigation_button_box">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="valign">start</property>
+                    <property name="layout_style">end</property>
+                    <child>
+                      <object class="GtkButton" id="cancel_button">
+                        <property name="label" translatable="yes">Cancel</property>
+                        <property name="visible">True</property>
+                        <property name="yalign">0.43999999761581421</property>
+                      </object>
+                      <packing>
+                        <property name="expand">True</property>
+                        <property name="fill">True</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkButton" id="proceed_button">
+                        <property name="label" translatable="yes">Register</property>
+                        <property name="visible">True</property>
+                        <property name="yalign">0.56999999284744263</property>
+                      </object>
+                      <packing>
+                        <property name="expand">True</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="register_box">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <child>
+                      <placeholder/>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">1</property>
+                  </packing>
                 </child>
               </object>
             </child>
diff --git a/src/subscription_manager/ga_impls/ga_gtk2/GObject.py b/src/subscription_manager/ga_impls/ga_gtk2/GObject.py
index 3783ce7..d77a280 100644
--- a/src/subscription_manager/ga_impls/ga_gtk2/GObject.py
+++ b/src/subscription_manager/ga_impls/ga_gtk2/GObject.py
@@ -5,21 +5,22 @@ from gobject import GObject
 from gobject import MainLoop
 
 # methods
-from gobject import add_emission_hook, idle_add, source_remove, timeout_add
+from gobject import add_emission_hook, idle_add, property
+from gobject import source_remove, timeout_add
 from gobject import markup_escape_text
 
 # enums
-from gobject import SIGNAL_RUN_LAST
+from gobject import SIGNAL_RUN_FIRST, SIGNAL_RUN_LAST
 from gobject import TYPE_BOOLEAN, TYPE_PYOBJECT, PARAM_READWRITE
 
 
 class SignalFlags(object):
+    RUN_FIRST = SIGNAL_RUN_FIRST
     RUN_LAST = SIGNAL_RUN_LAST
 
-
 constants = [TYPE_BOOLEAN, TYPE_PYOBJECT, PARAM_READWRITE]
 methods = [add_emission_hook, idle_add, markup_escape_text,
-           source_remove, timeout_add]
+           property, source_remove, timeout_add]
 enums = [SignalFlags]
 objects = [GObject, MainLoop]
 __all__ = objects + methods + constants + enums
diff --git a/src/subscription_manager/ga_impls/ga_gtk2/Gtk.py b/src/subscription_manager/ga_impls/ga_gtk2/Gtk.py
index d009019..3d04bbc 100644
--- a/src/subscription_manager/ga_impls/ga_gtk2/Gtk.py
+++ b/src/subscription_manager/ga_impls/ga_gtk2/Gtk.py
@@ -26,11 +26,13 @@ from gtk import SORT_ASCENDING
 from gtk import SELECTION_NONE
 from gtk import STATE_NORMAL
 from gtk import WINDOW_TOPLEVEL
-from gtk import WIN_POS_MOUSE, WIN_POS_CENTER_ON_PARENT
+from gtk import WIN_POS_MOUSE, WIN_POS_CENTER, WIN_POS_CENTER_ON_PARENT
 
 # methods
 from gtk import image_new_from_icon_name
+from gtk import events_pending
 from gtk import main
+from gtk import main_iteration
 from gtk import main_quit
 from gtk import check_version
 
@@ -98,6 +100,7 @@ class WindowType(object):
 
 class WindowPosition(object):
     MOUSE = WIN_POS_MOUSE
+    CENTER = WIN_POS_CENTER
     CENTER_ON_PARENT = WIN_POS_CENTER_ON_PARENT
 
 
@@ -129,6 +132,6 @@ widgets = [AboutDialog, Adjustment, Builder, Button, Calendar, CellRendererPixbu
            RadioButton, SpinButton, TextBuffer, TreeStore, TreeView, TreeViewColumn,
            VBox, Viewport, Window]
 
-methods = [check_version, main, main_quit]
+methods = [check_version, events_pending, main, main_iteration, main_quit]
 
 __all__ = widgets + constants + methods + enums
diff --git a/src/subscription_manager/gui/autobind.py b/src/subscription_manager/gui/autobind.py
index 8d55cf4..f863f0c 100644
--- a/src/subscription_manager/gui/autobind.py
+++ b/src/subscription_manager/gui/autobind.py
@@ -47,7 +47,6 @@ class DryRunResult(object):
         # The products that would be covered if we did this autobind:
         autobind_products = set()
 
-        log.debug("Unentitled products: %s" % required_products)
         for pool_quantity in self.json:
             pool = pool_quantity['pool']
             # This is usually the MKT product and has no content, but it
diff --git a/src/subscription_manager/gui/data/glade/choose_server.glade b/src/subscription_manager/gui/data/glade/choose_server.glade
index 622e4fc..e67b428 100644
--- a/src/subscription_manager/gui/data/glade/choose_server.glade
+++ b/src/subscription_manager/gui/data/glade/choose_server.glade
@@ -114,7 +114,6 @@
                 <property name="primary_icon_sensitive">True</property>
                 <property name="secondary_icon_sensitive">True</property>
                 <accessibility/>
-                <signal handler="on_server_entry_changed" name="changed"/>
                 <child internal-child="accessible">
                   <object class="AtkObject" id="a11y-server_entry1">
                     <property name="AtkObject::accessible-name" translatable="yes">server_entry</property>
diff --git a/src/subscription_manager/gui/data/glade/register_dialog.glade b/src/subscription_manager/gui/data/glade/register_dialog.glade
new file mode 100644
index 0000000..fe76ce1
--- /dev/null
+++ b/src/subscription_manager/gui/data/glade/register_dialog.glade
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <requires lib="gtk+" version="2.24"/>
+  <!-- interface-naming-policy project-wide -->
+  <object class="GtkDialog" id="register_dialog">
+    <property name="can_focus">False</property>
+    <property name="border_width">5</property>
+    <property name="title" translatable="yes">System Registration</property>
+    <property name="icon_name">subscription-manager</property>
+    <property name="type_hint">splashscreen</property>
+    <child internal-child="vbox">
+      <object class="GtkVBox" id="register_dialog_main_vbox">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="spacing">2</property>
+        <child internal-child="action_area">
+          <object class="GtkHButtonBox" id="dialog-action_area1">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="layout_style">end</property>
+            <child>
+              <object class="GtkButton" id="cancel_button">
+                <property name="label">gtk-cancel</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
+                <property name="image_position">right</property>
+                <child internal-child="accessible">
+                  <object class="AtkObject" id="cancel_button-atkobject">
+                    <property name="AtkObject::accessible-name" translatable="yes">cancel_button</property>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="register_button">
+                <property name="label" translatable="yes">Register</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="image_position">right</property>
+                <child internal-child="accessible">
+                  <object class="AtkObject" id="register_button-atkobject">
+                    <property name="AtkObject::accessible-name" translatable="yes">register_button</property>
+                    <property name="AtkObject::accessible-description" translatable="yes">register_button</property>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <placeholder/>
+        </child>
+      </object>
+    </child>
+    <action-widgets>
+      <action-widget response="0">cancel_button</action-widget>
+      <action-widget response="0">register_button</action-widget>
+    </action-widgets>
+  </object>
+</interface>
diff --git a/src/subscription_manager/gui/data/glade/registration.glade b/src/subscription_manager/gui/data/glade/registration.glade
index 02a9e61..b42f510 100644
--- a/src/subscription_manager/gui/data/glade/registration.glade
+++ b/src/subscription_manager/gui/data/glade/registration.glade
@@ -1,192 +1,103 @@
-<?xml version="1.0"?>
+<?xml version="1.0" encoding="UTF-8"?>
 <interface>
   <!-- interface-requires gtk+ 2.10 -->
-  <!--
- interface-naming-policy project-wide -->
-  <object class="GtkDialog" id="register_dialog">
+  <!-- interface-naming-policy toplevel-contextual -->
+  <object class="GtkVBox" id="register_widget">
+    <property name="visible">True</property>
     <property name="can_focus">False</property>
-    <property name="border_width">5</property>
-    <property name="title" translatable="yes">System Registration</property>
-    <property name="resizable">False</property>
-    <property name="modal">True</property>
-    <property name="window_position">center-on-parent</property>
-    <property name="destroy_with_parent">True</property>
-    <property name="icon_name">subscription-manager</property>
-    <property name="type_hint">dialog</property>
-    <property name="deletable">False</property>
-    <accessibility/>
-    <signal handler="on_register_dialog_delete_event" name="delete_event"/>
-    <child internal-child="vbox">
-      <object class="GtkVBox" id="dialog-vbox6">
+    <property name="spacing">2</property>
+    <child internal-child="accessible">
+      <object class="AtkObject" id="register_widget-atkobject">
+        <property name="AtkObject::accessible-name" translatable="yes">register_widget_main_vbox</property>
+      </object>
+    </child>
+    <child>
+      <object class="GtkNotebook" id="register_notebook">
         <property name="visible">True</property>
         <property name="can_focus">False</property>
-        <property name="spacing">2</property>
-        <accessibility/>
-        <child internal-child="action_area">
-          <object class="GtkHButtonBox" id="dialog-action_area6">
+        <property name="show_tabs">False</property>
+        <property name="show_border">False</property>
+        <child>
+          <object class="GtkVBox" id="progressVbox">
             <property name="visible">True</property>
             <property name="can_focus">False</property>
-            <property name="layout_style">end</property>
-            <accessibility/>
+            <property name="border_width">25</property>
+            <property name="spacing">7</property>
             <child>
-              <object class="GtkButton" id="cancel_button">
-                <property name="label">gtk-cancel</property>
+              <object class="GtkLabel" id="progress_label">
                 <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="use_stock">True</property>
-                <property name="image_position">right</property>
-                <accessibility/>
-                <signal handler="on_register_cancel_button_clicked" name="clicked"/>
+                <property name="can_focus">False</property>
+                <property name="xalign">0</property>
+                <property name="label" translatable="yes">&lt;b&gt;Registering&lt;/b&gt;</property>
+                <property name="use_markup">True</property>
                 <child internal-child="accessible">
-                  <object class="AtkObject" id="a11y-cancel_button1">
-                    <property name="AtkObject::accessible-name">cancel_button</property>
+                  <object class="AtkObject" id="progress_label-atkobject">
+                    <property name="AtkObject::accessible-name" translatable="yes">progress_label</property>
                   </object>
                 </child>
               </object>
               <packing>
                 <property name="expand">False</property>
                 <property name="fill">False</property>
+                <property name="padding">8</property>
                 <property name="position">0</property>
               </packing>
             </child>
             <child>
-              <object class="GtkButton" id="register_button">
-                <property name="label" translatable="yes">Register</property>
+              <object class="GtkProgressBar" id="register_progressbar">
                 <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="image_position">right</property>
-                <accessibility/>
-                <signal handler="on_register_button_clicked" name="clicked"/>
+                <property name="can_focus">False</property>
+                <property name="activity_mode">True</property>
+                <property name="pulse_step">0.25</property>
                 <child internal-child="accessible">
-                  <object class="AtkObject" id="a11y-register_button1">
-                    <property name="AtkObject::accessible-name" translatable="yes">register_button</property>
-                    <property name="AtkObject::accessible-description">register_button</property>
+                  <object class="AtkObject" id="register_progressbar-atkobject">
+                    <property name="AtkObject::accessible-name" translatable="yes">register_progressbar</property>
                   </object>
                 </child>
               </object>
               <packing>
                 <property name="expand">False</property>
-                <property name="fill">False</property>
+                <property name="fill">True</property>
                 <property name="position">1</property>
               </packing>
             </child>
-            <child internal-child="accessible">
-              <object class="AtkObject" id="a11y-dialog-action_area61">
-                <property name="AtkObject::accessible-name" translatable="yes">registration_dialog_action_area</property>
-              </object>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="pack_type">end</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkNotebook" id="register_notebook">
-            <property name="visible">True</property>
-            <property name="can_focus">True</property>
-            <property name="show_tabs">False</property>
-            <property name="show_border">False</property>
             <child>
-              <object class="GtkVBox" id="progressVbox">
+              <object class="GtkLabel" id="register_details_label">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
-                <property name="border_width">25</property>
-                <property name="spacing">7</property>
-                <child>
-                  <object class="GtkLabel" id="progress_label">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="xalign">0</property>
-                    <property name="label" translatable="yes">&lt;b&gt;Registering&lt;/b&gt;</property>
-                    <property name="use_markup">True</property>
-                    <accessibility/>
-                    <child internal-child="accessible">
-                      <object class="AtkObject" id="a11y-progress_label1">
-                        <property name="AtkObject::accessible-name" translatable="yes">progress_label</property>
-                      </object>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                    <property name="padding">8</property>
-                    <property name="position">0</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkProgressBar" id="register_progressbar">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="activity_mode">True</property>
-                    <accessibility/>
-                    <child internal-child="accessible">
-                      <object class="AtkObject" id="a11y-register_progressbar1">
-                        <property name="AtkObject::accessible-name" translatable="yes">register_progressbar</property>
-                      </object>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">True</property>
-                    <property name="position">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="register_details_label">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="xalign">0</property>
-                    <property name="use_markup">True</property>
-                    <accessibility/>
-                    <child internal-child="accessible">
-                      <object class="AtkObject" id="a11y-register_details_label1">
-                        <property name="AtkObject::accessible-name" translatable="yes">register_details_label</property>
-                      </object>
-                    </child>
+                <property name="xalign">0</property>
+                <property name="use_markup">True</property>
+                <property name="single_line_mode">True</property>
+                <child internal-child="accessible">
+                  <object class="AtkObject" id="register_details_label-atkobject">
+                    <property name="AtkObject::accessible-name" translatable="yes">register_details_label</property>
                   </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">True</property>
-                    <property name="position">2</property>
-                  </packing>
                 </child>
               </object>
-            </child>
-            <child type="tab">
-              <object class="GtkLabel" id="label2">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="label" translatable="yes">page 2</property>
-              </object>
               <packing>
-                <property name="tab_fill">False</property>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">2</property>
               </packing>
             </child>
           </object>
-          <packing>
-            <property name="expand">True</property>
-            <property name="fill">True</property>
-            <property name="position">1</property>
-          </packing>
         </child>
-        <child internal-child="accessible">
-          <object class="AtkObject" id="a11y-dialog-vbox61">
-            <property name="AtkObject::accessible-name" translatable="yes">register_dialog_main_vbox</property>
+        <child type="tab">
+          <object class="GtkLabel" id="tab_label">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="label" translatable="yes">Progress Page</property>
           </object>
+          <packing>
+            <property name="tab_fill">False</property>
+          </packing>
         </child>
       </object>
-    </child>
-    <child internal-child="accessible">
-      <object class="AtkObject" id="a11y-register_dialog1">
-        <property name="AtkObject::accessible-name">register_dialog</property>
-      </object>
+      <packing>
+        <property name="expand">True</property>
+        <property name="fill">True</property>
+        <property name="position">0</property>
+      </packing>
     </child>
   </object>
 </interface>
diff --git a/src/subscription_manager/gui/data/glade/repositories.glade b/src/subscription_manager/gui/data/glade/repositories.glade
index e45fc29..944db9a 100644
--- a/src/subscription_manager/gui/data/glade/repositories.glade
+++ b/src/subscription_manager/gui/data/glade/repositories.glade
@@ -19,7 +19,7 @@
         <property name="AtkObject::accessible-name" translatable="yes">manage_repositories_dialog</property>
       </object>
     </child>
-    <signal name="delete-event" handler="on_dialog_delete_event" swapped="no"/>
+    <signal name="delete-event" handler="on_dialog_delete_event" />
     <child internal-child="vbox">
       <object class="GtkVBox" id="main_container">
         <property name="visible">True</property>
@@ -240,7 +240,7 @@
                     <property name="AtkObject::accessible-name" translatable="yes">remove_all_overrides_button</property>
                   </object>
                 </child>
-                <signal name="clicked" handler="on_reset_button_clicked" swapped="no"/>
+                <signal name="clicked" handler="on_reset_button_clicked" />
               </object>
               <packing>
                 <property name="expand">False</property>
@@ -255,7 +255,7 @@
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
                 <property name="receives_default">True</property>
-                <signal name="clicked" handler="on_apply_button_clicked" swapped="no"/>
+                <signal name="clicked" handler="on_apply_button_clicked" />
               </object>
               <packing>
                 <property name="expand">False</property>
@@ -275,7 +275,7 @@
                     <property name="AtkObject::accessible-name" translatable="yes">close_button</property>
                   </object>
                 </child>
-                <signal name="clicked" handler="on_close_button_clicked" swapped="no"/>
+                <signal name="clicked" handler="on_close_button_clicked" />
               </object>
               <packing>
                 <property name="expand">False</property>
diff --git a/src/subscription_manager/gui/data/ui/choose_server.ui b/src/subscription_manager/gui/data/ui/choose_server.ui
index 5bd3e6b..8684f07 100644
--- a/src/subscription_manager/gui/data/ui/choose_server.ui
+++ b/src/subscription_manager/gui/data/ui/choose_server.ui
@@ -114,7 +114,6 @@
                 <property name="width_chars">30</property>
                 <property name="primary_icon_activatable">False</property>
                 <property name="secondary_icon_activatable">False</property>
-                <signal name="changed" handler="on_server_entry_changed" swapped="no"/>
                 <child internal-child="accessible">
                   <object class="AtkObject" id="server_entry-atkobject">
                     <property name="AtkObject::accessible-name" translatable="yes">server_entry</property>
diff --git a/src/subscription_manager/gui/data/ui/credentials.ui b/src/subscription_manager/gui/data/ui/credentials.ui
index 219d32a..283a410 100644
--- a/src/subscription_manager/gui/data/ui/credentials.ui
+++ b/src/subscription_manager/gui/data/ui/credentials.ui
@@ -53,9 +53,11 @@
               <object class="GtkBox" id="forgot_info_hbox">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
+                <property name="valign">start</property>
                 <child>
                   <object class="GtkImage" id="tip_icon_hosted">
                     <property name="visible">True</property>
+                    <property name="valign">center</property>
                     <property name="can_focus">False</property>
                     <property name="yalign">0</property>
                     <property name="stock">gtk-info</property>
@@ -75,11 +77,13 @@
                   <object class="GtkLabel" id="registration_tip_label">
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
-                    <property name="xalign">0</property>
-                    <property name="yalign">0</property>
+                    <property name="valign">start</property>
+                    <property name="selectable">True</property>
+                    <property name="ellipsize">middle</property>
                     <property name="xpad">1</property>
                     <property name="ypad">2</property>
                     <property name="use_markup">True</property>
+                    <property name="lines">1</property>
                     <property name="wrap">True</property>
                     <child internal-child="accessible">
                       <object class="AtkObject" id="registration_tip_label-atkobject">
diff --git a/src/subscription_manager/gui/data/ui/register_dialog.ui b/src/subscription_manager/gui/data/ui/register_dialog.ui
new file mode 100644
index 0000000..ed83845
--- /dev/null
+++ b/src/subscription_manager/gui/data/ui/register_dialog.ui
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.18.3 -->
+<interface>
+  <requires lib="gtk+" version="3.12"/>
+  <object class="GtkDialog" id="register_dialog">
+    <property name="can_focus">False</property>
+    <property name="halign">center</property>
+    <property name="valign">end</property>
+    <property name="title" translatable="yes">System Registration</property>
+    <property name="resizable">False</property>
+    <property name="window_position">center-on-parent</property>
+    <property name="destroy_with_parent">True</property>
+    <property name="icon_name">subscription-manager</property>
+    <property name="type_hint">dialog</property>
+    <property name="deletable">False</property>
+    <child internal-child="vbox">
+      <object class="GtkBox" id="register_dialog_main_vbox">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="valign">end</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">2</property>
+        <child internal-child="action_area">
+          <object class="GtkButtonBox" id="dialog-action_area3">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="layout_style">end</property>
+            <child>
+              <object class="GtkButton" id="cancel_button">
+                <property name="label">gtk-cancel</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
+                <property name="image_position">right</property>
+                <child internal-child="accessible">
+                  <object class="AtkObject" id="cancel_button-atkobject">
+                    <property name="AtkObject::accessible-name">cancel_button</property>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="register_button">
+                <property name="label" translatable="yes">Register</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="image_position">right</property>
+                <child internal-child="accessible">
+                  <object class="AtkObject" id="register_button-atkobject">
+                    <property name="AtkObject::accessible-name" translatable="yes">register_button</property>
+                    <property name="AtkObject::accessible-description">register_button</property>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child internal-child="accessible">
+              <object class="AtkObject" id="dialog-action_area3-atkobject">
+                <property name="AtkObject::accessible-name" translatable="yes">registration_dialog_action_area</property>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <placeholder/>
+        </child>
+        <child internal-child="accessible">
+          <object class="AtkObject" id="register_dialog_main_vbox_atkobject">
+            <property name="AtkObject::accessible-name" translatable="yes">register_dialog_main_vbox</property>
+          </object>
+        </child>
+      </object>
+    </child>
+    <child internal-child="accessible">
+      <object class="AtkObject" id="register_dialog-atkobject">
+        <property name="AtkObject::accessible-name">register_dialog</property>
+      </object>
+    </child>
+  </object>
+</interface>
diff --git a/src/subscription_manager/gui/data/ui/registration.ui b/src/subscription_manager/gui/data/ui/registration.ui
index 31baac9..3bf3d1a 100644
--- a/src/subscription_manager/gui/data/ui/registration.ui
+++ b/src/subscription_manager/gui/data/ui/registration.ui
@@ -2,188 +2,107 @@
 <!-- Generated with glade 3.18.3 -->
 <interface>
   <requires lib="gtk+" version="3.0"/>
-  <object class="GtkDialog" id="register_dialog">
+  <object class="GtkBox" id="register_widget">
+    <property name="visible">True</property>
     <property name="can_focus">False</property>
-    <property name="border_width">5</property>
-    <property name="title" translatable="yes">System Registration</property>
-    <property name="resizable">False</property>
-    <property name="modal">True</property>
-    <property name="window_position">center-on-parent</property>
-    <property name="destroy_with_parent">True</property>
-    <property name="icon_name">subscription-manager</property>
-    <property name="type_hint">dialog</property>
-    <property name="deletable">False</property>
-    <signal name="delete-event" handler="on_register_dialog_delete_event" swapped="no"/>
-    <child internal-child="vbox">
-      <object class="GtkBox" id="dialog_vbox6">
+    <property name="valign">start</property>
+    <property name="orientation">vertical</property>
+    <property name="spacing">2</property>
+    <child>
+      <object class="GtkNotebook" id="register_notebook">
         <property name="visible">True</property>
         <property name="can_focus">False</property>
-        <property name="halign">baseline</property>
-        <property name="valign">start</property>
-        <property name="orientation">vertical</property>
-        <property name="spacing">2</property>
-        <child internal-child="action_area">
-          <object class="GtkButtonBox" id="dialog-action_area6">
+        <property name="show_tabs">False</property>
+        <property name="show_border">False</property>
+        <child>
+          <object class="GtkBox" id="progressVbox">
             <property name="visible">True</property>
             <property name="can_focus">False</property>
-            <property name="valign">start</property>
-            <property name="layout_style">end</property>
+            <property name="border_width">25</property>
+            <property name="orientation">vertical</property>
+            <property name="spacing">7</property>
             <child>
-              <object class="GtkButton" id="cancel_button">
-                <property name="label">gtk-cancel</property>
+              <object class="GtkLabel" id="progress_label">
                 <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="use_stock">True</property>
-                <property name="image_position">right</property>
-                <signal name="clicked" handler="on_register_cancel_button_clicked" swapped="no"/>
+                <property name="can_focus">False</property>
+                <property name="label" translatable="yes">&lt;b&gt;Registering&lt;/b&gt;</property>
+                <property name="use_markup">True</property>
+                <property name="xalign">0</property>
                 <child internal-child="accessible">
-                  <object class="AtkObject" id="cancel_button-atkobject">
-                    <property name="AtkObject::accessible-name">cancel_button</property>
+                  <object class="AtkObject" id="progress_label-atkobject">
+                    <property name="AtkObject::accessible-name" translatable="yes">progress_label</property>
                   </object>
                 </child>
               </object>
               <packing>
                 <property name="expand">False</property>
                 <property name="fill">False</property>
+                <property name="padding">8</property>
                 <property name="position">0</property>
               </packing>
             </child>
             <child>
-              <object class="GtkButton" id="register_button">
-                <property name="label" translatable="yes">Register</property>
+              <object class="GtkProgressBar" id="register_progressbar">
                 <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="image_position">right</property>
-                <signal name="clicked" handler="on_register_button_clicked" swapped="no"/>
+                <property name="can_focus">False</property>
+                <property name="pulse_step">0.1</property>
                 <child internal-child="accessible">
-                  <object class="AtkObject" id="register_button-atkobject">
-                    <property name="AtkObject::accessible-name" translatable="yes">register_button</property>
-                    <property name="AtkObject::accessible-description">register_button</property>
+                  <object class="AtkObject" id="register_progressbar-atkobject">
+                    <property name="AtkObject::accessible-name" translatable="yes">register_progressbar</property>
                   </object>
                 </child>
               </object>
               <packing>
                 <property name="expand">False</property>
-                <property name="fill">False</property>
+                <property name="fill">True</property>
                 <property name="position">1</property>
               </packing>
             </child>
-            <child internal-child="accessible">
-              <object class="AtkObject" id="dialog-action_area6-atkobject">
-                <property name="AtkObject::accessible-name" translatable="yes">registration_dialog_action_area</property>
-              </object>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkNotebook" id="register_notebook">
-            <property name="visible">True</property>
-            <property name="can_focus">True</property>
-            <property name="valign">start</property>
-            <property name="show_tabs">False</property>
-            <property name="show_border">False</property>
             <child>
-              <object class="GtkBox" id="progressVbox">
+              <object class="GtkLabel" id="register_details_label">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
-                <property name="border_width">25</property>
-                <property name="orientation">vertical</property>
-                <property name="spacing">7</property>
-                <child>
-                  <object class="GtkLabel" id="progress_label">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="label" translatable="yes">&lt;b&gt;Registering&lt;/b&gt;</property>
-                    <property name="use_markup">True</property>
-                    <property name="xalign">0</property>
-                    <child internal-child="accessible">
-                      <object class="AtkObject" id="progress_label-atkobject">
-                        <property name="AtkObject::accessible-name" translatable="yes">progress_label</property>
-                      </object>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                    <property name="padding">8</property>
-                    <property name="position">0</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkProgressBar" id="register_progressbar">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <child internal-child="accessible">
-                      <object class="AtkObject" id="register_progressbar-atkobject">
-                        <property name="AtkObject::accessible-name" translatable="yes">register_progressbar</property>
-                      </object>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                    <property name="position">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="register_details_label">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="use_markup">True</property>
-                    <property name="xalign">0</property>
-                    <child internal-child="accessible">
-                      <object class="AtkObject" id="register_details_label-atkobject">
-                        <property name="AtkObject::accessible-name" translatable="yes">register_details_label</property>
-                      </object>
-                    </child>
+                <property name="use_markup">True</property>
+                <property name="xalign">0</property>
+                <child internal-child="accessible">
+                  <object class="AtkObject" id="register_details_label-atkobject">
+                    <property name="AtkObject::accessible-name" translatable="yes">register_details_label</property>
                   </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                    <property name="position">2</property>
-                  </packing>
                 </child>
               </object>
               <packing>
-                <property name="tab_fill">False</property>
-              </packing>
-            </child>
-            <child type="tab">
-              <object class="GtkLabel" id="label2">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="label" translatable="yes">page 2</property>
-              </object>
-              <packing>
-                <property name="tab_fill">False</property>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">2</property>
               </packing>
             </child>
           </object>
+        </child>
+        <child type="tab">
+          <object class="GtkLabel" id="tab_label">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="label" translatable="yes">Progress Page</property>
+          </object>
           <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">1</property>
+            <property name="tab_fill">False</property>
           </packing>
         </child>
         <child internal-child="accessible">
-          <object class="AtkObject" id="dialog_vbox6-atkobject">
-            <property name="AtkObject::accessible-name" translatable="yes">register_dialog_main_vbox</property>
+          <object class="AtkObject" id="register_notebook-atkobject">
+            <property name="AtkObject::accessible-name" translatable="yes">register_notebook</property>
           </object>
         </child>
       </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="fill">False</property>
+        <property name="position">1</property>
+      </packing>
     </child>
     <child internal-child="accessible">
-      <object class="AtkObject" id="register_dialog-atkobject">
-        <property name="AtkObject::accessible-name">register_dialog</property>
+      <object class="AtkObject" id="register_widget-atkobject">
+        <property name="AtkObject::accessible-name" translatable="yes">register_widget_main_vbox</property>
       </object>
     </child>
   </object>
diff --git a/src/subscription_manager/gui/firstboot/rhsm_login.py b/src/subscription_manager/gui/firstboot/rhsm_login.py
index 7c06f19..3aea9a6 100644
--- a/src/subscription_manager/gui/firstboot/rhsm_login.py
+++ b/src/subscription_manager/gui/firstboot/rhsm_login.py
@@ -1,14 +1,18 @@
 
 import gettext
-import socket
 import sys
 import logging
 
 _ = lambda x: gettext.ldgettext("rhsm", x)
 
-import gtk
 
-gtk.gdk.threads_init()
+from subscription_manager import ga_loader
+ga_loader.init_ga()
+
+from subscription_manager.ga import Gtk as ga_Gtk
+from subscription_manager.ga import gtk_compat
+
+gtk_compat.threads_init()
 
 import rhsm
 
@@ -26,20 +30,21 @@ running_as_firstboot()
 
 from subscription_manager.injectioninit import init_dep_injection
 init_dep_injection()
-from subscription_manager.injection import PLUGIN_MANAGER, IDENTITY, require
+
+from subscription_manager import injection as inj
 
 from subscription_manager.facts import Facts
 from subscription_manager.hwprobe import Hardware
-from subscription_manager.gui.firstboot_base import RhsmFirstbootModule
 from subscription_manager.gui import managergui
 from subscription_manager.gui import registergui
-from subscription_manager.gui.utils import handle_gui_exception
-from subscription_manager.gui.autobind import \
-        ServiceLevelNotSupportedException, NoProductsException, \
-        AllProductsCoveredException
-from subscription_manager import managerlib
+from subscription_manager.gui.utils import format_exception
+from subscription_manager.i18n import configure_i18n
+
+from firstboot import module
+from firstboot import constants
+
+configure_i18n(with_glade=True)
 
-from rhsm.connection import RestlibException
 from rhsm.utils import remove_scheme
 
 sys.path.append("/usr/share/rhn")
@@ -50,179 +55,36 @@ try:
 except ImportError:
     log.debug("no rhn-client-tools modules could be imported")
 
-MANUALLY_SUBSCRIBE_PAGE = 11
-
-
-class SelectSLAScreen(registergui.SelectSLAScreen):
-    """
-    override the default SelectSLAScreen to jump to the manual subscribe page.
-    """
-    def _on_get_service_levels_cb(self, result, error=None):
-        if error is not None:
-            if isinstance(error[1], ServiceLevelNotSupportedException):
-                message = _("Unable to auto-attach, server does not support "
-                            "service levels. Please run 'Subscription Manager' "
-                            "to manually attach a subscription.")
-                self._parent.manual_message = message
-                self._parent.pre_done(MANUALLY_SUBSCRIBE_PAGE)
-            elif isinstance(error[1], NoProductsException):
-                message = _("No installed products on system. No need to "
-                            "update subscriptions at this time.")
-                self._parent.manual_message = message
-                self._parent.pre_done(MANUALLY_SUBSCRIBE_PAGE)
-            elif isinstance(error[1], AllProductsCoveredException):
-                message = _("All installed products are fully subscribed.")
-                self._parent.manual_message = message
-                self._parent.pre_done(MANUALLY_SUBSCRIBE_PAGE)
-            else:
-                handle_gui_exception(error, _("Error subscribing"),
-                                     self._parent.window)
-                self._parent.finish_registration(failed=True)
-            return
-
-        (current_sla, unentitled_products, sla_data_map) = result
-
-        self._parent.current_sla = current_sla
-        if len(sla_data_map) == 1:
-            # If system already had a service level, we can hit this point
-            # when we cannot fix any unentitled products:
-            if current_sla is not None and \
-                    not self._can_add_more_subs(current_sla, sla_data_map):
-                message = _("Unable to attach any additional subscriptions at "
-                            "current service level: %s") % current_sla
-                self._parent.manual_message = message
-                self._parent.pre_done(MANUALLY_SUBSCRIBE_PAGE)
-                return
-
-            self._dry_run_result = sla_data_map.values()[0]
-            self._parent.pre_done(registergui.CONFIRM_SUBS_PAGE)
-        elif len(sla_data_map) > 1:
-            self._sla_data_map = sla_data_map
-            self.set_model(unentitled_products, sla_data_map)
-            self._parent.pre_done(registergui.DONT_CHANGE)
-        else:
-            message = _("No service levels will cover all installed products. "
-                "Please run 'Subscription Manager' to manually "
-                "attach subscriptions.")
-            self._parent.manual_message = message
-            self._parent.pre_done(MANUALLY_SUBSCRIBE_PAGE)
-
-
-class PerformRegisterScreen(registergui.PerformRegisterScreen):
-
-    def _on_registration_finished_cb(self, new_account, error=None):
-        if error is not None:
-            handle_gui_exception(error, registergui.REGISTER_ERROR,
-                    self._parent.window)
-            self._parent.finish_registration(failed=True)
-            return
-
-        try:
-            managerlib.persist_consumer_cert(new_account)
-            self._parent.backend.cs.force_cert_check()  # Ensure there isn't much wait time
-
-            if self._parent.activation_keys:
-                self._parent.pre_done(registergui.REFRESH_SUBSCRIPTIONS_PAGE)
-            elif self._parent.skip_auto_bind:
-                message = _("You have opted to skip auto-attach.")
-                self._parent.manual_message = message
-                self._parent.pre_done(MANUALLY_SUBSCRIBE_PAGE)
-            else:
-                self._parent.pre_done(registergui.SELECT_SLA_PAGE)
-
-        # If we get errors related to consumer name on register,
-        # go back to the credentials screen where we set the
-        # consumer name. See bz#865954
-        except RestlibException, e:
-            handle_gui_exception(e, registergui.REGISTER_ERROR,
-                self._parent.window)
-            if e.code == 404 and self._parent.activation_keys:
-                self._parent.pre_done(registergui.ACTIVATION_KEY_PAGE)
-            if e.code == 400:
-                self._parent.pre_done(registergui.CREDENTIALS_PAGE)
-
-        except Exception, e:
-            handle_gui_exception(e, registergui.REGISTER_ERROR,
-                    self._parent.window)
-            self._parent.finish_registration(failed=True)
-
-    def pre(self):
-        # TODO: this looks like it needs updating now that we run
-        # firstboot without rhn client tools.
-
-        # Because the RHN client tools check if certs exist and bypass our
-        # firstboot module if so, we know that if we reach this point and
-        # identity certs exist, someone must have hit the back button.
-        # TODO: i'd like this call to be inside the async progress stuff,
-        # since it does take some time
-        identity = require(IDENTITY)
-        if identity.is_valid():
-            try:
-                managerlib.unregister(self._parent.backend.cp_provider.get_consumer_auth_cp(),
-                        self._parent.identity.uuid)
-            except socket.error, e:
-                handle_gui_exception(e, e, self._parent.window)
-            self._parent._registration_finished = False
-
-        return registergui.PerformRegisterScreen.pre(self)
 
-
-class ManuallySubscribeScreen(registergui.Screen):
-    widget_names = registergui.Screen.widget_names + ['title']
-    gui_file = "manually_subscribe"
-
-    def __init__(self, parent, backend):
-        super(ManuallySubscribeScreen, self).__init__(parent, backend)
-
-        self.button_label = _("Finish")
-
-    def apply(self):
-        return registergui.FINISH
-
-    def pre(self):
-        if self._parent.manual_message:
-            self.title.set_label(self._parent.manual_message)
-        # XXX set message here.
-        return False
-
-
-class moduleClass(RhsmFirstbootModule, registergui.RegisterScreen):
+class moduleClass(module.Module, object):
 
     def __init__(self):
         """
         Create a new firstboot Module for the 'register' screen.
         """
-        RhsmFirstbootModule.__init__(self,        # Firstboot module title
-        # Note: translated title needs to be unique across all
-        # firstboot modules, not just the rhsm ones. See bz #828042
-                _("Subscription Management Registration"),
-                _("Subscription Registration"),
-                200.1, 109.10)
+        super(moduleClass, self).__init__()
 
-        backend = managergui.Backend()
-        self.plugin_manager = require(PLUGIN_MANAGER)
-        registergui.RegisterScreen.__init__(self, backend, Facts())
+        self.mode = constants.MODE_REGULAR
+        self.title = _("Subscription Management Registration")
+        self.sidebarTitle = _("Subscription Registration")
+        self.priority = 200.1
 
-        #insert our new screens
-        screen = SelectSLAScreen(self, backend)
-        screen.index = self._screens[registergui.SELECT_SLA_PAGE].index
-        self._screens[registergui.SELECT_SLA_PAGE] = screen
-        self.register_notebook.remove_page(screen.index)
-        self.register_notebook.insert_page(screen.container,
-                                           position=screen.index)
+        # NOTE: all of this is copied form former firstboot_base module
+        # and may no longer be needed
+        # set this so subclasses can override behaviour if needed
+        self._is_compat = False
 
-        screen = PerformRegisterScreen(self, backend)
-        self._screens[registergui.PERFORM_REGISTER_PAGE] = screen
-
-        screen = ManuallySubscribeScreen(self, backend)
-        self._screens.append(screen)
-        screen.index = self.register_notebook.append_page(screen.container)
+        reg_info = registergui.RegisterInfo()
+        backend = managergui.Backend()
+        self.plugin_manager = inj.require(inj.PLUGIN_MANAGER)
+        self.register_widget = registergui.RegisterWidget(backend, Facts(), reg_info)
 
         # Will be False if we are on an older RHEL version where
         # rhn-client-tools already does some things so we don't have to.
         self.standalone = True
         distribution = Hardware().get_distribution()
         log.debug("Distribution: %s" % str(distribution))
+
         try:
             dist_version = float(distribution[1])
             # We run this for Fedora as well, but all we really care about here
@@ -243,7 +105,141 @@ class moduleClass(RhsmFirstbootModule, registergui.RegisterScreen):
         self.interface = None
 
         self.proxies_were_enabled_from_gui = None
-        self._apply_result = self._RESULT_FAILURE
+        self._apply_result = constants.RESULT_FAILURE
+
+        self.page_status = constants.RESULT_FAILURE
+
+    def apply(self, interface, testing=False):
+        """
+        'Next' button has been clicked - try to register with the
+        provided user credentials and return the appropriate result
+        value.
+        """
+        self.interface = interface
+
+        self.register_widget.emit('proceed')
+
+        # This is always "fail" until we get to the done screen
+        return self.page_status
+
+    def createScreen(self):
+        """
+        Create a new instance of gtk.VBox, pulling in child widgets from the
+        glade file.
+        """
+        self.vbox = ga_Gtk.VBox()
+        # self.vbox.pack_start(self.get_widget("register_widget"), False, False, 0)
+        self.vbox.pack_start(self.register_widget.register_widget, False, False, 0)
+
+        self.register_widget.connect('finished', self.on_finished)
+        self.register_widget.connect('register-error', self.on_register_error)
+
+        # In firstboot, we leverage the RHN setup proxy settings already
+        # presented to the user, so hide the choose server screen's proxy
+        # text and button. But, if we are standalone, show our versions.
+        if not self.standalone and False:
+            screen = self._screens[registergui.CHOOSE_SERVER_PAGE]
+            screen.proxy_frame.destroy()
+
+    def focus(self):
+        """
+        Focus the initial UI element on the page, in this case the
+        login name field.
+        """
+        # FIXME:  This is currently broken
+        # login_text = self.glade.get_widget("account_login")
+        # login_text.grab_focus()
+
+    def initializeUI(self):
+        log.debug("initializeUi %s", self)
+        # Need to make sure that each time the UI is initialized we reset back
+        # to the main register screen.
+
+        # Note, even if we are standalone firstboot mode (no rhn modules),
+        # we may still have RHN installed, and possibly configured.
+        self._read_rhn_proxy_settings()
+
+        self.register_widget.initialize()
+
+    def needsNetwork(self):
+        """
+        This lets firstboot know that networking is required, in order to
+        talk to hosted UEP.
+        """
+        return True
+
+    def needsReboot(self):
+        return False
+
+    # TODO: verify this doesnt break anything
+    def not_renderModule(self, interface):
+        #ParentClass.renderModule(self, interface)
+
+        # firstboot module class docs state to not override renderModule,
+        # so this is breaking the law.
+        #
+        # This is to set line wrapping on the title label to resize
+        # correctly with our long titles and their even longer translations
+        super(moduleClass, self).renderModule(interface)
+
+        # FIXME: likely all of this should be behind a try/except, since it's
+        #        likely to break, and it is just to fix cosmetic issues.
+        # Walk down widget tree to find the title label
+        label_container = self.vbox.get_children()[0]
+        title_label = label_container.get_children()[0]
+
+        # Set the title to wrap and connect to size-allocate to
+        # properly resize the label so that it takes up the most
+        # space it can.
+        title_label.set_line_wrap(True)
+        title_label.connect('size-allocate',
+                             lambda label, size: label.set_size_request(size.width - 1, -1))
+
+    def shouldAppear(self):
+        """
+        Indicates to firstboot whether to show this screen.  In this case
+        we want to skip over this screen if there is already an identity
+        certificate on the machine (most likely laid down in a kickstart).
+        """
+        identity = inj.require(inj.IDENTITY)
+        return not identity.is_valid()
+
+    def on_register_error(self, obj, msg, exc_list):
+        self.page_status = constants.RESULT_FAILURE
+
+        # TODO: we can add the register state, error type (error or exc)
+        if exc_list:
+            self.handle_register_exception(obj, msg, exc_list)
+        else:
+            self.handle_register_error(obj, msg)
+            return True
+
+    def on_finished(self, obj):
+        self.finished = True
+        self.page_status = constants.RESULT_SUCCESS
+        return False
+
+    def handle_register_error(self, obj, msg):
+        self.error_dialog(msg)
+
+    def handle_register_exception(self, obj, msg, exc_info):
+        message = format_exception(exc_info, msg)
+        self.error_dialog(message)
+
+    def error_dialog(self, text):
+        dlg = ga_Gtk.MessageDialog(None, 0, ga_Gtk.MessageType.ERROR,
+                                   ga_Gtk.ButtonsType.OK, text)
+        dlg.set_markup(text)
+        dlg.set_skip_taskbar_hint(True)
+        dlg.set_skip_pager_hint(True)
+        dlg.set_position(ga_Gtk.WindowPosition.CENTER)
+
+        def response_handler(obj, response_id):
+            obj.destroy()
+
+        dlg.connect('response', response_handler)
+        dlg.set_modal(True)
+        dlg.show()
 
     def _get_initial_screen(self):
         """
@@ -310,47 +306,6 @@ class moduleClass(RhsmFirstbootModule, registergui.RegisterScreen):
 
         self.backend.cp_provider.set_connection_info()
 
-    def apply(self, interface, testing=False):
-        """
-        'Next' button has been clicked - try to register with the
-        provided user credentials and return the appropriate result
-        value.
-        """
-
-        # on el5 we can't just move to another page, we have to set the next
-        # page then do an apply. since we've already done our work async, skip
-        # this time through
-        if self._skip_apply_for_page_jump:
-            self._skip_apply_for_page_jump = False
-            # Reset back to first screen in our module in case the user hits back.
-            # The firstboot register screen subclass will handle unregistering
-            # if necessary when it runs again.
-            self.show()
-            return self._RESULT_SUCCESS
-
-        self.interface = interface
-
-        # bad proxy settings can cause socket.error or friends here
-        # see bz #810363
-        try:
-            valid_registration = self.register()
-
-        except socket.error, e:
-            handle_gui_exception(e, e, self.window)
-            return self._RESULT_FAILURE
-
-        # run main_iteration till we have no events, like idle
-        # loop sources, aka, the thread watchers are finished.
-        while gtk.events_pending():
-            gtk.main_iteration()
-
-        if valid_registration:
-            self._cached_credentials = self._get_credentials_hash()
-
-        # finish_registration/skip_remaining_screens should set
-        # __apply_result to RESULT_JUMP
-        return self._apply_result
-
     def close_window(self):
         """
         Overridden from RegisterScreen - we want to bypass the default behavior
@@ -365,49 +320,6 @@ class moduleClass(RhsmFirstbootModule, registergui.RegisterScreen):
         """
         pass
 
-    def createScreen(self):
-        """
-        Create a new instance of gtk.VBox, pulling in child widgets from the
-        glade file.
-        """
-        self.vbox = gtk.VBox(spacing=10)
-        self.register_dialog = self.get_widget("dialog-vbox6")
-        self.register_dialog.reparent(self.vbox)
-
-        # Get rid of the 'register' and 'cancel' buttons, as we are going to
-        # use the 'forward' and 'back' buttons provided by the firsboot module
-        # to drive the same functionality
-        self._destroy_widget('register_button')
-        self._destroy_widget('cancel_button')
-
-        # In firstboot, we leverage the RHN setup proxy settings already
-        # presented to the user, so hide the choose server screen's proxy
-        # text and button. But, if we are standalone, show our versions.
-        if not self.standalone:
-            screen = self._screens[registergui.CHOOSE_SERVER_PAGE]
-            screen.proxy_frame.destroy()
-
-    def initializeUI(self):
-        # Need to make sure that each time the UI is initialized we reset back
-        # to the main register screen.
-
-        # Note, even if we are standalone firstboot mode (no rhn modules),
-        # we may still have RHN installed, and possibly configured.
-        self._read_rhn_proxy_settings()
-
-        # NOTE: On EL5 this does not appear to be called when the user
-        # presses Back, only when they go through the first time.
-        self.show()
-
-    def focus(self):
-        """
-        Focus the initial UI element on the page, in this case the
-        login name field.
-        """
-        # FIXME:  This is currently broken
-        # login_text = self.glade.get_widget("account_login")
-        # login_text.grab_focus()
-
     def _destroy_widget(self, widget_name):
         """
         Destroy a widget by name.
@@ -489,6 +401,3 @@ class moduleClass(RhsmFirstbootModule, registergui.RegisterScreen):
         else:
             self._apply_result = self._RESULT_SUCCESS
             return
-
-# for el5
-childWindow = moduleClass
diff --git a/src/subscription_manager/gui/firstboot_base.py b/src/subscription_manager/gui/firstboot_base.py
deleted file mode 100644
index 1a7b507..0000000
--- a/src/subscription_manager/gui/firstboot_base.py
+++ /dev/null
@@ -1,122 +0,0 @@
-#
-# Copyright (c) 2012 Red Hat, Inc.
-#
-# This software is licensed to you under the GNU General Public License,
-# version 2 (GPLv2). There is NO WARRANTY for this software, express or
-# implied, including the implied warranties of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
-# along with this software; if not, see
-# http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
-#
-# Red Hat trademarks are not licensed under GPLv2. No permission is
-# granted to use or replicate Red Hat trademarks that are incorporated
-# in this software or its documentation.
-#
-
-import sys
-
-sys.path.append("/usr/share/rhsm")
-
-# rhsm_login init the injector before we are loaded
-from subscription_manager import injection as inj
-
-from subscription_manager.i18n import configure_i18n
-
-configure_i18n(with_glade=True)
-
-# Number of total RHSM firstboot screens, used to skip past to whatever's
-# next in a couple places.
-NUM_RHSM_SCREENS = 4
-
-try:
-    _version = "el6"
-    from firstboot.constants import RESULT_SUCCESS, RESULT_FAILURE, RESULT_JUMP
-    from firstboot.module import Module
-except Exception:
-    # we must be on el5
-    _version = "el5"
-    from firstboot_module_window import FirstbootModuleWindow
-
-
-if _version == "el5":
-    ParentClass = FirstbootModuleWindow
-else:
-    ParentClass = Module
-
-
-class RhsmFirstbootModule(ParentClass):
-
-    def __init__(self, title, sidebar_title, priority, compat_priority):
-        ParentClass.__init__(self)
-
-        if _version == "el6":
-            # set this so subclasses can override behaviour if needed
-            self._is_compat = False
-            self._RESULT_SUCCESS = RESULT_SUCCESS
-            self._RESULT_FAILURE = RESULT_FAILURE
-            self._RESULT_JUMP = RESULT_JUMP
-        else:
-            self._is_compat = True
-            self._RESULT_SUCCESS = True
-            self._RESULT_FAILURE = None
-            self._RESULT_JUMP = True
-
-        # this value is relative to when you want to load the screen
-        # so check other modules before setting
-        self.priority = priority
-        self.sidebarTitle = sidebar_title
-        self.title = title
-
-        # el5 values
-        self.runPriority = compat_priority
-        self.moduleName = self.sidebarTitle
-        self.windowTitle = self.moduleName
-        self.shortMessage = self.title
-        self.noSidebar = True
-
-        # el5 value to get access to parent object for page jumping
-        self.needsparent = 1
-
-    def renderModule(self, interface):
-        ParentClass.renderModule(self, interface)
-        label_container = self.vbox.get_children()[0]
-        title_label = label_container.get_children()[0]
-
-        # Set the title to wrap and connect to size-allocate to
-        # properly resize the label so that it takes up the most
-        # space it can.
-        title_label.set_line_wrap(True)
-        title_label.connect('size-allocate', lambda label, size: label.set_size_request(size.width - 1, -1))
-
-    def needsNetwork(self):
-        """
-        This lets firstboot know that networking is required, in order to
-        talk to hosted UEP.
-        """
-        return True
-
-    def shouldAppear(self):
-        """
-        Indicates to firstboot whether to show this screen.  In this case
-        we want to skip over this screen if there is already an identity
-        certificate on the machine (most likely laid down in a kickstart).
-        """
-        identity = inj.require(inj.IDENTITY)
-        return not identity.is_valid()
-
-    ##############################
-    # el5 compat functions follow
-    ##############################
-
-    def launch(self, doDebug=None):
-        self.createScreen()
-        return self.vbox, self.icon, self.windowTitle
-
-    def passInParent(self, parent):
-        self.compat_parent = parent
-
-        self.register_button = parent.nextButton
-        self.cancel_button = parent.backButton
-
-    def grabFocus(self):
-        self.initializeUI()
diff --git a/src/subscription_manager/gui/managergui.py b/src/subscription_manager/gui/managergui.py
index 2aae80e..cb2cec9 100644
--- a/src/subscription_manager/gui/managergui.py
+++ b/src/subscription_manager/gui/managergui.py
@@ -158,6 +158,7 @@ class MainWindow(widgets.SubmanBaseWidget):
         log.debug("Server Versions: %s " % get_server_versions(self.backend.cp_provider.get_consumer_auth_cp()))
 
         settings = self.main_window.get_settings()
+
         # prevent gtk from trying to save a list of recently used files, which
         # as root, causes gtk warning:
         #  "Attempting to set the permissions of `/root/.local/share/recently-used.xbel'
@@ -171,8 +172,7 @@ class MainWindow(widgets.SubmanBaseWidget):
 
         self.system_facts_dialog = factsgui.SystemFactsDialog(self.facts)
 
-        self.registration_dialog = registergui.RegisterScreen(self.backend, self.facts,
-                                                              self._get_window())
+        self.registration_dialog = registergui.RegisterDialog(self.backend, self.facts)
 
         self.preferences_dialog = PreferencesDialog(self.backend,
                                                     self._get_window())
@@ -360,7 +360,6 @@ class MainWindow(widgets.SubmanBaseWidget):
             self.redeem_menu_item.set_sensitive(False)
 
     def _register_item_clicked(self, widget):
-        self.log.debug("_register_item_clicked widget=%s", widget)
         self.registration_dialog.initialize()
         self.registration_dialog.show()
 
@@ -427,9 +426,8 @@ class MainWindow(widgets.SubmanBaseWidget):
         self.import_sub_dialog.show()
 
     def _update_certificates_button_clicked(self, widget):
-        autobind_wizard = registergui.AutobindWizard(self.backend,
-                                                     self.facts,
-                                                     self._get_window())
+        autobind_wizard = registergui.AutobindWizardDialog(self.backend,
+                                                           self.facts)
         autobind_wizard.initialize()
         autobind_wizard.show()
 
diff --git a/src/subscription_manager/gui/registergui.py b/src/subscription_manager/gui/registergui.py
index 123c783..3ba0fff 100644
--- a/src/subscription_manager/gui/registergui.py
+++ b/src/subscription_manager/gui/registergui.py
@@ -23,7 +23,6 @@ import socket
 import sys
 import threading
 
-
 from subscription_manager.ga import Gtk as ga_Gtk
 from subscription_manager.ga import GObject as ga_GObject
 
@@ -41,21 +40,16 @@ from subscription_manager import managerlib
 from subscription_manager.utils import is_valid_server_info, MissingCaCertException, \
         parse_server_info, restart_virt_who
 
-from subscription_manager.gui.utils import handle_gui_exception, show_error_window
+from subscription_manager.gui.utils import format_exception, show_error_window
 from subscription_manager.gui.autobind import DryRunResult, \
         ServiceLevelNotSupportedException, AllProductsCoveredException, \
         NoProductsException
-from subscription_manager.gui.messageWindow import InfoDialog, OkDialog
 from subscription_manager.jsonwrapper import PoolWrapper
 
 _ = lambda x: gettext.ldgettext("rhsm", x)
 
 gettext.textdomain("rhsm")
 
-#Gtk.glade.bindtextdomain("rhsm")
-
-#Gtk.glade.textdomain("rhsm")
-
 log = logging.getLogger('rhsm-app.' + __name__)
 
 CFG = config.initConfig()
@@ -74,6 +68,7 @@ def set_state(new_state):
     global state
     state = new_state
 
+ERROR_SCREEN = -3
 DONT_CHANGE = -2
 PROGRESS_PAGE = -1
 CHOOSE_SERVER_PAGE = 0
@@ -122,388 +117,545 @@ def reset_resolver():
         pass
 
 
-class RegistrationBox(widgets.SubmanBaseWidget):
-    gui_file = "registration_box"
-
-
-class RegisterScreen(widgets.SubmanBaseWidget):
-    """
-    Registration Widget Screen
-
-    RegisterScreen is the parent widget of registration screens, and
-    also the base class of the firstboot rhsm_module.
-
-    RegisterScreen has a list of Screen subclasses.
+class RegisterInfo(ga_GObject.GObject):
 
-    Screen subclasses can be Screen, NonGuiScreen, or GuiScreen
-    classes. Only GuiScreen classes are user visible. NonGuiScreen
-    and subclasses are used for state transitions (a between screens
-    check for pools, for example)
+    username = ga_GObject.property(type=str, default='')
+    password = ga_GObject.property(type=str, default='')
 
-    The rhsmModule.apply() runs RegisterScreen.register().
-    RegisterScreen.register runs the current screens .apply().
+    # server info
+    hostname = ga_GObject.property(type=str, default='')
+    port = ga_GObject.property(type=str, default='')
+    prefix = ga_GObject.property(type=str, default='')
 
-    A Screen.apply() will return the index of the next screen that
-    should be invoked (which may be a different screen, the same screen,
-    or the special numbers for DONT_CHANGE and FINISH.)
+    # rhsm model info
+    environment = ga_GObject.property(type=str, default='')
+    consumername = ga_GObject.property(type=str, default='')
+    owner_key = ga_GObject.property(type=ga_GObject.TYPE_PYOBJECT, default=None)
+    activation_keys = ga_GObject.property(type=ga_GObject.TYPE_PYOBJECT, default=None)
 
-    In firstboot, calling the firstboot modules .apply() results in calling
-    rhsm_module.moduleClass.apply() which calls the first Screen.apply()
-    (also self._current_screen).
+    # split into AttachInfo or FindSlaInfo?
+    current_sla = ga_GObject.property(type=ga_GObject.TYPE_PYOBJECT, default=None)
+    dry_run_result = ga_GObject.property(type=ga_GObject.TYPE_PYOBJECT, default=None)
 
-    After the Screen.apply(), RegisterScreen.register checks it's return
-    for DONT_CHANGE or FINISH.
+    # registergui states
+    skip_auto_bind = ga_GObject.property(type=bool, default=False)
+    details_label_txt = ga_GObject.property(type=str, default='')
+    register_state = ga_GObject.property(type=int, default=REGISTERING)
 
-    If the apply returns a screen index, then the Screen.post() is called.
-    The return value is ignored.
-
-    The RegisterScreen.register calls RegisterScreen.run_pre() on the
-    screen index that the current_screen .apply() returned(i.e. the
-    next screen).
-
-    run_pre() checks that it's arg (the result of above apply(), what
-    is still currently the next screen) is not DONT_CHANGE/FINISH.
+    # TODO: make a gobj prop as well, with custom set/get, so we can be notified
+    @property
+    def identity(self):
+        id = require(IDENTITY)
+        return id
 
-    If not, then it calls self._set_screen() which updates
-    self._current_screen to point to the next screen.
+    def __init__(self):
+        ga_GObject.GObject.__init__(self)
 
-    run_pre() then calls the new current_screens's .pre()
 
-    .register()
-        next_screen = current_screen.apply()
-        current_screen.post()
-        RegisterScreen.run_pre(next_screen)
-        RegisterScreen._set_screen(next_screen)
-            current_screen = next_screen
+class RegisterWidget(widgets.SubmanBaseWidget):
+    gui_file = "registration"
+    widget_names = ['register_widget', 'register_notebook',
+                    'register_details_label', 'register_progressbar',
+                    'progress_label']
+
+    __gsignals__ = {'proceed': (ga_GObject.SignalFlags.RUN_FIRST,
+                                None, []),
+                    'register-warning': (ga_GObject.SignalFlags.RUN_FIRST,
+                                         None, (ga_GObject.TYPE_PYOBJECT,)),
+                    'register-error': (ga_GObject.SignalFlags.RUN_FIRST,
+                                       None, (ga_GObject.TYPE_PYOBJECT,
+                                              ga_GObject.TYPE_PYOBJECT)),
+                    'finished': (ga_GObject.SignalFlags.RUN_FIRST,
+                                 None, []),
+                    'attach-finished': (ga_GObject.SignalFlags.RUN_FIRST,
+                                        None, []),
+                    'register-finished': (ga_GObject.SignalFlags.RUN_FIRST,
+                                          None, [])}
+
+    initial_screen = CHOOSE_SERVER_PAGE
+
+    register_button_label = ga_GObject.property(type=str, default=_('Register'))
+    # TODO: a prop equilivent to initial-setups 'completed' and 'status' props
+
+    def __init__(self, backend, facts, reg_info=None, parent_window=None):
+        super(RegisterWidget, self).__init__()
 
-            Then if current_screen is a gui screen, the visible
-            gui will update with the new widgets.
+        self.backend = backend
+        self.identity = require(IDENTITY)
+        self.facts = facts
 
-        The new current_screen has its pre() method invoked. pre()
-        methods may return an async representing that a request
-        has been called and a callback registered. If that's the case,
-        then RegisterScreen._set_screen() sets the current screen
-        to a progress screen.
+        self.async = AsyncBackend(self.backend)
 
-    The return value of RegisterScreen.run_pre() is ignored, and
-    RegisterScreen.register() returns False.
+        # TODO: should be able to get rid of this soon, the
+        #       only thing that uses it is the NetworkConfigDialog in
+        #       chooseServerScreen and we can replace that with an embedded
+        #       widget
+        self.parent_window = parent_window
+
+        self.info = reg_info or RegisterInfo()
+
+        self.progress_timer = None
+
+        # TODO: move these handlers into their own class
+        self.info.connect("notify::username",
+                          self._on_username_password_change)
+        self.info.connect("notify::password",
+                          self._on_username_password_change)
+        self.info.connect("notify::hostname",
+                          self._on_connection_info_change)
+        self.info.connect("notify::port",
+                          self._on_connection_info_change)
+        self.info.connect("notify::prefix",
+                          self._on_connection_info_change)
+        self.info.connect("notify::activation-keys",
+                          self._on_activation_keys_change)
+        self.info.connect('notify::details-label-txt',
+                          self._on_details_label_txt_change)
+        self.info.connect('notify::register-state',
+                          self._on_register_state_change)
+
+        # expect this to be driving from the parent dialog
+        self.connect('proceed',
+                     self._on_proceed)
+
+        # FIXME: change glade name
+        self.details_label = self.register_details_label
+
+        # To update the 'next/register' button in the parent dialog based on the new page
+        self.register_notebook.connect('switch-page',
+                                       self._on_switch_page)
 
-    This returns to rhsm_login.apply(), where valid_registration is
-    set to the return value. valid_registration=True indicates a
-    succesful registration
+        screen_classes = [ChooseServerScreen, ActivationKeyScreen,
+                          CredentialsScreen, OrganizationScreen,
+                          EnvironmentScreen, PerformRegisterScreen,
+                          SelectSLAScreen, ConfirmSubscriptionsScreen,
+                          PerformSubscribeScreen, RefreshSubscriptionsScreen,
+                          InfoScreen, DoneScreen]
+        self._screens = []
 
-    If valid_registration=True, we are basically done with registeration.
-    But rhsm_login can't return from apply() yet, since that could
-    potential lead to firstboot ending if it's the last or only module.
+        # TODO: current_screen as a gobject property
+        for idx, screen_class in enumerate(screen_classes):
+            self.add_screen(idx, screen_class)
 
-    gtk main loop iterations are run, mostly to let any threads finish
-    up and any idle loop thread watchers to dry up.
+        self._current_screen = None
 
-    The return value of rhsm_login.apply() at this point is actualy
-    the _apply_result instance variable. Register Screens() are expected
-    to set this by calling their finish_registration() method. For
-    subscription-manager-gui that means RegisterScreen.finish_registration,
-    usually access as a Screens() self._parent.finish_registration.
+        # Track screens we "show" so we can choose a reasonable error screen
+        self.screen_history = []
 
-    For firstboot screens, self._parent will be rhsm_module.moduleClass
-    (also a subclass of RegisterScreen).
+        # FIXME: modify property instead
+        self.callbacks = []
 
-    rhsm_module.finish_registration() will check the "failed" boolean,
-    and either return to a Screen() (CredentialsPage, atm). Or if
-    failed=True, it will also call RegisterScreen.finish_registration(),
-    that closes the gui window.
+        self.register_widget.show()
 
-    The UI flow is a result of the order of RegisterScreen._screens,
-    and the screen indexes returned by Screen.apply().
+    def add_screen(self, idx, screen_class):
+        screen = screen_class(reg_info=self.info,
+                              async_backend=self.async,
+                              facts=self.facts,
+                              parent_window=self.parent_window)
 
-    But, between the Screen activity call also change the flow, most
-    notably the results of any async calls and callbacks invoked from
-    the screens .pre()
+        # add the index of the screen in self._screens to the class itself
+        screen.screens_index = idx
 
-    A common case is the async callbacks error handling calling
-    self._parent.finish_registration(failed=True)
+        # connect handlers to various screen signals. The screens are
+        # Gobjects not gtk widgets, so they can't propagate normally.
+        screen.connect('move-to-screen', self._on_move_to_screen)
+        screen.connect('stay-on-screen', self._on_stay_on_screen)
+        screen.connect('register-error', self._on_screen_register_error)
+        screen.connect('register-finished',
+                       self._on_screen_register_finished)
+        screen.connect('attach-finished',
+                       self._on_screen_attach_finished)
 
-    The async callback can also call RegisterScreen.pre_done() to send the
-    UI to a different screen. RHSM api call results that indicate multiple
-    choices for a sub would send flow to a chooseSub GuiScreen vs a
-    NonGuiScreen for attaching a sub, for example.
+        self._screens.append(screen)
 
-    RegisterScreen.run_pre schedules async jobs, they get queued, and
-    wait for their callbacks. The callbacks then can use pre_done()
-    to finish the tasks the run_pre started. Typicaly the UI will
-    see the Progress screens in the meantime.
+        # Some screens have no gui controls, they just use the
+        # PROGRESS_PAGE, so the indexes to the register_notebook's pages and
+        # to self._screen differ
+        if screen.needs_gui:
+            # screen.index is the screens index in self.register_notebook
+            screen.index = self.register_notebook.append_page(screen.container,
+                                                              tab_label=None)
 
-    If going to screen requires an async task, run_pre starts it by
-    calling the new screens pre(), setting that screen to current (_set_screen),
-    and then setting the GuiScreen to the progress screens. Screen
-    transitions that don't need async tasks just return nothing from
-    their pre() and go to the next screen in the order in self._screens.
+    def initialize(self):
+        self.set_initial_screen()
+        self.clear_screens()
+        # TODO: move this so it's only running when a progress bar is "active"
+        self.register_widget.show_all()
+
+    def start_progress_timer(self):
+        if not self.progress_timer:
+            self.progress_timer = ga_GObject.timeout_add(100, self._timeout_callback)
+
+    def stop_progress_timer(self):
+        if self.progress_timer:
+            ga_GObject.source_remove(self.progress_timer)
+            self.progress_timer = None
+
+    def set_initial_screen(self):
+        self._set_screen(self.initial_screen)
+        self._current_screen = self.initial_screen
+        self.screen_history = [self.initial_screen]
+
+    # switch-page should be after the current screen is reset
+    def _on_switch_page(self, notebook, page, page_num):
+        current_screen = self._screens[self._current_screen]
+        # NonGuiScreens have a None button label
+        if current_screen.button_label:
+            self.set_property('register-button-label', current_screen.button_label)
+
+    # HMMM: If the connect/backend/async, and the auth info is composited into
+    #       the same GObject, these could be class closure handlers
+    def _on_username_password_change(self, *args):
+        self.async.set_user_pass(self.info.username, self.info.password)
+
+    def _on_connection_info_change(self, *args):
+        self.async.update()
+
+    def _on_activation_keys_change(self, obj, param):
+        activation_keys = obj.get_property('activation-keys')
+
+        # Unset backend from attempting to use basic auth
+        if activation_keys:
+            self.async.cp_provider.set_user_pass()
+            self.async.update()
+
+    def _on_details_label_txt_change(self, obj, value):
+        """Update the label under the progress bar on progress page."""
+        self.details_label.set_label("<small>%s</small>" %
+                                     obj.get_property('details-label-txt'))
+
+    def _on_register_state_change(self, obj, value):
+        """Handler for the signal indicating we moved from registering to attaching.
+
+        (the 'register-state' property changed), so update the
+        related label on progress page."""
+        state = obj.get_property('register-state')
+        if state == REGISTERING:
+            self.progress_label.set_markup(_("<b>Registering</b>"))
+        elif state == SUBSCRIBING:
+            self.progress_label.set_markup(_("<b>Attaching</b>"))
 
-    Note the the flow of firstboot through multiple modules is driven
-    by the return value of rhsm_login.apply(). firstboot itself maintains
-    a list of modules and a an ordered list of them. True goes to the
-    next screen, False stays. Except for RHEL6, where it is the opposite.
+    def do_register_error(self, msg, exc_info):
+        """Class closure signal handler for 'register-error'.
 
-    As of RHEL7.0+, none of that matters much, since rhsm_login is the
-    only module in firstboot.
+        This should always get run first, when this widget emits a
+        'register-error', then it's emitted to other handlers (set up by
+        any parent dialogs for example)."""
+        # return to the last gui screen we showed.
 
-    """
+        self._set_screen(self.screen_history[-1])
 
-    widget_names = ['register_dialog', 'register_notebook',
-                    'register_progressbar', 'register_details_label',
-                    'cancel_button', 'register_button', 'progress_label',
-                    'dialog_vbox6']
-    gui_file = "registration"
-    __gtype_name__ = 'RegisterScreen'
+    def _on_screen_register_error(self, obj, msg, exc_info):
+        """Handler for 'register-error' signals emitted from the Screens.
 
-    def __init__(self, backend, facts=None, parent=None, callbacks=None):
-        """
-        Callbacks will be executed when registration status changes.
-        """
-        super(RegisterScreen, self).__init__()
+        Then emit one ourselves. Now emit a new signal for parent widget and
+        self.do_register_error() to handle"""
 
-        self.backend = backend
-        self.identity = require(IDENTITY)
-        self.facts = facts
-        self.parent = parent
-        self.callbacks = callbacks or []
+        self.emit('register-error', msg, exc_info)
 
-        self.async = AsyncBackend(self.backend)
+        # do_register_error handles it for this widget, so stop emission
+        return False
 
-        callbacks = {"on_register_cancel_button_clicked": self.cancel,
-                     "on_register_button_clicked": self._on_register_button_clicked,
-                     "hide": self.cancel,
-                     "on_register_dialog_delete_event": self._delete_event}
-        self.connect_signals(callbacks)
+    def _on_stay_on_screen(self, current_screen):
+        """A 'stay-on-screen' handler, for errors that need to be corrected before proceeding.
 
-        self.window = self.register_dialog
-        self.register_dialog.set_transient_for(self.parent)
+        A screen has been shown, and error handling emits this to indicate the
+        widget should not move to a different screen.
 
-        screen_classes = [ChooseServerScreen, ActivationKeyScreen,
-                          CredentialsScreen, OrganizationScreen,
-                          EnvironmentScreen, PerformRegisterScreen,
-                          SelectSLAScreen, ConfirmSubscriptionsScreen,
-                          PerformSubscribeScreen, RefreshSubscriptionsScreen,
-                          InfoScreen, DoneScreen]
-        self._screens = []
-        for screen_class in screen_classes:
-            screen = screen_class(self, self.backend)
-            self._screens.append(screen)
-            if screen.needs_gui:
-                screen.index = self.register_notebook.append_page(
-                        screen.container, tab_label=None)
-
-        self._current_screen = CHOOSE_SERVER_PAGE
-        self._error_screen = DONT_CHANGE
-
-        # values that will be set by the screens
-        self.username = None
-        self.consumername = None
-        self.activation_keys = None
-        self.owner_key = None
-        self.environment = None
-        self.current_sla = None
-        self.dry_run_result = None
-        self.skip_auto_bind = False
-
-        # XXX needed by firstboot
-        self.password = None
+        This also represents screens that allow the user to potentially correct
+        an error, so we track the history of these screens so errors can go to
+        a useful screen."""
+        self.screen_history.append(current_screen.screens_index)
+        self._set_screen(self._current_screen)
 
-        # FIXME: a 'done' signal maybe?
-        # initial_setup needs to be able to make this empty
-        self.close_window_callback = self._close_window_callback
+    # TODO: replace most of the gui flow logic in the Screen subclasses with
+    #       some state machine that drives them, possibly driving via signals
+    #       indicating each state
 
-    def initialize(self):
-        # Ensure that we start on the first page and that
-        # all widgets are cleared.
-        self._set_initial_screen()
+    def _on_move_to_screen(self, current_screen, next_screen_id):
+        """Handler for the 'move-to-screen' signal, indicating a jump to another screen.
 
-        self._set_navigation_sensitive(True)
-        self._clear_registration_widgets()
-        self.timer = ga_GObject.timeout_add(100, self._timeout_callback)
+        This can be used to send the UI to any other screen, including the next screen.
+        For example, to skip SLA selection if there is only one SLA."""
+        self.change_screen(next_screen_id)
 
-    def show(self):
-        # initial-setup module skips this, since it results in a
-        # new top level window that isn't reparented to the initial-setup
-        # screen.
-        self.register_dialog.show()
+    def change_screen(self, next_screen_id):
+        """Move to the next screen and call the next screens .pre().
 
-    def _set_initial_screen(self):
-        target = self._get_initial_screen()
-        self._set_screen(target)
+        If next_screen.pre() indicates it is async (by returning True)and is spinning
+        off a thread and we should wait for a callback, then move the screen to the
+        PROGRESS_PAGE. The callback passed to AsyncBackend in pre() is then responsible
+        for sending the user to the right screen via 'move-to-screen' signal."""
+        next_screen = self._screens[next_screen_id]
 
-    def _get_initial_screen(self):
-        return CHOOSE_SERVER_PAGE
+        self._set_screen(next_screen_id)
 
-    # for subman gui, we don't need to switch screens on error
-    # but for firstboot, we will go back to the info screen if
-    # we have it.
-    @property
-    def error_screen(self):
-        return self._error_screen
-
-    def goto_error_screen(self):
-        self._set_navigation_sensitive(True)
-        self._set_screen(self.error_screen)
-
-    # FIXME: This exists because standalone gui needs to update the nav
-    #        buttons in it's own top level window, while firstboot needs to
-    #        update the buttons in the main firstboot window. Firstboot version
-    #        has additional logic for rhel5/rhel6 differences.
-    # FIXME: just split this into a registerWidget and a registerDialog
-    def _set_navigation_sensitive(self, sensitive):
-        # We could unsens the cancel button here, but since we use it as
-        # a 'do over' button that sends the dialog back to the start, just
-        # leave it enabled, to avoid leaving un unsens after an async error
-        # handler.
-        self.register_button.set_sensitive(sensitive)
+        async = next_screen.pre()
+        if async:
+            self.start_progress_timer()
+            next_screen.emit('move-to-screen', PROGRESS_PAGE)
 
     def _set_screen(self, screen):
+        """Handle both updating self._current_screen, and updating register_notebook."""
+        next_notebook_page = screen
+
         if screen > PROGRESS_PAGE:
             self._current_screen = screen
+            # FIXME: If we just add ProgressPage in the screen order, we
+            # shouldn't need this bookeeping
             if self._screens[screen].needs_gui:
-                self._set_register_label(screen)
-                self.register_notebook.set_current_page(self._screens[screen].index)
+                next_notebook_page = self._screens[screen].index
         else:
-            self.register_notebook.set_current_page(screen + 1)
+            # TODO: replace with a generator
+            next_notebook_page = screen + 1
+
+        # set_current_page changes the gui, and also results in the
+        # 'switch-page' attribute of the gtk notebook being emitted,
+        # indicating the gui has switched to that page.
+        self.register_notebook.set_current_page(next_notebook_page)
+
+    # FIXME: figure out to determine we are on first screen, then this
+    # could just be 'move-to-screen', next screen
+    # Go to the next screen/state
+    def _on_proceed(self, obj):
+        self.apply_current_screen()
+
+    def apply_current_screen(self):
+        """Extract any info from the widgets and call the screens apply()."""
+        self._screens[self._current_screen].apply()
+
+    def _on_screen_register_finished(self, obj):
+        """Handler for 'register-finished' signal, indicating register is finished.
+
+        The 'register-finished' signal indicates that we are finished with
+        registration (either completly, or because it's not needed, etc).
+        RegisterWidget then emits it's own 'register-finished' for any parent
+        dialogs to handle. Note: 'register-finished' only means the registration
+        steps are finished, and not neccasarily that the gui should be close.
+        It may need to auto attach, etc. The 'finished' signal indicates register
+        and attach are finished, while 'register-finished' is just the first part."""
+
+        self.emit('register-finished')
+
+        # We are done if there is auto bind is being skipped ("Manually attach
+        # to subscriptions" is clicked in the gui)
+        if self.info.get_property('skip-auto-bind'):
+            self.emit('finished')
+
+    def _on_screen_attach_finished(self, obj):
+        """Handler for 'attach-finished' signal from our Screens.
+
+        One of our Screens has indicated that subscription attachment is done.
+        Note: This doesn't neccasarily indicate success, just that the gui has
+        done all the attaching it can. RegisterWidget emits it's own
+        'attach-finished' for parent widgets to handle. Again, note that
+        attach-finished is not the same as 'finished', even though at the moment,
+        'finished' does immediately follow 'attach-finished'"""
+
+        self.emit('attach-finished')
+
+        # If attach is finished, we are done.
+        # let RegisterWidget's self.do_finished() handle any self specific
+        # shutdown (like detaching self.timer) first.
+        self.emit('finished')
+
+    def do_finished(self):
+        """Class closure signal handler for the 'finished' signal.
+
+        Ran first before the any other signal handlers attach to 'finished'"""
+        if self.progress_timer:
+            ga_GObject.source_remove(self.progress_timer)
+
+        # Switch to the 'done' screen before telling other signal handlers we
+        # are done. This way, parent widgets like initial-setup that don't just
+        # close the window have something to display.
+        self.done()
 
-        if get_state() == REGISTERING:
-            # aka, if this is firstboot
-            if not isinstance(self.register_dialog, ga_Gtk.VBox):
-                self.register_dialog.set_title(_("System Registration"))
-            self.progress_label.set_markup(_("<b>Registering</b>"))
-        elif get_state() == SUBSCRIBING:
-            if not isinstance(self.register_dialog, ga_Gtk.VBox):
-                self.register_dialog.set_title(_("Subscription Attachment"))
-            self.progress_label.set_markup(_("<b>Attaching</b>"))
-
-    def _set_register_label(self, screen):
-        button_label = self._screens[screen].button_label
-        self.register_button.set_label(button_label)
+    def done(self):
+        self.change_screen(DONE_PAGE)
 
-    def _delete_event(self, event, data=None):
-        return self.close_window()
+    def clear_screens(self):
+        for screen in self._screens:
+            screen.clear()
 
-    def cancel(self, button):
-        self.close_window()
+    def _timeout_callback(self):
+        """Callback used to drive the progress bar 'pulse'."""
+        self.register_progressbar.pulse()
+        # return true to keep it pulsing
+        return True
 
-    # callback needs the extra arg, so just a wrapper here
-    def _on_register_button_clicked(self, button):
-        self.register()
 
-    def register(self):
+class RegisterDialog(widgets.SubmanBaseWidget):
 
-        result = self._screens[self._current_screen].apply()
+    widget_names = ['register_dialog', 'register_dialog_main_vbox',
+                    'register_details_label',
+                    'cancel_button', 'register_button', 'progress_label',
+                    'dialog_vbox6']
 
-        if result == FINISH:
-            self.finish_registration()
-            return True
-        elif result == DONT_CHANGE:
-            return False
+    gui_file = "register_dialog"
+    __gtype_name__ = 'RegisterDialog'
 
-        self._screens[self._current_screen].post()
+    def __init__(self, backend, facts=None, callbacks=None):
+        """
+        Callbacks will be executed when registration status changes.
+        """
+        super(RegisterDialog, self).__init__()
 
-        self._run_pre(result)
-        return False
+        # dialog
+        callbacks = {"on_register_cancel_button_clicked": self.cancel,
+                     "on_register_button_clicked": self._on_register_button_clicked,
+                     "hide": self.cancel,
+                     "on_register_dialog_delete_event": self.cancel}
+        self.connect_signals(callbacks)
 
-    def _run_pre(self, screen):
-        # XXX move this into the button handling somehow?
-        if screen == FINISH:
-            self.finish_registration()
-            return
+        self.reg_info = RegisterInfo()
+        # FIXME: Need better error handling in general, but it's kind of
+        # annoying to have to pass the top level widget all over the place
+        self.register_widget = RegisterWidget(backend, facts,
+                                              reg_info=self.reg_info,
+                                              parent_window=self.register_dialog)
 
-        self._set_screen(screen)
-        async = self._screens[self._current_screen].pre()
-        if async:
-            self._set_navigation_sensitive(False)
-            self._set_screen(PROGRESS_PAGE)
-            self._set_register_details_label(
-                    self._screens[self._current_screen].pre_message)
+        # Ensure that we start on the first page and that
+        # all widgets are cleared.
+        self.register_widget.initialize()
 
-    def _timeout_callback(self):
-        self.register_progressbar.pulse()
-        # return true to keep it pulsing
-        return True
+        self.register_dialog_main_vbox.pack_start(self.register_widget.register_widget,
+                                                  True, True, 0)
 
-    def finish_registration(self, failed=False):
-        # failed is used by the firstboot subclasses to decide if they should
-        # advance the screen or not.
-        # XXX it would be cool here to do some async spinning while the
-        # main window gui refreshes itself
+        self.register_button.connect('clicked', self._on_register_button_clicked)
+        self.cancel_button.connect('clicked', self.cancel)
 
-        if failed:
-            self.goto_error_screen()
-            return
+        # initial-setup will likely handle these itself
+        self.register_widget.connect('finished', self.cancel)
+        self.register_widget.connect('register-error', self.on_register_error)
 
-        # FIXME: subman-gui needs this but initial-setup doesnt
-        self.close_window_callback()
+        # update window title on register state changes
+        self.register_widget.info.connect('notify::register-state',
+                                           self._on_register_state_change)
 
-        self.emit_consumer_signal()
+        # update the 'next/register button on page change'
+        self.register_widget.connect('notify::register-button-label',
+                                     self._on_register_button_label_change)
 
-        ga_GObject.source_remove(self.timer)
+        self.window = self.register_dialog
 
-    def emit_consumer_signal(self):
-        for method in self.callbacks:
-            method()
+        # FIXME: needed by firstboot
+        self.password = None
 
-    def done(self):
-        self._set_screen(DONE_PAGE)
+    def initialize(self):
+        self.register_widget.clear_screens()
+        # self.register_widget.initialize()
 
-    def close_window(self):
-        if self.close_window_callback:
-            self.close_window_callback()
+    def show(self):
+        # initial-setup module skips this, since it results in a
+        # new top level window that isn't reparented to the initial-setup
+        # screen.
+        self.register_dialog.show()
 
-    def _close_window_callback(self):
-        set_state(REGISTERING)
+    def cancel(self, button):
         self.register_dialog.hide()
         return True
 
-    def _set_register_details_label(self, details):
-        self.register_details_label.set_label("<small>%s</small>" % details)
+    def on_register_error(self, obj, msg, exc_list):
+        # TODO: we can add the register state, error type (error or exc)
+        if exc_list:
+            self.handle_register_exception(obj, msg, exc_list)
+        else:
+            self.handle_register_error(obj, msg)
+        return True
 
-    def _clear_registration_widgets(self):
-        for screen in self._screens:
-            screen.clear()
+    def handle_register_error(self, obj, msg):
+        log.error("registration error: %s", msg)
+        self.error_dialog(obj, msg)
 
-    def pre_done(self, next_screen):
-        self._set_navigation_sensitive(True)
-        if next_screen == DONT_CHANGE:
-            self._set_screen(self._current_screen)
-        else:
-            self._screens[self._current_screen].post()
-            self._run_pre(next_screen)
+        # RegisterWidget.do_register_error() will take care of changing screens
+
+    def handle_register_exception(self, obj, msg, exc_info):
+        # format_exception ends up logging the exception as well
+        message = format_exception(exc_info, msg)
+        self.error_dialog(obj, message)
 
+    def error_dialog(self, obj, msg):
+        show_error_window(msg)
 
-class AutobindWizard(RegisterScreen):
+    def _on_register_button_clicked(self, button):
+        self.register_widget.emit('proceed')
 
-    def __init__(self, backend, facts, parent):
-        super(AutobindWizard, self).__init__(backend, facts, parent)
+    def _on_register_state_change(self, obj, value):
+        state = obj.get_property('register-state')
+        if state == REGISTERING:
+            self.register_dialog.set_title(_("System Registration"))
+        elif state == SUBSCRIBING:
+            self.register_dialog.set_title(_("Subscription Attachment"))
 
-    def show(self):
-        super(AutobindWizard, self).show()
-        self._run_pre(SELECT_SLA_PAGE)
+    def _on_register_button_label_change(self, obj, value):
+        register_label = obj.get_property('register-button-label')
+        # FIXME: button_label can be None for NonGuiScreens. Seems like
+        #
+        if register_label:
+            self.register_button.set_label(register_label)
 
-    def _get_initial_screen(self):
-        return SELECT_SLA_PAGE
 
+class AutobindWizardDialog(RegisterDialog):
+    __gtype_name__ = "AutobindWizard"
+
+    initial_screen = SELECT_SLA_PAGE
+
+    def __init__(self, backend, facts):
+        super(AutobindWizardDialog, self).__init__(backend, facts)
+
+    def show(self):
+        super(AutobindWizardDialog, self).show()
+        self.register_widget.change_screen(SELECT_SLA_PAGE)
 
+
+# TODO: Screen could be a container widget, that has the rest of the gui as
+#       a child. That way, we could add the Screen class to the
+#       register_notebook directly, and follow up to the parent the normal
+#       way. Then we could stop passing 'parent' around. And RegisterInfo
+#       could be on the parent register_notebook. I think the various GtkDialogs
+#       for error handling (handle_gui_exception, etc) would also find it by
+#       default.
 class Screen(widgets.SubmanBaseWidget):
     widget_names = ['container']
     gui_file = None
-
-    def __init__(self, parent, backend):
+    screen_enum = None
+
+    # TODO: replace page int with class enum
+    __gsignals__ = {'stay-on-screen': (ga_GObject.SignalFlags.RUN_FIRST,
+                                 None, []),
+                    'register-finished': (ga_GObject.SignalFlags.RUN_FIRST,
+                                 None, []),
+                    'attach-finished': (ga_GObject.SignalFlags.RUN_FIRST,
+                                 None, []),
+                    'register-error': (ga_GObject.SignalFlags.RUN_FIRST,
+                              None, (ga_GObject.TYPE_PYOBJECT,
+                                     ga_GObject.TYPE_PYOBJECT)),
+                    'move-to-screen': (ga_GObject.SignalFlags.RUN_FIRST,
+                                     None, (int,))}
+
+    def __init__(self, reg_info, async_backend, facts, parent_window):
         super(Screen, self).__init__()
 
         self.pre_message = ""
         self.button_label = _("Register")
         self.needs_gui = True
         self.index = -1
-        self._parent = parent
-        self._backend = backend
+        # REMOVE self._error_screen = self.index
+
+        self.parent_window = parent_window
+        self.info = reg_info
+        self.async = async_backend
+        self.facts = facts
+
+    def stay(self):
+        self.emit('stay-on-screen')
 
     def pre(self):
         return False
 
+    # do whatever the screen indicates, and emit any signals indicating where
+    # to move to next. apply() should not return anything.
     def apply(self):
         pass
 
@@ -514,19 +666,45 @@ class Screen(widgets.SubmanBaseWidget):
         pass
 
 
-class NoGuiScreen(object):
+class NoGuiScreen(ga_GObject.GObject):
+    screen_enum = None
+
+    __gsignals__ = {'identity-updated': (ga_GObject.SignalFlags.RUN_FIRST,
+                                         None, []),
+                    'move-to-screen': (ga_GObject.SignalFlags.RUN_FIRST,
+                                       None, (int,)),
+                    'stay-on-screen': (ga_GObject.SignalFlags.RUN_FIRST,
+                                       None, []),
+                    'register-finished': (ga_GObject.SignalFlags.RUN_FIRST,
+                                 None, []),
+                    'attach-finished': (ga_GObject.SignalFlags.RUN_FIRST,
+                                 None, []),
+                    'register-error': (ga_GObject.SignalFlags.RUN_FIRST,
+                              None, (ga_GObject.TYPE_PYOBJECT,
+                                     ga_GObject.TYPE_PYOBJECT)),
+                    'certs-updated': (ga_GObject.SignalFlags.RUN_FIRST,
+                                      None, [])}
+
+    def __init__(self, reg_info, async_backend, facts, parent_window):
+        ga_GObject.GObject.__init__(self)
+
+        self.parent_window = parent_window
+        self.info = reg_info
+        self.async = async_backend
+        self.facts = facts
 
-    def __init__(self, parent, backend):
-        self._parent = parent
-        self._backend = backend
         self.button_label = None
         self.needs_gui = False
+        self.pre_message = "Default Pre Message"
+
+    # FIXME: a do_register_error could be used for logging?
+    #        Otherwise it's up to the parent dialog to do the logging.
 
     def pre(self):
         return True
 
     def apply(self):
-        return 1
+        self.emit('move-to-screen')
 
     def post(self):
         pass
@@ -536,82 +714,99 @@ class NoGuiScreen(object):
 
 
 class PerformRegisterScreen(NoGuiScreen):
+    screen_enum = PERFORM_REGISTER_PAGE
 
-    def __init__(self, parent, backend):
-        super(PerformRegisterScreen, self).__init__(parent, backend)
-        self.pre_message = _("Registering your system")
+    def __init__(self, reg_info, async_backend, facts, parent_window):
+        super(PerformRegisterScreen, self).__init__(reg_info, async_backend, facts, parent_window)
 
     def _on_registration_finished_cb(self, new_account, error=None):
         if error is not None:
-            handle_gui_exception(error, REGISTER_ERROR, self._parent.parent)
-            self._parent.finish_registration(failed=True)
+            self.emit('register-error',
+                      REGISTER_ERROR,
+                      error)
+            # TODO: register state
             return
 
         try:
             managerlib.persist_consumer_cert(new_account)
-            self._parent.backend.cs.force_cert_check()  # Ensure there isn't much wait time
-
-            if self._parent.activation_keys:
-                self._parent.pre_done(REFRESH_SUBSCRIPTIONS_PAGE)
-            elif self._parent.skip_auto_bind:
-                self._parent.pre_done(FINISH)
-            else:
-                self._parent.pre_done(SELECT_SLA_PAGE)
         except Exception, e:
-            handle_gui_exception(e, REGISTER_ERROR, self._parent.parent)
-            self._parent.finish_registration(failed=True)
+            # hint: register error, back to creds?
+            self.emit('register-error', REGISTER_ERROR, e)
+            return
+
+        # trigger a id cert reload
+        self.emit('identity-updated')
+
+        # Force all the cert dir backends to update, but mostly
+        # force the identity cert monitor to run, which will
+        # also update Backend. It also blocks until the new
+        # identity is reloaded, so we don't start the selectSLA
+        # screen before it.
+        self.async.backend.cs.force_cert_check()
+
+        # Done with the registration stuff, now on to attach
+        self.emit('register-finished')
+
+        if self.info.get_property('activation-keys'):
+            self.emit('move-to-screen', REFRESH_SUBSCRIPTIONS_PAGE)
+            return
+        elif self.info.get_property('skip-auto-bind'):
+            return
+        else:
+            self.emit('move-to-screen', SELECT_SLA_PAGE)
+            return
 
     def pre(self):
         log.info("Registering to owner: %s environment: %s" %
-                 (self._parent.owner_key, self._parent.environment))
+                 (self.info.get_property('owner-key'),
+                  self.info.get_property('environment')))
 
-        self._parent.async.register_consumer(self._parent.consumername,
-                                             self._parent.facts,
-                                             self._parent.owner_key,
-                                             self._parent.environment,
-                                             self._parent.activation_keys,
-                                             self._on_registration_finished_cb)
+        self.async.register_consumer(self.info.get_property('consumername'),
+                                     self.facts,
+                                     self.info.get_property('owner-key'),
+                                     self.info.get_property('environment'),
+                                     self.info.get_property('activation-keys'),
+                                     self._on_registration_finished_cb)
 
         return True
 
 
 class PerformSubscribeScreen(NoGuiScreen):
+    screen_enum = PERFORM_SUBSCRIBE_PAGE
 
-    def __init__(self, parent, backend):
-        super(PerformSubscribeScreen, self).__init__(parent, backend)
+    def __init__(self, reg_info, async_backend, facts, parent_window):
+        super(PerformSubscribeScreen, self).__init__(reg_info, async_backend, facts, parent_window)
         self.pre_message = _("Attaching subscriptions")
 
     def _on_subscribing_finished_cb(self, unused, error=None):
         if error is not None:
-            handle_gui_exception(error, _("Error subscribing: %s"),
-                                 self._parent.parent)
-            self._parent.finish_registration(failed=True)
+            message = _("Error subscribing: %s")
+            self.emit('register-error', message, error)
             return
 
-        self._parent.pre_done(FINISH)
-        self._parent.backend.cs.force_cert_check()
+        self.emit('certs-updated')
+        self.emit('attach-finished')
 
     def pre(self):
-        self._parent.async.subscribe(self._parent.identity.uuid,
-                                     self._parent.current_sla,
-                                     self._parent.dry_run_result,
-                                     self._on_subscribing_finished_cb)
+        self.info.set_property('details-label-txt', self.pre_message)
+        self.async.subscribe(self.info.identity.uuid,
+                             self.info.get_property('current-sla'),
+                             self.info.get_property('dry-run-result'),
+                             self._on_subscribing_finished_cb)
 
         return True
 
 
 class ConfirmSubscriptionsScreen(Screen):
     """ Confirm Subscriptions GUI Window """
-
+    screen_enum = CONFIRM_SUBS_PAGE
     widget_names = Screen.widget_names + ['subs_treeview', 'back_button',
                                           'sla_label']
 
     gui_file = "confirmsubs"
 
-    def __init__(self, parent, backend):
-
-        super(ConfirmSubscriptionsScreen, self).__init__(parent,
-                                                         backend)
+    def __init__(self, reg_info, async_backend, facts, parent_window):
+        super(ConfirmSubscriptionsScreen, self).__init__(reg_info, async_backend, facts, parent_window)
         self.button_label = _("Attach")
 
         self.store = ga_Gtk.ListStore(str, bool, str)
@@ -636,18 +831,22 @@ class ConfirmSubscriptionsScreen(Screen):
         return column
 
     def apply(self):
-        return PERFORM_SUBSCRIBE_PAGE
+        self.emit('move-to-screen', PERFORM_SUBSCRIBE_PAGE)
 
     def set_model(self):
-        self._dry_run_result = self._parent.dry_run_result
+        dry_run_result = self.info.get_property('dry-run-result')
 
         # Make sure that the store is cleared each time
         # the data is loaded into the screen.
         self.store.clear()
-        self.sla_label.set_markup("<b>" + self._dry_run_result.service_level +
+
+        if not dry_run_result:
+            return
+
+        self.sla_label.set_markup("<b>" + dry_run_result.service_level +
                                   "</b>")
 
-        for pool_quantity in self._dry_run_result.json:
+        for pool_quantity in dry_run_result.json:
             self.store.append([pool_quantity['pool']['productName'],
                               PoolWrapper(pool_quantity['pool']).is_virt_only(),
                               str(pool_quantity['quantity'])])
@@ -662,19 +861,18 @@ class SelectSLAScreen(Screen):
     An wizard screen that displays the available
     SLAs that are provided by the installed products.
     """
+    screen_enum = SELECT_SLA_PAGE
     widget_names = Screen.widget_names + ['product_list_label',
                                           'sla_radio_container',
                                           'owner_treeview']
     gui_file = "selectsla"
 
-    def __init__(self, parent, backend):
-        super(SelectSLAScreen, self).__init__(parent, backend)
+    def __init__(self, reg_info, async_backend, facts, parent_window):
+        super(SelectSLAScreen, self).__init__(reg_info, async_backend, facts, parent_window)
 
         self.pre_message = _("Finding suitable service levels")
         self.button_label = _("Next")
 
-        self._dry_run_result = None
-
     def set_model(self, unentitled_prod_certs, sla_data_map):
         self.product_list_label.set_text(
                 self._format_prods(unentitled_prod_certs))
@@ -684,7 +882,9 @@ class SelectSLAScreen(Screen):
         # of the screen.
         for sla in reversed(sla_data_map.keys()):
             radio = ga_Gtk.RadioButton(group=group, label=sla)
-            radio.connect("toggled", self._radio_clicked, sla)
+            radio.connect("toggled",
+                          self._radio_clicked,
+                          (sla, sla_data_map))
             self.sla_radio_container.pack_start(radio, expand=False,
                                                 fill=False, padding=0)
             radio.show()
@@ -694,19 +894,19 @@ class SelectSLAScreen(Screen):
         group.set_active(True)
 
     def apply(self):
-        return CONFIRM_SUBS_PAGE
-
-    def post(self):
-        self._parent.dry_run_result = self._dry_run_result
+        self.emit('move-to-screen', CONFIRM_SUBS_PAGE)
 
     def clear(self):
         child_widgets = self.sla_radio_container.get_children()
         for child in child_widgets:
             self.sla_radio_container.remove(child)
 
-    def _radio_clicked(self, button, service_level):
+    def _radio_clicked(self, button, data):
+        sla, sla_data_map = data
+
         if button.get_active():
-            self._dry_run_result = self._sla_data_map[service_level]
+            self.info.set_property('dry-run-result',
+                                           sla_data_map[sla])
 
     def _format_prods(self, prod_certs):
         prod_str = ""
@@ -718,71 +918,89 @@ class SelectSLAScreen(Screen):
         return prod_str
 
     # so much for service level simplifying things
+    # FIXME: this could be split into 'on_get_all_service_levels_cb' and
+    #        and 'on_get_service_levels_cb'
     def _on_get_service_levels_cb(self, result, error=None):
-        # The parent for the dialogs is set to the grandparent window
-        # (which is MainWindow) because the parent window is closed
-        # by finish_registration() after displaying the dialogs.  See
-        # BZ #855762.
         if error is not None:
             if isinstance(error[1], ServiceLevelNotSupportedException):
-                OkDialog(_("Unable to auto-attach, server does not support service levels."),
-                        parent=self._parent.parent)
+                msg = _("Unable to auto-attach, server does not support service levels.")
+                self.emit('register-error', msg, None)
+                # HMM: if we make the ok a register-error as well, we may get
+                # wacky ordering if the register-error is followed immed by a
+                # register-finished?
+                self.emit('attach-finished')
+                return
             elif isinstance(error[1], NoProductsException):
-                InfoDialog(_("No installed products on system. No need to attach subscriptions at this time."),
-                           parent=self._parent.parent)
+                msg = _("No installed products on system. No need to attach subscriptions at this time.")
+                self.emit('register-error', msg, None)
+                self.emit('attach-finished')
+                return
             elif isinstance(error[1], AllProductsCoveredException):
-                InfoDialog(_("All installed products are covered by valid entitlements. No need to attach subscriptions at this time."),
-                           parent=self._parent.parent)
+                msg = _("All installed products are covered by valid entitlements. "
+                        "No need to attach subscriptions at this time.")
+                self.emit('register-error', msg, None)
+                self.emit('attach-finished')
+                return
             elif isinstance(error[1], GoneException):
-                InfoDialog(_("Consumer has been deleted."), parent=self._parent.parent)
+                # FIXME: shoudl we log here about deleted consumer or
+                #        did we do that when we created GoneException?
+                msg = _("Consumer has been deleted.")
+                self.emit('register-error', msg, None)
+                return
+                # TODO: where we should go from here?
             else:
                 log.exception(error)
-                handle_gui_exception(error, _("Error subscribing"),
-                                     self._parent.parent)
-            self._parent.finish_registration(failed=True)
-            return
+                self.emit('register-error',
+                          _("Error subscribing"),
+                          error)
+                return
 
         (current_sla, unentitled_products, sla_data_map) = result
 
-        self._parent.current_sla = current_sla
+        self.info.set_property('current-sla', current_sla)
+
         if len(sla_data_map) == 1:
             # If system already had a service level, we can hit this point
             # when we cannot fix any unentitled products:
             if current_sla is not None and \
                     not self._can_add_more_subs(current_sla, sla_data_map):
-                handle_gui_exception(None,
-                                     _("No available subscriptions at "
-                                     "the current service level: %s. "
-                                     "Please use the \"All Available "
-                                     "Subscriptions\" tab to manually "
-                                     "attach subscriptions.") % current_sla,
-                                    self._parent.parent)
-                self._parent.finish_registration(failed=True)
+                msg = _("No available subscriptions at "
+                        "the current service level: %s. "
+                        "Please use the \"All Available "
+                        "Subscriptions\" tab to manually "
+                        "attach subscriptions.") % current_sla
+                # TODO: add 'attach' state
+                self.emit('register-error', msg, None)
+                self.emit('attach-finished')
                 return
 
-            self._dry_run_result = sla_data_map.values()[0]
-            self._parent.pre_done(CONFIRM_SUBS_PAGE)
+            self.info.set_property('dry-run-result',
+                                           sla_data_map.values()[0])
+            self.emit('move-to-screen', CONFIRM_SUBS_PAGE)
+            return
         elif len(sla_data_map) > 1:
-            self._sla_data_map = sla_data_map
             self.set_model(unentitled_products, sla_data_map)
-            self._parent.pre_done(DONT_CHANGE)
+            self.stay()
+            return
         else:
             log.info("No suitable service levels found.")
-            handle_gui_exception(None,
-                                 _("No service level will cover all "
-                                 "installed products. Please manually "
-                                 "subscribe using multiple service levels "
-                                 "via the \"All Available Subscriptions\" "
-                                 "tab or purchase additional subscriptions."),
-                                 parent=self._parent.parent)
-            self._parent.finish_registration(failed=True)
+            msg = _("No service level will cover all "
+                    "installed products. Please manually "
+                    "subscribe using multiple service levels "
+                    "via the \"All Available Subscriptions\" "
+                    "tab or purchase additional subscriptions.")
+            # TODO: add 'registering/attaching' state info
+            self.emit('register-error', msg, None)
+            self.emit('attach-finished')
 
     def pre(self):
-        set_state(SUBSCRIBING)
-        self._parent.identity.reload()
-        self._parent.async.find_service_levels(self._parent.identity.uuid,
-                                               self._parent.facts,
-                                               self._on_get_service_levels_cb)
+        self.info.set_property('details-label-txt', self.pre_message)
+        self.info.set_property('register-state', SUBSCRIBING)
+        self.info.identity.reload()
+
+        self.async.find_service_levels(self.info.identity.uuid,
+                                       self.facts,
+                                       self._on_get_service_levels_cb)
         return True
 
     def _can_add_more_subs(self, current_sla, sla_data_map):
@@ -800,8 +1018,8 @@ class EnvironmentScreen(Screen):
     widget_names = Screen.widget_names + ['environment_treeview']
     gui_file = "environment"
 
-    def __init__(self, parent, backend):
-        super(EnvironmentScreen, self).__init__(parent, backend)
+    def __init__(self, reg_info, async_backend, facts, parent_window):
+        super(EnvironmentScreen, self).__init__(reg_info, async_backend, facts, parent_window)
 
         self.pre_message = _("Fetching list of possible environments")
         renderer = ga_Gtk.CellRendererText()
@@ -812,35 +1030,39 @@ class EnvironmentScreen(Screen):
     def _on_get_environment_list_cb(self, result_tuple, error=None):
         environments = result_tuple
         if error is not None:
-            handle_gui_exception(error, REGISTER_ERROR, self._parent.parent)
-            self._parent.finish_registration(failed=True)
+            # TODO: registering state
+            self.emit('register-error', REGISTER_ERROR, error)
             return
 
         if not environments:
-            self._environment = None
-            self._parent.pre_done(PERFORM_REGISTER_PAGE)
+            self.set_environment(None)
+            self.emit('move-to-screen', PERFORM_REGISTER_PAGE)
             return
 
         envs = [(env['id'], env['name']) for env in environments]
         if len(envs) == 1:
-            self._environment = envs[0][0]
-            self._parent.pre_done(PERFORM_REGISTER_PAGE)
+            self.set_environement(envs[0][0])
+            self.emit('move-to-screen', PERFORM_REGISTER_PAGE)
+            return
+
         else:
             self.set_model(envs)
-            self._parent.pre_done(DONT_CHANGE)
+            self.stay()
+            return
 
     def pre(self):
-        self._parent.async.get_environment_list(self._parent.owner_key,
-                                                self._on_get_environment_list_cb)
+        self.info.set_property('details-label-txt', self.pre_message)
+        self.async.get_environment_list(self.info.get_property('owner-key'),
+                                        self._on_get_environment_list_cb)
         return True
 
     def apply(self):
         model, tree_iter = self.environment_treeview.get_selection().get_selected()
-        self._environment = model.get_value(tree_iter, 0)
-        return PERFORM_REGISTER_PAGE
+        self.set_environment(model.get_value(tree_iter, 0))
+        self.emit('move-to-screen', PERFORM_REGISTER_PAGE)
 
-    def post(self):
-        self._parent.environment = self._environment
+    def set_environment(self, environment):
+        self.info.set_property('environment', environment)
 
     def set_model(self, envs):
         environment_model = ga_Gtk.ListStore(str, str)
@@ -857,8 +1079,8 @@ class OrganizationScreen(Screen):
     widget_names = Screen.widget_names + ['owner_treeview']
     gui_file = "organization"
 
-    def __init__(self, parent, backend):
-        super(OrganizationScreen, self).__init__(parent, backend)
+    def __init__(self, reg_info, async_backend, facts, parent_window):
+        super(OrganizationScreen, self).__init__(reg_info, async_backend, facts, parent_window)
 
         self.pre_message = _("Fetching list of possible organizations")
 
@@ -867,13 +1089,9 @@ class OrganizationScreen(Screen):
         self.owner_treeview.set_property("headers-visible", False)
         self.owner_treeview.append_column(column)
 
-        self._owner_key = None
-
     def _on_get_owner_list_cb(self, owners, error=None):
         if error is not None:
-            handle_gui_exception(error, REGISTER_ERROR,
-                    self._parent.window)
-            self._parent.finish_registration(failed=True)
+            self.emit('register-error', REGISTER_ERROR, error)
             return
 
         owners = [(owner['key'], owner['displayName']) for owner in owners]
@@ -881,32 +1099,35 @@ class OrganizationScreen(Screen):
         owners = sorted(owners, key=lambda item: item[1])
 
         if len(owners) == 0:
-            handle_gui_exception(None,
-                                 _("<b>User %s is not able to register with any orgs.</b>") %
-                                   (self._parent.username),
-                    self._parent.parent)
-            self._parent.finish_registration(failed=True)
+            msg = _("<b>User %s is not able to register with any orgs.</b>") % \
+                    self.info.get_property('username')
+            self.emit('register-error', msg, None)
             return
 
         if len(owners) == 1:
-            self._owner_key = owners[0][0]
-            self._parent.pre_done(ENVIRONMENT_SELECT_PAGE)
+            owner_key = owners[0][0]
+            self.info.set_property('owner-key', owner_key)
+            # only one org, use it and skip the org selection screen
+            self.emit('move-to-screen', ENVIRONMENT_SELECT_PAGE)
+            return
+
         else:
             self.set_model(owners)
-            self._parent.pre_done(DONT_CHANGE)
+            self.stay()
+            return
 
     def pre(self):
-        self._parent.async.get_owner_list(self._parent.username,
-                                          self._on_get_owner_list_cb)
+        self.info.set_property('details-label-txt', self.pre_message)
+        self.async.get_owner_list(self.info.get_property('username'),
+                                  self._on_get_owner_list_cb)
         return True
 
     def apply(self):
+        # check for selection exists
         model, tree_iter = self.owner_treeview.get_selection().get_selected()
-        self._owner_key = model.get_value(tree_iter, 0)
-        return ENVIRONMENT_SELECT_PAGE
-
-    def post(self):
-        self._parent.owner_key = self._owner_key
+        owner_key = model.get_value(tree_iter, 0)
+        self.info.set_property('owner-key', owner_key)
+        self.emit('move-to-screen', ENVIRONMENT_SELECT_PAGE)
 
     def set_model(self, owners):
         owner_model = ga_Gtk.ListStore(str, str)
@@ -927,11 +1148,10 @@ class CredentialsScreen(Screen):
 
     gui_file = "credentials"
 
-    def __init__(self, parent, backend):
-        super(CredentialsScreen, self).__init__(parent, backend)
+    def __init__(self, reg_info, async_backend, facts, parent_window):
+        super(CredentialsScreen, self).__init__(reg_info, async_backend, facts, parent_window)
 
         self._initialize_consumer_name()
-
         self.registration_tip_label.set_label("<small>%s</small>" %
                                           get_branding().GUI_FORGOT_LOGIN_TIP)
 
@@ -944,7 +1164,11 @@ class CredentialsScreen(Screen):
 
     def _validate_consumername(self, consumername):
         if not consumername:
-            show_error_window(_("You must enter a system name."), self._parent.window)
+            # TODO: register state to signal
+            self.emit('register-error',
+                      _("You must enter a system name."),
+                      None)
+
             self.consumer_name.grab_focus()
             return False
         return True
@@ -952,42 +1176,46 @@ class CredentialsScreen(Screen):
     def _validate_account(self):
         # validate / check user name
         if self.account_login.get_text().strip() == "":
-            show_error_window(_("You must enter a login."), self._parent.window)
+            self.emit('register-error',
+                      _("You must enter a login."),
+                      None)
+
             self.account_login.grab_focus()
             return False
 
         if self.account_password.get_text().strip() == "":
-            show_error_window(_("You must enter a password."), self._parent.window)
+            self.emit('register-error',
+                      _("You must enter a password."),
+                      None)
+
             self.account_password.grab_focus()
             return False
         return True
 
     def pre(self):
+        self.info.set_property('details-label-txt', self.pre_message)
         self.account_login.grab_focus()
         return False
 
     def apply(self):
-        self._username = self.account_login.get_text().strip()
-        self._password = self.account_password.get_text().strip()
-        self._consumername = self.consumer_name.get_text()
-        self._skip_auto_bind = self.skip_auto_bind.get_active()
+        self.stay()
+        username = self.account_login.get_text().strip()
+        password = self.account_password.get_text().strip()
+        consumername = self.consumer_name.get_text()
+        skip_auto_bind = self.skip_auto_bind.get_active()
 
-        if not self._validate_consumername(self._consumername):
-            return DONT_CHANGE
+        if not self._validate_consumername(consumername):
+            return
 
         if not self._validate_account():
-            return DONT_CHANGE
+            return
 
-        self._backend.cp_provider.set_user_pass(self._username, self._password)
+        self.info.set_property('username', username)
+        self.info.set_property('password', password)
+        self.info.set_property('skip-auto-bind', skip_auto_bind)
+        self.info.set_property('consumername', consumername)
 
-        return OWNER_SELECT_PAGE
-
-    def post(self):
-        self._parent.username = self._username
-        self._parent.password = self._password
-        self._parent.consumername = self._consumername
-        self._parent.skip_auto_bind = self._skip_auto_bind
-        self._parent.activation_keys = None
+        self.emit('move-to-screen', OWNER_SELECT_PAGE)
 
     def clear(self):
         self.account_login.set_text("")
@@ -1005,8 +1233,8 @@ class ActivationKeyScreen(Screen):
         ]
     gui_file = "activation_key"
 
-    def __init__(self, parent, backend):
-        super(ActivationKeyScreen, self).__init__(parent, backend)
+    def __init__(self, reg_info, async_backend, facts, parent_window):
+        super(ActivationKeyScreen, self).__init__(reg_info, async_backend, facts, parent_window)
         self._initialize_consumer_name()
 
     def _initialize_consumer_name(self):
@@ -1014,21 +1242,26 @@ class ActivationKeyScreen(Screen):
             self.consumer_entry.set_text(socket.gethostname())
 
     def apply(self):
-        self._activation_keys = self._split_activation_keys(
+        self.stay()
+        activation_keys = self._split_activation_keys(
             self.activation_key_entry.get_text().strip())
-        self._owner_key = self.organization_entry.get_text().strip()
-        self._consumername = self.consumer_entry.get_text().strip()
+        owner_key = self.organization_entry.get_text().strip()
+        consumername = self.consumer_entry.get_text().strip()
+
+        if not self._validate_owner_key(owner_key):
+            return
 
-        if not self._validate_owner_key(self._owner_key):
-            return DONT_CHANGE
+        if not self._validate_activation_keys(activation_keys):
+            return
 
-        if not self._validate_activation_keys(self._activation_keys):
-            return DONT_CHANGE
+        if not self._validate_consumername(consumername):
+            return
 
-        if not self._validate_consumername(self._consumername):
-            return DONT_CHANGE
+        self.info.set_property('consumername', consumername)
+        self.info.set_property('owner-key', owner_key)
+        self.info.set_property('activation-keys', activation_keys)
 
-        return PERFORM_REGISTER_PAGE
+        self.emit('move-to-screen', PERFORM_REGISTER_PAGE)
 
     def _split_activation_keys(self, entry):
         keys = re.split(',\s*|\s+', entry)
@@ -1036,56 +1269,59 @@ class ActivationKeyScreen(Screen):
 
     def _validate_owner_key(self, owner_key):
         if not owner_key:
-            show_error_window(_("You must enter an organization."), self._parent.window)
+            self.emit('register-error',
+                      _("You must enter an organization."),
+                      None)
+
             self.organization_entry.grab_focus()
             return False
         return True
 
     def _validate_activation_keys(self, activation_keys):
         if not activation_keys:
-            show_error_window(_("You must enter an activation key."), self._parent.window)
+            self.emit('register-error',
+                      _("You must enter an activation key."),
+                      None)
+
             self.activation_key_entry.grab_focus()
             return False
         return True
 
     def _validate_consumername(self, consumername):
         if not consumername:
-            show_error_window(_("You must enter a system name."), self._parent.window)
+            self.emit('register-error',
+                      _("You must enter a system name."),
+                      None)
+
             self.consumer_entry.grab_focus()
             return False
         return True
 
     def pre(self):
+        self.info.set_property('details-label-txt', self.pre_message)
         self.organization_entry.grab_focus()
         return False
 
-    def post(self):
-        self._parent.activation_keys = self._activation_keys
-        self._parent.owner_key = self._owner_key
-        self._parent.consumername = self._consumername
-        # Environments aren't used with activation keys so clear any
-        # cached value.
-        self._parent.environment = None
-        self._backend.cp_provider.set_user_pass()
-
 
 class RefreshSubscriptionsScreen(NoGuiScreen):
 
-    def __init__(self, parent, backend):
-        super(RefreshSubscriptionsScreen, self).__init__(parent, backend)
+    def __init__(self, reg_info, async_backend, facts, parent_window):
+        super(RefreshSubscriptionsScreen, self).__init__(reg_info, async_backend, facts, parent_window)
         self.pre_message = _("Attaching subscriptions")
 
     def _on_refresh_cb(self, error=None):
         if error is not None:
-            handle_gui_exception(error, _("Error subscribing: %s"),
-                                 self._parent.parent)
-            self._parent.finish_registration(failed=True)
+            self.emit('register-error',
+                      _("Error subscribing: %s"),
+                      error)
+            # TODO: register state
             return
 
-        self._parent.pre_done(FINISH)
+        self.emit('attach-finished')
 
     def pre(self):
-        self._parent.async.refresh(self._on_refresh_cb)
+        self.info.set_property('details-label-txt', self.pre_message)
+        self.async.refresh(self._on_refresh_cb)
         return True
 
 
@@ -1095,16 +1331,14 @@ class ChooseServerScreen(Screen):
                                           'activation_key_checkbox']
     gui_file = "choose_server"
 
-    def __init__(self, parent, backend):
-
-        super(ChooseServerScreen, self).__init__(parent, backend)
+    def __init__(self, reg_info, async_backend, facts, parent_window):
+        super(ChooseServerScreen, self).__init__(reg_info, async_backend, facts, parent_window)
 
         self.button_label = _("Next")
 
         callbacks = {
                 "on_default_button_clicked": self._on_default_button_clicked,
                 "on_proxy_button_clicked": self._on_proxy_button_clicked,
-                "on_server_entry_changed": self._on_server_entry_changed,
             }
 
         self.connect_signals(callbacks)
@@ -1121,29 +1355,8 @@ class ChooseServerScreen(Screen):
         # bump the resolver as well.
         self.reset_resolver()
 
-        self.network_config_dialog.set_parent_window(self._parent.window)
         self.network_config_dialog.show()
 
-    def _on_server_entry_changed(self, widget):
-        """
-        Disable the activation key checkbox if the user is registering
-        to hosted.
-        """
-        server = self.server_entry.get_text()
-        try:
-            (hostname, port, prefix) = parse_server_info(server)
-            if re.search('subscription\.rhn\.(.*\.)*redhat\.com', hostname):
-                sensitive = False
-                self.activation_key_checkbox.set_active(False)
-            else:
-                sensitive = True
-            self.activation_key_checkbox.set_sensitive(sensitive)
-        except ServerUrlParseError:
-            # This may seem like it should be False, but we don't want
-            # the checkbox blinking on and off as the user types a value
-            # that is first unparseable and then later parseable.
-            self.activation_key_checkbox.set_sensitive(True)
-
     def reset_resolver(self):
         try:
             reset_resolver()
@@ -1151,7 +1364,11 @@ class ChooseServerScreen(Screen):
             log.warn("Error from reset_resolver: %s", e)
 
     def apply(self):
+        self.stay()
         server = self.server_entry.get_text()
+
+        # TODO: test the values before saving, then update
+        #       self.info and cfg if it works
         try:
             (hostname, port, prefix) = parse_server_info(server)
             CFG.set('server', 'hostname', hostname)
@@ -1162,27 +1379,38 @@ class ChooseServerScreen(Screen):
 
             try:
                 if not is_valid_server_info(hostname, port, prefix):
-                    show_error_window(_("Unable to reach the server at %s:%s%s") %
-                                      (hostname, port, prefix),
-                                      self._parent.window)
-                    return self._parent.error_screen
+                    self.emit('register-error',
+                              _("Unable to reach the server at %s:%s%s") %
+                                (hostname, port, prefix),
+                              None)
+                    return
             except MissingCaCertException:
-                show_error_window(_("CA certificate for subscription service has not been installed."),
-                                  self._parent.window)
-                return self._parent.error_screen
+                self.emit('register-error',
+                          _("CA certificate for subscription service has not been installed."),
+                          None)
+                return
 
         except ServerUrlParseError:
-            show_error_window(_("Please provide a hostname with optional port and/or prefix: hostname[:port][/prefix]"),
-                              self._parent.window)
-            return self._parent.error_screen
+            self.emit('register-error',
+                      _("Please provide a hostname with optional port and/or prefix: "
+                        "hostname[:port][/prefix]"),
+                      None)
+            return
 
         log.debug("Writing server data to rhsm.conf")
         CFG.save()
-        self._backend.update()
+
+        self.info.set_property('hostname', hostname)
+        self.info.set_property('port', port)
+        self.info.set_property('prefix', prefix)
+
         if self.activation_key_checkbox.get_active():
-            return ACTIVATION_KEY_PAGE
+            self.emit('move-to-screen', ACTIVATION_KEY_PAGE)
+            return
+
         else:
-            return CREDENTIALS_PAGE
+            self.emit('move-to-screen', CREDENTIALS_PAGE)
+            return
 
     def clear(self):
         # Load the current server values from rhsm.conf:
@@ -1205,6 +1433,28 @@ class AsyncBackend(object):
         self.plugin_manager = require(PLUGIN_MANAGER)
         self.queue = Queue.Queue()
 
+    def update(self):
+        self.backend.update()
+
+    def set_user_pass(self, username, password):
+        self.backend.cp_provider.set_user_pass(username, password)
+        self.backend.update()
+
+    def _watch_thread(self):
+        """
+        glib idle method to watch for thread completion.
+        runs the provided callback method in the main thread.
+        """
+        try:
+            (callback, retval, error) = self.queue.get(block=False)
+            if error:
+                callback(retval, error=error)
+            else:
+                callback(retval)
+            return False
+        except Queue.Empty:
+            return True
+
     def _get_owner_list(self, username, callback):
         """
         method run in the worker thread.
@@ -1243,14 +1493,20 @@ class AsyncBackend(object):
         try:
             installed_mgr = require(INSTALLED_PRODUCTS_MANAGER)
 
+            # TODO: not sure why we pass in a facts.Facts, and call it's
+            #       get_facts() three times. The two bracketing plugin calls
+            #       are meant to be able to enhance/tweak facts
             self.plugin_manager.run("pre_register_consumer", name=name,
-                facts=facts.get_facts())
-            retval = self.backend.cp_provider.get_basic_auth_cp().registerConsumer(name=name,
-                    facts=facts.get_facts(), owner=owner, environment=env,
-                    keys=activation_keys,
-                    installed_products=installed_mgr.format_for_server())
+                                    facts=facts.get_facts())
+
+            cp = self.backend.cp_provider.get_basic_auth_cp()
+            retval = cp.registerConsumer(name=name, facts=facts.get_facts(),
+                                         owner=owner, environment=env,
+                                         keys=activation_keys,
+                                          installed_products=installed_mgr.format_for_server())
+
             self.plugin_manager.run("post_register_consumer", consumer=retval,
-                facts=facts.get_facts())
+                                    facts=facts.get_facts())
 
             require(IDENTITY).reload()
             # Facts and installed products went out with the registration
@@ -1288,6 +1544,7 @@ class AsyncBackend(object):
         try:
             if not current_sla:
                 log.debug("Saving selected service level for this system.")
+
                 self.backend.cp_provider.get_consumer_auth_cp().updateConsumer(uuid,
                         service_level=dry_run_result.service_level)
 
@@ -1301,10 +1558,12 @@ class AsyncBackend(object):
                                         pool_id=pool_id, quantity=quantity)
                 ents = self.backend.cp_provider.get_consumer_auth_cp().bindByEntitlementPool(uuid, pool_id, quantity)
                 self.plugin_manager.run("post_subscribe", consumer_uuid=uuid, entitlement_data=ents)
+            # FIXME: this should be a different asyncBackend task
             managerlib.fetch_certificates(self.backend.certlib)
         except Exception:
             # Going to try to update certificates just in case we errored out
             # mid-way through a bunch of binds:
+            # FIXME: emit update-ent-certs signal
             try:
                 managerlib.fetch_certificates(self.backend.certlib)
             except Exception, cert_update_ex:
@@ -1316,6 +1575,16 @@ class AsyncBackend(object):
 
     # This guy is really ugly to run in a thread, can we run it
     # in the main thread with just the network stuff threaded?
+
+    # get_consumer
+    # get_service_level_list
+    # update_consumer
+    #  action_client
+    #    update_installed_products
+    #    update_facts
+    #    update_other_action_client_stuff
+    # for sla in available_slas:
+    #   get_dry_run_bind for sla
     def _find_suitable_service_levels(self, consumer_uuid, facts):
 
         # FIXME:
@@ -1356,7 +1625,14 @@ class AsyncBackend(object):
         action_client.update()
 
         for sla in available_slas:
+
+            # TODO: what kind of madness would happen if we did a couple of
+            # these in parallel in seperate threads?
             dry_run_json = self.backend.cp_provider.get_consumer_auth_cp().dryRunBind(consumer_uuid, sla)
+
+            # FIXME: are we modifying cert_sorter (self.backend.cs) state here?
+            # FIXME: it's only to get the unentitled products list, can pass
+            #        that in
             dry_run = DryRunResult(sla, dry_run_json, self.backend.cs)
 
             # If we have a current SLA for this system, we do not need
@@ -1364,6 +1640,8 @@ class AsyncBackend(object):
             # this wizard:
             if current_sla or dry_run.covers_required_products():
                 suitable_slas[sla] = dry_run
+
+        # why do we call cert_sorter stuff in the return?
         return (current_sla, self.backend.cs.unentitled_products.values(), suitable_slas)
 
     def _find_service_levels(self, consumer_uuid, facts, callback):
@@ -1383,21 +1661,6 @@ class AsyncBackend(object):
         except Exception:
             self.queue.put((callback, None, sys.exc_info()))
 
-    def _watch_thread(self):
-        """
-        glib idle method to watch for thread completion.
-        runs the provided callback method in the main thread.
-        """
-        try:
-            (callback, retval, error) = self.queue.get(block=False)
-            if error:
-                callback(retval, error=error)
-            else:
-                callback(retval)
-            return False
-        except Queue.Empty:
-            return True
-
     def get_owner_list(self, username, callback):
         ga_GObject.idle_add(self._watch_thread)
         threading.Thread(target=self._get_owner_list,
@@ -1440,11 +1703,12 @@ class AsyncBackend(object):
                          args=(callback,)).start()
 
 
+# TODO: make this a more informative 'summary' page.
 class DoneScreen(Screen):
     gui_file = "done_box"
 
-    def __init__(self, parent, backend):
-        super(DoneScreen, self).__init__(parent, backend)
+    def __init__(self, reg_info, async_backend, facts, parent_window):
+        super(DoneScreen, self).__init__(reg_info, async_backend, facts, parent_window)
         self.pre_message = "We are done."
 
 
@@ -1463,32 +1727,30 @@ class InfoScreen(Screen):
         ]
     gui_file = "registration_info"
 
-    def __init__(self, parent, backend):
-        super(InfoScreen, self).__init__(parent, backend)
+    def __init__(self, reg_info, async_backend, facts, parent_window):
+        super(InfoScreen, self).__init__(reg_info, async_backend, facts, parent_window)
         self.button_label = _("Next")
-        callbacks = {
-                "on_why_register_button_clicked":
-                    self._on_why_register_button_clicked,
-                "on_back_to_reg_button_clicked":
-                    self._on_back_to_reg_button_clicked
-            }
+        callbacks = {"on_why_register_button_clicked":
+                     self._on_why_register_button_clicked,
+                     "on_back_to_reg_button_clicked":
+                     self._on_back_to_reg_button_clicked
+                     }
 
-        # FIXME: self.conntect_signals to wrap self.gui.connect_signals
         self.connect_signals(callbacks)
 
     def pre(self):
         return False
 
     def apply(self):
+        self.stay()
         if self.register_radio.get_active():
             log.debug("Proceeding with registration.")
-            return CHOOSE_SERVER_PAGE
+            self.emit('move-to-screen', CHOOSE_SERVER_PAGE)
+            return
+
         else:
             log.debug("Skipping registration.")
-            return FINISH
-
-    def post(self):
-        pass
+            self.emit('move-to-screen', FINISH)
 
     def _on_why_register_button_clicked(self, button):
         self.why_register_dialog.show()
diff --git a/src/subscription_manager/gui/utils.py b/src/subscription_manager/gui/utils.py
index 6c77ff7..9b8a52e 100644
--- a/src/subscription_manager/gui/utils.py
+++ b/src/subscription_manager/gui/utils.py
@@ -103,6 +103,52 @@ def handle_gui_exception(e, msg, parent, format_msg=True, log_msg=None):
             show_error_window(msg, parent=parent)
 
 
+def format_mapped_message(e, msg, mapped_message, format_msg=True):
+    message = None
+    if isinstance(e, connection.RestlibException):
+        # If this exception's code is in the 200 range (such as 202 ACCEPTED)
+        # we're going to ignore the message we were given and just display
+        # the message from the server as an info dialog. (not an error)
+        if 200 < int(e.code) < 300:
+            message = linkify(mapped_message)
+        else:
+            try:
+                if format_msg:
+                    message = msg % linkify(mapped_message)
+                else:
+                    message = linkify(mapped_message)
+            except Exception:
+                message = msg
+    return message
+
+
+def format_interpolated_message(e, msg, mapped_message, format_msg=True):
+    message = None
+    #catch-all, try to interpolate and if it doesn't work out, just display the message
+    try:
+        interpolated_str = msg % e
+        message = interpolated_str
+    except Exception:
+        message = msg
+    return message
+
+
+def format_exception(e, msg, format_msg=True, log_msg=None):
+    if isinstance(e, tuple):
+        log.error(log_msg, exc_info=e)
+        # Get the class instance of the exception
+        e = e[1]
+    message = None
+    exception_mapper = ExceptionMapper()
+    mapped_message = exception_mapper.get_message(e)
+    if mapped_message:
+        message = format_mapped_message(e, msg, mapped_message, format_msg=format_msg)
+    else:
+        message = format_interpolated_message(e, msg, mapped_message, format_msg=format_msg)
+
+    return message
+
+
 def show_error_window(message, parent=None):
     messageWindow.ErrorDialog(messageWindow.wrap_text(message),
             parent)
diff --git a/src/subscription_manager/gui/widgets.py b/src/subscription_manager/gui/widgets.py
index 57d400d..c1615a2 100644
--- a/src/subscription_manager/gui/widgets.py
+++ b/src/subscription_manager/gui/widgets.py
@@ -96,7 +96,7 @@ class BuilderFileBasedWidget(FileBasedGui):
         builder_based_widget = cls()
         builder_based_widget.gui_file = builder_file
 
-        #print "ga", ga.GTK_BUILDER_FILES_DIR
+        builder_based_widget.builder.set_translation_domain('rhsm')
         builder_based_widget.gui_file_suffix = ga_gtk_compat.GTK_BUILDER_FILES_SUFFIX
         builder_based_widget.file_dir = ga_gtk_compat.GTK_BUILDER_FILES_DIR
 
@@ -126,11 +126,12 @@ class BuilderFileBasedWidget(FileBasedGui):
 
 
 # FIXME: not actually a widget, just an object that has a widget
-class SubmanBaseWidget(object):
+class SubmanBaseWidget(ga_GObject.GObject):
     widget_names = []
     gui_file = None
 
     def __init__(self):
+        ga_GObject.GObject.__init__(self)
         self.gui = self._gui_factory()
         self.pull_widgets(self.gui, self.widget_names)
         self.log = logging.getLogger('rhsm-app.' + __name__ +
diff --git a/src/subscription_manager/managercli.py b/src/subscription_manager/managercli.py
index 1b50b67..3933c30 100644
--- a/src/subscription_manager/managercli.py
+++ b/src/subscription_manager/managercli.py
@@ -305,7 +305,7 @@ class CliCommand(AbstractCLICommand):
         self.parser.add_option("--serverurl", dest="server_url",
                                default=None, help=_("server URL in the form of https://hostname:port/prefix"))
         self.parser.add_option("--insecure", action="store_true",
-                                default=False, help=_("do not check the server SSL certificate against available certificate authorities"))
+                                default=False, help=_("do not check the entitlement server SSL certificate against available certificate authorities"))
 
     def _add_proxy_options(self):
         """ Add proxy options that apply to sub-commands that require network connections. """
@@ -534,8 +534,6 @@ class UserPassCommand(CliCommand):
     @property
     def username(self):
         if not self._username:
-            print _("Registering to: %s:%s%s") % \
-                (cfg.get("server", "hostname"), cfg.get("server", "port"), cfg.get("server", "prefix"))
             (self._username, self._password) = self._get_username_and_password(
                     self.options.username, self.options.password)
         return self._username
@@ -1041,6 +1039,8 @@ class RegisterCommand(UserPassCommand):
         # Proceed with new registration:
         try:
             if not self.options.activation_keys:
+                print _("Registering to: %s:%s%s") % \
+                    (cfg.get("server", "hostname"), cfg.get("server", "port"), cfg.get("server", "prefix"))
                 self.cp_provider.set_user_pass(self.username, self.password)
                 admin_cp = self.cp_provider.get_basic_auth_cp()
             else:
diff --git a/subscription-manager.spec b/subscription-manager.spec
index 1d4b9a4..e6d4b1d 100644
--- a/subscription-manager.spec
+++ b/subscription-manager.spec
@@ -49,7 +49,7 @@
 
 Name: subscription-manager
 Version: 1.15.9
-Release: 7%{?dist}
+Release: 8%{?dist}
 Summary: Tools and libraries for subscription and repository management
 Group:   System Environment/Base
 License: GPLv2
@@ -542,6 +542,13 @@ fi
 %endif
 
 %changelog
+* Wed Sep 02 2015 Chris Rog <crog@redhat.com> 1.15.9-8
+- 884288: Better registergui for initial-setup (alikins@redhat.com)
+- Fix 'make gladelint' errors in repositories.glade (alikins@redhat.com)
+- 1254349: Move registering to message (vrjain@redhat.com)
+- 1257460: Set text domain on Gtk.Builder widgets (alikins@redhat.com)
+- 1207247: Insecure parameter needs more explanation (wpoteat@redhat.com)
+
 * Wed Aug 19 2015 Chris Rog <crog@redhat.com> 1.15.9-7
 - search-disabled-repos: ignore failed temporarily enabled repos
   (vmukhame@redhat.com)
diff --git a/test/stubs.py b/test/stubs.py
index 5704cca..36c8888 100644
--- a/test/stubs.py
+++ b/test/stubs.py
@@ -468,15 +468,9 @@ class StubBackend(object):
         self.overrides = None
         self.certlib = None
 
-    def monitor_certs(self, callback):
+    def on_cert_check_timer(self):
         pass
 
-    def monitor_identity(self, callback):
-        pass
-
-    def create_admin_uep(self, username, password):
-        return StubUEP(username, password)
-
     def update(self):
         pass
 
diff --git a/test/test_managergui.py b/test/test_managergui.py
index af78f9e..150a2f0 100644
--- a/test/test_managergui.py
+++ b/test/test_managergui.py
@@ -12,9 +12,6 @@ from subscription_manager.injection import provide, \
 class TestManagerGuiMainWindow(SubManFixture):
     def test_main_window(self):
 
-        managergui.Backend = stubs.StubBackend
-        managergui.Facts = stubs.StubFacts()
-
         provide(PROD_DIR, stubs.StubProductDirectory([]))
         provide(PRODUCT_DATE_RANGE_CALCULATOR, mock.Mock())
 
@@ -25,8 +22,11 @@ class TestManagerGuiMainWindow(SubManFixture):
 
 class TestRegisterScreen(unittest.TestCase):
     def test_register_screen(self):
-        registergui.RegisterScreen(stubs.StubBackend())
+        registergui.RegisterDialog(stubs.StubBackend())
 
     def test_register_screen_register(self):
-        rs = registergui.RegisterScreen(stubs.StubBackend())
-        rs.register()
+        rd = registergui.RegisterDialog(stubs.StubBackend())
+        #rs.initialize()
+        rd.show()
+        rd.register_dialog.hide()
+        #rs.cancel()
diff --git a/test/test_migration.py b/test/test_migration.py
index 7286b3e..019b2f9 100644
--- a/test/test_migration.py
+++ b/test/test_migration.py
@@ -26,8 +26,14 @@ from fixture import Capture, SubManFixture, temp_file
 from optparse import OptionParser
 from textwrap import dedent
 
+from nose import SkipTest
+
 from subscription_manager import injection as inj
-from subscription_manager.migrate import migrate
+try:
+    from subscription_manager.migrate import migrate
+except ImportError:
+    raise SkipTest("Couldn't import rhn modules for migration tests")
+
 from subscription_manager.certdirectory import ProductDirectory
 
 
diff --git a/test/test_registrationgui.py b/test/test_registrationgui.py
index 9610c33..9374325 100644
--- a/test/test_registrationgui.py
+++ b/test/test_registrationgui.py
@@ -4,14 +4,17 @@ from mock import Mock
 from fixture import SubManFixture
 
 from stubs import StubBackend, StubFacts
-from subscription_manager.gui.registergui import RegisterScreen, \
-        CredentialsScreen, ActivationKeyScreen, ChooseServerScreen, \
-        CREDENTIALS_PAGE, CHOOSE_SERVER_PAGE
+from subscription_manager.gui.registergui import RegisterWidget, \
+    CredentialsScreen, ActivationKeyScreen, ChooseServerScreen, \
+    CREDENTIALS_PAGE, CHOOSE_SERVER_PAGE
 
+from subscription_manager.ga import GObject as ga_GObject
+from subscription_manager.ga import Gtk as ga_Gtk
 
-class RegisterScreenTests(SubManFixture):
+
+class RegisterWidgetTests(SubManFixture):
     def setUp(self):
-        super(RegisterScreenTests, self).setUp()
+        super(RegisterWidgetTests, self).setUp()
         self.backend = StubBackend()
         expected_facts = {'fact1': 'one',
                           'fact2': 'two',
@@ -19,7 +22,7 @@ class RegisterScreenTests(SubManFixture):
                           'system.uuid': 'MOCKUUID'}
         self.facts = StubFacts(fact_dict=expected_facts)
 
-        self.rs = RegisterScreen(self.backend, self.facts)
+        self.rs = RegisterWidget(self.backend, self.facts)
 
         self.rs._screens[CHOOSE_SERVER_PAGE] = Mock()
         self.rs._screens[CHOOSE_SERVER_PAGE].index = 0
@@ -29,29 +32,77 @@ class RegisterScreenTests(SubManFixture):
 
     def test_show(self):
         self.rs.initialize()
-        self.rs.show()
 
-    def test_show_registration_returns_to_choose_server_screen(self):
-        self.rs.initialize()
-        self.rs.show()
-        self.rs.register()
-        self.assertEquals(CREDENTIALS_PAGE,
-                          self.rs.register_notebook.get_current_page() - 1)
-        self.rs.cancel(self.rs.cancel_button)
+    # FIXME: unit tests for gtk is a weird universe
+    def test_registration_error_returns_to_page(self):
         self.rs.initialize()
-        self.rs.show()
-        self.assertEquals(CHOOSE_SERVER_PAGE,
-                          self.rs.register_notebook.get_current_page())
+
+        self.correct_page = None
+
+        def error_handler(obj, msg, exc_info):
+            page_after = self.rs.register_notebook.get_current_page()
+
+            # NOTE: these exceptions are not in the nost test context,
+            #       so they don't actually fail nose
+            self.assertEquals(page_after, 0)
+            self.correct_page = True
+            self.quit()
+
+        def emit_proceed():
+            self.rs.emit('proceed')
+            return False
+
+        def emit_error():
+            self.rs.emit('register-error', 'Some register error', None)
+            return False
+
+        self.rs.connect('register-error', error_handler)
+
+        ga_GObject.timeout_add(250, self.quit)
+        ga_GObject.idle_add(emit_proceed)
+        ga_GObject.idle_add(emit_error)
+
+        # run till quit or timeout
+        # if we get to the state we want we can call quit
+        ga_Gtk.main()
+
+        # verify class scope self.correct_page got set correct in error handler
+        self.assertTrue(self.correct_page)
+
+    def quit(self):
+        ga_Gtk.main_quit()
+
+
+def mock_parent():
+    parent = Mock()
+    backend = StubBackend()
+    parent.backend = backend
+    parent.async = Mock()
+
+
+class StubReg(object):
+    def __init__(self):
+        self.parent_window = Mock()
+        self.backend = StubBackend()
+        self.async = Mock()
+        self.reg_info = Mock()
+        self.expected_facts = {'fact1': 'one',
+                               'fact2': 'two',
+                               'system': '',
+                               'system.uuid': 'MOCKUUID'}
+        self.facts = StubFacts(fact_dict=self.expected_facts)
 
 
 class CredentialsScreenTests(SubManFixture):
 
     def setUp(self):
         super(CredentialsScreenTests, self).setUp()
-        self.backend = StubBackend()
-        self.parent = Mock()
 
-        self.screen = CredentialsScreen(self.backend, self.parent)
+        stub_reg = StubReg()
+        self.screen = CredentialsScreen(reg_info=stub_reg.reg_info,
+                                        async_backend=stub_reg.async,
+                                        facts=stub_reg.facts,
+                                        parent_window=stub_reg.parent_window)
 
     def test_clear_credentials_dialog(self):
         # Pull initial value here since it will be different per machine.
@@ -71,9 +122,11 @@ class CredentialsScreenTests(SubManFixture):
 class ActivationKeyScreenTests(SubManFixture):
     def setUp(self):
         super(ActivationKeyScreenTests, self).setUp()
-        self.backend = StubBackend()
-        self.parent = Mock()
-        self.screen = ActivationKeyScreen(self.backend, self.parent)
+        stub_reg = StubReg()
+        self.screen = ActivationKeyScreen(reg_info=stub_reg.reg_info,
+                                          async_backend=stub_reg.async,
+                                          facts=stub_reg.facts,
+                                          parent_window=stub_reg.parent_window)
 
     def test_split_activation_keys(self):
         expected = ['hello', 'world', 'how', 'are', 'you']
@@ -85,21 +138,23 @@ class ActivationKeyScreenTests(SubManFixture):
 class ChooseServerScreenTests(SubManFixture):
     def setUp(self):
         super(ChooseServerScreenTests, self).setUp()
-        self.backend = StubBackend()
-        self.parent = Mock()
-        self.screen = ChooseServerScreen(self.backend, self.parent)
+        stub_reg = StubReg()
+        self.screen = ChooseServerScreen(reg_info=stub_reg.reg_info,
+                                         async_backend=stub_reg.async,
+                                         facts=stub_reg.facts,
+                                         parent_window=stub_reg.parent_window)
 
     def test_activation_key_checkbox_sensitive(self):
         self.screen.server_entry.set_text("foo.bar:443/baz")
         self.assertTrue(self.screen.activation_key_checkbox.get_property('sensitive'))
 
-    def test_activation_key_checkbox_insensitive(self):
+    def test_activation_key_checkbox_prod_sensitive(self):
         self.screen.server_entry.set_text("subscription.rhn.redhat.com:443/baz")
-        self.assertFalse(self.screen.activation_key_checkbox.get_property('sensitive'))
+        self.assertTrue(self.screen.activation_key_checkbox.get_property('sensitive'))
 
     def test_activation_key_checkbox_inactive_when_insensitive(self):
         self.screen.server_entry.set_text("foo.bar:443/baz")
         self.screen.activation_key_checkbox.set_active(True)
         self.screen.server_entry.set_text("subscription.rhn.redhat.com:443/baz")
-        self.assertFalse(self.screen.activation_key_checkbox.get_property('sensitive'))
-        self.assertFalse(self.screen.activation_key_checkbox.get_property('active'))
+        self.assertTrue(self.screen.activation_key_checkbox.get_property('sensitive'))
+        self.assertTrue(self.screen.activation_key_checkbox.get_property('active'))