buffet: Configure buffet from the file.

We used to keep a lot of constants in the source files, now
let's start to move necessary constants into configuration
file to make it easier control buffet behaviour.

BUG=chromium:364692
TEST=manual

Change-Id: I77b95976746ac11e9b1a16cfc6476b8ac1464295
Reviewed-on: https://chromium-review.googlesource.com/231301
Reviewed-by: Anton Muhin <antonm@chromium.org>
Commit-Queue: Anton Muhin <antonm@chromium.org>
Tested-by: Anton Muhin <antonm@chromium.org>
diff --git a/buffet/device_registration_info.cc b/buffet/device_registration_info.cc
index a54825c..6336c5d 100644
--- a/buffet/device_registration_info.cc
+++ b/buffet/device_registration_info.cc
@@ -15,6 +15,7 @@
 #include <chromeos/data_encoding.h>
 #include <chromeos/errors/error_codes.h>
 #include <chromeos/http/http_utils.h>
+#include <chromeos/key_value_store.h>
 #include <chromeos/mime_utils.h>
 #include <chromeos/strings/string_utils.h>
 #include <chromeos/url_utils.h>
@@ -58,18 +59,6 @@
 const base::FilePath::CharType kDeviceInfoFilePath[] =
     FILE_PATH_LITERAL("/var/lib/buffet/device_reg_info");
 
-bool GetParamValue(
-    const std::map<std::string, std::string>& params,
-    const std::string& param_name,
-    std::string* param_value) {
-  auto p = params.find(param_name);
-  if (p == params.end())
-    return false;
-
-  *param_value = p->second;
-  return true;
-}
-
 std::pair<std::string, std::string> BuildAuthHeader(
     const std::string& access_token_type,
     const std::string& access_token) {
@@ -155,10 +144,12 @@
 
 DeviceRegistrationInfo::DeviceRegistrationInfo(
     const std::shared_ptr<CommandManager>& command_manager,
-    const std::shared_ptr<StateManager>& state_manager)
+    const std::shared_ptr<StateManager>& state_manager,
+    std::unique_ptr<chromeos::KeyValueStore> config_store)
     : DeviceRegistrationInfo(
         command_manager,
         state_manager,
+        std::move(config_store),
         chromeos::http::Transport::CreateDefault(),
         // TODO(avakulenko): Figure out security implications of storing
         // this data unencrypted.
@@ -168,14 +159,18 @@
 DeviceRegistrationInfo::DeviceRegistrationInfo(
     const std::shared_ptr<CommandManager>& command_manager,
     const std::shared_ptr<StateManager>& state_manager,
+    std::unique_ptr<chromeos::KeyValueStore> config_store,
     const std::shared_ptr<chromeos::http::Transport>& transport,
     const std::shared_ptr<StorageInterface>& storage)
     : transport_{transport},
       storage_{storage},
       command_manager_{command_manager},
-      state_manager_{state_manager} {
+      state_manager_{state_manager},
+      config_store_{std::move(config_store)} {
 }
 
+DeviceRegistrationInfo::~DeviceRegistrationInfo() = default;
+
 std::pair<std::string, std::string>
     DeviceRegistrationInfo::GetAuthorizationHeader() const {
   return BuildAuthHeader("Bearer", access_token_);
@@ -833,4 +828,18 @@
       base::Bind(&IgnoreCloudResult), base::Bind(&IgnoreCloudError));
 }
 
+void DeviceRegistrationInfo::GetParamValue(
+    const std::map<std::string, std::string>& params,
+    const std::string& param_name,
+    std::string* param_value) {
+  auto p = params.find(param_name);
+  if (p != params.end()) {
+    *param_value = p->second;
+    return;
+  }
+
+  bool present = config_store_->GetString(param_name, param_value);
+  CHECK(present) << "No default for parameter " << param_name;
+}
+
 }  // namespace buffet
