shill: Implement write-only properties

Certain properties (e.g. WIFI Passphrase) are write only and must
not be returned when Service.GetProperties() is called over D-Bus.

This CL implements WriteOnlyProperties, a write-only analog of the
read-only ConstProperties.

Also add a ReadablePropertyConstIterator which only returns the
readable properties. Switch over DBus adaptor and PropertyStore
to use that.

BUG=chromium-os:21196
TEST=Added 2 new unittests.

Change-Id: I52815cc395650e0b49e1acac8d4954deeebcee5d
Reviewed-on: https://gerrit.chromium.org/gerrit/11402
Commit-Ready: Gaurav Shah <gauravsh@chromium.org>
Reviewed-by: Gaurav Shah <gauravsh@chromium.org>
Tested-by: Gaurav Shah <gauravsh@chromium.org>
diff --git a/property_accessor.h b/property_accessor.h
index 542fd8d..306f9c8 100644
--- a/property_accessor.h
+++ b/property_accessor.h
@@ -7,6 +7,7 @@
 
 #include <base/basictypes.h>
 #include <base/logging.h>
+#include <gtest/gtest_prod.h>  // for FRIEND_TEST.
 
 #include "shill/accessor_interface.h"
 #include "shill/error.h"
@@ -34,7 +35,7 @@
   }
   virtual ~PropertyAccessor() {}
 
-  const T &Get() { return *property_; }
+  T Get(Error */*error*/) { return *property_; }
   void Set(const T &value, Error */*error*/) {
     *property_ = value;
   }
@@ -52,7 +53,7 @@
   }
   virtual ~ConstPropertyAccessor() {}
 
-  const T &Get() { return *property_; }
+  T Get(Error */*error*/) { return *property_; }
   void Set(const T &/*value*/, Error *error) {
     // TODO(quiche): check if this is the right error.
     // (maybe Error::kPermissionDenied instead?)
@@ -64,6 +65,31 @@
   DISALLOW_COPY_AND_ASSIGN(ConstPropertyAccessor);
 };
 
+template <class T>
+class WriteOnlyPropertyAccessor : public AccessorInterface<T> {
+ public:
+  explicit WriteOnlyPropertyAccessor(T *property) : property_(property) {
+    DCHECK(property);
+  }
+  virtual ~WriteOnlyPropertyAccessor() {}
+
+  T Get(Error *error) {
+    error->Populate(Error::kPermissionDenied, "Property is write-only");
+    return T();
+  }
+  void Set(const T &value, Error */*error*/) {
+    *property_ = value;
+  }
+
+ private:
+  FRIEND_TEST(PropertyAccessorTest, SignedIntCorrectness);
+  FRIEND_TEST(PropertyAccessorTest, UnsignedIntCorrectness);
+  FRIEND_TEST(PropertyAccessorTest, StringCorrectness);
+
+  T * const property_;
+  DISALLOW_COPY_AND_ASSIGN(WriteOnlyPropertyAccessor);
+};
+
 // CustomAccessor<> allows custom getter and setter methods to be provided.
 // Thus, if the state to be returned is to be derived on-demand, we can
 // still fit it into the AccessorInterface<> framework.
@@ -75,17 +101,23 @@
   // attempts to set via the accessor.
   // It is an error to pass NULL for either of the other two arguments.
   CustomAccessor(C *target,
-                 T(C::*getter)(),
+                 T(C::*getter)(Error *),
                  void(C::*setter)(const T&, Error *))
       : target_(target),
         getter_(getter),
         setter_(setter) {
     DCHECK(target);
-    DCHECK(getter);
   }
   virtual ~CustomAccessor() {}
 
-  const T &Get() { return storage_ = (target_->*getter_)(); }
+  T Get(Error *error) {
+    if (getter_)
+      return storage_ = (target_->*getter_)(error);
+
+    error->Populate(Error::kPermissionDenied, "Property is write-only");
+    return T();
+  }
+
   void Set(const T &value, Error *error) {
     if (setter_) {
       (target_->*setter_)(value, error);
@@ -99,7 +131,7 @@
   // Get() returns a const&, so we need to have internal storage to which to
   // return a reference.
   T storage_;
-  T(C::*getter_)(void);
+  T(C::*getter_)(Error *);
   void(C::*setter_)(const T&, Error *);
   DISALLOW_COPY_AND_ASSIGN(CustomAccessor);
 };