shill: teach property accessors how to clear properties,
and update code that instantiates property accessors
accordingly.

BUG=chromium-os:24814
TEST=new unit tests

Change-Id: Iae385c331648e74916c2eb2b69c41ccc9cdcafdf
Reviewed-on: https://gerrit.chromium.org/gerrit/15289
Reviewed-by: mukesh agrawal <quiche@chromium.org>
Tested-by: mukesh agrawal <quiche@chromium.org>
Commit-Ready: mukesh agrawal <quiche@chromium.org>
diff --git a/wifi_service.cc b/wifi_service.cc
index b4ef8bb..6ef3dbb 100644
--- a/wifi_service.cc
+++ b/wifi_service.cc
@@ -60,10 +60,10 @@
       ssid_(ssid) {
   PropertyStore *store = this->mutable_store();
   store->RegisterConstString(flimflam::kModeProperty, &mode_);
-  HelpRegisterDerivedString(store,
-                            flimflam::kPassphraseProperty,
-                            NULL,
-                            &WiFiService::SetPassphrase);
+  HelpRegisterWriteOnlyDerivedString(flimflam::kPassphraseProperty,
+                                     &WiFiService::SetPassphrase,
+                                     &WiFiService::ClearPassphrase,
+                                     NULL);
   store->RegisterBool(flimflam::kPassphraseRequiredProperty, &need_passphrase_);
   store->RegisterConstString(flimflam::kSecurityProperty, &security_);
 
@@ -206,6 +206,13 @@
   UpdateConnectable();
 }
 
+// ClearPassphrase is separate from SetPassphrase, because the default
+// value for |passphrase_| would not pass validation.
+void WiFiService::ClearPassphrase(Error */*error*/) {
+  passphrase_.clear();
+  UpdateConnectable();
+}
+
 bool WiFiService::IsLoadableFrom(StoreInterface *storage) const {
   return storage->ContainsGroup(GetGenericStorageIdentifier()) ||
       storage->ContainsGroup(GetSpecificStorageIdentifier());
@@ -335,14 +342,16 @@
 }
 
 // private methods
-void WiFiService::HelpRegisterDerivedString(
-    PropertyStore *store,
-    const std::string &name,
-    std::string(WiFiService::*get)(Error *),
-    void(WiFiService::*set)(const std::string&, Error *)) {
-  store->RegisterDerivedString(
+void WiFiService::HelpRegisterWriteOnlyDerivedString(
+    const string &name,
+    void(WiFiService::*set)(const string &, Error *),
+    void(WiFiService::*clear)(Error *),
+    const string *default_value) {
+  mutable_store()->RegisterDerivedString(
       name,
-      StringAccessor(new CustomAccessor<WiFiService, string>(this, get, set)));
+      StringAccessor(
+          new CustomWriteOnlyAccessor<WiFiService, string>(
+              this, set, clear, default_value)));
 }
 
 void WiFiService::ConnectTask() {