diff --git a/configure.ac b/configure.ac
index fc706e1..03271a9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1415,7 +1415,7 @@ else
 	    $CUPS_API_MAJOR -eq 1 -a $CUPS_API_MINOR -ge 6; then
       AC_DEFINE(HAVE_CUPS_API_1_6, 1,
                 [Define to 1 if CUPS 1.6 API is available])
-
+      have_cups_api_1_6=yes
     fi
 
     AC_SUBST(CUPS_API_MAJOR)
@@ -1446,6 +1446,37 @@ else
   fi
 fi
 
+# Check for Avahi flags
+AC_ARG_ENABLE(avahi-browsing,
+              [AS_HELP_STRING([--disable-avahi-browsing],
+                              [disable avahi browsing of printers])],,
+              [enable_avahi_browsing=auto])
+
+if test "x$enable_avahi_browsing" != "xno" -a "x$have_cups_api_1_6" = "xyes"; then
+  AC_MSG_CHECKING([avahi-gobject])
+
+  if $PKG_CONFIG --exists avahi-gobject ; then
+    AVAHI_CFLAGS=`$PKG_CONFIG --cflags avahi-gobject`
+    AC_SUBST(AVAHI_CFLAGS)
+    AVAHI_LIBS=`$PKG_CONFIG --libs avahi-gobject`
+    AC_SUBST(AVAHI_LIBS)
+    have_avahi_gobject=yes
+    AC_MSG_RESULT([yes])
+  else
+    AC_MSG_RESULT([no])
+  fi
+
+  if test "x$have_avahi_gobject" = "xyes" ; then
+    AC_DEFINE([HAVE_AVAHI_BROWSING], [1], [Define to 1 if avahi-gobject available])
+  else
+    AC_MSG_ERROR([
+*** avahi-gobject not found.
+])
+  fi
+fi
+
+AM_CONDITIONAL(HAVE_AVAHI_GOBJECT, test "x$enable_avahi_browsing" = "xyes" -a "x$have_avahi_gobject" = "xyes")
+
 # Checks to see if we should compile with PAPI backend for GTK+
 #
 
diff --git a/modules/printbackends/cups/Makefile.am b/modules/printbackends/cups/Makefile.am
index e9d4c2f..2e5b927 100644
--- a/modules/printbackends/cups/Makefile.am
+++ b/modules/printbackends/cups/Makefile.am
@@ -12,6 +12,7 @@ AM_CPPFLAGS = \
 	-I$(top_builddir)/gdk				\
 	$(CUPS_CFLAGS)					\
 	$(COLORD_CFLAGS)				\
+	$(AVAHI_CFLAGS)					\
 	-DGTK_COMPILATION				\
 	-DGTK_PRINT_BACKEND_ENABLE_UNSUPPORTED		\
 	$(GTK_DEP_CFLAGS)				\
@@ -37,6 +38,6 @@ noinst_HEADERS =			\
 	gtkcupsutils.h
 
 libprintbackend_cups_la_LDFLAGS =  -avoid-version -module $(no_undefined)
-libprintbackend_cups_la_LIBADD = $(LDADDS) $(CUPS_LIBS)
+libprintbackend_cups_la_LIBADD = $(LDADDS) $(CUPS_LIBS) $(AVAHI_LIBS)
 
 -include $(top_srcdir)/git.mk
diff --git a/modules/printbackends/cups/gtkprintbackendcups.c b/modules/printbackends/cups/gtkprintbackendcups.c
index ca8ef5a..844af84 100644
--- a/modules/printbackends/cups/gtkprintbackendcups.c
+++ b/modules/printbackends/cups/gtkprintbackendcups.c
@@ -53,6 +53,10 @@
 #include <gtk/gtkprintbackend.h>
 #include <gtk/gtkunixprint.h>
 #include <gtk/gtkprinter-private.h>
+#include <avahi-gobject/ga-client.h>
+#include <avahi-gobject/ga-service-browser.h>
+#include <avahi-gobject/ga-service-resolver.h>
+#include <avahi-gobject/ga-error.h>
 
 #include "gtkprintbackendcups.h"
 #include "gtkprintercups.h"
@@ -137,6 +141,13 @@ struct _GtkPrintBackendCups
 #ifdef HAVE_COLORD
   CdClient   *colord_client;
 #endif
+#ifdef HAVE_AVAHI_BROWSING
+  GaServiceResolver *avahi_ipp_resolver;
+  GaServiceResolver *avahi_ipps_resolver;
+  GaServiceBrowser  *avahi_ipp_browser;
+  GaServiceBrowser  *avahi_ipps_browser;
+  GaClient          *avahi_client;
+#endif
 };
 
 static GObjectClass *backend_parent_class;
