[shill] Profiles need to own their own storage

We're moving to a model where we rely on the StoreInterface
implementation to maintain profile state, instead of managing
a list of Service objects manually.  Thus, we need to allow
Profile to own its own StoreInterface.

BUG=chromium-os:17253
TEST=unit

Change-Id: Ie62462686ecf598efeac08a2d3180cd372430bb9
Reviewed-on: http://gerrit.chromium.org/gerrit/9916
Commit-Ready: Chris Masone <cmasone@chromium.org>
Reviewed-by: Chris Masone <cmasone@chromium.org>
Tested-by: Chris Masone <cmasone@chromium.org>
Reviewed-by: Paul Stewart <pstew@chromium.org>
diff --git a/profile.cc b/profile.cc
index 4111588..f65aa1b 100644
--- a/profile.cc
+++ b/profile.cc
@@ -8,6 +8,7 @@
 #include <string>
 #include <vector>
 
+#include <base/file_path.h>
 #include <base/logging.h>
 #include <base/stl_util-inl.h>
 #include <base/string_util.h>
@@ -16,6 +17,7 @@
 
 #include "shill/adaptor_interfaces.h"
 #include "shill/control_interface.h"
+#include "shill/key_file_store.h"
 #include "shill/manager.h"
 #include "shill/property_accessor.h"
 #include "shill/service.h"
@@ -57,6 +59,26 @@
   DCHECK_EQ(services_.size(), 0);
 }
 
+bool Profile::InitStorage(GLib *glib) {
+  FilePath final_path;
+  if (!GetStoragePath(&final_path)) {
+    PLOG(ERROR) <<
+        base::StringPrintf("Could not set up profile storage for %s:%s",
+                           name_.user.c_str(), name_.identifier.c_str());
+    return false;
+  }
+  scoped_ptr<KeyFileStore> storage(new KeyFileStore(glib));
+  storage->set_path(final_path);
+  if (!storage->Open()) {
+    PLOG(ERROR) <<
+        base::StringPrintf("Could not open profile storage for %s:%s",
+                           name_.user.c_str(), name_.identifier.c_str());
+    return false;
+  }
+  set_storage(storage.release());
+  return true;
+}
+
 string Profile::GetFriendlyName() {
   return (name_.user.empty() ? "" : name_.user + "/") + name_.identifier;
 }
@@ -65,6 +87,10 @@
   return adaptor_->GetRpcIdentifier();
 }
 
+void Profile::set_storage(StoreInterface *storage) {
+  storage_.reset(storage);
+}
+
 bool Profile::AdoptService(const ServiceRefPtr &service) {
   if (ContainsKey(services_, service->UniqueName()))
     return false;
@@ -90,10 +116,11 @@
 }
 
 bool Profile::MergeService(const ServiceRefPtr &service) {
+  // TODO(cmasone): Make |service| just load itself from |store_|.
   map<string, ServiceRefPtr>::iterator it;
   for (it = services_.begin(); it != services_.end(); ++it) {
     if (Mergeable(it->second, service))
-      return true;  // TODO(cmasone): Perform merge.
+      return true;
   }
   return false;
 }
@@ -104,8 +131,8 @@
   return NULL;
 }
 
-void Profile::Finalize(StoreInterface *storage) {
-  Save(storage);
+void Profile::Finalize() {
+  Save();
   services_.clear();
 }
 
@@ -150,12 +177,8 @@
   return true;
 }
 
-bool Profile::Load(StoreInterface */*storage*/) {
-  return false;
-}
-
-bool Profile::Save(StoreInterface *storage) {
-  return SaveServices(storage);
+bool Profile::Save() {
+  return SaveServices() && storage_->Flush();
 }
 
 bool Profile::GetStoragePath(FilePath *path) {
@@ -192,12 +215,12 @@
       StringsAccessor(new CustomAccessor<Profile, Strings>(this, get, set)));
 }
 
-bool Profile::SaveServices(StoreInterface *storage) {
+bool Profile::SaveServices() {
   for (map<string, ServiceRefPtr>::iterator it = services_.begin();
        it != services_.end();
        ++it) {
     VLOG(1) << "Saving service named " << it->first;
-    if (!it->second->Save(storage))
+    if (!it->second->Save(storage()))
       return false;
   }
   return true;