diff --git a/buffet/device_registration_info.h b/buffet/device_registration_info.h
index 91b897c..714652b 100644
--- a/buffet/device_registration_info.h
+++ b/buffet/device_registration_info.h
@@ -23,6 +23,10 @@
 class Value;
 }  // namespace base
 
+namespace chromeos {
+class KeyValueStore;
+}  // namespace chromeos
+
 namespace buffet {
 
 class CommandManager;
@@ -40,15 +44,19 @@
   // This constructor uses CURL HTTP transport.
   DeviceRegistrationInfo(
       const std::shared_ptr<CommandManager>& command_manager,
-      const std::shared_ptr<StateManager>& state_manager);
+      const std::shared_ptr<StateManager>& state_manager,
+      std::unique_ptr<chromeos::KeyValueStore> config_store);
   // This constructor allows to pass in a custom HTTP transport
   // (mainly for testing).
   DeviceRegistrationInfo(
       const std::shared_ptr<CommandManager>& command_manager,
       const std::shared_ptr<StateManager>& state_manager,
+      std::unique_ptr<chromeos::KeyValueStore> config_store,
       const std::shared_ptr<chromeos::http::Transport>& transport,
       const std::shared_ptr<StorageInterface>& storage);
 
+  ~DeviceRegistrationInfo();
+
   // Returns the authorization HTTP header that can be used to talk
   // to GCD server for authenticated device communication.
   // Make sure ValidateAndRefreshAccessToken() is called before this call.
@@ -155,33 +163,35 @@
 
   void PublishStateUpdates();
 
+  void GetParamValue(
+    const std::map<std::string, std::string>& params,
+    const std::string& param_name,
+    std::string* param_value);
+
   // Builds Cloud API devices collection REST resouce which matches
   // current state of the device including command definitions
   // for all supported commands and current device state.
   std::unique_ptr<base::DictionaryValue> BuildDeviceResource(
       chromeos::ErrorPtr* error);
 
-  // Persistent data. Some of default values for testing purposes are used.
-  // TODO(avakulenko): remove these default values in the future.
-  // http://crbug.com/364692
-  std::string client_id_ = "58855907228.apps.googleusercontent.com";
-  std::string client_secret_ = "eHSAREAHrIqPsHBxCE9zPPBi";
-  std::string api_key_ = "AIzaSyDSq46gG-AxUnC3zoqD9COIPrjolFsMfMA";
+  std::string client_id_;
+  std::string client_secret_;
+  std::string api_key_;
   std::string refresh_token_;
   std::string device_id_;
   std::string device_robot_account_;
-  std::string oauth_url_ = "https://accounts.google.com/o/oauth2/";
-  std::string service_url_ = "https://www.googleapis.com/clouddevices/v1/";
+  std::string oauth_url_;
+  std::string service_url_;
 
   // Transient data
   std::string access_token_;
   base::Time access_token_expiration_;
   std::string ticket_id_;
-  std::string device_kind_ = "vendor";
-  std::string name_ = "coffee_pot";
-  std::string display_name_ = "Coffee Pot";
-  std::string description_ = "Easy to clean";
-  std::string location_ = "Kitchen";
+  std::string device_kind_;
+  std::string name_;
+  std::string display_name_;
+  std::string description_;
+  std::string location_;
 
   // HTTP transport used for communications.
   std::shared_ptr<chromeos::http::Transport> transport_;
@@ -192,6 +202,9 @@
   // Device state manager.
   std::shared_ptr<StateManager> state_manager_;
 
+  // Buffet configuration.
+  std::unique_ptr<chromeos::KeyValueStore> config_store_;
+
   friend class TestHelper;
   DISALLOW_COPY_AND_ASSIGN(DeviceRegistrationInfo);
 };
