Merge remote-tracking branch 'weave/master' into dev_dev2

* weave/master:
  libweave: Add libgtest.a dependencies to Makefiles
  Fix assigning error in SecurityManager
  README: fix typo in examples rule
diff --git a/examples/daemon/common/daemon.h b/examples/daemon/common/daemon.h
index 4cccff3..6dc021d 100644
--- a/examples/daemon/common/daemon.h
+++ b/examples/daemon/common/daemon.h
@@ -69,10 +69,11 @@
   };
 
   Daemon(const Options& opts)
-      : config_store_{new weave::examples::FileConfigStore(
-            opts.disable_security_,
-            opts.model_id_)},
-        task_runner_{new weave::examples::EventTaskRunner},
+      : task_runner_{new weave::examples::EventTaskRunner},
+        config_store_{
+            new weave::examples::FileConfigStore(opts.disable_security_,
+                                                 opts.model_id_,
+                                                 task_runner_.get())},
         http_client_{new weave::examples::CurlHttpClient(task_runner_.get())},
         network_{new weave::examples::EventNetworkImpl(task_runner_.get())},
         bluetooth_{new weave::examples::BluetoothImpl} {
@@ -114,8 +115,8 @@
       LOG(INFO) << "Device registered: " << device->GetSettings().cloud_id;
   }
 
-  std::unique_ptr<weave::examples::FileConfigStore> config_store_;
   std::unique_ptr<weave::examples::EventTaskRunner> task_runner_;
+  std::unique_ptr<weave::examples::FileConfigStore> config_store_;
   std::unique_ptr<weave::examples::CurlHttpClient> http_client_;
   std::unique_ptr<weave::examples::EventNetworkImpl> network_;
   std::unique_ptr<weave::examples::BluetoothImpl> bluetooth_;
diff --git a/examples/provider/file_config_store.cc b/examples/provider/file_config_store.cc
index 6faa242..31efaa7 100644
--- a/examples/provider/file_config_store.cc
+++ b/examples/provider/file_config_store.cc
@@ -12,16 +12,27 @@
 #include <string>
 #include <vector>
 
