[shill] Wire IPConfig objects to dbus

BUG=chromium-os:17154
TEST=unit tests
STATUS=Verified

Change-Id: If4344b1df2806dcff914fe1e79d6f0d7705a6eb3
Reviewed-on: http://gerrit.chromium.org/gerrit/3494
Reviewed-by: Darin Petkov <petkov@chromium.org>
Tested-by: Chris Masone <cmasone@chromium.org>
diff --git a/Makefile b/Makefile
index d6cbf1b..47cd615 100644
--- a/Makefile
+++ b/Makefile
@@ -62,6 +62,7 @@
 	glib.o \
 	glib_io_handler.o \
 	ipconfig.o \
+	ipconfig_dbus_adaptor.o \
 	key_file_store.o \
 	manager.o \
 	manager_dbus_adaptor.o \
diff --git a/adaptor_interfaces.h b/adaptor_interfaces.h
index b951cd2..4384456 100644
--- a/adaptor_interfaces.h
+++ b/adaptor_interfaces.h
@@ -72,6 +72,26 @@
  public:
   virtual ~ProfileAdaptorInterface() {}
 
+  // Getter for the opaque identifier that represents this object on the
+  // RPC interface to which the implementation is adapting.
+  virtual const std::string &GetRpcIdentifier() = 0;
+
+  virtual void EmitBoolChanged(const std::string& name, bool value) = 0;
+  virtual void EmitUintChanged(const std::string& name, uint32 value) = 0;
+  virtual void EmitIntChanged(const std::string& name, int value) = 0;
+  virtual void EmitStringChanged(const std::string& name,
+                                 const std::string& value) = 0;
+};
+
+// These are the functions that an IPConfig adaptor must support
+class IPConfigAdaptorInterface {
+ public:
+  virtual ~IPConfigAdaptorInterface() {}
+
+  // Getter for the opaque identifier that represents this object on the
+  // RPC interface to which the implementation is adapting.
+  virtual const std::string &GetRpcIdentifier() = 0;
+
   virtual void EmitBoolChanged(const std::string& name, bool value) = 0;
   virtual void EmitUintChanged(const std::string& name, uint32 value) = 0;
   virtual void EmitIntChanged(const std::string& name, int value) = 0;
diff --git a/control_interface.h b/control_interface.h
index ca8d4dd..680ac63 100644
--- a/control_interface.h
+++ b/control_interface.h
@@ -9,6 +9,8 @@
 
 class Device;
 class DeviceAdaptorInterface;
+class IPConfig;
+class IPConfigAdaptorInterface;
 class Manager;
 class ManagerAdaptorInterface;
 class Profile;
@@ -20,10 +22,12 @@
 class ControlInterface {
  public:
   virtual ~ControlInterface() {}
-  virtual ManagerAdaptorInterface *CreateManagerAdaptor(Manager *manager) = 0;
-  virtual ServiceAdaptorInterface *CreateServiceAdaptor(Service *service) = 0;
   virtual DeviceAdaptorInterface *CreateDeviceAdaptor(Device *device) = 0;
+  virtual IPConfigAdaptorInterface *CreateIPConfigAdaptor(
+      IPConfig *ipconfig) = 0;
+  virtual ManagerAdaptorInterface *CreateManagerAdaptor(Manager *manager) = 0;
   virtual ProfileAdaptorInterface *CreateProfileAdaptor(Profile *profile) = 0;
+  virtual ServiceAdaptorInterface *CreateServiceAdaptor(Service *service) = 0;
 };
 
 }  // namespace shill
diff --git a/dbus_control.cc b/dbus_control.cc
index 0823398..8452c8f 100644
--- a/dbus_control.cc
+++ b/dbus_control.cc
@@ -10,6 +10,7 @@
 
 #include "shill/dbus_control.h"
 #include "shill/device_dbus_adaptor.h"
