libweave: Move reading/writing commands ans states files out of libweave

ConfigStore implementation will read and provide that data to libweave.

BUG=brillo:1257
TEST=`FEATURES=test emerge-gizmo libweave buffet`

Change-Id: I8c88e14712d9c5475e759439c222b76e01559a5e
Reviewed-on: https://chromium-review.googlesource.com/293951
Tested-by: Vitaly Buka <vitalybuka@chromium.org>
Reviewed-by: Alex Vakulenko <avakulenko@chromium.org>
Commit-Queue: Vitaly Buka <vitalybuka@chromium.org>
diff --git a/libweave/include/weave/config_store.h b/libweave/include/weave/config_store.h
index e2bb710..8a5af58 100644
--- a/libweave/include/weave/config_store.h
+++ b/libweave/include/weave/config_store.h
@@ -5,8 +5,10 @@
 #ifndef LIBWEAVE_INCLUDE_WEAVE_CONFIG_STORE_H_
 #define LIBWEAVE_INCLUDE_WEAVE_CONFIG_STORE_H_
 
+#include <map>
 #include <set>
 #include <string>
+#include <vector>
 
 #include <base/callback.h>
 #include <base/time/time.h>
@@ -52,6 +54,15 @@
   virtual void SaveSettings(const std::string& settings) = 0;
   virtual void OnSettingsChanged(const Settings& settings) = 0;
 
+  virtual std::string LoadBaseCommandDefs() = 0;
+  virtual std::map<std::string, std::string> LoadCommandDefs() = 0;
+
+  virtual std::string LoadBaseStateDefs() = 0;
+  virtual std::string LoadBaseStateDefaults() = 0;
+
+  virtual std::map<std::string, std::string> LoadStateDefs() = 0;
+  virtual std::vector<std::string> LoadStateDefaults() = 0;
+
  protected:
   virtual ~ConfigStore() = default;
 };
diff --git a/libweave/include/weave/device.h b/libweave/include/weave/device.h
index 47e854c..cdac496 100644
--- a/libweave/include/weave/device.h
+++ b/libweave/include/weave/device.h
@@ -27,8 +27,6 @@
 class Device {
  public:
   struct Options {
-    base::FilePath definitions_path;
-    base::FilePath test_definitions_path;
     bool xmpp_enabled = true;
     bool disable_privet = false;
     bool disable_security = false;
diff --git a/libweave/include/weave/mock_config_store.h b/libweave/include/weave/mock_config_store.h
index de44877..0d03cf2 100644
--- a/libweave/include/weave/mock_config_store.h
+++ b/libweave/include/weave/mock_config_store.h
@@ -5,7 +5,9 @@
 #ifndef LIBWEAVE_INCLUDE_WEAVE_MOCK_CONFIG_STORE_H_
 #define LIBWEAVE_INCLUDE_WEAVE_MOCK_CONFIG_STORE_H_
 
+#include <map>
 #include <string>
+#include <vector>
 
 #include <gmock/gmock.h>
 #include <weave/config_store.h>
@@ -28,6 +30,15 @@
   MOCK_METHOD0(LoadSettings, std::string());
   MOCK_METHOD1(SaveSettings, void(const std::string&));
   MOCK_METHOD1(OnSettingsChanged, void(const Settings&));
+
+  MOCK_METHOD0(LoadBaseCommandDefs, std::string());
+  MOCK_METHOD0(LoadCommandDefs, std::map<std::string, std::string>());
+
+  MOCK_METHOD0(LoadBaseStateDefs, std::string());
+  MOCK_METHOD0(LoadBaseStateDefaults, std::string());
+
+  MOCK_METHOD0(LoadStateDefs, std::map<std::string, std::string>());
+  MOCK_METHOD0(LoadStateDefaults, std::vector<std::string>());
 };
 
 }  // namespace unittests
diff --git a/libweave/src/commands/command_manager.cc b/libweave/src/commands/command_manager.cc
index 34b10e6..6ecd8ba 100644
--- a/libweave/src/commands/command_manager.cc
+++ b/libweave/src/commands/command_manager.cc
@@ -6,6 +6,7 @@
 
 #include <base/files/file_enumerator.h>
 #include <base/values.h>
+#include <weave/config_store.h>
 #include <weave/enum_to_string.h>
 #include <weave/error.h>
 