+#include <base/bind.h>
+
 namespace weave {
 namespace examples {
 
 const char kSettingsDir[] = "/var/lib/weave/";
 
 FileConfigStore::FileConfigStore(bool disable_security,
-                                 const std::string& model_id)
+                                 const std::string& model_id,
+                                 provider::TaskRunner* task_runner)
     : disable_security_{disable_security},
       model_id_{model_id},
-      settings_path_{"/var/lib/weave/weave_settings_" + model_id + ".json"} {}
+      task_runner_{task_runner} {}
+
+std::string FileConfigStore::GetPath(const std::string& name) const {
+  std::string path{kSettingsDir};
+  path += path + "weave_settings_" + model_id_;
+  if (!name.empty())
+    path += "_" + name;
+  return path + ".json";
+}
 
 bool FileConfigStore::LoadDefaults(Settings* settings) {
   char host_name[HOST_NAME_MAX] = {};
@@ -55,17 +66,25 @@
 }
 
 std::string FileConfigStore::LoadSettings() {
-  LOG(INFO) << "Loading settings from " << settings_path_;
-  std::ifstream str(settings_path_);
+  return LoadSettings("");
+}
+
+std::string FileConfigStore::LoadSettings(const std::string& name) {
+  LOG(INFO) << "Loading settings from " << GetPath(name);
+  std::ifstream str(GetPath(name));
   return std::string(std::istreambuf_iterator<char>(str),
                      std::istreambuf_iterator<char>());
 }
 
-void FileConfigStore::SaveSettings(const std::string& settings) {
+void FileConfigStore::SaveSettings(const std::string& name,
+                                   const std::string& settings,
+                                   const DoneCallback& callback) {
   CHECK(mkdir(kSettingsDir, S_IRWXU) == 0 || errno == EEXIST);
-  LOG(INFO) << "Saving settings to " << settings_path_;
-  std::ofstream str(settings_path_);
+  LOG(INFO) << "Saving settings to " << GetPath(name);
+  std::ofstream str(GetPath(name));
   str << settings;
+  if (!callback.is_null())
+    task_runner_->PostDelayedTask(FROM_HERE, base::Bind(callback, nullptr), {});
 }
 
 }  // namespace examples
diff --git a/examples/provider/file_config_store.h b/examples/provider/file_config_store.h
index 578f940..e7398d1 100644
--- a/examples/provider/file_config_store.h
+++ b/examples/provider/file_config_store.h
@@ -10,22 +10,30 @@
 #include <vector>
 
 #include <weave/provider/config_store.h>
+#include <weave/provider/task_runner.h>
 
 namespace weave {
 namespace examples {
 
 class FileConfigStore : public provider::ConfigStore {
  public:
-  FileConfigStore(bool disable_security, const std::string& model_id);
+  FileConfigStore(bool disable_security,
+                  const std::string& model_id,
+                  provider::TaskRunner* task_runner);
 
   bool LoadDefaults(Settings* settings) override;
+  std::string LoadSettings(const std::string& name) override;
+  void SaveSettings(const std::string& name,
+                    const std::string& settings,
+                    const DoneCallback& callback) override;
+
   std::string LoadSettings() override;
-  void SaveSettings(const std::string& settings) override;
 
  private:
+  std::string GetPath(const std::string& name) const;
   const bool disable_security_;
   const std::string model_id_;
-  const std::string settings_path_;
+  provider::TaskRunner* task_runner_{nullptr};
 };
 
 }  // namespace examples
diff --git a/include/weave/provider/config_store.h b/include/weave/provider/config_store.h
index 1b7988f..128eccc 100644
--- a/include/weave/provider/config_store.h
+++ b/include/weave/provider/config_store.h
@@ -13,6 +13,7 @@
 #include <base/callback.h>
 #include <base/time/time.h>
 #include <weave/enum_to_string.h>
+#include <weave/error.h>
 #include <weave/settings.h>
 
 namespace weave {
@@ -36,8 +37,8 @@
 // Implementation of LoadSettings() method should load previously
 // stored settings from the persistent storage (file, flash, etc).
 // For example:
-//   std::string FileConfigStore::LoadSettings() {
-//     std::ifstream str("/var/lib/weave/weave_settings.json");
+//   std::string FileConfigStore::LoadSettings(const std::string& name) {
+//     std::ifstream str("/var/lib/weave/weave_" + name + ".json");
 //     return std::string(std::istreambuf_iterator<char>(str),
 //                        std::istreambuf_iterator<char>());
 //   }
@@ -47,9 +48,14 @@
 // Implementation of SaveSettings(...) method should store data in the
 // persistent storage (file, flash, etc).
 // For example:
-//   void FileConfigStore::SaveSettings(const std::string& settings) {
-//     std::ofstream str(kSettingsPath);
+//   void FileConfigStore::SaveSettings(const std::string& name,
+//                                      const std::string& settings,
+//                                      const DoneCallback& callback) {
+//     std::ofstream str("/var/lib/weave/weave_" + name + ".json");
 //     str << settings;
+//     if (!callback.is_null())
+//       task_runner_->PostDelayedTask(FROM_HERE, base::Bind(callback, nullptr),
+//                                     {});
 //   }
 // It is highly recommended to protected data using encryption with
 // hardware backed key.
@@ -67,12 +73,20 @@
 
   // Returns settings saved by SaveSettings during last run of libweave.
   // Implementation should return data as-is without parsing or modifications.
-  virtual std::string LoadSettings() = 0;
+  // |name| is the name of settings blob. Could be used as filename.
+  virtual std::string LoadSettings(const std::string& name) = 0;
 
   // Saves settings. Implementation should save data as-is without parsing or
   // modifications. Data stored in settings can be sensitive, so it's highly
   // recommended to protect data, e.g. using encryption.
-  virtual void SaveSettings(const std::string& settings) = 0;
+  // |name| is the name of settings blob. Could be used as filename.
+  // Implementation must call or post callback
+  virtual void SaveSettings(const std::string& name,
+                            const std::string& settings,
+                            const DoneCallback& callback) = 0;
+
+  // Deprecated: only for migration of old configs to version with |name|.
+  virtual std::string LoadSettings() = 0;
 
  protected:
   virtual ~ConfigStore() {}
diff --git a/include/weave/provider/test/mock_config_store.h b/include/weave/provider/test/mock_config_store.h
index 3873251..e6411d6 100644
--- a/include/weave/provider/test/mock_config_store.h
+++ b/include/weave/provider/test/mock_config_store.h
@@ -39,11 +39,21 @@
           "version": 1,
           "device_id": "TEST_DEVICE_ID"
         })"));
-    EXPECT_CALL(*this, SaveSettings(_)).WillRepeatedly(Return());
+    EXPECT_CALL(*this, LoadSettings("config")).WillRepeatedly(Return(""));
+    EXPECT_CALL(*this, SaveSettings("config", _, _))
+        .WillRepeatedly(testing::WithArgs<1, 2>(testing::Invoke(
+            [](const std::string& json, const DoneCallback& callback) {
+              if (!callback.is_null())
+                callback.Run(nullptr);
+            })));
   }
   MOCK_METHOD1(LoadDefaults, bool(Settings*));
