=== modified file 'UnityCore/DBusIndicators.cpp'
--- UnityCore/DBusIndicators.cpp	2012-03-21 12:31:11 +0000
+++ UnityCore/DBusIndicators.cpp	2012-10-09 11:53:25 +0000
@@ -43,7 +43,7 @@
 class DBusIndicators::Impl
 {
 public:
-  Impl(DBusIndicators* owner);
+  Impl(std::string const& dbus_name, DBusIndicators* owner);
   ~Impl();
 
   void CheckLocalService();
@@ -85,12 +85,12 @@
 
 
 // Public Methods
-DBusIndicators::Impl::Impl(DBusIndicators* owner)
+DBusIndicators::Impl::Impl(std::string const& dbus_name, DBusIndicators* owner)
   : owner_(owner)
   , reconnect_timeout_id_(0)
   , show_entry_idle_id_(0)
   , show_appmenu_idle_id_(0)
-  , gproxy_(SERVICE_NAME, SERVICE_PATH, SERVICE_IFACE,
+  , gproxy_(dbus_name, SERVICE_PATH, SERVICE_IFACE,
             G_BUS_TYPE_SESSION, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES)
 {
   gproxy_.Connect("ReSync", sigc::mem_fun(this, &DBusIndicators::Impl::OnReSync));
@@ -313,6 +313,8 @@
     return;
 
   std::map<Indicator::Ptr, Indicator::Entries> indicators;
+  int wantedIndex = 0;
+  bool anyIndexDifferent = false;
 
   g_variant_get(args, "(a(ssssbbusbbi))", &iter);
   while (g_variant_iter_loop(iter, "(ssssbbusbbi)",
@@ -342,7 +344,18 @@
     // Null entries (entry_id == "") are empty indicators.
     if (entry != "")
     {
-      Entry::Ptr e = indicator->GetEntry(entry_id);
+      Entry::Ptr e;
+      if (!anyIndexDifferent)
+      {
+        // Indicators can only add or remove entries, so if
+        // there is a index change we can't reuse the existing ones
+        // after that index
+        int existingEntryIndex = indicator->EntryIndex(entry_id);
+        if (wantedIndex == existingEntryIndex)
+          e = indicator->GetEntry(entry_id);
+        else
+          anyIndexDifferent = true;
+      }
 
       if (!e)
       {
@@ -365,6 +378,7 @@
       }
 
       entries.push_back(e);
+      wantedIndex++;
     }
   }
   g_variant_iter_free(iter);
@@ -437,12 +451,21 @@
 }
 
 DBusIndicators::DBusIndicators()
-  : pimpl(new Impl(this))
+  : pimpl(new Impl(SERVICE_NAME, this))
+{}
+
+DBusIndicators::DBusIndicators(std::string const& dbus_name)
+  : pimpl(new Impl(dbus_name, this))
 {}
 
 DBusIndicators::~DBusIndicators()
 {}
 
+bool DBusIndicators::IsConnected() const
+{
+  return pimpl->gproxy_.IsConnected();
+}
+
 void DBusIndicators::SyncGeometries(std::string const& name,
                                     EntryLocationMap const& locations)
 {

=== modified file 'UnityCore/DBusIndicators.h'
--- UnityCore/DBusIndicators.h	2012-03-14 00:27:01 +0000
+++ UnityCore/DBusIndicators.h	2012-10-09 11:53:25 +0000
@@ -50,6 +50,10 @@
   virtual void OnShowAppMenu(unsigned int xid, int x, int y,
                              unsigned int timestamp);
 
+protected:
+  DBusIndicators(std::string const& dbus_name);
+  bool IsConnected() const;
+
 private:
   class Impl;
   std::unique_ptr<Impl> pimpl;

=== modified file 'UnityCore/Indicator.cpp'
--- UnityCore/Indicator.cpp	2012-02-01 01:41:18 +0000
+++ UnityCore/Indicator.cpp	2012-10-09 11:53:25 +0000
@@ -120,6 +120,21 @@
   return Entry::Ptr();
 }
 
+int Indicator::EntryIndex(std::string const& entry_id) const
+{
+  int i = 0;
+  for (auto entry : entries_)
+  {
+    if (entry->id() == entry_id)
+    {
+      return i;
+    }
+    ++i;
+  }
+
+  return -1;
+}
+
 void Indicator::OnEntryShowMenu(std::string const& entry_id, unsigned int xid,
                                 int x, int y, unsigned int button, unsigned int timestamp)
 {

=== modified file 'UnityCore/Indicator.h'
--- UnityCore/Indicator.h	2012-02-01 01:41:18 +0000
+++ UnityCore/Indicator.h	2012-10-09 11:53:25 +0000
@@ -48,6 +48,7 @@
 
   void Sync(Entries const& new_entries);
   Entry::Ptr GetEntry(std::string const& entry_id) const;
+  int EntryIndex(std::string const& entry_id) const;
   Entries GetEntries() const;
 
   // Signals

=== modified file 'tests/CMakeLists.txt'
--- tests/CMakeLists.txt	2012-07-26 13:12:26 +0000
+++ tests/CMakeLists.txt	2012-10-09 11:53:25 +0000
@@ -110,7 +110,9 @@
                  test_service_lens.h
                  test_service_main.c
                  test_service_model.c
-                 test_service_model.h)
+                 test_service_model.h
+                 test_service_panel.c
+                 test_service_panel.c)
   target_link_libraries(test-gtest-service ${LIBS})
   add_dependencies (test-gtest-service unity-core-${UNITY_API_VERSION} gtest)
 
@@ -189,6 +191,7 @@
                  test_utils.h
                  test_ratings_filter.cpp
                  test_results.cpp
+                 test_dbus_indicators.cpp
                 )
   target_link_libraries(test-gtest-dbus gtest ${LIBS})
   add_test(UnityGTestDBus test-gtest-dbus)

=== added file 'tests/test_dbus_indicators.cpp'
--- tests/test_dbus_indicators.cpp	1970-01-01 00:00:00 +0000
+++ tests/test_dbus_indicators.cpp	2012-10-09 11:53:25 +0000
@@ -0,0 +1,98 @@
+#include <gtest/gtest.h>
+
+#include <UnityCore/GLibDBusProxy.h>
+#include <UnityCore/GLibWrapper.h>
+#include <UnityCore/DBusIndicators.h>
+
+#include "test_utils.h"
+
+using namespace unity;
+using namespace unity::indicator;
+
+namespace
+{
+
+class DBusIndicatorsTest : public DBusIndicators
+{
+public:
+  DBusIndicatorsTest() : DBusIndicators("com.canonical.Unity.Test")
+  {
+  }
+
+  bool HasIndicators() const
+  {
+    return !GetIndicators().empty();
+  }
+
+  using DBusIndicators::IsConnected;
+};
+
+class TestDBusIndicators : public ::testing::Test
+{
+public:
+  void SetUp()
+  {
+    session = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL);
+    g_dbus_connection_set_exit_on_close(session, FALSE);
+
+    dbus_indicators.reset(new DBusIndicatorsTest ());
+
+    // wait until the dbus indicator has connected to the panel service
+    Utils::WaitUntil(sigc::mem_fun(*dbus_indicators, &DBusIndicatorsTest::IsConnected));
+  }
+
+  bool TriggerResync1Sent() const
+  {
+    GVariant *ret = CallPanelMethod("TriggerResync1Sent");
+    return g_variant_get_boolean(g_variant_get_child_value(ret, 0));
+  }
+
+  GVariant* CallPanelMethod(std::string const& name) const
+  {
+    return g_dbus_connection_call_sync(session,
+                                       "com.canonical.Unity.Test",
+                                       "/com/canonical/Unity/Panel/Service",
+                                       "com.canonical.Unity.Panel.Service",
+                                       name.c_str(),
+                                       NULL,
+                                       NULL,
+                                       G_DBUS_CALL_FLAGS_NONE,
+                                       -1,
+                                       NULL,
+                                       NULL);
+  }
+
+  glib::Object<GDBusConnection> session;
+  std::shared_ptr<DBusIndicatorsTest> dbus_indicators;
+};
+
+TEST_F(TestDBusIndicators, TestConstruction)
+{
+  EXPECT_EQ(dbus_indicators->IsConnected(), true);
+}
+
+TEST_F(TestDBusIndicators, TestSync)
+{
+  // wait until the dbus indicator gets any indicator from the panel service
+  Utils::WaitUntil(sigc::mem_fun(*dbus_indicators, &DBusIndicatorsTest::HasIndicators));
+
+  EXPECT_EQ(dbus_indicators->GetIndicators().size(), 1);
+  EXPECT_EQ(dbus_indicators->GetIndicators().front()->GetEntries().size(), 2);
+  EXPECT_EQ(dbus_indicators->GetIndicators().front()->GetEntries().front()->id(), "test_entry_id");
+  EXPECT_EQ(dbus_indicators->GetIndicators().front()->GetEntries().back()->id(), "test_entry_id2");
+
+  // Tell the service to trigger a resync and to send the entries in the reverse order
+  CallPanelMethod("TriggerResync1");
+
+  Utils::WaitUntil(sigc::mem_fun(this, &TestDBusIndicators::TriggerResync1Sent));
+  // We know the resync has been sent, but it may have not been processed
+  // so do one interation of the main loop more
+  g_main_context_iteration(g_main_context_get_thread_default(), TRUE);
+
+  EXPECT_EQ(dbus_indicators->GetIndicators().size(), 1);
+  EXPECT_EQ(dbus_indicators->GetIndicators().front()->GetEntries().size(), 2);
+  EXPECT_EQ(dbus_indicators->GetIndicators().front()->GetEntries().front()->id(), "test_entry_id2");
+  EXPECT_EQ(dbus_indicators->GetIndicators().front()->GetEntries().back()->id(), "test_entry_id");
+}
+
+}