diff --git a/buffet/device_registration_info_unittest.cc b/buffet/device_registration_info_unittest.cc
index 38ada93..56e294a 100644
--- a/buffet/device_registration_info_unittest.cc
+++ b/buffet/device_registration_info_unittest.cc
@@ -9,6 +9,7 @@
 #include <chromeos/bind_lambda.h>
 #include <chromeos/http/http_request.h>
 #include <chromeos/http/http_transport_fake.h>
+#include <chromeos/key_value_store.h>
 #include <chromeos/mime_utils.h>
 #include <gtest/gtest.h>
 
@@ -169,8 +170,21 @@
     transport_ = std::make_shared<chromeos::http::fake::Transport>();
     command_manager_ = std::make_shared<CommandManager>();
     state_manager_ = std::make_shared<StateManager>(&mock_state_change_queue_);
+    std::unique_ptr<chromeos::KeyValueStore> config_store{
+      new chromeos::KeyValueStore};
+    config_store->SetString("client_id", test_data::kClientId);
+    config_store->SetString("client_secret", test_data::kClientSecret);
+    config_store->SetString("api_key", test_data::kApiKey);
+    config_store->SetString("device_kind",  "vendor");
+    config_store->SetString("name",  "coffee_pot");
+    config_store->SetString("display_name",  "Coffee Pot");
+    config_store->SetString("description",  "Easy to clean");
+    config_store->SetString("location",  "Kitchen");
+    config_store->SetString("oauth_url", test_data::kOAuthURL);
+    config_store->SetString("service_url", test_data::kServiceURL);
     dev_reg_ = std::unique_ptr<DeviceRegistrationInfo>(
         new DeviceRegistrationInfo(command_manager_, state_manager_,
+                                   std::move(config_store),
                                    transport_, storage_));
   }
 
diff --git a/buffet/etc/buffet/buffet.conf b/buffet/etc/buffet/buffet.conf
new file mode 100644
index 0000000..a9b3d31
--- /dev/null
+++ b/buffet/etc/buffet/buffet.conf
@@ -0,0 +1,12 @@
+client_id=58855907228.apps.googleusercontent.com
+client_secret=eHSAREAHrIqPsHBxCE9zPPBi
+api_key=AIzaSyDSq46gG-AxUnC3zoqD9COIPrjolFsMfMA
+
+oauth_url=https://accounts.google.com/o/oauth2/
+service_url=https://www.googleapis.com/clouddevices/v1/
+
+device_kind=vendor
+name=coffee_pot
+display_name=Coffee Pot
+description=Easy to clean
+location=Kitchen
diff --git a/buffet/manager.cc b/buffet/manager.cc
index 13ca49f..35010d4 100644
--- a/buffet/manager.cc
+++ b/buffet/manager.cc
@@ -14,6 +14,7 @@
 #include <chromeos/dbus/async_event_sequencer.h>
 #include <chromeos/dbus/exported_object_manager.h>
 #include <chromeos/errors/error.h>
+#include <chromeos/key_value_store.h>
 #include <dbus/bus.h>
 #include <dbus/object_path.h>
 #include <dbus/values_util.h>
@@ -49,8 +50,14 @@
       new StateChangeQueue(kMaxStateChangeQueueSize));
   state_manager_ = std::make_shared<StateManager>(state_change_queue_.get());
   state_manager_->Startup();
+  std::unique_ptr<chromeos::KeyValueStore> config_store{
+    new chromeos::KeyValueStore};
+  config_store->Load(base::FilePath(
+      FILE_PATH_LITERAL("/etc/buffet/buffet.conf")));
   device_info_ = std::unique_ptr<DeviceRegistrationInfo>(
-      new DeviceRegistrationInfo(command_manager_, state_manager_));
+      new DeviceRegistrationInfo(command_manager_,
+                                 state_manager_,
+                                 std::move(config_store)));
   device_info_->Load();
   dbus_adaptor_.RegisterWithDBusObject(&dbus_object_);
   dbus_object_.RegisterAsync(cb);