+  MOCK_METHOD1(LoadSettings, std::string(const std::string&));
+  MOCK_METHOD3(SaveSettings,
+               void(const std::string&,
+                    const std::string&,
+                    const DoneCallback&));
   MOCK_METHOD0(LoadSettings, std::string());
-  MOCK_METHOD1(SaveSettings, void(const std::string&));
 };
 
 }  // namespace test
diff --git a/src/config.cc b/src/config.cc
index 37e907c..4c6b140 100644
--- a/src/config.cc
+++ b/src/config.cc
@@ -18,9 +18,12 @@
 #include "src/data_encoding.h"
 #include "src/privet/privet_types.h"
 #include "src/string_utils.h"
+#include "src/bind_lambda.h"
 
 namespace weave {
 
+const char kConfigName[] = "config";
+
 namespace config_keys {
 
 const char kVersion[] = "version";
@@ -140,9 +143,12 @@
 void Config::Transaction::LoadState() {
   if (!config_->config_store_)
     return;
-  std::string json_string = config_->config_store_->LoadSettings();
-  if (json_string.empty())
-    return;
+  std::string json_string = config_->config_store_->LoadSettings(kConfigName);
+  if (json_string.empty()) {
+    json_string = config_->config_store_->LoadSettings();
+    if (json_string.empty())
+      return;
+  }
 
   auto value = base::JSONReader::Read(json_string);
   base::DictionaryValue* dict = nullptr;
@@ -267,7 +273,9 @@
   base::JSONWriter::WriteWithOptions(
       dict, base::JSONWriter::OPTIONS_PRETTY_PRINT, &json_string);
 
-  config_store_->SaveSettings(json_string);
+  config_store_->SaveSettings(
+      kConfigName, json_string,
+      base::Bind([](ErrorPtr error) { CHECK(!error); }));
 }
 
 Config::Transaction::~Transaction() {
diff --git a/src/config_unittest.cc b/src/config_unittest.cc
index 0367516..fbb558a 100644
--- a/src/config_unittest.cc
+++ b/src/config_unittest.cc
@@ -17,18 +17,20 @@
 using testing::_;
 using testing::Invoke;
 using testing::Return;
+using testing::WithArgs;
 
 namespace weave {
 
+const char kConfigName[] = "config";
+
 class ConfigTest : public ::testing::Test {
  protected:
   void SetUp() override {
-    EXPECT_CALL(*this, OnConfigChanged(_))
-        .Times(1);  // Called from AddOnChangedCallback
     Reload();
   }
 
   void Reload() {
+    EXPECT_CALL(*this, OnConfigChanged(_)).Times(1);
     config_.reset(new Config{&config_store_});
     config_->AddOnChangedCallback(
         base::Bind(&ConfigTest::OnConfigChanged, base::Unretained(this)));
@@ -86,31 +88,45 @@
 }
 
 TEST_F(ConfigTest, LoadStateV0) {
-  EXPECT_CALL(config_store_, LoadSettings())
+  EXPECT_CALL(config_store_, LoadSettings(kConfigName))
       .WillOnce(Return(R"({
     "device_id": "state_device_id"
   })"));
 
-  EXPECT_CALL(*this, OnConfigChanged(_)).Times(1);
   Reload();
 
   EXPECT_EQ("state_device_id", GetSettings().cloud_id);
   EXPECT_FALSE(GetSettings().device_id.empty());
   EXPECT_NE(GetSettings().cloud_id, GetSettings().device_id);
 
-  EXPECT_CALL(config_store_, LoadSettings())
+  EXPECT_CALL(config_store_, LoadSettings(kConfigName))
       .WillOnce(Return(R"({
     "device_id": "state_device_id",
     "cloud_id": "state_cloud_id"
   })"));
 
-  EXPECT_CALL(*this, OnConfigChanged(_)).Times(1);
   Reload();
 
   EXPECT_EQ("state_cloud_id", GetSettings().cloud_id);
   EXPECT_EQ("state_device_id", GetSettings().device_id);
 }
 
+TEST_F(ConfigTest, LoadStateUnnamed) {
+  EXPECT_CALL(config_store_, LoadSettings(kConfigName)).WillOnce(Return(""));
+
+  EXPECT_CALL(config_store_, LoadSettings()).Times(1);
+
+  Reload();
+}
+
+TEST_F(ConfigTest, LoadStateNamed) {
+  EXPECT_CALL(config_store_, LoadSettings(kConfigName)).WillOnce(Return("{}"));
+
+  EXPECT_CALL(config_store_, LoadSettings()).Times(0);
+
+  Reload();
+}
+
 TEST_F(ConfigTest, LoadState) {
   auto state = R"({
     "version": 1,
@@ -133,9 +149,8 @@
     "secret": "c3RhdGVfc2VjcmV0",
     "service_url": "state_service_url"
   })";
-  EXPECT_CALL(config_store_, LoadSettings()).WillOnce(Return(state));
+  EXPECT_CALL(config_store_, LoadSettings(kConfigName)).WillOnce(Return(state));
 
-  EXPECT_CALL(*this, OnConfigChanged(_)).Times(1);
   Reload();
 
   EXPECT_EQ("state_client_id", GetSettings().client_id);
@@ -243,9 +258,10 @@
 
   EXPECT_CALL(*this, OnConfigChanged(_)).Times(1);
 
-  EXPECT_CALL(config_store_, SaveSettings(_))
-      .WillOnce(Invoke([](const std::string& json) {
-        auto expected = R"({
+  EXPECT_CALL(config_store_, SaveSettings(kConfigName, _, _))
+      .WillOnce(WithArgs<1, 2>(
+          Invoke([](const std::string& json, const DoneCallback& callback) {
+            auto expected = R"({
           'version': 1,
           'api_key': 'set_api_key',
           'client_id': 'set_client_id',
@@ -266,8 +282,9 @@
           'secret': 'AQIDBAU=',
           'service_url': 'set_service_url'
         })";
-        EXPECT_JSON_EQ(expected, *test::CreateValue(json));
-      }));
+            EXPECT_JSON_EQ(expected, *test::CreateValue(json));
+            callback.Run(nullptr);
+          })));
 
   change.Commit();
 }
diff --git a/src/weave_unittest.cc b/src/weave_unittest.cc
index b106aab..8df63ae 100644
--- a/src/weave_unittest.cc
+++ b/src/weave_unittest.cc
@@ -204,10 +204,6 @@
             })));
   }
 
-  void InitConfigStore() {
-    EXPECT_CALL(config_store_, SaveSettings("")).WillRepeatedly(Return());
-  }
-
   void InitNetwork() {
     EXPECT_CALL(network_, AddConnectionChangedCallback(_))
         .WillRepeatedly(Invoke(
@@ -267,7 +263,6 @@
   }
 
   void InitDefaultExpectations() {
-    InitConfigStore();
     InitNetwork();
     EXPECT_CALL(wifi_, StartAccessPoint(MatchesRegex("TEST_NAME.*prv")))
         .WillOnce(Return());
@@ -360,13 +355,11 @@
 }
 
 TEST_F(WeaveTest, StartMinimal) {
-  InitConfigStore();
   device_ = weave::Device::Create(&config_store_, &task_runner_, &http_client_,
                                   &network_, nullptr, nullptr, &wifi_, nullptr);
 }
 
 TEST_F(WeaveTest, StartNoWifi) {
-  InitConfigStore();
   InitNetwork();
   InitHttpServer();
   InitDnsSd();
@@ -451,7 +444,6 @@
   void SetUp() override {
     WeaveTest::SetUp();
 
-    InitConfigStore();
     InitHttpServer();
     InitNetwork();
     InitDnsSd();