=== modified file 'tests/test_indicator.cpp'
--- tests/test_indicator.cpp	2012-02-01 01:55:05 +0000
+++ tests/test_indicator.cpp	2012-10-09 11:53:25 +0000
@@ -35,6 +35,7 @@
   EXPECT_EQ(indicator.name(), "indicator-test");
   EXPECT_FALSE(indicator.IsAppmenu());
   EXPECT_EQ(indicator.GetEntry("test-entry"), nullptr);
+  EXPECT_EQ(indicator.EntryIndex("test-entry"), -1);
   EXPECT_TRUE(indicator.GetEntries().empty());
 }
 
@@ -76,6 +77,7 @@
   indicator.Sync(sync_data);
   EXPECT_EQ(indicator.GetEntries().size(), 3);
   EXPECT_EQ(indicator.GetEntry("test-entry-2"), entry2);
+  EXPECT_EQ(indicator.EntryIndex("test-entry-2"), 1);
   EXPECT_EQ(added.size(), 3);
   EXPECT_EQ(added.front()->id(), "test-entry-1");
   EXPECT_EQ(added.back()->id(), "test-entry-3");
@@ -91,6 +93,7 @@
   indicator.Sync(sync_data);
   EXPECT_EQ(indicator.GetEntries().size(), 2);
   EXPECT_EQ(indicator.GetEntry("test-entry-2"), nullptr);