@@ -27,65 +28,47 @@
   return dictionary_;
 }
 
-bool CommandManager::LoadBaseCommands(const base::DictionaryValue& json,
+bool CommandManager::LoadBaseCommands(const base::DictionaryValue& dict,
                                       ErrorPtr* error) {
-  return base_dictionary_.LoadCommands(json, "", nullptr, error);
+  return base_dictionary_.LoadCommands(dict, "", nullptr, error);
 }
 
-bool CommandManager::LoadBaseCommands(const base::FilePath& json_file_path,
+bool CommandManager::LoadBaseCommands(const std::string& json,
                                       ErrorPtr* error) {
-  std::unique_ptr<const base::DictionaryValue> json =
-      LoadJsonDict(json_file_path, error);
-  if (!json)
+  std::unique_ptr<const base::DictionaryValue> dict = LoadJsonDict(json, error);
+  if (!dict)
     return false;
-  return LoadBaseCommands(*json, error);
+  return LoadBaseCommands(*dict, error);
 }
 
-bool CommandManager::LoadCommands(const base::DictionaryValue& json,
+bool CommandManager::LoadCommands(const base::DictionaryValue& dict,
                                   const std::string& category,
                                   ErrorPtr* error) {
   bool result =
-      dictionary_.LoadCommands(json, category, &base_dictionary_, error);
+      dictionary_.LoadCommands(dict, category, &base_dictionary_, error);
   for (const auto& cb : on_command_changed_)
     cb.Run();
   return result;
 }
 
-bool CommandManager::LoadCommands(const base::FilePath& json_file_path,
+bool CommandManager::LoadCommands(const std::string& json,
+                                  const std::string& category,
                                   ErrorPtr* error) {
-  std::unique_ptr<const base::DictionaryValue> json =
-      LoadJsonDict(json_file_path, error);
-  if (!json)
+  std::unique_ptr<const base::DictionaryValue> dict = LoadJsonDict(json, error);
+  if (!dict)
     return false;
-  std::string category = json_file_path.BaseName().RemoveExtension().value();
-  return LoadCommands(*json, category, error);
+  return LoadCommands(*dict, category, error);
 }
 
-void CommandManager::Startup(const base::FilePath& definitions_path,
-                             const base::FilePath& test_definitions_path) {
+void CommandManager::Startup(ConfigStore* config_store) {
   LOG(INFO) << "Initializing CommandManager.";
-  // Load global standard GCD command dictionary.
-  base::FilePath base_command_file{definitions_path.Append("gcd.json")};
-  LOG(INFO) << "Loading standard commands from " << base_command_file.value();
-  CHECK(LoadBaseCommands(base_command_file, nullptr))
-      << "Failed to load the standard command definitions.";
 
-  auto LoadPackages = [this](const base::FilePath& root,
-                             const base::FilePath::StringType& pattern) {
-    base::FilePath device_command_dir{root.Append("commands")};
-    VLOG(2) << "Looking for commands in " << root.value();
-    base::FileEnumerator enumerator(device_command_dir, false,
-                                    base::FileEnumerator::FILES, pattern);
-    base::FilePath json_file_path = enumerator.Next();
-    while (!json_file_path.empty()) {
-      LOG(INFO) << "Loading command schema from " << json_file_path.value();
-      CHECK(this->LoadCommands(json_file_path, nullptr))
-          << "Failed to load the command definition file.";
-      json_file_path = enumerator.Next();
-    }
-  };
-  LoadPackages(definitions_path, FILE_PATH_LITERAL("*.json"));
-  LoadPackages(test_definitions_path, FILE_PATH_LITERAL("*test.json"));
+  // Load global standard GCD command dictionary.
+  CHECK(LoadBaseCommands(config_store->LoadBaseCommandDefs(), nullptr));
+
+  // Loading the rest of commands.
+  for (const auto& defs : config_store->LoadCommandDefs())
+    CHECK(this->LoadCommands(defs.second, defs.first, nullptr));
 }
 
 void CommandManager::AddCommand(
diff --git a/libweave/src/commands/command_manager.h b/libweave/src/commands/command_manager.h
index f42e293..b533579 100644
--- a/libweave/src/commands/command_manager.h
+++ b/libweave/src/commands/command_manager.h
@@ -21,6 +21,7 @@
 namespace weave {
 
 class CommandInstance;
+class ConfigStore;
 
 // CommandManager class that will have a list of all the device command
 // schemas as well as the live command queue of pending command instances
@@ -47,22 +48,22 @@
   const CommandDictionary& GetCommandDictionary() const;
 
   // Loads base/standard GCD command definitions.
-  // |json| is the full JSON schema of standard GCD commands. These commands
+  // |dict| is the full JSON schema of standard GCD commands. These commands
   // are not necessarily supported by a particular device but rather
   // all the standard commands defined by GCD standard for all known/supported
   // device kinds.
   // On success, returns true. Otherwise, |error| contains additional
   // error information.
-  bool LoadBaseCommands(const base::DictionaryValue& json, ErrorPtr* error);
+  bool LoadBaseCommands(const base::DictionaryValue& dict, ErrorPtr* error);
 
   // Same as the overload above, but takes a path to a json file to read
   // the base command definitions from.
-  bool LoadBaseCommands(const base::FilePath& json_file_path, ErrorPtr* error);
+  bool LoadBaseCommands(const std::string& json, ErrorPtr* error);
 
   // Loads device command schema for particular category.
   // See CommandDictionary::LoadCommands for detailed description of the
   // parameters.
-  bool LoadCommands(const base::DictionaryValue& json,
+  bool LoadCommands(const base::DictionaryValue& dict,
                     const std::string& category,
                     ErrorPtr* error);
 
@@ -70,16 +71,15 @@
   // the base command definitions from. Also, the command category is
   // derived from file name (without extension). So, if the path points to
   // "power_manager.json", the command category used will be "power_manager".
-  bool LoadCommands(const base::FilePath& json_file_path, ErrorPtr* error);
+  bool LoadCommands(const std::string& json,
+                    const std::string& category,
+                    ErrorPtr* error);
 
   // Startup method to be called by buffet daemon at startup.
-  // Initializes the object and reads files in |definitions_path| to load
+  // Initializes the object and loads:
   //   1) the standard GCD command dictionary
   //   2) static vendor-provided command definitions
-  // If |test_definitions_path| is not empty, we'll also look there for
-  // additional commands.
-  void Startup(const base::FilePath& definitions_path,
-               const base::FilePath& test_definitions_path);
+  void Startup(weave::ConfigStore* config_store);
 
   // Adds a new command to the command queue.
   void AddCommand(std::unique_ptr<CommandInstance> command_instance);
diff --git a/libweave/src/commands/command_manager_unittest.cc b/libweave/src/commands/command_manager_unittest.cc
index 8d79db2..a3b3de6 100644
--- a/libweave/src/commands/command_manager_unittest.cc
+++ b/libweave/src/commands/command_manager_unittest.cc
@@ -4,10 +4,13 @@
 
 #include "libweave/src/commands/command_manager.h"
 
+#include <map>
+
 #include <base/files/file_util.h>
 #include <base/files/scoped_temp_dir.h>
 #include <base/json/json_writer.h>
 #include <gtest/gtest.h>
+#include <weave/mock_config_store.h>
 
 #include "libweave/src/bind_lambda.h"
 #include "libweave/src/commands/unittest_utils.h"
@@ -19,55 +22,40 @@
 namespace {
 
 const char kTestBaseCommands[] = R"({
-  'base': {
-    'reboot': {
-      'parameters': {'delay': 'integer'},
-      'results': {}
+  "base": {
+    "reboot": {
+      "parameters": {"delay": "integer"},
+      "results": {}
     },
-    'shutdown': {
-      'parameters': {},
-      'results': {}
+    "shutdown": {
+      "parameters": {},
+      "results": {}
     }
   }
 })";
 
 const char kTestVendorCommands[] = R"({
-  'robot': {
-    '_jump': {
-      'parameters': {'height': 'integer'},
-      'results': {}
+  "robot": {
+    "_jump": {
+      "parameters": {"height": "integer"},
+      "results": {}
     },
-    '_speak': {
-      'parameters': {'phrase': 'string'},
-      'results': {}
+    "_speak": {
+      "parameters": {"phrase": "string"},
+      "results": {}
     }
   }
 })";
 
 const char kTestTestCommands[] = R"({
-  'test': {
-    '_yo': {
-      'parameters': {'name': 'string'},
-      'results': {}
+  "test": {
+    "_yo": {
+      "parameters": {"name": "string"},
+      "results": {}
     }
   }
 })";
 
-static void SaveJsonToFile(const base::DictionaryValue& dict,
-                           const base::FilePath& file_path) {
-  std::string json;
-  base::JSONWriter::Write(dict, &json);
-  const int bytes_to_write = static_cast<int>(json.size());
-  CHECK_EQ(bytes_to_write, WriteFile(file_path, json.data(), bytes_to_write));
-}
-
-static base::FilePath SaveJsonToTempFile(const base::DictionaryValue& dict) {
-  base::FilePath temp_file;
-  base::CreateTemporaryFile(&temp_file);
-  SaveJsonToFile(dict, temp_file);
-  return temp_file;
-}
-
 }  // namespace
 
 TEST(CommandManager, Empty) {
@@ -81,21 +69,13 @@
   EXPECT_TRUE(manager.LoadBaseCommands(*json, nullptr));
 }
 
-TEST(CommandManager, LoadBaseCommandsFile) {
-  CommandManager manager;
-  auto json = CreateDictionaryValue(kTestBaseCommands);
-  base::FilePath temp_file = SaveJsonToTempFile(*json);
-  EXPECT_TRUE(manager.LoadBaseCommands(temp_file, nullptr));
-  base::DeleteFile(temp_file, false);
-}
-
-TEST(CommandManager, LoadCommandsJSON) {
+TEST(CommandManager, LoadCommandsDict) {
   CommandManager manager;
   auto json = CreateDictionaryValue(kTestVendorCommands);
   EXPECT_TRUE(manager.LoadCommands(*json, "category", nullptr));
 }
 
-TEST(CommandManager, LoadCommandsFile) {
+TEST(CommandManager, LoadCommandsJson) {
   CommandManager manager;
   // Load some standard command definitions first.
   auto json = CreateDictionaryValue(R"({
@@ -111,24 +91,23 @@
     }
   })");
   manager.LoadBaseCommands(*json, nullptr);
+
   // Load device-supported commands.
-  json = CreateDictionaryValue(R"({
-    'base': {
-      'reboot': {
-        'parameters': {'delay': 'integer'},
-        'results': {}
+  auto json_str = R"({
+    "base": {
+      "reboot": {
+        "parameters": {"delay": "integer"},
+        "results": {}
       }
     },
-    'robot': {
-      '_jump': {
-        'parameters': {'height': 'integer'},
-        'results': {}
+    "robot": {
+      "_jump": {
+        "parameters": {"height": "integer"},
+        "results": {}
       }
     }
-  })");
-  base::FilePath temp_file = SaveJsonToTempFile(*json);
-  EXPECT_TRUE(manager.LoadCommands(temp_file, nullptr));
-  base::DeleteFile(temp_file, false);
+  })";
+  EXPECT_TRUE(manager.LoadCommands(json_str, "test", nullptr));
   EXPECT_EQ(2, manager.GetCommandDictionary().GetSize());
   EXPECT_NE(nullptr, manager.GetCommandDictionary().FindCommand("base.reboot"));
   EXPECT_NE(nullptr, manager.GetCommandDictionary().FindCommand("robot._jump"));
@@ -136,21 +115,13 @@
 
 TEST(CommandManager, ShouldLoadStandardAndTestDefinitions) {
   CommandManager manager;
-  base::ScopedTempDir temp;
-  CHECK(temp.CreateUniqueTempDir());
-  base::FilePath base_path{temp.path().Append("base_defs")};
-  base::FilePath test_path{temp.path().Append("test_defs")};
-  base::FilePath base_commands_path{base_path.Append("commands")};
-  base::FilePath test_commands_path{test_path.Append("commands")};
-  CHECK(CreateDirectory(base_commands_path));
-  CHECK(CreateDirectory(test_commands_path));
-  SaveJsonToFile(*CreateDictionaryValue(kTestBaseCommands),
-                 base_path.Append("gcd.json"));
-  SaveJsonToFile(*CreateDictionaryValue(kTestVendorCommands),
-                 base_commands_path.Append("category.json"));
-  SaveJsonToFile(*CreateDictionaryValue(kTestTestCommands),
-                 test_commands_path.Append("test.json"));
-  manager.Startup(base_path, test_path);
+  unittests::MockConfigStore config_store;
+  EXPECT_CALL(config_store, LoadBaseCommandDefs())
+      .WillOnce(Return(kTestBaseCommands));
+  EXPECT_CALL(config_store, LoadCommandDefs())
+      .WillOnce(Return(std::map<std::string, std::string>{
+          {"category", kTestVendorCommands}, {"test", kTestTestCommands}}));
+  manager.Startup(&config_store);
   EXPECT_EQ(3, manager.GetCommandDictionary().GetSize());
   EXPECT_NE(nullptr, manager.GetCommandDictionary().FindCommand("robot._jump"));
   EXPECT_NE(nullptr,
diff --git a/libweave/src/device_manager.cc b/libweave/src/device_manager.cc
index e5710d4..0f51098 100644
--- a/libweave/src/device_manager.cc
+++ b/libweave/src/device_manager.cc
@@ -35,11 +35,10 @@
                           Mdns* mdns,
                           HttpServer* http_server) {
   command_manager_ = std::make_shared<CommandManager>();
-  command_manager_->Startup(options.definitions_path,
-                            options.test_definitions_path);
+  command_manager_->Startup(config_store);
   state_change_queue_.reset(new StateChangeQueue(kMaxStateChangeQueueSize));
   state_manager_ = std::make_shared<StateManager>(state_change_queue_.get());
-  state_manager_->Startup();
+  state_manager_->Startup(config_store);
 
   std::unique_ptr<Config> config{new Config{config_store}};
   config->Load();
diff --git a/libweave/src/device_registration_info.cc b/libweave/src/device_registration_info.cc
index 26e47ed..62d1ac9 100644
--- a/libweave/src/device_registration_info.cc
+++ b/libweave/src/device_registration_info.cc
@@ -827,8 +827,9 @@
     ErrorPtr* error) {
   Config::Transaction change(config_.get());
   if (!change.set_local_anonymous_access_role(anonymous_access_role)) {
-    Error::AddToPrintf(error, FROM_HERE, kErrorDomain, "invalid_parameter",
-                       "Invalid role: %s", anonymous_access_role.c_str());
+    Error::AddToPrintf(error, FROM_HERE, errors::kErrorDomain,
+                       "invalid_parameter", "Invalid role: %s",
+                       anonymous_access_role.c_str());
     return false;
   }
 
@@ -846,7 +847,7 @@
     const std::string& service_url,
     ErrorPtr* error) {
   if (HaveRegistrationCredentials()) {
-    Error::AddTo(error, FROM_HERE, kErrorDomain, "already_registered",
+    Error::AddTo(error, FROM_HERE, errors::kErrorDomain, "already_registered",
                  "Unable to change config for registered device");
     return false;
   }
diff --git a/libweave/src/states/state_manager.cc b/libweave/src/states/state_manager.cc
index 455b563..9d78178 100644
--- a/libweave/src/states/state_manager.cc
+++ b/libweave/src/states/state_manager.cc
@@ -4,10 +4,9 @@
 
 #include "libweave/src/states/state_manager.h"
 
-#include <base/files/file_enumerator.h>
-#include <base/files/file_path.h>
 #include <base/logging.h>
 #include <base/values.h>
+#include <weave/config_store.h>
 
 #include "libweave/src/json_error_codes.h"
 #include "libweave/src/states/error_codes.h"
@@ -29,47 +28,22 @@
   callback.Run();  // Force to read current state.
 }
 
-void StateManager::Startup() {
+void StateManager::Startup(ConfigStore* config_store) {
   LOG(INFO) << "Initializing StateManager.";
 
   // Load standard device state definition.
-  base::FilePath base_state_file("/etc/buffet/base_state.schema.json");
-  LOG(INFO) << "Loading standard state definition from "
-            << base_state_file.value();
-  CHECK(LoadBaseStateDefinition(base_state_file, nullptr))
-      << "Failed to load the standard state definition file.";
+  CHECK(LoadBaseStateDefinition(config_store->LoadBaseStateDefs(), nullptr));
 
   // Load component-specific device state definitions.
-  base::FilePath device_state_dir("/etc/buffet/states");
-  base::FileEnumerator enumerator(device_state_dir, false,
-                                  base::FileEnumerator::FILES,
-                                  FILE_PATH_LITERAL("*.schema.json"));
-  base::FilePath json_file_path = enumerator.Next();
-  while (!json_file_path.empty()) {
-    LOG(INFO) << "Loading state definition from " << json_file_path.value();
-    CHECK(LoadStateDefinition(json_file_path, nullptr))
-        << "Failed to load the state definition file.";
-    json_file_path = enumerator.Next();
-  }
+  for (const auto& pair : config_store->LoadStateDefs())
+    CHECK(LoadStateDefinition(pair.first, pair.second, nullptr));
 
   // Load standard device state defaults.
-  base::FilePath base_state_defaults("/etc/buffet/base_state.defaults.json");
-  LOG(INFO) << "Loading base state defaults from "
-            << base_state_defaults.value();
-  CHECK(LoadStateDefaults(base_state_defaults, nullptr))
-      << "Failed to load the base state defaults.";
+  CHECK(LoadStateDefaults(config_store->LoadBaseStateDefaults(), nullptr));
 
   // Load component-specific device state defaults.
-  base::FileEnumerator enumerator2(device_state_dir, false,
-                                   base::FileEnumerator::FILES,
-                                   FILE_PATH_LITERAL("*.defaults.json"));
-  json_file_path = enumerator2.Next();
-  while (!json_file_path.empty()) {
-    LOG(INFO) << "Loading state defaults from " << json_file_path.value();
-    CHECK(LoadStateDefaults(json_file_path, nullptr))
-        << "Failed to load the state defaults.";
-    json_file_path = enumerator2.Next();
-  }
+  for (const auto& json : config_store->LoadStateDefaults())
+    CHECK(LoadStateDefaults(json, nullptr));
 
   for (const auto& cb : on_changed_)
     cb.Run();
@@ -151,15 +125,15 @@
   state_change_queue_->NotifyStateUpdatedOnServer(id);
 }
 
-bool StateManager::LoadStateDefinition(const base::DictionaryValue& json,
+bool StateManager::LoadStateDefinition(const base::DictionaryValue& dict,
                                        const std::string& category,
                                        ErrorPtr* error) {
-  base::DictionaryValue::Iterator iter(json);
+  base::DictionaryValue::Iterator iter(dict);
   while (!iter.IsAtEnd()) {
     std::string package_name = iter.key();
     if (package_name.empty()) {
-      Error::AddTo(error, FROM_HERE, kErrorDomain, kInvalidPackageError,
-                   "State package name is empty");
+      Error::AddTo(error, FROM_HERE, errors::kErrorDomain,
+                   errors::kInvalidPackageError, "State package name is empty");
       return false;
     }
     const base::DictionaryValue* package_dict = nullptr;
@@ -182,52 +156,50 @@
   return true;
 }
 
-bool StateManager::LoadStateDefinition(const base::FilePath& json_file_path,
+bool StateManager::LoadStateDefinition(const std::string& json,
+                                       const std::string& category,
                                        ErrorPtr* error) {
-  std::unique_ptr<const base::DictionaryValue> json =
-      LoadJsonDict(json_file_path, error);
-  if (!json)
+  std::unique_ptr<const base::DictionaryValue> dict = LoadJsonDict(json, error);
+  if (!dict)
     return false;
-  std::string category = json_file_path.BaseName().RemoveExtension().value();
   if (category == kDefaultCategory) {
-    Error::AddToPrintf(error, FROM_HERE, kErrorDomain, kInvalidCategoryError,
-                       "Invalid state category specified in '%s'",
-                       json_file_path.value().c_str());
+    Error::AddToPrintf(error, FROM_HERE, errors::kErrorDomain,
+                       errors::kInvalidCategoryError,
+                       "Invalid state category: '%s'", category.c_str());
     return false;
   }
 
-  if (!LoadStateDefinition(*json, category, error)) {
-    Error::AddToPrintf(error, FROM_HERE, kErrorDomain, kFileReadError,
-                       "Failed to load file '%s'",
-                       json_file_path.value().c_str());
+  if (!LoadStateDefinition(*dict, category, error)) {
+    Error::AddToPrintf(error, FROM_HERE, errors::kErrorDomain,
+                       errors::kSchemaError,
+                       "Failed to load state definition: '%s'", json.c_str());
     return false;
   }
   return true;
 }
 
-bool StateManager::LoadBaseStateDefinition(const base::FilePath& json_file_path,
+bool StateManager::LoadBaseStateDefinition(const std::string& json,
                                            ErrorPtr* error) {
-  std::unique_ptr<const base::DictionaryValue> json =
-      LoadJsonDict(json_file_path, error);
-  if (!json)
+  std::unique_ptr<const base::DictionaryValue> dict = LoadJsonDict(json, error);
+  if (!dict)
     return false;
-  if (!LoadStateDefinition(*json, kDefaultCategory, error)) {
-    Error::AddToPrintf(error, FROM_HERE, kErrorDomain, kFileReadError,
-                       "Failed to load file '%s'",
-                       json_file_path.value().c_str());
+  if (!LoadStateDefinition(*dict, kDefaultCategory, error)) {
+    Error::AddToPrintf(
+        error, FROM_HERE, errors::kErrorDomain, errors::kSchemaError,
+        "Failed to load base state definition: '%s'", json.c_str());
     return false;
   }
   return true;
 }
 
-bool StateManager::LoadStateDefaults(const base::DictionaryValue& json,
+bool StateManager::LoadStateDefaults(const base::DictionaryValue& dict,
                                      ErrorPtr* error) {
-  base::DictionaryValue::Iterator iter(json);
+  base::DictionaryValue::Iterator iter(dict);
   while (!iter.IsAtEnd()) {
     std::string package_name = iter.key();
     if (package_name.empty()) {
-      Error::AddTo(error, FROM_HERE, kErrorDomain, kInvalidPackageError,
-                   "State package name is empty");
+      Error::AddTo(error, FROM_HERE, errors::kErrorDomain,
+                   errors::kInvalidPackageError, "State package name is empty");
       return false;
     }
     const base::DictionaryValue* package_dict = nullptr;
@@ -253,16 +225,14 @@
   return true;
 }
 
-bool StateManager::LoadStateDefaults(const base::FilePath& json_file_path,
-                                     ErrorPtr* error) {
-  std::unique_ptr<const base::DictionaryValue> json =
-      LoadJsonDict(json_file_path, error);
-  if (!json)
+bool StateManager::LoadStateDefaults(const std::string& json, ErrorPtr* error) {
+  std::unique_ptr<const base::DictionaryValue> dict = LoadJsonDict(json, error);
+  if (!dict)
     return false;
-  if (!LoadStateDefaults(*json, error)) {
-    Error::AddToPrintf(error, FROM_HERE, kErrorDomain, kFileReadError,
-                       "Failed to load file '%s'",
-                       json_file_path.value().c_str());
+  if (!LoadStateDefaults(*dict, error)) {
+    Error::AddToPrintf(error, FROM_HERE, errors::kErrorDomain,
+                       errors::kSchemaError, "Failed to load defaults: '%s'",
+                       json.c_str());
     return false;
   }
   return true;
diff --git a/libweave/src/states/state_manager.h b/libweave/src/states/state_manager.h
index 1668bb2..59c7716 100644
--- a/libweave/src/states/state_manager.h
+++ b/libweave/src/states/state_manager.h
@@ -22,12 +22,13 @@
 
 namespace base {
 class DictionaryValue;
-class FilePath;
 class Time;
 }  // namespace base
 
 namespace weave {
 
+class ConfigStore;
+
 // StateManager is the class that aggregates the device state fragments
 // provided by device daemons and makes the aggregate device state available
 // to the GCD cloud server and local clients.
@@ -44,7 +45,7 @@
 
   // Initializes the state manager and load device state fragments.
   // Called by Buffet daemon at startup.
-  void Startup();
+  void Startup(ConfigStore* config_store);
 
   // Returns all the categories the state properties are registered from.
   // As with GCD command handling, the category normally represent a device
@@ -78,26 +79,25 @@
   // Loads a device state fragment from a JSON object. |category| represents
   // a device daemon providing the state fragment or empty string for the
   // base state fragment.
-  bool LoadStateDefinition(const base::DictionaryValue& json,
+  bool LoadStateDefinition(const base::DictionaryValue& dict,
                            const std::string& category,
                            ErrorPtr* error);
 
-  // Loads a device state fragment JSON file. The file name (without extension)
-  // is used as the state fragment category.
-  bool LoadStateDefinition(const base::FilePath& json_file_path,
+  // Loads a device state fragment JSON.
+  bool LoadStateDefinition(const std::string& json,
+                           const std::string& category,
                            ErrorPtr* error);
 
-  // Loads the base device state fragment JSON file. This state fragment
+  // Loads the base device state fragment JSON. This state fragment
   // defines the standard state properties from the 'base' package as defined
   // by GCD specification.
-  bool LoadBaseStateDefinition(const base::FilePath& json_file_path,
-                               ErrorPtr* error);
+  bool LoadBaseStateDefinition(const std::string& json, ErrorPtr* error);
 
   // Loads state default values from JSON object.
-  bool LoadStateDefaults(const base::DictionaryValue& json, ErrorPtr* error);
+  bool LoadStateDefaults(const base::DictionaryValue& dict, ErrorPtr* error);
 
-  // Loads state default values from JSON file.
-  bool LoadStateDefaults(const base::FilePath& json_file_path, ErrorPtr* error);
+  // Loads state default values from JSON.
+  bool LoadStateDefaults(const std::string& json, ErrorPtr* error);
 
   // Finds a package by its name. Returns nullptr if not found.
   StatePackage* FindPackage(const std::string& package_name);
diff --git a/libweave/src/utils.cc b/libweave/src/utils.cc
index dd62f88..317eb5d 100644
--- a/libweave/src/utils.cc
+++ b/libweave/src/utils.cc
@@ -5,7 +5,6 @@
 #include "libweave/src/utils.h"
 
 #include <base/bind_helpers.h>
-#include <base/files/file_util.h>
 #include <base/json/json_reader.h>
 
 #include "libweave/src/json_error_codes.h"
@@ -26,23 +25,12 @@
 
 }  // anonymous namespace
 
+namespace errors {
 const char kErrorDomain[] = "weave";
-const char kFileReadError[] = "file_read_error";
+const char kSchemaError[] = "schema_error";
 const char kInvalidCategoryError[] = "invalid_category";
 const char kInvalidPackageError[] = "invalid_package";
-
-std::unique_ptr<base::DictionaryValue> LoadJsonDict(
-    const base::FilePath& json_file_path,
-    ErrorPtr* error) {
-  std::string json_string;
-  if (!base::ReadFileToString(json_file_path, &json_string)) {
-    Error::AddToPrintf(error, FROM_HERE, kErrorDomain, kFileReadError,
-                       "Failed to read file '%s'",
-                       json_file_path.value().c_str());
-    return {};
-  }
-  return LoadJsonDict(json_string, error);
-}
+}  // namespace errors
 
 std::unique_ptr<base::DictionaryValue> LoadJsonDict(
     const std::string& json_string,
diff --git a/libweave/src/utils.h b/libweave/src/utils.h
index 7ef4fa1..29ea138 100644
--- a/libweave/src/utils.h
+++ b/libweave/src/utils.h
@@ -9,30 +9,22 @@
 #include <string>
 
 #include <base/values.h>
-#include <base/files/file_path.h>
 #include <weave/error.h>
 
 namespace weave {
 
-// TODO(avakulenko): This should be consolidated into errors::<domain> namespace
-// See crbug.com/417274
+namespace errors {
 extern const char kErrorDomain[];
-extern const char kFileReadError[];
+extern const char kSchemaError[];
 extern const char kInvalidCategoryError[];
 extern const char kInvalidPackageError[];
+}  // namespace errors
 
 // kDefaultCategory represents a default state property category for standard
 // properties from "base" package which are provided by buffet and not any of
 // the daemons running on the device.
 const char kDefaultCategory[] = "";
 
-// Helper function to load a JSON file that is expected to be
-// an object/dictionary. In case of error, returns empty unique ptr and fills
-// in error details in |error|.
-std::unique_ptr<base::DictionaryValue> LoadJsonDict(
-    const base::FilePath& json_file_path,
-    ErrorPtr* error);
-
 // Helper function to load a JSON dictionary from a string.
 std::unique_ptr<base::DictionaryValue> LoadJsonDict(
     const std::string& json_string,