@@ -203,6 +214,11 @@ void                        overwrite_and_free                      (gpointer
 static gboolean             is_address_local                        (const gchar                      *address);
 static gboolean             request_auth_info                       (gpointer                          data);
 
+#ifdef HAVE_AVAHI_BROWSING
+static void                 avahi_data_free                         (GtkPrintBackendCups              *cups_backend);
+static void                 avahi_request_printer_list              (GtkPrintBackendCups              *cups_backend);
+#endif
+
 static void
 gtk_print_backend_cups_register_type (GTypeModule *module)
 {
@@ -595,23 +611,46 @@ gtk_print_backend_cups_print_stream (GtkPrintBackend         *print_backend,
   cups_printer = GTK_PRINTER_CUPS (gtk_print_job_get_printer (job));
   settings = gtk_print_job_get_settings (job);
 
-  request = gtk_cups_request_new_with_username (NULL,
-                                                GTK_CUPS_POST,
-                                                IPP_PRINT_JOB,
-                                                data_io,
-                                                NULL,
-                                                cups_printer->device_uri,
-                                                GTK_PRINT_BACKEND_CUPS (print_backend)->username);
+#ifdef HAVE_AVAHI_BROWSING
+  if (cups_printer->avahi_browsed)
+    {
+      http_t *http;
 
-  httpAssembleURIf (HTTP_URI_CODING_ALL,
-                    printer_absolute_uri,
-                    sizeof (printer_absolute_uri),
-                    "ipp",
-                    NULL,
-                    "localhost",
-                    ippPort (),
-                    "/printers/%s",
-                    gtk_printer_get_name (gtk_print_job_get_printer (job)));
+      http = httpConnectEncrypt (cups_printer->hostname,
+                                 cups_printer->port,
+                                 HTTP_ENCRYPT_IF_REQUESTED);
+
+      request = gtk_cups_request_new_with_username (http,
+                                                    GTK_CUPS_POST,
+                                                    IPP_PRINT_JOB,
+                                                    data_io,
+                                                    cups_printer->hostname,
+                                                    cups_printer->device_uri,
+                                                    GTK_PRINT_BACKEND_CUPS (print_backend)->username);
+
+      g_snprintf (printer_absolute_uri, HTTP_MAX_URI, cups_printer->printer_uri);
+    }
+  else
+#endif
+    {
+      request = gtk_cups_request_new_with_username (NULL,
+                                                    GTK_CUPS_POST,
+                                                    IPP_PRINT_JOB,
+                                                    data_io,
+                                                    NULL,
+                                                    cups_printer->device_uri,
+                                                    GTK_PRINT_BACKEND_CUPS (print_backend)->username);
+
+      httpAssembleURIf (HTTP_URI_CODING_ALL,
+                        printer_absolute_uri,
+                        sizeof (printer_absolute_uri),
+                        "ipp",
+                        NULL,
+                        "localhost",
+                        ippPort (),
+                        "/printers/%s",
+                        gtk_printer_get_name (gtk_print_job_get_printer (job)));
+    }
 
   gtk_cups_request_ipp_add_string (request, IPP_TAG_OPERATION,
                                    IPP_TAG_URI, "printer-uri",
@@ -681,6 +720,14 @@ gtk_print_backend_cups_init (GtkPrintBackendCups *backend_cups)
   backend_cups->colord_client = cd_client_new ();
 #endif
 
+#ifdef HAVE_AVAHI_BROWSING
+  backend_cups->avahi_ipp_resolver = NULL;
+  backend_cups->avahi_ipps_resolver = NULL;
+  backend_cups->avahi_ipp_browser = NULL;
+  backend_cups->avahi_ipps_browser = NULL;
+  backend_cups->avahi_client = NULL;
+#endif
+
   cups_get_local_default_printer (backend_cups);
 }
 
@@ -711,6 +758,10 @@ gtk_print_backend_cups_finalize (GObject *object)
   g_object_unref (backend_cups->colord_client);
 #endif
 
+#ifdef HAVE_AVAHI_BROWSING
+  avahi_data_free (backend_cups);
+#endif
+
   backend_parent_class->finalize (object);
 }
 
@@ -1708,6 +1759,9 @@ typedef struct
   gboolean default_printer;
   gboolean got_printer_type;
   gboolean remote_printer;
+#ifdef HAVE_AVAHI_BROWSING
+  gboolean avahi_printer;
+#endif
   gchar  **auth_info_required;
   gint     default_number_up;
 } PrinterSetupInfo;
@@ -1862,9 +1916,16 @@ cups_create_printer (GtkPrintBackendCups *cups_backend,
   char *cups_server;            /* CUPS server */
 
 #ifdef HAVE_COLORD
-  cups_printer = gtk_printer_cups_new (info->printer_name,
-				       backend,
-				       cups_backend->colord_client);
+#ifdef HAVE_AVAHI_BROWSING
+  if (info->avahi_printer)
+    cups_printer = gtk_printer_cups_new (info->printer_name,
+					 backend,
+					 NULL);
+  else
+#endif
+    cups_printer = gtk_printer_cups_new (info->printer_name,
+					 backend,
+					 cups_backend->colord_client);
 #else
   cups_printer = gtk_printer_cups_new (info->printer_name, backend, NULL);
 #endif
@@ -1935,11 +1996,621 @@ cups_create_printer (GtkPrintBackendCups *cups_backend,
       strcmp (cups_backend->default_printer, gtk_printer_get_name (printer)) == 0)
     gtk_printer_set_is_default (printer, TRUE);
 
+#ifdef HAVE_AVAHI_BROWSING
+  cups_printer->avahi_browsed = info->avahi_printer;
+#endif
 
   gtk_print_backend_add_printer (backend, printer);
   return printer;
 }
 
+static void
+set_printer_icon_name_from_info (GtkPrinter       *printer,
+                                 PrinterSetupInfo *info)
+{
+  /* Set printer icon according to importance
+     (none, report, warning, error - report is omitted). */
+  if (info->reason_level == GTK_PRINTER_STATE_LEVEL_ERROR)
+    gtk_printer_set_icon_name (printer, "printer-error");
+  else if (info->reason_level == GTK_PRINTER_STATE_LEVEL_WARNING)
+    gtk_printer_set_icon_name (printer, "printer-warning");
+  else if (gtk_printer_is_paused (printer))
+    gtk_printer_set_icon_name (printer, "printer-paused");
+  else
+    gtk_printer_set_icon_name (printer, "printer");
+}
+
+static void
+set_info_state_message (PrinterSetupInfo *info)
+{
+  gint i;
+
+  if (info->state_msg && strlen (info->state_msg) == 0)
+    {
+      gchar *tmp_msg2 = NULL;
+      if (info->is_paused && !info->is_accepting_jobs)
+        /* Translators: this is a printer status. */
+        tmp_msg2 = g_strdup ( N_("Paused ; Rejecting Jobs"));
+      if (info->is_paused && info->is_accepting_jobs)
+        /* Translators: this is a printer status. */
+        tmp_msg2 = g_strdup ( N_("Paused"));
+      if (!info->is_paused && !info->is_accepting_jobs)
+        /* Translators: this is a printer status. */
+        tmp_msg2 = g_strdup ( N_("Rejecting Jobs"));
+
+      if (tmp_msg2 != NULL)
+        {
+          info->state_msg = tmp_msg2;
+          g_free (tmp_msg2);
+        }
+    }
+
+  /* Set description of the reason and combine it with printer-state-message. */
+  if (info->reason_msg)
+    {
+      gchar *reason_msg_desc = NULL;
+      gboolean found = FALSE;
+
+      for (i = 0; i < G_N_ELEMENTS (printer_messages); i++)
+        {
+          if (strncmp (info->reason_msg, printer_messages[i],
+                       strlen (printer_messages[i])) == 0)
+            {
+              reason_msg_desc = g_strdup_printf (printer_strings[i],
+                                                 info->printer_name);
+              found = TRUE;
+              break;
+            }
+        }
+
+      if (!found)
+        info->reason_level = GTK_PRINTER_STATE_LEVEL_NONE;
+
+      if (info->reason_level >= GTK_PRINTER_STATE_LEVEL_WARNING)
+        {
+          if (strlen (info->state_msg) == 0)
+            info->state_msg = reason_msg_desc;
+          else
+            {
+              gchar *tmp_msg = NULL;
+              tmp_msg = g_strjoin (" ; ", info->state_msg,
+                                   reason_msg_desc, NULL);
+              info->state_msg = tmp_msg;
+              g_free (tmp_msg);
+            }
+        }
+
+      g_free (reason_msg_desc);
+    }
+}
+
+#ifdef HAVE_AVAHI_BROWSING
+typedef struct
+{
+  gchar *name;
+  gchar *type;
+  gchar *domain;
+} AvahiService;
+
+void
+avahi_service_free (AvahiService *service)
+{
+  if (service)
+    {
+      g_free (service->name);
+      g_free (service->type);
+      g_free (service->domain);
+      g_free (service);
+    }
+}
+
+static void
+avahi_data_free (GtkPrintBackendCups *cups_backend)
+{
+  if (cups_backend)
+    {
+      g_clear_object (&cups_backend->avahi_ipp_resolver);
+      g_clear_object (&cups_backend->avahi_ipps_resolver);
+      g_clear_object (&cups_backend->avahi_ipp_browser);
+      g_clear_object (&cups_backend->avahi_ipps_browser);
+      g_clear_object (&cups_backend->avahi_client);
+    }
+}
+
+static void
+cups_request_avahi_printer_info_cb (GtkPrintBackendCups *cups_backend,
+                                    GtkCupsResult       *result,
+                                    gpointer             user_data)
+{
+  PrinterSetupInfo *info = g_slice_new0 (PrinterSetupInfo);
+  GtkPrintBackend  *backend = GTK_PRINT_BACKEND (cups_backend);
+  ipp_attribute_t  *attr;
+  AvahiService     *service = (AvahiService *) user_data;
+  GtkPrinter       *printer;
+  gboolean          list_has_changed = FALSE;
+  gboolean          status_changed = FALSE;
+  ipp_t            *response;
+  gchar            *remote_default_printer = NULL;
+
+  gdk_threads_enter ();
+
+  GTK_NOTE (PRINTING,
+            g_print ("CUPS Backend: %s\n", G_STRFUNC));
+
+  if (gtk_cups_result_is_error (result))
+    {
+      GTK_NOTE (PRINTING,
+                g_warning ("CUPS Backend: Error getting printer info: %s %d %d",
+                           gtk_cups_result_get_error_string (result),
+                           gtk_cups_result_get_error_type (result),
+                           gtk_cups_result_get_error_code (result)));
+
+      goto done;
+    }
+
+  response = gtk_cups_result_get_response (result);
+  attr = ippFirstAttribute (response);
+  while (attr && ippGetGroupTag (attr) != IPP_TAG_PRINTER)
+    attr = ippNextAttribute (response);
+
+  if (attr)
+    {
+      while (attr && ippGetGroupTag (attr) == IPP_TAG_PRINTER)
+        {
+          cups_printer_handle_attribute (cups_backend, attr, info);
+          attr = ippNextAttribute (response);
+        }
+
+      if (info->printer_name &&
+          (info->printer_uri || info->member_uris))
+        {
+          if (info->got_printer_type)
+            {
+              if (info->default_printer && !cups_backend->got_default_printer)
+                {
+                  if (!info->remote_printer)
+                    {
+                      cups_backend->got_default_printer = TRUE;
+                      cups_backend->default_printer = g_strdup (info->printer_name);
+                    }
+                  else
+                    {
+                      if (remote_default_printer == NULL)
+                        remote_default_printer = g_strdup (info->printer_name);
+                    }
+                }
+            }
+          else
+            {
+              if (!cups_backend->got_default_printer)
+                cups_get_default_printer (cups_backend);
+            }
+
+          info->avahi_printer = TRUE;
+          set_info_state_message (info);
+
+          printer = gtk_print_backend_find_printer (backend, info->printer_name);
+          if (!printer)
+            {
+              printer = cups_create_printer (cups_backend, info);
+              list_has_changed = TRUE;
+            }
+          else
+            {
+              g_object_ref (printer);
+            }
+
+          gtk_printer_set_is_paused (printer, info->is_paused);
+          gtk_printer_set_is_accepting_jobs (printer, info->is_accepting_jobs);
+
+          if (!gtk_printer_is_active (printer))
+            {
+              gtk_printer_set_is_active (printer, TRUE);
+              gtk_printer_set_is_new (printer, TRUE);
+              list_has_changed = TRUE;
+            }
+
+          GTK_PRINTER_CUPS (printer)->remote = info->remote_printer;
+          GTK_PRINTER_CUPS (printer)->avahi_name = g_strdup (service->name);
+          GTK_PRINTER_CUPS (printer)->avahi_type = g_strdup (service->type);
+          GTK_PRINTER_CUPS (printer)->avahi_domain = g_strdup (service->domain);
+          GTK_PRINTER_CUPS (printer)->state = info->state;
+          status_changed = gtk_printer_set_job_count (printer, info->job_count);
+          status_changed |= gtk_printer_set_location (printer, info->location);
+          status_changed |= gtk_printer_set_description (printer, info->description);
+          status_changed |= gtk_printer_set_state_message (printer, info->state_msg);
+          status_changed |= gtk_printer_set_is_accepting_jobs (printer, info->is_accepting_jobs);
+
+          set_printer_icon_name_from_info (printer, info);
+
+          if (gtk_printer_is_new (printer))
+            {
+              g_signal_emit_by_name (backend, "printer-added", printer);
+              gtk_printer_set_is_new (printer, FALSE);
+            }
+
+          if (status_changed)
+            g_signal_emit_by_name (GTK_PRINT_BACKEND (backend),
+                                   "printer-status-changed", printer);
+
+          /* The ref is held by GtkPrintBackend, in add_printer() */
+          g_object_unref (printer);
+        }
+    }
+
+done:
+  if (list_has_changed)
+    g_signal_emit_by_name (backend, "printer-list-changed");
+
+  if (!cups_backend->got_default_printer && remote_default_printer != NULL)
+    {
+      cups_backend->default_printer = g_strdup (remote_default_printer);
+      cups_backend->got_default_printer = TRUE;
+      g_free (remote_default_printer);
+
+      if (cups_backend->default_printer != NULL)
+        {
+          GtkPrinter *default_printer = NULL;
+          default_printer = gtk_print_backend_find_printer (GTK_PRINT_BACKEND (cups_backend),
+                                                            cups_backend->default_printer);
+          if (default_printer != NULL)
+            {
+              gtk_printer_set_is_default (default_printer, TRUE);
+              g_signal_emit_by_name (GTK_PRINT_BACKEND (cups_backend),
+                                     "printer-status-changed", default_printer);
+            }
+        }
+    }
+
+  g_slice_free (PrinterSetupInfo, info);
+
+  gdk_threads_leave ();
+}
+
+static void
+cups_request_avahi_printer_info (const gchar         *printer_uri,
+                                 const gchar         *host,
+                                 gint                 port,
+                                 const gchar         *name,
+                                 const gchar         *type,
+                                 const gchar         *domain,
+                                 GtkPrintBackendCups *backend)
+{
+  GtkCupsRequest *request;
+  AvahiService   *service;
+  http_t         *http;
+  static const char * const pattrs[] =
+    {
+      "printer-name",
+      "printer-uri-supported",
+      "member-uris",
+      "printer-location",
+      "printer-info",
+      "printer-state-message",
+      "printer-state-reasons",
+      "printer-state",
+      "queued-job-count",
+      "printer-is-accepting-jobs",
+      "job-sheets-supported",
+      "job-sheets-default",
+      "printer-type",
+      "auth-info-required",
+      "number-up-default"
+    };
+
+  service = (AvahiService *) g_new0 (AvahiService, 1);
+  service->name = g_strdup (name);
+  service->type = g_strdup (type);
+  service->domain = g_strdup (domain);
+
+  http = httpConnect (host, port);
+  request = gtk_cups_request_new_with_username (http,
+                                                GTK_CUPS_POST,
+                                                IPP_GET_PRINTER_ATTRIBUTES,
+                                                NULL,
+                                                NULL,
+                                                NULL,
+                                                backend->username);
+
+  gtk_cups_request_ipp_add_string (request, IPP_TAG_OPERATION, IPP_TAG_URI,
+                                   "printer-uri", NULL, printer_uri);
+
+  gtk_cups_request_ipp_add_strings (request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+                                    "requested-attributes", G_N_ELEMENTS (pattrs),
+                                    NULL, pattrs);
+
+  cups_request_execute (backend,
+                        request,
+                        (GtkPrintCupsResponseCallbackFunc) cups_request_avahi_printer_info_cb,
+                        service,
+                        (GDestroyNotify) avahi_service_free);
+}
+
+static void
+resolver_found_cb (GaServiceResolver  *resolver,
+                   int                 interface,
+                   GaProtocol          protocol,
+                   const char         *name,
+                   const char         *type,
+                   const char         *domain,
+                   const char         *host_name,
+                   const AvahiAddress *address,
+                   guint16             port,
+                   AvahiStringList    *txt,
+                   glong               flags,
+                   gpointer           *user_data)
+{
+  GtkPrintBackendCups *backend = GTK_PRINT_BACKEND_CUPS (user_data);
+  AvahiStringList     *item;
+  gchar                host[AVAHI_ADDRESS_STR_MAX];
+  gchar               *suffix = NULL;
+  gchar               *printer_uri;
+
+  avahi_address_snprint (host, sizeof (host), address);
+
+  item = avahi_string_list_find (txt, "rp");
+  if (item)
+    avahi_string_list_get_pair (item, NULL, &suffix, NULL);
+
+  if (suffix)
+    {
+      if (g_strcmp0 (type, "_ipp._tcp") == 0)
+        printer_uri = g_strdup_printf ("ipp://%s:%u/%s", host, port, suffix);
+      else
+        printer_uri = g_strdup_printf ("ipps://%s:%u/%s", host, port, suffix);
+
+      cups_request_avahi_printer_info (printer_uri,
+                                       host,
+                                       port,
+                                       name,
+                                       type,
+                                       domain,
+                                       backend);
+
+      g_free (printer_uri);
+      g_free (suffix);
+    }
+}
+
+static void
+browser_new_service_cb (GaServiceBrowser *browser,
+                        int               interface,
+                        GaProtocol        protocol,
+                        const char       *name,
+                        const char       *type,
+                        const char       *domain,
+                        glong             flags,
+                        gpointer          user_data)
+{
+  GtkPrintBackendCups *backend = GTK_PRINT_BACKEND_CUPS (user_data);
+  GError              *error = NULL;
+
+  if (g_strcmp0 (type, "_ipp._tcp") == 0 && !backend->avahi_ipp_resolver)
+    {
+      backend->avahi_ipp_resolver =
+        ga_service_resolver_new (AVAHI_IF_UNSPEC,
+                                 AVAHI_PROTO_UNSPEC,
+                                 name, type, domain,
+                                 AVAHI_PROTO_UNSPEC,
+                                 GA_LOOKUP_USE_MULTICAST);
+
+      g_signal_connect (backend->avahi_ipp_resolver, "found",
+                        G_CALLBACK (resolver_found_cb), user_data);
+
+      if (!ga_service_resolver_attach (backend->avahi_ipp_resolver,
+                                       backend->avahi_client,
+                                       &error))
+        {
+          GTK_NOTE (PRINTING,
+                    g_warning ("CUPS Backend: Error resolving Avahi service %s: %s",
+                               name, error->message));
+          g_clear_object (&backend->avahi_ipp_resolver);
+          g_clear_error (&error);
+          return;
+        }
+    }
+  else if (g_strcmp0 (type, "_ipps._tcp") == 0 && !backend->avahi_ipps_resolver)
+    {
+      backend->avahi_ipps_resolver =
+        ga_service_resolver_new (AVAHI_IF_UNSPEC,
+                                 AVAHI_PROTO_UNSPEC,
+                                 name, type, domain,
+                                 AVAHI_PROTO_UNSPEC,
+                                 GA_LOOKUP_USE_MULTICAST);
+
+      g_signal_connect (backend->avahi_ipps_resolver, "found",
+                        G_CALLBACK (resolver_found_cb), user_data);
+
+      if (!ga_service_resolver_attach (backend->avahi_ipps_resolver,
+                                       backend->avahi_client,
+                                       &error))
+        {
+          GTK_NOTE (PRINTING,
+                    g_warning ("CUPS Backend: Error resolving Avahi service %s: %s",
+                               name, error->message));
+          g_clear_object (&backend->avahi_ipps_resolver);
+          g_clear_error (&error);
+          return;
+        }
+    }
+}
+
+static void
+browser_removed_service_cb (GaServiceBrowser *browser,
+                            int               interface,
+                            GaProtocol        protocol,
+                            const char       *name,
+                            const char       *type,
+                            const char       *domain,
+                            glong             flags,
+                            gpointer          user_data)
+{
+  GtkPrintBackendCups *backend = GTK_PRINT_BACKEND_CUPS (user_data);
+  GtkPrinterCups      *printer;
+  GList               *list;
+  GList               *iter;
+
+  list = gtk_print_backend_get_printer_list (GTK_PRINT_BACKEND (backend));
+
+  for (iter = list; iter; iter = iter->next)
+    {
+      printer = GTK_PRINTER_CUPS (iter->data);
+      if (g_strcmp0 (printer->avahi_name, name) == 0 &&
+          g_strcmp0 (printer->avahi_type, type) == 0 &&
+          g_strcmp0 (printer->avahi_domain, domain) == 0)
+        {
+          g_signal_emit_by_name (backend, "printer-removed", printer);
+          gtk_print_backend_remove_printer (GTK_PRINT_BACKEND (backend),
+                                            GTK_PRINTER (printer));
+          g_signal_emit_by_name (backend, "printer-list-changed");
+          break;
+        }
+    }
+
+  g_list_free (list);
+}
+
+static gboolean
+ga_client_renew (gpointer user_data)
+{
+  GtkPrintBackendCups *backend = GTK_PRINT_BACKEND_CUPS (user_data);
+  gboolean             avahi_printers_removed = TRUE;
+  GList               *list;
+  GList               *iter;
+
+  list = gtk_print_backend_get_printer_list (GTK_PRINT_BACKEND (backend));
+
+  for (iter = list; iter; iter = iter->next)
+    if (GTK_PRINTER_CUPS (iter->data)->avahi_browsed)
+      avahi_printers_removed = FALSE;
+
+  g_list_free (list);
+
+  if (avahi_printers_removed)
+    {
+      avahi_data_free (backend);
+      avahi_request_printer_list (backend);
+      return FALSE;
+    }
+  else
+    {
+      return TRUE;
+    }
+}
+
+static void
+ga_client_state_changed_cb (GaClient      *ga_client,
+                            GaClientState  state,
+                            gpointer       user_data)
+{
+  GtkPrintBackendCups *backend = GTK_PRINT_BACKEND_CUPS (user_data);
+  GtkPrinterCups      *printer;
+  gboolean             list_has_changed = FALSE;
+  GError              *error = NULL;
+  GList               *list;
+  GList               *iter;
+
+  switch (state)
+    {
+      case GA_CLIENT_STATE_FAILURE:
+        if (avahi_client_errno (ga_client->avahi_client) == AVAHI_ERR_DISCONNECTED)
+          {
+            list = gtk_print_backend_get_printer_list (GTK_PRINT_BACKEND (backend));
+
+            for (iter = list; iter; iter = iter->next)
+              {
+                printer = GTK_PRINTER_CUPS (iter->data);
+                if (printer->avahi_browsed)
+                  {
+                    g_signal_emit_by_name (backend, "printer-removed", printer);
+                    gtk_print_backend_remove_printer (GTK_PRINT_BACKEND (backend),
+                                                      GTK_PRINTER (printer));
+                    list_has_changed = TRUE;
+                  }
+              }
+
+            if (list_has_changed)
+              g_signal_emit_by_name (backend, "printer-list-changed");
+
+            g_idle_add (ga_client_renew, backend);
+
+            g_list_free (list);
+          }
+        break;
+
+      case GA_CLIENT_STATE_S_RUNNING:
+        backend->avahi_ipp_browser = ga_service_browser_new ("_ipp._tcp");
+
+        g_signal_connect (backend->avahi_ipp_browser, "new-service",
+                          G_CALLBACK (browser_new_service_cb),
+                          user_data);
+
+        g_signal_connect (backend->avahi_ipp_browser, "removed-service",
+                          G_CALLBACK (browser_removed_service_cb),
+                          user_data);
+
+        if (!ga_service_browser_attach (backend->avahi_ipp_browser,
+                                        backend->avahi_client,
+                                        &error))
+          {
+            GTK_NOTE (PRINTING,
+                      g_warning ("CUPS Backend: Error getting printer list from Avahi: %s",
+                                 error->message));
+            g_clear_object (&backend->avahi_ipp_browser);
+            g_clear_error (&error);
+          }
+
+        backend->avahi_ipps_browser = ga_service_browser_new ("_ipps._tcp");
+
+        g_signal_connect (backend->avahi_ipps_browser, "new-service",
+                          G_CALLBACK (browser_new_service_cb),
+                          user_data);
+
+        g_signal_connect (backend->avahi_ipps_browser, "removed-service",
+                          G_CALLBACK (browser_removed_service_cb),
+                          user_data);
+
+        if (!ga_service_browser_attach (backend->avahi_ipps_browser,
+                                        backend->avahi_client,
+                                        &error))
+          {
+            GTK_NOTE (PRINTING,
+                      g_warning ("CUPS Backend: Error getting printer list from Avahi: %s",
+                                 error->message));
+            g_clear_object (&backend->avahi_ipps_browser);
+            g_clear_error (&error);
+          }
+        break;
+
+      default:
+        break;
+    }
+}
+
+static void
+avahi_request_printer_list (GtkPrintBackendCups *cups_backend)
+{
+  GError *error = NULL;
+
+  if (!cups_backend->avahi_client)
+    {
+      cups_backend->avahi_client = ga_client_new (GA_CLIENT_FLAG_NO_FLAGS);
+
+      g_signal_connect (cups_backend->avahi_client, "state-changed",
+                        G_CALLBACK (ga_client_state_changed_cb),
+                        cups_backend);
+
+      if (!ga_client_start (cups_backend->avahi_client, &error))
+        {
+          GTK_NOTE (PRINTING,
+                    g_warning ("CUPS Backend: Error getting printer list from Avahi: %s",
+                               error->message));
+          g_clear_object (&cups_backend->avahi_client);
+          g_clear_error (&error);
+        }
+    }
+}
+#endif
 
 static void
 cups_request_printer_list_cb (GtkPrintBackendCups *cups_backend,
@@ -1952,6 +2623,7 @@ cups_request_printer_list_cb (GtkPrintBackendCups *cups_backend,
   gboolean list_has_changed;
   GList *removed_printer_checklist;
   gchar *remote_default_printer = NULL;
+  GList *iter;
 
   gdk_threads_enter ();
 
@@ -1996,7 +2668,6 @@ cups_request_printer_list_cb (GtkPrintBackendCups *cups_backend,
       GtkPrinter *printer;
       gboolean status_changed = FALSE;
       GList *node;
-      gint i;
       PrinterSetupInfo *info = g_slice_new0 (PrinterSetupInfo);
 
       /* Skip leading attributes until we hit a printer...
@@ -2017,7 +2688,6 @@ cups_request_printer_list_cb (GtkPrintBackendCups *cups_backend,
       GtkPrinter *printer;
       gboolean status_changed = FALSE;
       GList *node;
-      gint i;
       PrinterSetupInfo *info = g_slice_new0 (PrinterSetupInfo);
       info->default_number_up = 1;
 
@@ -2115,79 +2785,12 @@ cups_request_printer_list_cb (GtkPrintBackendCups *cups_backend,
       status_changed |= gtk_printer_set_description (printer,
 						     info->description);
 
-      if (info->state_msg != NULL && strlen (info->state_msg) == 0)
-        {
-	  gchar *tmp_msg2 = NULL;
-	  if (info->is_paused && !info->is_accepting_jobs)
-	    /* Translators: this is a printer status. */
-            tmp_msg2 = g_strdup ( N_("Paused ; Rejecting Jobs"));
-          if (info->is_paused && info->is_accepting_jobs)
-	    /* Translators: this is a printer status. */
-            tmp_msg2 = g_strdup ( N_("Paused"));
-          if (!info->is_paused && !info->is_accepting_jobs)
-	    /* Translators: this is a printer status. */
-            tmp_msg2 = g_strdup ( N_("Rejecting Jobs"));
-
-          if (tmp_msg2 != NULL)
-	    {
-	      info->state_msg = tmp_msg2;
-	      g_free (tmp_msg2);
-	    }
-	}
-
-      /* Set description of the reason and combine it with printer-state-message. */
-      if ( (info->reason_msg != NULL))
-        {
-	  gchar *reason_msg_desc = NULL;
-	  gboolean found = FALSE;
-
-          for (i = 0; i < G_N_ELEMENTS (printer_messages); i++)
-            {
-              if (strncmp (info->reason_msg, printer_messages[i],
-			   strlen (printer_messages[i])) == 0)
-                {
-                  reason_msg_desc = g_strdup_printf (printer_strings[i],
-						     info->printer_name);
-                  found = TRUE;
-                  break;
-                }
-            }
-
-          if (!found)
-            info->reason_level = GTK_PRINTER_STATE_LEVEL_NONE;
-
-          if (info->reason_level >= GTK_PRINTER_STATE_LEVEL_WARNING)
-            {
-              if (strlen (info->state_msg) == 0)
-                info->state_msg = reason_msg_desc;
-              else
-                {
-		  gchar *tmp_msg = NULL;
-		  tmp_msg = g_strjoin (" ; ", info->state_msg,
-				       reason_msg_desc, NULL);
-                  info->state_msg = tmp_msg;
-		  g_free (tmp_msg);
-                }
-            }
-	  if (reason_msg_desc != NULL)
-	    g_free (reason_msg_desc);
-        }
+      set_info_state_message (info);
 
       status_changed |= gtk_printer_set_state_message (printer, info->state_msg);
       status_changed |= gtk_printer_set_is_accepting_jobs (printer, info->is_accepting_jobs);
 
-
-
-      /* Set printer icon according to importance
-         (none, report, warning, error - report is omitted). */
-      if (info->reason_level == GTK_PRINTER_STATE_LEVEL_ERROR)
-        gtk_printer_set_icon_name (printer, "printer-error");
-      else if (info->reason_level == GTK_PRINTER_STATE_LEVEL_WARNING)
-        gtk_printer_set_icon_name (printer, "printer-warning");
-      else if (gtk_printer_is_paused (printer))
-        gtk_printer_set_icon_name (printer, "printer-paused");
-      else
-        gtk_printer_set_icon_name (printer, "printer");
+      set_printer_icon_name_from_info (printer, info);
 
       if (status_changed)
         g_signal_emit_by_name (GTK_PRINT_BACKEND (backend),
@@ -2205,9 +2808,18 @@ cups_request_printer_list_cb (GtkPrintBackendCups *cups_backend,
      as inactive if it is in the list, emitting a printer_removed signal */
   if (removed_printer_checklist != NULL)
     {
-      g_list_foreach (removed_printer_checklist, (GFunc) mark_printer_inactive, backend);
+      for (iter = removed_printer_checklist; iter; iter = iter->next)
+        {
+#ifdef HAVE_AVAHI_BROWSING
+          if (!GTK_PRINTER_CUPS (iter->data)->avahi_browsed)
+#endif
+            {
+              mark_printer_inactive (GTK_PRINTER (iter->data), backend);
+              list_has_changed = TRUE;
+            }
+        }
+
       g_list_free (removed_printer_checklist);
-      list_has_changed = TRUE;
     }
 
 done:
@@ -2342,6 +2954,10 @@ cups_get_printer_list (GtkPrintBackend *backend)
         cups_backend->list_printers_poll = gdk_threads_add_timeout (50,
                                              (GSourceFunc) cups_request_printer_list,
                                              backend);
+
+#ifdef HAVE_AVAHI_BROWSING
+      avahi_request_printer_list (cups_backend);
+#endif
     }
 }
 
diff --git a/modules/printbackends/cups/gtkprintercups.c b/modules/printbackends/cups/gtkprintercups.c
index 128b3b3..830a1ba 100644
--- a/modules/printbackends/cups/gtkprintercups.c
+++ b/modules/printbackends/cups/gtkprintercups.c
@@ -114,6 +114,12 @@ gtk_printer_cups_init (GtkPrinterCups *printer)
   printer->remote_cups_connection_test = NULL;
   printer->auth_info_required = NULL;
   printer->default_number_up = 1;
+#ifdef HAVE_AVAHI_BROWSING
+  printer->avahi_browsed = FALSE;
+  printer->avahi_name = NULL;
+  printer->avahi_type = NULL;
+  printer->avahi_domain = NULL;
+#endif
 }
 
 static void
@@ -134,8 +140,11 @@ gtk_printer_cups_finalize (GObject *object)
   g_strfreev (printer->auth_info_required);
 
 #ifdef HAVE_COLORD
-  g_cancellable_cancel (printer->colord_cancellable);
-  g_object_unref (printer->colord_cancellable);
+  if (printer->colord_cancellable)
+    {
+      g_cancellable_cancel (printer->colord_cancellable);
+      g_object_unref (printer->colord_cancellable);
+    }
   g_free (printer->colord_title);
   g_free (printer->colord_qualifier);
   if (printer->colord_client)
@@ -146,6 +155,12 @@ gtk_printer_cups_finalize (GObject *object)
     g_object_unref (printer->colord_profile);
 #endif
 
+#ifdef HAVE_AVAHI_BROWSING
+  g_free (printer->avahi_name);
+  g_free (printer->avahi_type);
+  g_free (printer->avahi_domain);
+#endif
+
   if (printer->ppd_file)
     ppdClose (printer->ppd_file);
 
@@ -512,7 +527,8 @@ colord_printer_details_aquired_cb (GtkPrinterCups *printer,
                                    gpointer user_data)
 {
   /* refresh the device */
-  colord_update_device (printer);
+  if (printer->colord_client)
+    colord_update_device (printer);
 }
 #endif
 
diff --git a/modules/printbackends/cups/gtkprintercups.h b/modules/printbackends/cups/gtkprintercups.h
index ecc5e38..6e47b2d 100644
--- a/modules/printbackends/cups/gtkprintercups.h
+++ b/modules/printbackends/cups/gtkprintercups.h
@@ -75,6 +75,12 @@ struct _GtkPrinterCups
   gchar        *colord_title;
   gchar        *colord_qualifier;
 #endif
+#ifdef HAVE_AVAHI_BROWSING
+  gboolean  avahi_browsed;
+  gchar    *avahi_name;
+  gchar    *avahi_type;
+  gchar    *avahi_domain;
+#endif
 };
 
 struct _GtkPrinterCupsClass