+#include "shill/ipconfig_dbus_adaptor.h"
 #include "shill/manager_dbus_adaptor.h"
 #include "shill/profile_dbus_adaptor.h"
 #include "shill/service_dbus_adaptor.h"
@@ -19,26 +20,31 @@
 
 DBusControl::~DBusControl() {}
 
-ManagerAdaptorInterface *DBusControl::CreateManagerAdaptor(Manager *manager) {
-  connection_->request_name(ManagerDBusAdaptor::kInterfaceName);
-  return new(std::nothrow) ManagerDBusAdaptor(connection_.get(), manager);
-}
-
-ServiceAdaptorInterface *DBusControl::CreateServiceAdaptor(Service *service) {
-  connection_->request_name(ServiceDBusAdaptor::kInterfaceName);
-  return new(std::nothrow) ServiceDBusAdaptor(connection_.get(), service);
-}
-
 DeviceAdaptorInterface *DBusControl::CreateDeviceAdaptor(Device *device) {
   connection_->request_name(DeviceDBusAdaptor::kInterfaceName);
   return new(std::nothrow) DeviceDBusAdaptor(connection_.get(), device);
 }
 
+IPConfigAdaptorInterface *DBusControl::CreateIPConfigAdaptor(IPConfig *config) {
+  connection_->request_name(IPConfigDBusAdaptor::kInterfaceName);
+  return new(std::nothrow) IPConfigDBusAdaptor(connection_.get(), config);
+}
+
+ManagerAdaptorInterface *DBusControl::CreateManagerAdaptor(Manager *manager) {
+  connection_->request_name(ManagerDBusAdaptor::kInterfaceName);
+  return new(std::nothrow) ManagerDBusAdaptor(connection_.get(), manager);
+}
+
 ProfileAdaptorInterface *DBusControl::CreateProfileAdaptor(Profile *profile) {
   connection_->request_name(ProfileDBusAdaptor::kInterfaceName);
   return new(std::nothrow) ProfileDBusAdaptor(connection_.get(), profile);
 }
 