+  EXPECT_EQ(indicator.EntryIndex("test-entry-2"), -1);
   EXPECT_EQ(added.size(), 0);
   EXPECT_EQ(removed.size(), 1);
   EXPECT_EQ(removed.front(), entry2->id());

=== modified file 'tests/test_service_main.c'
--- tests/test_service_main.c	2012-03-14 06:24:18 +0000
+++ tests/test_service_main.c	2012-10-09 11:53:25 +0000
@@ -3,6 +3,7 @@
 #include "test_service_lens.h"
 #include "test_service_model.h"
 #include "test_service_hud.h"
+#include "test_service_panel.h"
 #include "test_service_gdbus_wrapper.h"
 
 static void on_bus_aquired(GDBusConnection* conn, const gchar* name, gpointer null);
@@ -37,6 +38,7 @@
 static ServiceLens* lens_ = NULL;
 static ServiceModel* model_ = NULL;
 static ServiceHud* hud_ = NULL;
+static ServicePanel* panel_ = NULL;
 static ServiceGDBusWrapper* gdbus_wrapper_ = NULL;
 gint
 main(gint argc, gchar** argv)
@@ -48,6 +50,7 @@
   lens_ = service_lens_new();
   model_ = service_model_new();
   hud_ = service_hud_new();
+  panel_ = service_panel_new();
   gdbus_wrapper_ = service_gdbus_wrapper_new();
 
   g_bus_own_name(G_BUS_TYPE_SESSION,
@@ -65,6 +68,7 @@
   //g_object_unref(lens_);
   //g_object_unref(model_);
   g_object_unref(hud_);
+  g_object_unref(panel_);
   g_dbus_node_info_unref(introspection_data);
 
   return 0;

=== added file 'tests/test_service_panel.c'
--- tests/test_service_panel.c	1970-01-01 00:00:00 +0000
+++ tests/test_service_panel.c	2012-10-09 11:53:25 +0000
@@ -0,0 +1,253 @@
+#include "test_service_panel.h"
+#include <unity.h>
+#include <gio/gio.h>
+
+static const char * panel_interface = 
+"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+"<node name=\"/\">\n"
+"        <interface name=\"com.canonical.Unity.Panel.Service\">\n"
+"\n"
+"<!-- Begin of real methods/signals -->\n"
+"    <method name='Sync'>"
+"      <arg type='a(ssssbbusbbi)' name='state' direction='out'/>"
+"    </method>"
+"\n"
+"    <signal name='ReSync'>"
+"     <arg type='s' name='indicator_id' />"
+"    </signal>"
+"\n"
+"<!-- Begin of test only methods/signals -->\n"
+"\n"
+"    <method name='TriggerResync1' />"
+"\n"
+"    <method name='TriggerResync1Sent'>"
+"      <arg type='b' name='sent' direction='out'/>"
+"    </method>"
+"\n"
+"        </interface>\n"
+"</node>\n"
+;
+static void bus_got_cb          (GObject *object, GAsyncResult * res, gpointer user_data);
+static void bus_method          (GDBusConnection *connection,
+                                const gchar *sender,
+                                const gchar *object_path,
+                                const gchar *interface_name,
+                                const gchar *method_name,
+                                GVariant *parameters,
+                                GDBusMethodInvocation *invocation,
+                                gpointer user_data);
+
+G_DEFINE_TYPE(ServicePanel, service_panel, G_TYPE_OBJECT);
+static GDBusNodeInfo * node_info = NULL;
+static GDBusInterfaceInfo * iface_info = NULL;
+static GDBusInterfaceVTable bus_vtable = {
+  method_call: bus_method,
+  get_property: NULL,
+  set_property: NULL,
+};
+
+struct _ServicePanelPrivate
+{
+  GDBusConnection * bus;
+  GCancellable * bus_lookup;
+  guint bus_registration;
+  guint sig_emission_handle;
+};
+
+static void
+service_panel_dispose(GObject* object)
+{
+  ServicePanel* self = SERVICE_PANEL(object);
+  if (self->priv->bus_lookup != NULL) {
+    g_cancellable_cancel(self->priv->bus_lookup);
+    g_object_unref(self->priv->bus_lookup);
+    self->priv->bus_lookup = NULL;
+  }
+
+  if (self->priv->bus_registration != 0) {
+    g_dbus_connection_unregister_object(self->priv->bus, self->priv->bus_registration);
+    self->priv->bus_registration = 0;
+  }
+
+  if (self->priv->bus != NULL) {
+    g_object_unref(self->priv->bus);
+    self->priv->bus = NULL;
+  }
+
+  if (self->priv->sig_emission_handle) {
+    g_source_remove(self->priv->sig_emission_handle);
+    self->priv->sig_emission_handle = 0;
+  }
+
+}
+
+static void
+service_panel_class_init(ServicePanelClass* klass)
+{
+  G_OBJECT_CLASS(klass)->dispose = service_panel_dispose;
+  g_type_class_add_private (klass, sizeof (ServicePanelPrivate));
+
+  if (node_info == NULL) 
+  {
+    GError * error = NULL;
+
+    node_info = g_dbus_node_info_new_for_xml(panel_interface, &error);
+    if (error != NULL) 
+    {
+        g_error("Unable to parse Panel interface: %s", error->message);
+        g_error_free(error);
+    }
+  }
+
+  if (node_info != NULL && iface_info == NULL) 
+  {
+    iface_info = g_dbus_node_info_lookup_interface(node_info,"com.canonical.Unity.Panel.Service");
+    if (iface_info == NULL) 
+    {
+      g_error("Unable to find interface 'com.canonical.Unity.Panel.Service'");
+    }
+  }
+
+}
+
+static void
+service_panel_init(ServicePanel* self)
+{
+  self->priv = G_TYPE_INSTANCE_GET_PRIVATE(self, SERVICE_TYPE_PANEL, ServicePanelPrivate);
+  self->priv->bus = NULL;
+  self->priv->bus_lookup = NULL;
+  self->priv->bus_registration = 0;
+  
+  self->priv->bus_lookup = g_cancellable_new();
+  g_bus_get(G_BUS_TYPE_SESSION, self->priv->bus_lookup, bus_got_cb, self);
+}
+
+ServicePanel*
+service_panel_new()
+{
+  return g_object_new(SERVICE_TYPE_PANEL, NULL);
+}
+
+static void
+bus_got_cb (GObject *object, GAsyncResult * res, gpointer user_data)
+{
+  GError * error = NULL;
+  ServicePanel * self = SERVICE_PANEL(user_data);
+  GDBusConnection * bus;
+
+  bus = g_bus_get_finish(res, &error);
+  if (error != NULL) {
+    g_critical("Unable to get bus: %s", error->message);
+    g_error_free(error);
+    return;
+  }
+
+  self->priv->bus = bus;
+
+  /* Register object */
+  self->priv->bus_registration = g_dbus_connection_register_object(bus,
+                                                  /* path */       "/com/canonical/Unity/Panel/Service",
+                                                  /* interface */  iface_info,
+                                                  /* vtable */     &bus_vtable,
+                                                  /* userdata */   self,
+                                                  /* destroy */    NULL,
+                                                  /* error */      &error);
+
+  if (error != NULL) {
+    g_critical ("Unable to create bus connection object, %s", error->message);
+    g_error_free(error);
+    return;
+  }
+
+  return;
+}
+
+static void
+add_entry_id(GVariantBuilder *b)
+{
+  g_variant_builder_add (b, "(ssssbbusbbi)",
+                      "test_indicator_id",
+                      "test_entry_id",
+                      "test_entry_name_hint",
+                      "test_entry_label",
+                      TRUE, /* label sensitive */
+                      TRUE, /* label visible */
+                      0, /* image type */
+                      "", /* image_data */
+                      TRUE, /* image sensitive */
+                      TRUE, /* image visible */
+                      1 /* priority  */);
+}
+
+static void
+add_entry_id_2(GVariantBuilder *b)
+{
+  g_variant_builder_add (b, "(ssssbbusbbi)",
+                      "test_indicator_id",
+                      "test_entry_id2",
+                      "test_entry_name_hint2",
+                      "test_entry_label2",
+                      TRUE, /* label sensitive */
+                      TRUE, /* label visible */
+                      0, /* image type */
+                      "", /* image_data */
+                      TRUE, /* image sensitive */
+                      TRUE, /* image visible */
+                      1 /* priority  */);
+}
+
+static int sync_return_mode = 0;
+static int trigger_resync1_sent = FALSE;
+
+static void
+bus_method (GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *method_name, GVariant *parameters, GDBusMethodInvocation *invocation, gpointer user_data)
+{
+  if (g_strcmp0(method_name, "Sync") == 0) 
+  {
+    GVariantBuilder b;
+
+    g_variant_builder_init (&b, G_VARIANT_TYPE ("(a(ssssbbusbbi))"));
+    g_variant_builder_open (&b, G_VARIANT_TYPE ("a(ssssbbusbbi)"));
+
+    if (sync_return_mode == 0)
+    {
+      add_entry_id(&b);
+      add_entry_id_2(&b);
+    }
+    else if (sync_return_mode == 1)
+    {
+      add_entry_id_2(&b);
+      add_entry_id(&b);
+    }
+
+    g_variant_builder_close (&b);
+
+    g_dbus_method_invocation_return_value(invocation, g_variant_builder_end (&b));
+
+    if (sync_return_mode == 1)
+    {
+      trigger_resync1_sent = TRUE;
+    }
+  }
+  else if (g_strcmp0(method_name, "TriggerResync1") == 0) 
+  {
+    sync_return_mode = 1;
+    trigger_resync1_sent = FALSE;
+
+    g_dbus_method_invocation_return_value(invocation, NULL);
+    GVariantBuilder ret_builder;
+    g_variant_builder_init(&ret_builder, G_VARIANT_TYPE_TUPLE);
+    g_variant_builder_add_value(&ret_builder, g_variant_new_string(""));
+    g_dbus_connection_emit_signal (connection, NULL, "/com/canonical/Unity/Panel/Service", "com.canonical.Unity.Panel.Service", "ReSync", g_variant_builder_end(&ret_builder), NULL);
+  }
+  else if (g_strcmp0(method_name, "TriggerResync1Sent") == 0) 
+  {
+    GVariantBuilder ret_builder;
+    g_variant_builder_init(&ret_builder, G_VARIANT_TYPE ("(b)"));
+    g_variant_builder_add_value (&ret_builder, g_variant_new_boolean(trigger_resync1_sent));
+    g_dbus_method_invocation_return_value(invocation, g_variant_builder_end (&ret_builder));
+  }
+
+  return;
+}
+

=== added file 'tests/test_service_panel.h'
--- tests/test_service_panel.h	1970-01-01 00:00:00 +0000
+++ tests/test_service_panel.h	2012-10-09 11:53:25 +0000
@@ -0,0 +1,46 @@
+#ifndef _SERVICE_PANEL_H_
+#define _SERVICE_PANEL_H_
+
+#include <glib-object.h>
+G_BEGIN_DECLS
+
+#define SERVICE_TYPE_PANEL (service_panel_get_type ())
+
+#define SERVICE_PANEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),\
+  SERVICE_TYPE_PANEL, ServicePanel))
+
+#define SERVICE_PANEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass),\
+  SERVICE_TYPE_PANEL, ServicePanelClass))
+
+#define SERVICE_IS_PANEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),\
+  SERVICE_TYPE_PANEL))
+
+#define SERVICE_IS_PANEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),\
+  SERVICE_TYPE_PANEL))
+
+#define ServicePanel_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),\
+  SERVICE_TYPE_PANEL, ServicePanelClass))
+
+typedef struct _ServicePanel        ServicePanel;
+typedef struct _ServicePanelClass   ServicePanelClass;
+typedef struct _ServicePanelPrivate ServicePanelPrivate;
+
+struct _ServicePanel
+{
+  GObject parent;
+
+  ServicePanelPrivate *priv;
+};
+
+struct _ServicePanelClass
+{
+  GObjectClass parent_class;
+};
+
+GType service_panel_get_type(void) G_GNUC_CONST;
+
+ServicePanel* service_panel_new(void);
+
+G_END_DECLS
+
+#endif /* _SERVICE_PANEL_H_ */

=== modified file 'tests/test_utils.h'
--- tests/test_utils.h	2012-03-14 06:24:18 +0000
+++ tests/test_utils.h	2012-10-09 11:53:25 +0000
@@ -46,6 +46,20 @@
     EXPECT_TRUE(success);
   }
 
+  static void WaitUntil(std::function<bool()> check_function, bool result = true, unsigned int max_wait = 10)
+  {
+    bool timeout_reached = false;
+    guint32 timeout_id = ScheduleTimeout(&timeout_reached, max_wait * 1000);
+
+    while (!check_function() && !timeout_reached)
+      g_main_context_iteration(g_main_context_get_thread_default(), TRUE);
+
+    if (check_function())
+      g_source_remove(timeout_id);
+
+    EXPECT_EQ(check_function(), result);
+  }
+
   static guint32 ScheduleTimeout(bool* timeout_reached, unsigned int timeout_duration = 10)
   {
     return g_timeout_add(timeout_duration*1000, TimeoutCallback, timeout_reached);

