buffet: Extract StorageInterface and implementations into separate files

This will make it easy to reuse file storage and memory storage
implementations in the forthcoming state aggregator.

BUG=chromium:369322
TEST=Unittests

Change-Id: Ie0dc0dbbfcc13e038352ecf77e2ad28bd41907d9
Reviewed-on: https://chromium-review.googlesource.com/198045
Tested-by: Christopher Wiley <wiley@chromium.org>
Reviewed-by: Alex Vakulenko <avakulenko@chromium.org>
Commit-Queue: Alex Vakulenko <avakulenko@chromium.org>
Tested-by: Alex Vakulenko <avakulenko@chromium.org>
diff --git a/buffet/buffet.gyp b/buffet/buffet.gyp
index b94677c..ed036bd 100644
--- a/buffet/buffet.gyp
+++ b/buffet/buffet.gyp
@@ -41,6 +41,7 @@
         'async_event_sequencer.cc',
         'manager.cc',
         'mime_utils.cc',
+        'storage_impls.cc',
         'string_utils.cc',
         'url_utils.cc'
       ],
diff --git a/buffet/device_registration_info.cc b/buffet/device_registration_info.cc
index c9aea9f..e1cadbf 100644
--- a/buffet/device_registration_info.cc
+++ b/buffet/device_registration_info.cc
@@ -4,15 +4,14 @@
 
 #include "buffet/device_registration_info.h"
 
-#include <base/file_util.h>
-#include <base/files/important_file_writer.h>
-#include <base/json/json_reader.h>
+#include <memory>
+
 #include <base/json/json_writer.h>
 #include <base/values.h>
-#include <memory>
 
 #include "buffet/data_encoding.h"
 #include "buffet/device_registration_storage_keys.h"
+#include "buffet/storage_impls.h"
 #include "buffet/http_transport_curl.h"
 #include "buffet/http_utils.h"
 #include "buffet/mime_utils.h"
@@ -94,41 +93,15 @@
   return url::AppendQueryParams(result, params);
 }
 