+ServiceAdaptorInterface *DBusControl::CreateServiceAdaptor(Service *service) {
+  connection_->request_name(ServiceDBusAdaptor::kInterfaceName);
+  return new(std::nothrow) ServiceDBusAdaptor(connection_.get(), service);
+}
+
 void DBusControl::Init() {
   CHECK(!connection_.get());
   dispatcher_.reset(new(std::nothrow) DBus::Glib::BusDispatcher());
diff --git a/dbus_control.h b/dbus_control.h
index a20e67e..a229d73 100644
--- a/dbus_control.h
+++ b/dbus_control.h
@@ -18,10 +18,11 @@
   DBusControl();
   virtual ~DBusControl();
 
-  ManagerAdaptorInterface *CreateManagerAdaptor(Manager *manager);
-  ServiceAdaptorInterface *CreateServiceAdaptor(Service *service);
-  DeviceAdaptorInterface *CreateDeviceAdaptor(Device *device);
-  ProfileAdaptorInterface *CreateProfileAdaptor(Profile *profile);
+  virtual DeviceAdaptorInterface *CreateDeviceAdaptor(Device *device);
+  virtual IPConfigAdaptorInterface *CreateIPConfigAdaptor(IPConfig *ipconfig);
+  virtual ManagerAdaptorInterface *CreateManagerAdaptor(Manager *manager);
+  virtual ProfileAdaptorInterface *CreateProfileAdaptor(Profile *profile);
+  virtual ServiceAdaptorInterface *CreateServiceAdaptor(Service *service);
 
   void Init();
   DBus::Connection *connection() { return connection_.get(); }
diff --git a/ipconfig.cc b/ipconfig.cc
index 5e42eb2..339a198 100644
--- a/ipconfig.cc
+++ b/ipconfig.cc
@@ -6,6 +6,8 @@
 
 #include <base/logging.h>
 
+#include "shill/adaptor_interfaces.h"
+
 using std::string;
 
 namespace shill {
diff --git a/ipconfig.h b/ipconfig.h
index f6ac640..cd9e8fd 100644
--- a/ipconfig.h
+++ b/ipconfig.h
@@ -13,13 +13,17 @@
 #include <base/memory/scoped_ptr.h>
 #include <gtest/gtest_prod.h>  // for FRIEND_TEST
 
+#include "shill/property_store.h"
 #include "shill/refptr_types.h"
 
 namespace shill {
+class ControlInterface;
+class Error;
+class IPConfigAdaptorInterface;
 
 // IPConfig superclass. Individual IP configuration types will inherit from this
 // class.
-class IPConfig : public base::RefCounted<IPConfig> {
+class IPConfig : public PropertyStore, public base::RefCounted<IPConfig> {
  public:
   enum AddressFamily {
     kAddressFamilyUnknown,
@@ -72,11 +76,14 @@
   void UpdateProperties(const Properties &properties, bool success);
 
  private:
+  friend class IPConfigAdaptorInterface;
+
   FRIEND_TEST(DeviceTest, AcquireDHCPConfig);
   FRIEND_TEST(DeviceTest, DestroyIPConfig);
   FRIEND_TEST(IPConfigTest, UpdateCallback);
   FRIEND_TEST(IPConfigTest, UpdateProperties);
 
+  scoped_ptr<IPConfigAdaptorInterface> adaptor_;
   const std::string device_name_;
   Properties properties_;
   scoped_ptr<Callback2<const IPConfigRefPtr&, bool>::Type> update_callback_;
diff --git a/ipconfig_dbus_adaptor.cc b/ipconfig_dbus_adaptor.cc
new file mode 100644
index 0000000..edd97cf
--- /dev/null
+++ b/ipconfig_dbus_adaptor.cc
@@ -0,0 +1,86 @@
+// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "shill/ipconfig_dbus_adaptor.h"
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include <base/logging.h>
+#include <dbus-c++/dbus.h>
+
+#include "shill/error.h"
+#include "shill/ipconfig.h"
+
+using std::map;
+using std::string;
+using std::vector;
+
+namespace shill {
+
+// static
+const char IPConfigDBusAdaptor::kInterfaceName[] = SHILL_INTERFACE;
+// static
+const char IPConfigDBusAdaptor::kPath[] = "/ipconfig/";
+
+IPConfigDBusAdaptor::IPConfigDBusAdaptor(DBus::Connection* conn,
+                                         IPConfig *config)
+    : DBusAdaptor(conn, kPath),
+      ipconfig_(config) {
+}
+
+IPConfigDBusAdaptor::~IPConfigDBusAdaptor() {
+  ipconfig_ = NULL;
+}
+
+void IPConfigDBusAdaptor::EmitBoolChanged(const string &name, bool value) {
+  PropertyChanged(name, DBusAdaptor::BoolToVariant(value));
+}
+
+void IPConfigDBusAdaptor::EmitUintChanged(const string &name,
+                                          uint32 value) {
+  PropertyChanged(name, DBusAdaptor::Uint32ToVariant(value));
+}
+
+void IPConfigDBusAdaptor::EmitIntChanged(const string &name, int value) {
+  PropertyChanged(name, DBusAdaptor::Int32ToVariant(value));
+}
+
+void IPConfigDBusAdaptor::EmitStringChanged(const string &name,
+                                            const string &value) {
+  PropertyChanged(name, DBusAdaptor::StringToVariant(value));
+}
+
+map<string, ::DBus::Variant> IPConfigDBusAdaptor::GetProperties(
+    ::DBus::Error &error) {
+  map<string, ::DBus::Variant> properties;
+  DBusAdaptor::GetProperties(ipconfig_, &properties, &error);
+  return properties;
+}
+
+void IPConfigDBusAdaptor::SetProperty(const string &name,
+                                      const ::DBus::Variant &value,
+                                      ::DBus::Error &error) {
+  if (DBusAdaptor::DispatchOnType(ipconfig_, name, value, &error)) {
+    PropertyChanged(name, value);
+  }
+}
+
+void IPConfigDBusAdaptor::ClearProperty(const std::string& name,
+                                        ::DBus::Error &error) {
+}
+
+void IPConfigDBusAdaptor::Remove(::DBus::Error &error) {
+}
+
+void IPConfigDBusAdaptor::MoveBefore(const ::DBus::Path& path,
+                                     ::DBus::Error &error) {
+}
+
+void IPConfigDBusAdaptor::MoveAfter(const ::DBus::Path& path,
+                                    ::DBus::Error &error) {
+}
+
+}  // namespace shill
diff --git a/ipconfig_dbus_adaptor.h b/ipconfig_dbus_adaptor.h
new file mode 100644
index 0000000..ce6fbf3
--- /dev/null
+++ b/ipconfig_dbus_adaptor.h
@@ -0,0 +1,63 @@
+// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SHILL_IPCONFIG_DBUS_ADAPTOR_H_
+#define SHILL_IPCONFIG_DBUS_ADAPTOR_H_
+
+#include <map>
+#include <string>
+
+#include <base/basictypes.h>
+#include <dbus-c++/dbus.h>
+
+#include "shill/adaptor_interfaces.h"
+#include "shill/dbus_adaptor.h"
+#include "shill/flimflam-ipconfig.h"
+
+namespace shill {
+
+class IPConfig;
+
+// Subclass of DBusAdaptor for IPConfig objects
+// There is a 1:1 mapping between IPConfig and IPConfigDBusAdaptor
+// instances.  Furthermore, the IPConfig owns the IPConfigDBusAdaptor
+// and manages its lifetime, so we're OK with IPConfigDBusAdaptor
+// having a bare pointer to its owner ipconfig.
+class IPConfigDBusAdaptor : public org::chromium::flimflam::IPConfig_adaptor,
+                            public DBusAdaptor,
+                            public IPConfigAdaptorInterface {
+ public:
+  static const char kInterfaceName[];
+  static const char kPath[];
+
+  IPConfigDBusAdaptor(DBus::Connection *conn, IPConfig *ipconfig);
+  virtual ~IPConfigDBusAdaptor();
+
+  // Implementation of IPConfigAdaptorInterface.
+  virtual const std::string &GetRpcIdentifier() { return path(); }
+  virtual void EmitBoolChanged(const std::string &name, bool value);
+  virtual void EmitUintChanged(const std::string &name, uint32 value);
+  virtual void EmitIntChanged(const std::string &name, int value);
+  virtual void EmitStringChanged(const std::string &name,
+                                 const std::string &value);
+
+  // Implementation of IPConfig_adaptor
+  virtual std::map<std::string, ::DBus::Variant> GetProperties(
+      ::DBus::Error &error);
+  virtual void SetProperty(const std::string &name,
+                           const ::DBus::Variant &value,
+                           ::DBus::Error &error);
+  // TODO(cmasone): implement these stubs.
+  virtual void ClearProperty(const std::string& , ::DBus::Error &error);
+  virtual void Remove(::DBus::Error &error);
+  virtual void MoveBefore(const ::DBus::Path& , ::DBus::Error &error);
+  virtual void MoveAfter(const ::DBus::Path& , ::DBus::Error &error);
+
+ private:
+  IPConfig *ipconfig_;
+  DISALLOW_COPY_AND_ASSIGN(IPConfigDBusAdaptor);
+};
+
+}  // namespace shill
+#endif  // SHILL_IPCONFIG_DBUS_ADAPTOR_H_
diff --git a/mock_adaptors.cc b/mock_adaptors.cc
index ae3b97c..75e4953 100644
--- a/mock_adaptors.cc
+++ b/mock_adaptors.cc
@@ -9,6 +9,24 @@
 namespace shill {
 
 // static
+const char DeviceMockAdaptor::kRpcId[] = "device-rpc";
+
+DeviceMockAdaptor::DeviceMockAdaptor() : rpc_id(kRpcId) {}
+
+DeviceMockAdaptor::~DeviceMockAdaptor() {}
+
+const std::string &DeviceMockAdaptor::GetRpcIdentifier() { return rpc_id; }
+
+// static
+const char IPConfigMockAdaptor::kRpcId[] = "ipconfig-rpc";
+
+IPConfigMockAdaptor::IPConfigMockAdaptor() : rpc_id(kRpcId) {}
+
+IPConfigMockAdaptor::~IPConfigMockAdaptor() {}
+
+const std::string &IPConfigMockAdaptor::GetRpcIdentifier() { return rpc_id; }
+
+// static
 const char ManagerMockAdaptor::kRpcId[] = "manager-rpc";
 
 ManagerMockAdaptor::ManagerMockAdaptor() : rpc_id(kRpcId) {}
@@ -18,6 +36,15 @@
 const std::string &ManagerMockAdaptor::GetRpcIdentifier() { return rpc_id; }
 
 // static
+const char ProfileMockAdaptor::kRpcId[] = "profile-rpc";
+
+ProfileMockAdaptor::ProfileMockAdaptor() : rpc_id(kRpcId) {}
+
+ProfileMockAdaptor::~ProfileMockAdaptor() {}
+
+const std::string &ProfileMockAdaptor::GetRpcIdentifier() { return rpc_id; }
+
+// static
 const char ServiceMockAdaptor::kRpcId[] = "service-rpc";
 
 ServiceMockAdaptor::ServiceMockAdaptor() : rpc_id(kRpcId) {}
@@ -25,14 +52,4 @@
 ServiceMockAdaptor::~ServiceMockAdaptor() {}
 
 const std::string &ServiceMockAdaptor::GetRpcIdentifier() { return rpc_id; }
-
-// static
-const char DeviceMockAdaptor::kRpcId[] = "device-rpc";
-
-DeviceMockAdaptor::DeviceMockAdaptor() : rpc_id(kRpcId) {}
-
-DeviceMockAdaptor::~DeviceMockAdaptor() {}
-
-const std::string &DeviceMockAdaptor::GetRpcIdentifier() { return rpc_id; }
-
 }  // namespace shill
diff --git a/mock_adaptors.h b/mock_adaptors.h
index 4f993ca..3bbf671 100644
--- a/mock_adaptors.h
+++ b/mock_adaptors.h
@@ -13,6 +13,43 @@
 
 namespace shill {
 
+// These are the functions that a Device adaptor must support
+class DeviceMockAdaptor : public DeviceAdaptorInterface {
+ public:
+  static const char kRpcId[];
+
+  DeviceMockAdaptor();
+  virtual ~DeviceMockAdaptor();
+  virtual const std::string &GetRpcIdentifier();
+
+  MOCK_METHOD0(UpdateEnabled, void(void));
+  MOCK_METHOD2(EmitBoolChanged, void(const std::string&, bool));
+  MOCK_METHOD2(EmitUintChanged, void(const std::string&, uint32));
+  MOCK_METHOD2(EmitIntChanged, void(const std::string&, int));
+  MOCK_METHOD2(EmitStringChanged, void(const std::string&, const std::string&));
+
+ private:
+  const std::string rpc_id;
+};
+
+// These are the functions that a IPConfig adaptor must support
+class IPConfigMockAdaptor : public IPConfigAdaptorInterface {
+ public:
+  static const char kRpcId[];
+
+  IPConfigMockAdaptor();
+  virtual ~IPConfigMockAdaptor();
+  virtual const std::string &GetRpcIdentifier();
+
+  MOCK_METHOD2(EmitBoolChanged, void(const std::string&, bool));
+  MOCK_METHOD2(EmitUintChanged, void(const std::string&, uint32));
+  MOCK_METHOD2(EmitIntChanged, void(const std::string&, int));
+  MOCK_METHOD2(EmitStringChanged, void(const std::string&, const std::string&));
+
+ private:
+  const std::string rpc_id;
+};
+
 // These are the functions that a Manager adaptor must support
 class ManagerMockAdaptor : public ManagerAdaptorInterface {
  public:
@@ -34,6 +71,24 @@
   const std::string rpc_id;
 };
 
+// These are the functions that a Profile adaptor must support
+class ProfileMockAdaptor : public ProfileAdaptorInterface {
+ public:
+  static const char kRpcId[];
+
+  ProfileMockAdaptor();
+  virtual ~ProfileMockAdaptor();
+  virtual const std::string &GetRpcIdentifier();
+
+  MOCK_METHOD2(EmitBoolChanged, void(const std::string&, bool));
+  MOCK_METHOD2(EmitUintChanged, void(const std::string&, uint32));
+  MOCK_METHOD2(EmitIntChanged, void(const std::string&, int));
+  MOCK_METHOD2(EmitStringChanged, void(const std::string&, const std::string&));
+
+ private:
+  const std::string rpc_id;
+};
+
 // These are the functions that a Service adaptor must support
 class ServiceMockAdaptor : public ServiceAdaptorInterface {
  public:
@@ -53,35 +108,5 @@
   const std::string rpc_id;
 };
 
-// These are the functions that a Device adaptor must support
-class DeviceMockAdaptor : public DeviceAdaptorInterface {
- public:
-  static const char kRpcId[];
-
-  DeviceMockAdaptor();
-  virtual ~DeviceMockAdaptor();
-  virtual const std::string &GetRpcIdentifier();
-
-  MOCK_METHOD0(UpdateEnabled, void(void));
-  MOCK_METHOD2(EmitBoolChanged, void(const std::string&, bool));
-  MOCK_METHOD2(EmitUintChanged, void(const std::string&, uint32));
-  MOCK_METHOD2(EmitIntChanged, void(const std::string&, int));
-  MOCK_METHOD2(EmitStringChanged, void(const std::string&, const std::string&));
-
- private:
-  const std::string rpc_id;
-};
-
-// These are the functions that a Profile adaptor must support
-class ProfileMockAdaptor : public ProfileAdaptorInterface {
- public:
-  ProfileMockAdaptor() {}
-  virtual ~ProfileMockAdaptor() {}
-  MOCK_METHOD2(EmitBoolChanged, void(const std::string&, bool));
-  MOCK_METHOD2(EmitUintChanged, void(const std::string&, uint32));
-  MOCK_METHOD2(EmitIntChanged, void(const std::string&, int));
-  MOCK_METHOD2(EmitStringChanged, void(const std::string&, const std::string&));
-};
-
 }  // namespace shill
 #endif  // SHILL_MOCK_ADAPTORS_
diff --git a/mock_control.cc b/mock_control.cc
index 0504963..4358cec 100644
--- a/mock_control.cc
+++ b/mock_control.cc
@@ -11,20 +11,24 @@
 
 MockControl::~MockControl() {}
 
-ManagerAdaptorInterface *MockControl::CreateManagerAdaptor(Manager *manager) {
-  return new ManagerMockAdaptor();
-}
-
-ServiceAdaptorInterface *MockControl::CreateServiceAdaptor(Service *service) {
-  return new ServiceMockAdaptor();
-}
-
 DeviceAdaptorInterface *MockControl::CreateDeviceAdaptor(Device *device) {
   return new DeviceMockAdaptor();
 }
 
+IPConfigAdaptorInterface *MockControl::CreateIPConfigAdaptor(IPConfig *config) {
+  return new IPConfigMockAdaptor();
+}
+
+ManagerAdaptorInterface *MockControl::CreateManagerAdaptor(Manager *manager) {
+  return new ManagerMockAdaptor();
+}
+
 ProfileAdaptorInterface *MockControl::CreateProfileAdaptor(Profile *profile) {
   return new ProfileMockAdaptor();
 }
 
+ServiceAdaptorInterface *MockControl::CreateServiceAdaptor(Service *service) {
+  return new ServiceMockAdaptor();
+}
+
 }  // namespace shill
diff --git a/mock_control.h b/mock_control.h
index 207a1dd..8590796 100644
--- a/mock_control.h
+++ b/mock_control.h
@@ -19,10 +19,11 @@
 
   // Each of these can be called once.  Ownership of the appropriate
   // interface pointer is given up upon call.
-  ManagerAdaptorInterface *CreateManagerAdaptor(Manager *manager);
-  ServiceAdaptorInterface *CreateServiceAdaptor(Service *service);
-  DeviceAdaptorInterface *CreateDeviceAdaptor(Device *device);
-  ProfileAdaptorInterface *CreateProfileAdaptor(Profile *profile);
+  virtual DeviceAdaptorInterface *CreateDeviceAdaptor(Device *device);
+  virtual IPConfigAdaptorInterface *CreateIPConfigAdaptor(IPConfig *config);
+  virtual ManagerAdaptorInterface *CreateManagerAdaptor(Manager *manager);
+  virtual ProfileAdaptorInterface *CreateProfileAdaptor(Profile *profile);
+  virtual ServiceAdaptorInterface *CreateServiceAdaptor(Service *service);
 
  private:
   DISALLOW_COPY_AND_ASSIGN(MockControl);
diff --git a/profile_dbus_adaptor.h b/profile_dbus_adaptor.h
index 2cd0308..0030b4b 100644
--- a/profile_dbus_adaptor.h
+++ b/profile_dbus_adaptor.h
@@ -37,25 +37,28 @@
   virtual ~ProfileDBusAdaptor();
 
   // Implementation of ProfileAdaptorInterface.
-  void EmitBoolChanged(const std::string &name, bool value);
-  void EmitUintChanged(const std::string &name, uint32 value);
-  void EmitIntChanged(const std::string &name, int value);
-  void EmitStringChanged(const std::string &name, const std::string &value);
-  void EmitStateChanged(const std::string &new_state);
+  virtual const std::string &GetRpcIdentifier() { return path(); }
+  virtual void EmitBoolChanged(const std::string &name, bool value);
+  virtual void EmitUintChanged(const std::string &name, uint32 value);
+  virtual void EmitIntChanged(const std::string &name, int value);
+  virtual void EmitStringChanged(const std::string &name,
+                                 const std::string &value);
 
   // Implementation of Profile_adaptor
-  std::map<std::string, ::DBus::Variant> GetProperties(::DBus::Error &error);
-  void SetProperty(const std::string &name,
-                   const ::DBus::Variant &value,
-                   ::DBus::Error &error);
+  virtual std::map<std::string, ::DBus::Variant> GetProperties(
+      ::DBus::Error &error);
+  virtual void SetProperty(const std::string &name,
+                           const ::DBus::Variant &value,
+                           ::DBus::Error &error);
 
   // Gets an "Entry", which is apparently a different set of properties than
   // those returned by GetProperties.
-  std::map< std::string, ::DBus::Variant> GetEntry(const std::string& ,
-                                                   ::DBus::Error &error);
+  virtual std::map< std::string, ::DBus::Variant> GetEntry(
+      const std::string& ,
+      ::DBus::Error &error);
 
   // Deletes an Entry.
-  void DeleteEntry(const std::string& , ::DBus::Error &error);
+  virtual void DeleteEntry(const std::string& , ::DBus::Error &error);
 
  private:
   Profile *profile_;