-class FileStorage : public buffet::DeviceRegistrationInfo::StorageInterface {
- public:
-  virtual std::unique_ptr<base::Value> Load() override {
-    // TODO(avakulenko): Figure out security implications of storing
-    // this data unencrypted.
-    std::string json;
-    if (!base::ReadFileToString(GetFilePath(), &json))
-      return std::unique_ptr<base::Value>();
-
-    return std::unique_ptr<base::Value>(base::JSONReader::Read(json));
-  }
-
-  virtual bool Save(const base::Value* config) {
-    // TODO(avakulenko): Figure out security implications of storing
-    // this data unencrypted.
-    std::string json;
-    base::JSONWriter::WriteWithOptions(config,
-                                       base::JSONWriter::OPTIONS_PRETTY_PRINT,
-                                       &json);
-    return base::ImportantFileWriter::WriteFileAtomically(GetFilePath(), json);
-  }
-
- private:
-  base::FilePath GetFilePath() const{
-    return base::FilePath(kDeviceInfoFilePath);
-  }
-};
-
 }  // anonymous namespace
 
 namespace buffet {
 
 DeviceRegistrationInfo::DeviceRegistrationInfo()
     : transport_(new http::curl::Transport()),
-      storage_(new FileStorage()) {
+      // TODO(avakulenko): Figure out security implications of storing
+      // this data unencrypted.
+      storage_(new FileStorage(base::FilePath(kDeviceInfoFilePath))) {
 }
 
 DeviceRegistrationInfo::DeviceRegistrationInfo(
diff --git a/buffet/device_registration_info.h b/buffet/device_registration_info.h
index c60cf69..f48bae9 100644
--- a/buffet/device_registration_info.h
+++ b/buffet/device_registration_info.h
@@ -14,6 +14,7 @@
 
 #include "buffet/data_encoding.h"
 #include "buffet/http_transport.h"
+#include "buffet/storage_interface.h"
 
 namespace base {
   class Value;
@@ -24,19 +25,6 @@
 // The DeviceRegistrationInfo class represents device registration information.
 class DeviceRegistrationInfo {
  public:
-  // The device registration configuration storage interface.
-  struct StorageInterface {
-    virtual ~StorageInterface() = default;
-    // Load the device registration configuration from storage.
-    // If it fails (e.g. the storage container [file?] doesn't exist), then
-    // it returns empty unique_ptr (aka nullptr).
-    virtual std::unique_ptr<base::Value> Load() = 0;
-    // Save the device registration configuration to storage.
-    // If saved successfully, returns true. Could fail when writing to
-    // physical storage like file system for various reasons (out of disk space,
-    // access permissions, etc).
-    virtual bool Save(const base::Value* config) = 0;
-  };
   // This is a helper class for unit testing.
   class TestHelper;
   // Default-constructed uses CURL HTTP transport.
diff --git a/buffet/device_registration_info_unittest.cc b/buffet/device_registration_info_unittest.cc
index 2357904..93584b4 100644
--- a/buffet/device_registration_info_unittest.cc
+++ b/buffet/device_registration_info_unittest.cc
@@ -12,30 +12,13 @@
 #include "buffet/http_request.h"
 #include "buffet/http_transport_fake.h"
 #include "buffet/mime_utils.h"
+#include "buffet/storage_impls.h"
 
 using namespace buffet;
 using namespace chromeos;
 using namespace chromeos::http;
 
 namespace {
-// StorageInterface for testing. Just stores the values in memory.
-class MemStorage : public DeviceRegistrationInfo::StorageInterface {
- public:
-  virtual std::unique_ptr<base::Value> Load() override {
-    return std::unique_ptr<base::Value>(cache_->DeepCopy());
-  }
-
-  virtual bool Save(const base::Value* config) {
-    cache_.reset(config->DeepCopy());
-    ++save_count_;
-    return true;
-  }
-
-  int save_count_ = 0;
-
-private:
-  std::unique_ptr<base::Value> cache_;
-};
 
 namespace test_data {
 
@@ -332,10 +315,10 @@
   transport->AddHandler(dev_reg->GetOAuthURL("token"), request_type::kPost,
                         base::Bind(OAuth2Handler));
 
-  storage->save_count_ = 0;
+  storage->reset_save_count();
   DeviceRegistrationInfo::TestHelper::SetTestTicketId(dev_reg.get());
   EXPECT_TRUE(dev_reg->FinishRegistration(""));
-  EXPECT_EQ(1, storage->save_count_); // The device info must have been saved.
+  EXPECT_EQ(1, storage->save_count()); // The device info must have been saved.
   EXPECT_EQ(2, transport->GetRequestCount());
 
   // Validate the device info saved to storage...
@@ -401,9 +384,9 @@
   transport->AddHandler(ticket_url, request_type::kPatch,
                         base::Bind(email_patch_handler));
 
-  storage->save_count_ = 0;
+  storage->reset_save_count();
   DeviceRegistrationInfo::TestHelper::SetTestTicketId(dev_reg.get());
   EXPECT_TRUE(dev_reg->FinishRegistration(test_data::kUserAccountAuthCode));
-  EXPECT_EQ(1, storage->save_count_); // The device info must have been saved.
+  EXPECT_EQ(1, storage->save_count()); // The device info must have been saved.
   EXPECT_EQ(4, transport->GetRequestCount());
 }
diff --git a/buffet/storage_impls.cc b/buffet/storage_impls.cc
new file mode 100644
index 0000000..2d2531d
--- /dev/null
+++ b/buffet/storage_impls.cc
@@ -0,0 +1,42 @@
+// Copyright 2014 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 "buffet/storage_impls.h"
+
+#include <base/files/important_file_writer.h>
+#include <base/json/json_reader.h>
+#include <base/json/json_writer.h>
+
+namespace buffet {
+
+FileStorage::FileStorage(const base::FilePath& file_path)
+    : file_path_(file_path) { }
+
+std::unique_ptr<base::Value> FileStorage::Load() {
+  std::string json;
+  if (!base::ReadFileToString(file_path_, &json))
+    return std::unique_ptr<base::Value>();
+
+  return std::unique_ptr<base::Value>(base::JSONReader::Read(json));
+}
+
+bool FileStorage::Save(const base::Value* config) {
+  std::string json;
+  base::JSONWriter::WriteWithOptions(
+      config, base::JSONWriter::OPTIONS_PRETTY_PRINT, &json);
+  return base::ImportantFileWriter::WriteFileAtomically(file_path_, json);
+}
+
+
+std::unique_ptr<base::Value> MemStorage::Load() {
+  return std::unique_ptr<base::Value>(cache_->DeepCopy());
+}
+
+bool MemStorage::Save(const base::Value* config) {
+  cache_.reset(config->DeepCopy());
+  ++save_count_;
+  return true;
+}
+
+}  // namespace buffet
diff --git a/buffet/storage_impls.h b/buffet/storage_impls.h
new file mode 100644
index 0000000..04d5f0f
--- /dev/null
+++ b/buffet/storage_impls.h
@@ -0,0 +1,47 @@
+// Copyright 2014 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 BUFFET_STORAGE_IMPLS_H_
+#define BUFFET_STORAGE_IMPLS_H_
+
+#include <base/basictypes.h>
+#include <base/file_util.h>
+#include <base/values.h>
+
+#include "buffet/storage_interface.h"
+
+namespace buffet {
+
+// Persists the given Value to an atomically written file.
+class FileStorage : public StorageInterface {
+ public:
+  FileStorage(const base::FilePath& file_path);
+  virtual ~FileStorage() = default;
+  virtual std::unique_ptr<base::Value> Load() override;
+  virtual bool Save(const base::Value* config) override;
+
+ private:
+  base::FilePath file_path_;
+  DISALLOW_COPY_AND_ASSIGN(FileStorage);
+};
+
+// StorageInterface for testing. Just stores the values in memory.
+class MemStorage : public StorageInterface {
+ public:
+  MemStorage() = default;
+  virtual ~MemStorage() = default;
+  virtual std::unique_ptr<base::Value> Load() override;
+  virtual bool Save(const base::Value* config) override;
+  int save_count() { return save_count_; }
+  void reset_save_count() { save_count_ = 0; }
+
+ private:
+  int save_count_ = 0;
+  std::unique_ptr<base::Value> cache_;
+  DISALLOW_COPY_AND_ASSIGN(MemStorage);
+};
+
+}  // namespace buffet
+
+#endif  // BUFFET_STORAGE_IMPLS_H_
diff --git a/buffet/storage_interface.h b/buffet/storage_interface.h
new file mode 100644
index 0000000..26d71c1
--- /dev/null
+++ b/buffet/storage_interface.h
@@ -0,0 +1,32 @@
+// Copyright 2014 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 BUFFET_STORAGE_INTERFACE_H_
+#define BUFFET_STORAGE_INTERFACE_H_
+
+#include <memory>
+
+#include <base/values.h>
+
+namespace buffet {
+
+// We need to persist data in a couple places, and it is convenient to hide
+// the details of this storage behind an interface for test purposes.
+class StorageInterface {
+ public:
+  // Load the device registration configuration from storage.
+  // If it fails (e.g. the storage container [file?] doesn't exist), then
+  // it returns empty unique_ptr (aka nullptr).
+  virtual std::unique_ptr<base::Value> Load() = 0;
+
+  // Save the device registration configuration to storage.
+  // If saved successfully, returns true. Could fail when writing to
+  // physical storage like file system for various reasons (out of disk space,
+  // access permissions, etc).
+  virtual bool Save(const base::Value* config) = 0;
+};
+
+}  // namespace buffet
+
+#endif  // BUFFET_STORAGE_INTERFACE_H_