Switch to use ComponentManager for traits/components

Removed the old StateManager, CommandManager and related classes
and switched over to using ComponentManager for all device trait and
component definitions as well as device state.

Change-Id: I99b99a935ba217703d31aa523a3124cca0fa3e90
Reviewed-on: https://weave-review.googlesource.com/1788
Reviewed-by: Alex Vakulenko <avakulenko@google.com>
diff --git a/libweave.gypi b/libweave.gypi
index dc2e6f0..fb7dd03 100644
--- a/libweave.gypi
+++ b/libweave.gypi
@@ -7,9 +7,7 @@
       'src/backoff_entry.cc',
       'src/base_api_handler.cc',
       'src/commands/cloud_command_proxy.cc',
-      'src/commands/command_dictionary.cc',
       'src/commands/command_instance.cc',
-      'src/commands/command_manager.cc',
       'src/commands/command_queue.cc',
       'src/commands/schema_constants.cc',
       'src/component_manager_impl.cc',
@@ -40,10 +38,7 @@
       'src/privet/wifi_bootstrap_manager.cc',
       'src/privet/wifi_ssid_generator.cc',
       'src/registration_status.cc',
-      'src/states/error_codes.cc',
       'src/states/state_change_queue.cc',
-      'src/states/state_manager.cc',
-      'src/states/state_package.cc',
       'src/streams.cc',
       'src/string_utils.cc',
       'src/utils.cc',
@@ -61,9 +56,7 @@
       'src/backoff_entry_unittest.cc',
       'src/base_api_handler_unittest.cc',
       'src/commands/cloud_command_proxy_unittest.cc',
-      'src/commands/command_dictionary_unittest.cc',
       'src/commands/command_instance_unittest.cc',
-      'src/commands/command_manager_unittest.cc',
       'src/commands/command_queue_unittest.cc',
       'src/component_manager_unittest.cc',
       'src/config_unittest.cc',
@@ -80,8 +73,6 @@
       'src/privet/security_manager_unittest.cc',
       'src/privet/wifi_ssid_generator_unittest.cc',
       'src/states/state_change_queue_unittest.cc',
-      'src/states/state_manager_unittest.cc',
-      'src/states/state_package_unittest.cc',
       'src/streams_unittest.cc',
       'src/string_utils_unittest.cc',
       'src/test/weave_testrunner.cc',
diff --git a/src/base_api_handler.cc b/src/base_api_handler.cc
index 1423dd1..6808949 100644
--- a/src/base_api_handler.cc
+++ b/src/base_api_handler.cc
@@ -13,6 +13,8 @@
 namespace weave {
 
 namespace {
+const char kBaseComponent[] = "weave";
+const char kBaseTrait[] = "base";
 const char kBaseStateFirmwareVersion[] = "base.firmwareVersion";
 const char kBaseStateAnonymousAccessRole[] = "base.localAnonymousAccessMaxRole";
 const char kBaseStateDiscoveryEnabled[] = "base.localDiscoveryEnabled";
@@ -22,61 +24,64 @@
 BaseApiHandler::BaseApiHandler(DeviceRegistrationInfo* device_info,
                                Device* device)
     : device_info_{device_info}, device_{device} {
-  device_->AddStateDefinitionsFromJson(R"({
+  device_->AddTraitDefinitionsFromJson(R"({
     "base": {
-      "firmwareVersion": "string",
-      "localDiscoveryEnabled": "boolean",
-      "localAnonymousAccessMaxRole": [ "none", "viewer", "user" ],
-      "localPairingEnabled": "boolean"
+      "commands": {
+        "updateBaseConfiguration": {
+          "minimalRole": "manager",
+          "parameters": {
+            "localAnonymousAccessMaxRole": {
+              "enum": [ "none", "viewer", "user" ],
+              "type": "string"
+            },
+            "localDiscoveryEnabled": {
+              "type": "boolean"
+            },
+            "localPairingEnabled": {
+              "type": "boolean"
+            }
+          }
+        },
+        "updateDeviceInfo": {
+          "minimalRole": "manager",
+          "parameters": {
+            "description": {
+              "type": "string"
+            },
+            "location": {
+              "type": "string"
+            },
+            "name": {
+              "type": "string"
+            }
+          }
+        }
+      },
+      "state": {
+        "firmwareVersion": "string",
+        "localDiscoveryEnabled": "boolean",
+        "localAnonymousAccessMaxRole": [ "none", "viewer", "user" ],
+        "localPairingEnabled": "boolean"
+      }
     }
   })");
+  CHECK(device_->AddComponent(kBaseComponent, {kBaseTrait}, nullptr));
   OnConfigChanged(device_->GetSettings());
 
   const auto& settings = device_info_->GetSettings();
   base::DictionaryValue state;
   state.SetString(kBaseStateFirmwareVersion, settings.firmware_version);
-  CHECK(device_->SetStateProperties(state, nullptr));
-
-  device->AddCommandDefinitionsFromJson(R"({
-    "base": {
-      "updateBaseConfiguration": {
-        "minimalRole": "manager",
-        "parameters": {
-          "localAnonymousAccessMaxRole": {
-            "enum": [ "none", "viewer", "user" ],
-            "type": "string"
-          },
-          "localDiscoveryEnabled": {
-            "type": "boolean"
-          },
-          "localPairingEnabled": {
-            "type": "boolean"
-          }
-        }
-      },
-      "updateDeviceInfo": {
-        "minimalRole": "manager",
-        "parameters": {
-          "description": {
-            "type": "string"
-          },
-          "location": {
-            "type": "string"
-          },
-          "name": {
-            "type": "string"
-          }
-        }
-      }
-    }
-  })");
+  CHECK(device_->SetStateProperty(kBaseComponent, kBaseStateFirmwareVersion,
+                                  base::StringValue{settings.firmware_version},
+                                  nullptr));
 
   device_->AddCommandHandler(
+      kBaseComponent,
       "base.updateBaseConfiguration",
       base::Bind(&BaseApiHandler::UpdateBaseConfiguration,
                  weak_ptr_factory_.GetWeakPtr()));
 
-  device_->AddCommandHandler("base.updateDeviceInfo",
+  device_->AddCommandHandler(kBaseComponent, "base.updateDeviceInfo",
                              base::Bind(&BaseApiHandler::UpdateDeviceInfo,
                                         weak_ptr_factory_.GetWeakPtr()));
 
@@ -128,7 +133,7 @@
   state.SetBoolean(kBaseStateDiscoveryEnabled,
                    settings.local_discovery_enabled);
   state.SetBoolean(kBaseStatePairingEnabled, settings.local_pairing_enabled);
-  device_->SetStateProperties(state, nullptr);
+  device_->SetStateProperties(kBaseComponent, state, nullptr);
 }
 
 void BaseApiHandler::UpdateDeviceInfo(const std::weak_ptr<Command>& cmd) {
diff --git a/src/base_api_handler_unittest.cc b/src/base_api_handler_unittest.cc
index 5c6a8a5..23ef95e 100644
--- a/src/base_api_handler_unittest.cc
+++ b/src/base_api_handler_unittest.cc
@@ -12,11 +12,9 @@
 #include <weave/test/mock_device.h>
 #include <weave/test/unittest_utils.h>
 
-#include "src/commands/command_manager.h"
+#include "src/component_manager_impl.h"
 #include "src/config.h"
 #include "src/device_registration_info.h"
-#include "src/states/mock_state_change_queue_interface.h"
-#include "src/states/state_manager.h"
 
 using testing::_;
 using testing::AnyOf;
@@ -31,35 +29,33 @@
 class BaseApiHandlerTest : public ::testing::Test {
  protected:
   void SetUp() override {
-    EXPECT_CALL(mock_state_change_queue_, NotifyPropertiesUpdated(_, _))
-        .WillRepeatedly(Return(true));
-
-    command_manager_ = std::make_shared<CommandManager>();
-
-    state_manager_ = std::make_shared<StateManager>(&mock_state_change_queue_);
-
-    EXPECT_CALL(device_, AddStateDefinitionsFromJson(_))
+    EXPECT_CALL(device_, AddTraitDefinitionsFromJson(_))
         .WillRepeatedly(Invoke([this](const std::string& json) {
-          EXPECT_TRUE(
-              state_manager_->LoadStateDefinitionFromJson(json, nullptr));
+          EXPECT_TRUE(component_manager_.LoadTraits(json, nullptr));
         }));
-    EXPECT_CALL(device_, SetStateProperties(_, _))
-        .WillRepeatedly(
-            Invoke(state_manager_.get(), &StateManager::SetProperties));
-    EXPECT_CALL(device_, AddCommandDefinitionsFromJson(_))
-        .WillRepeatedly(Invoke([this](const std::string& json) {
-          EXPECT_TRUE(command_manager_->LoadCommands(json, nullptr));
+    EXPECT_CALL(device_, SetStateProperties(_, _, _))
+        .WillRepeatedly(Invoke(&component_manager_,
+                               &ComponentManager::SetStateProperties));
+    EXPECT_CALL(device_, SetStateProperty(_, _, _, _))
+        .WillRepeatedly(Invoke(&component_manager_,
+                               &ComponentManager::SetStateProperty));
+    EXPECT_CALL(device_, AddComponent(_, _, _))
+        .WillRepeatedly(Invoke([this](const std::string& name,
+                                      const std::vector<std::string>& traits,
+                                      ErrorPtr* error) {
+          return component_manager_.AddComponent("", name, traits, error);
         }));
 
-    EXPECT_CALL(device_, AddCommandHandler(AnyOf("base.updateBaseConfiguration",
+    EXPECT_CALL(device_, AddCommandHandler(_,
+                                           AnyOf("base.updateBaseConfiguration",
                                                  "base.updateDeviceInfo"),
                                            _))
-        .WillRepeatedly(
-            Invoke(command_manager_.get(), &CommandManager::AddCommandHandler));
+        .WillRepeatedly(Invoke(&component_manager_,
+                               &ComponentManager::AddCommandHandler));
 
     std::unique_ptr<Config> config{new Config{&config_store_}};
     config->Load();
-    dev_reg_.reset(new DeviceRegistrationInfo(command_manager_, state_manager_,
+    dev_reg_.reset(new DeviceRegistrationInfo(&component_manager_,
                                               std::move(config), nullptr,
                                               &http_client_, nullptr));
 
@@ -70,48 +66,44 @@
   }
 
   void AddCommand(const std::string& command) {
-    auto command_instance = CommandInstance::FromJson(
-        test::CreateDictionaryValue(command.c_str()).get(),
-        Command::Origin::kLocal, nullptr, nullptr);
-    EXPECT_TRUE(!!command_instance);
-
-    std::string id{base::IntToString(++command_id_)};
-    command_instance->SetID(id);
-    command_instance->SetComponent("device");
-    command_manager_->AddCommand(std::move(command_instance));
+    std::string id;
+    auto command_instance = component_manager_.ParseCommandInstance(
+        *test::CreateDictionaryValue(command.c_str()), Command::Origin::kLocal,
+        UserRole::kOwner, &id, nullptr);
+    ASSERT_NE(nullptr, command_instance.get());
+    component_manager_.AddCommand(std::move(command_instance));
     EXPECT_EQ(Command::State::kDone,
-              command_manager_->FindCommand(id)->GetState());
+              component_manager_.FindCommand(id)->GetState());
   }
 
   std::unique_ptr<base::DictionaryValue> GetBaseState() {
-    std::unique_ptr<base::DictionaryValue> state{
-        state_manager_->GetState().DeepCopy()};
-    std::set<std::string> result;
-    for (base::DictionaryValue::Iterator it{*state}; !it.IsAtEnd();
-         it.Advance()) {
-      if (it.key() != "base")
-        state->Remove(it.key(), nullptr);
-    }
+    std::unique_ptr<base::DictionaryValue> state;
+    std::string path = component_manager_.FindComponentWithTrait("base");
+    EXPECT_FALSE(path.empty());
+    const auto* component = component_manager_.FindComponent(path, nullptr);
+    CHECK(component);
+    const base::DictionaryValue* base_state = nullptr;
+    if (component->GetDictionary("state.base", &base_state))
+      state.reset(base_state->DeepCopy());
+    else
+      state.reset(new base::DictionaryValue);
     return state;
   }
 
   provider::test::MockConfigStore config_store_;
   StrictMock<provider::test::MockHttpClient> http_client_;
   std::unique_ptr<DeviceRegistrationInfo> dev_reg_;
-  std::shared_ptr<CommandManager> command_manager_;
-  testing::StrictMock<MockStateChangeQueueInterface> mock_state_change_queue_;
-  std::shared_ptr<StateManager> state_manager_;
+  ComponentManagerImpl component_manager_;
   std::unique_ptr<BaseApiHandler> handler_;
   StrictMock<test::MockDevice> device_;
-  int command_id_{0};
 };
 
 TEST_F(BaseApiHandlerTest, Initialization) {
-  const auto& command_defs =
-      command_manager_->GetCommandDictionary().GetCommandsAsJson();
+  const base::DictionaryValue* trait = nullptr;
+  ASSERT_TRUE(component_manager_.GetTraits().GetDictionary("base", &trait));
 
   auto expected = R"({
-    "base": {
+    "commands": {
       "updateBaseConfiguration": {
         "minimalRole": "manager",
         "parameters": {
@@ -141,9 +133,15 @@
           }
         }
       }
-    }
+    },
+   "state": {
+      "firmwareVersion": "string",
+      "localAnonymousAccessMaxRole": [ "none", "viewer", "user" ],
+      "localDiscoveryEnabled": "boolean",
+      "localPairingEnabled": "boolean"
+   }
   })";
-  EXPECT_JSON_EQ(expected, command_defs);
+  EXPECT_JSON_EQ(expected, *trait);
 }
 
 TEST_F(BaseApiHandlerTest, UpdateBaseConfiguration) {
@@ -151,6 +149,7 @@
 
   AddCommand(R"({
     'name' : 'base.updateBaseConfiguration',
+    'component': 'weave',
     'parameters': {
       'localDiscoveryEnabled': false,
       'localAnonymousAccessMaxRole': 'none',
@@ -162,17 +161,16 @@
   EXPECT_FALSE(settings.local_pairing_enabled);
 
   auto expected = R"({
-    'base': {
-      'firmwareVersion': 'TEST_FIRMWARE',
-      'localAnonymousAccessMaxRole': 'none',
-      'localDiscoveryEnabled': false,
-      'localPairingEnabled': false
-    }
+    'firmwareVersion': 'TEST_FIRMWARE',
+    'localAnonymousAccessMaxRole': 'none',
+    'localDiscoveryEnabled': false,
+    'localPairingEnabled': false
   })";
   EXPECT_JSON_EQ(expected, *GetBaseState());
 
   AddCommand(R"({
     'name' : 'base.updateBaseConfiguration',
+    'component': 'weave',
     'parameters': {
       'localDiscoveryEnabled': true,
       'localAnonymousAccessMaxRole': 'user',
@@ -183,12 +181,10 @@
   EXPECT_TRUE(settings.local_discovery_enabled);
   EXPECT_TRUE(settings.local_pairing_enabled);
   expected = R"({
-    'base': {
-      'firmwareVersion': 'TEST_FIRMWARE',
-      'localAnonymousAccessMaxRole': 'user',
-      'localDiscoveryEnabled': true,
-      'localPairingEnabled': true
-    }
+    'firmwareVersion': 'TEST_FIRMWARE',
+    'localAnonymousAccessMaxRole': 'user',
+    'localDiscoveryEnabled': true,
+    'localPairingEnabled': true
   })";
   EXPECT_JSON_EQ(expected, *GetBaseState());
 
@@ -197,12 +193,10 @@
     change.set_local_anonymous_access_role(AuthScope::kViewer);
   }
   expected = R"({
-    'base': {
-      'firmwareVersion': 'TEST_FIRMWARE',
-      'localAnonymousAccessMaxRole': 'viewer',
-      'localDiscoveryEnabled': true,
-      'localPairingEnabled': true
-    }
+    'firmwareVersion': 'TEST_FIRMWARE',
+    'localAnonymousAccessMaxRole': 'viewer',
+    'localDiscoveryEnabled': true,
+    'localPairingEnabled': true
   })";
   EXPECT_JSON_EQ(expected, *GetBaseState());
 }
@@ -210,6 +204,7 @@
 TEST_F(BaseApiHandlerTest, UpdateDeviceInfo) {
   AddCommand(R"({
     'name' : 'base.updateDeviceInfo',
+    'component': 'weave',
     'parameters': {
       'name': 'testName',
       'description': 'testDescription',
@@ -224,6 +219,7 @@
 
   AddCommand(R"({
     'name' : 'base.updateDeviceInfo',
+    'component': 'weave',
     'parameters': {
       'location': 'newLocation'
     }
diff --git a/src/commands/cloud_command_proxy.cc b/src/commands/cloud_command_proxy.cc
index 3d472c7..f8f8d1f 100644
--- a/src/commands/cloud_command_proxy.cc
+++ b/src/commands/cloud_command_proxy.cc
@@ -17,15 +17,15 @@
 CloudCommandProxy::CloudCommandProxy(
     CommandInstance* command_instance,
     CloudCommandUpdateInterface* cloud_command_updater,
-    StateChangeQueueInterface* state_change_queue,
+    ComponentManager* component_manager,
     std::unique_ptr<BackoffEntry> backoff_entry,
     provider::TaskRunner* task_runner)
     : command_instance_{command_instance},
       cloud_command_updater_{cloud_command_updater},
-      state_change_queue_{state_change_queue},
+      component_manager_{component_manager},
       task_runner_{task_runner},
       cloud_backoff_entry_{std::move(backoff_entry)} {
-  callback_token_ = state_change_queue_->AddOnStateUpdatedCallback(
+  callback_token_ = component_manager_->AddServerStateUpdatedCallback(
       base::Bind(&CloudCommandProxy::OnDeviceStateUpdated,
                  weak_ptr_factory_.GetWeakPtr()));
   observer_.Add(command_instance);
@@ -67,7 +67,7 @@
 
 void CloudCommandProxy::QueueCommandUpdate(
     std::unique_ptr<base::DictionaryValue> patch) {
-  UpdateID id = state_change_queue_->GetLastStateChangeId();
+  ComponentManager::UpdateID id = component_manager_->GetLastStateChangeId();
   if (update_queue_.empty() || update_queue_.back().first != id) {
     // If queue is currently empty or the device state has changed since the
     // last patch request queued, add a new request to the queue.
@@ -158,7 +158,8 @@
   SendCommandUpdate();
 }
 
-void CloudCommandProxy::OnDeviceStateUpdated(UpdateID update_id) {
+void CloudCommandProxy::OnDeviceStateUpdated(
+    ComponentManager::UpdateID update_id) {
   last_state_update_id_ = update_id;
   // Try to send out any queued command updates that could be performed after
   // a device state is updated.
diff --git a/src/commands/cloud_command_proxy.h b/src/commands/cloud_command_proxy.h
index ee6358f..13f4654 100644
--- a/src/commands/cloud_command_proxy.h
+++ b/src/commands/cloud_command_proxy.h
@@ -18,7 +18,7 @@
 #include "src/backoff_entry.h"
 #include "src/commands/cloud_command_update_interface.h"
 #include "src/commands/command_instance.h"
-#include "src/states/state_change_queue_interface.h"
+#include "src/component_manager.h"
 
 namespace weave {
 
@@ -33,7 +33,7 @@
  public:
   CloudCommandProxy(CommandInstance* command_instance,
                     CloudCommandUpdateInterface* cloud_command_updater,
-                    StateChangeQueueInterface* state_change_queue,
+                    ComponentManager* component_manager,
                     std::unique_ptr<BackoffEntry> backoff_entry,
                     provider::TaskRunner* task_runner);
   ~CloudCommandProxy() override = default;
@@ -46,10 +46,8 @@
   void OnStateChanged() override;
 
  private:
-  using UpdateID = StateChangeQueueInterface::UpdateID;
-  using UpdateQueueEntry =
-      std::pair<UpdateID, std::unique_ptr<base::DictionaryValue>>;
-
+  using UpdateQueueEntry = std::pair<ComponentManager::UpdateID,
+                                     std::unique_ptr<base::DictionaryValue>>;
   // Puts a command update data into the update queue, and optionally sends an
   // asynchronous request to GCD server to update the command resource, if there
   // are no pending device status updates.
@@ -68,11 +66,11 @@
   // Callback invoked by the device state change queue to notify of the
   // successful device state update. |update_id| is the ID of the state that
   // has been updated on the server.
-  void OnDeviceStateUpdated(UpdateID update_id);
+  void OnDeviceStateUpdated(ComponentManager::UpdateID update_id);
 
   CommandInstance* command_instance_;
   CloudCommandUpdateInterface* cloud_command_updater_;
-  StateChangeQueueInterface* state_change_queue_;
+  ComponentManager* component_manager_;
   provider::TaskRunner* task_runner_{nullptr};
 
   // Backoff for SendCommandUpdate() method.
@@ -87,11 +85,11 @@
   // Callback token from the state change queue for OnDeviceStateUpdated()
   // callback for ask the device state change queue to call when the state
   // is updated on the server.
-  StateChangeQueueInterface::Token callback_token_;
+  ComponentManager::Token callback_token_;
 
   // Last device state update ID that has been sent out to the server
   // successfully.
-  UpdateID last_state_update_id_{0};
+  ComponentManager::UpdateID last_state_update_id_{0};
 
   ScopedObserver<CommandInstance, CommandInstance::Observer> observer_{this};
 
diff --git a/src/commands/cloud_command_proxy_unittest.cc b/src/commands/cloud_command_proxy_unittest.cc
index c022b79..d3a9965 100644
--- a/src/commands/cloud_command_proxy_unittest.cc
+++ b/src/commands/cloud_command_proxy_unittest.cc
@@ -12,9 +12,8 @@
 #include <weave/provider/test/fake_task_runner.h>
 #include <weave/test/unittest_utils.h>
 
-#include "src/commands/command_dictionary.h"
 #include "src/commands/command_instance.h"
-#include "src/states/mock_state_change_queue_interface.h"
+#include "src/mock_component_manager.h"
 
 using testing::_;
 using testing::DoAll;
@@ -66,14 +65,14 @@
 class CloudCommandProxyTest : public ::testing::Test {
  protected:
   void SetUp() override {
-    // Set up the test StateChangeQueue.
-    auto callback = [this](
-        const base::Callback<void(StateChangeQueueInterface::UpdateID)>& call) {
+    // Set up the test ComponentManager.
+    auto callback =
+        [this](const base::Callback<void(ComponentManager::UpdateID)>& call) {
       return callbacks_.Add(call).release();
     };
-    EXPECT_CALL(state_change_queue_, MockAddOnStateUpdatedCallback(_))
+    EXPECT_CALL(component_manager_, MockAddServerStateUpdatedCallback(_))
         .WillRepeatedly(Invoke(callback));
-    EXPECT_CALL(state_change_queue_, GetLastStateChangeId())
+    EXPECT_CALL(component_manager_, GetLastStateChangeId())
         .WillRepeatedly(testing::ReturnPointee(&current_state_update_id_));
 
     CreateCommandInstance();
@@ -102,7 +101,7 @@
 
     // Finally construct the CloudCommandProxy we are going to test here.
     std::unique_ptr<CloudCommandProxy> proxy{new CloudCommandProxy{
-        command_instance_.get(), &cloud_updater_, &state_change_queue_,
+        command_instance_.get(), &cloud_updater_, &component_manager_,
         std::move(backoff), &task_runner_}};
     // CloudCommandProxy::CloudCommandProxy() subscribe itself to weave::Command
     // notifications. When weave::Command is being destroyed it sends
@@ -110,10 +109,10 @@
     proxy.release();
   }
 
-  StateChangeQueueInterface::UpdateID current_state_update_id_{0};
-  base::CallbackList<void(StateChangeQueueInterface::UpdateID)> callbacks_;
+  ComponentManager::UpdateID current_state_update_id_{0};
+  base::CallbackList<void(ComponentManager::UpdateID)> callbacks_;
   testing::StrictMock<MockCloudCommandUpdateInterface> cloud_updater_;
-  testing::StrictMock<MockStateChangeQueueInterface> state_change_queue_;
+  testing::StrictMock<MockComponentManager> component_manager_;
   testing::StrictMock<provider::test::FakeTaskRunner> task_runner_;
   std::queue<base::Closure> task_queue_;
   std::unique_ptr<CommandInstance> command_instance_;
diff --git a/src/commands/command_dictionary.cc b/src/commands/command_dictionary.cc
deleted file mode 100644
index f6a409d..0000000
--- a/src/commands/command_dictionary.cc
+++ /dev/null
@@ -1,151 +0,0 @@
-// Copyright 2015 The Weave 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 "src/commands/command_dictionary.h"
-
-#include <algorithm>
-
-#include <base/values.h>
-#include <weave/enum_to_string.h>
-
-#include "src/commands/schema_constants.h"
-#include "src/string_utils.h"
-
-namespace weave {
-
-namespace {
-const EnumToStringMap<UserRole>::Map kMap[] = {
-    {UserRole::kViewer, commands::attributes::kCommand_Role_Viewer},
-    {UserRole::kUser, commands::attributes::kCommand_Role_User},
-    {UserRole::kOwner, commands::attributes::kCommand_Role_Owner},
-    {UserRole::kManager, commands::attributes::kCommand_Role_Manager},
-};
-}  // anonymous namespace
-
-template <>
-LIBWEAVE_EXPORT EnumToStringMap<UserRole>::EnumToStringMap()
-    : EnumToStringMap(kMap) {}
-
-bool CommandDictionary::LoadCommands(const base::DictionaryValue& json,
-                                     ErrorPtr* error) {
-  // |json| contains a list of nested objects with the following structure:
-  // {"<pkg_name>": {"<cmd_name>": {"parameters": {object_schema}}, ...}, ...}
-  // Iterate over traits
-  base::DictionaryValue::Iterator trait_iter(json);
-  for (base::DictionaryValue::Iterator trait_iter(json);
-       !trait_iter.IsAtEnd(); trait_iter.Advance()) {
-    std::string trait_name = trait_iter.key();
-    const base::DictionaryValue* trait_def = nullptr;
-    if (!trait_iter.value().GetAsDictionary(&trait_def)) {
-      Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
-                         errors::commands::kTypeMismatch,
-                         "Expecting an object for trait '%s'",
-                         trait_name.c_str());
-      return false;
-    }
-    // Iterate over command definitions within the current trait.
-    for (base::DictionaryValue::Iterator command_iter(*trait_def);
-         !command_iter.IsAtEnd(); command_iter.Advance()) {
-      std::string command_name = command_iter.key();
-      if (command_name.empty()) {
-        Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
-                           errors::commands::kInvalidCommandName,
-                           "Unnamed command encountered in trait '%s'",
-                           trait_name.c_str());
-        return false;
-      }
-      const base::DictionaryValue* command_def_json = nullptr;
-      if (!command_iter.value().GetAsDictionary(&command_def_json)) {
-        Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
-                           errors::commands::kTypeMismatch,
-                           "Expecting an object for command '%s'",
-                           command_name.c_str());
-        return false;
-      }
-
-      // Construct the compound command name as "trait_name.cmd_name".
-      std::string full_command_name = Join(".", trait_name, command_name);
-
-      // Validate the 'minimalRole' value if present. That's the only thing we
-      // care about so far.
-      std::string value;
-      if (!command_def_json->GetString(commands::attributes::kCommand_Role,
-                                       &value)) {
-        Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
-                           errors::commands::kInvalidMinimalRole,
-                           "Missing '%s' attribute for command '%s'",
-                           commands::attributes::kCommand_Role,
-                           full_command_name.c_str());
-        return false;
-      }
-      UserRole minimal_role;
-      if (!StringToEnum(value, &minimal_role)) {
-        Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
-                           errors::commands::kInvalidMinimalRole,
-                           "Invalid role '%s' for command '%s'", value.c_str(),
-                           full_command_name.c_str());
-        return false;
-      }
-      // Check if we already have this command defined.
-      CHECK(!definitions_.Get(full_command_name, nullptr))
-          << "Definition for command '" << full_command_name
-          << "' overrides an earlier definition";
-      definitions_.Set(full_command_name, command_def_json->DeepCopy());
-    }
-  }
-  return true;
-}
-
-const base::DictionaryValue& CommandDictionary::GetCommandsAsJson() const {
-  return definitions_;
-}
-
-size_t CommandDictionary::GetSize() const {
-  size_t size = 0;
-  base::DictionaryValue::Iterator trait_iter(definitions_);
-  while (!trait_iter.IsAtEnd()) {
-    std::string trait_name = trait_iter.key();
-    const base::DictionaryValue* trait_def = nullptr;
-    CHECK(trait_iter.value().GetAsDictionary(&trait_def));
-    size += trait_def->size();
-    trait_iter.Advance();
-  }
-  return size;
-}
-
-const base::DictionaryValue* CommandDictionary::FindCommand(
-    const std::string& command_name) const {
-  const base::DictionaryValue* definition = nullptr;
-  // Make sure the |command_name| came in form of trait_name.command_name.
-  // For this, we just verify it has a single period in its name.
-  if (std::count(command_name.begin(), command_name.end(), '.') != 1)
-    return definition;
-  definitions_.GetDictionary(command_name, &definition);
-  return definition;
-}
-
-void CommandDictionary::Clear() {
-  definitions_.Clear();
-}
-
-bool CommandDictionary::GetMinimalRole(const std::string& command_name,
-                                       UserRole* minimal_role,
-                                       ErrorPtr* error) const {
-  const base::DictionaryValue* command_def = FindCommand(command_name);
-  if (!command_def) {
-    Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
-                        errors::commands::kInvalidCommandName,
-                        "Command definition for '%s' not found",
-                        command_name.c_str());
-    return false;
-  }
-  std::string value;
-  // The JSON definition has been pre-validated already in LoadCommands, so
-  // just using CHECKs here.
-  CHECK(command_def->GetString(commands::attributes::kCommand_Role, &value));
-  CHECK(StringToEnum(value, minimal_role));
-  return true;
-}
-
-}  // namespace weave
diff --git a/src/commands/command_dictionary.h b/src/commands/command_dictionary.h
deleted file mode 100644
index 12f7e40..0000000
--- a/src/commands/command_dictionary.h
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright 2015 The Weave 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 LIBWEAVE_SRC_COMMANDS_COMMAND_DICTIONARY_H_
-#define LIBWEAVE_SRC_COMMANDS_COMMAND_DICTIONARY_H_
-
-#include <map>
-#include <memory>
-#include <set>
-#include <string>
-#include <vector>
-
-#include <base/macros.h>
-#include <base/values.h>
-#include <weave/error.h>
-
-namespace weave {
-
-enum class UserRole {
-  kViewer,
-  kUser,
-  kManager,
-  kOwner,
-};
-
-// CommandDictionary is a wrapper around a container of command definition
-// schema. The command name is a compound name in a form of
-// "trait_name.command_name", where "trait_name" is a name of command trait such
-// as "base", "onOff", and others. So the full command name could be
-// "base.reboot", for example.
-class CommandDictionary final {
- public:
-  CommandDictionary() = default;
-
-  // Loads command definitions from a JSON object. This is done at the daemon
-  // startup and whenever a device daemon decides to update its command list.
-  // |json| is a JSON dictionary that describes the complete commands. Optional
-  // Returns false on failure and |error| provides additional error information
-  // when provided.
-  bool LoadCommands(const base::DictionaryValue& json,
-                    ErrorPtr* error);
-  // Converts all the command definitions to a JSON object for CDD/Device
-  // draft.
-  const base::DictionaryValue& GetCommandsAsJson() const;
-  // Returns the number of command definitions in the dictionary.
-  size_t GetSize() const;
-  // Checks if the dictionary has no command definitions.
-  bool IsEmpty() const { return definitions_.empty(); }
-  // Remove all the command definitions from the dictionary.
-  void Clear();
-  // Finds a definition for the given command.
-  const base::DictionaryValue* FindCommand(
-      const std::string& command_name) const;
-  // Determines the minimal role for the given command. Returns false if the
-  // command with given name is not found.
-  bool GetMinimalRole(const std::string& command_name,
-                      UserRole* minimal_role,
-                      ErrorPtr* error) const;
-
- private:
-  base::DictionaryValue definitions_;  // List of all available command defs.
-  DISALLOW_COPY_AND_ASSIGN(CommandDictionary);
-};
-
-}  // namespace weave
-
-#endif  // LIBWEAVE_SRC_COMMANDS_COMMAND_DICTIONARY_H_
diff --git a/src/commands/command_dictionary_unittest.cc b/src/commands/command_dictionary_unittest.cc
deleted file mode 100644
index 7c53935..0000000
--- a/src/commands/command_dictionary_unittest.cc
+++ /dev/null
@@ -1,159 +0,0 @@
-// Copyright 2015 The Weave 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 "src/commands/command_dictionary.h"
-
-#include <gtest/gtest.h>
-#include <weave/test/unittest_utils.h>
-
-namespace weave {
-
-using test::CreateDictionaryValue;
-using test::IsEqualValue;
-
-TEST(CommandDictionary, Empty) {
-  CommandDictionary dict;
-  EXPECT_TRUE(dict.IsEmpty());
-  EXPECT_EQ(nullptr, dict.FindCommand("robot.jump"));
-}
-
-TEST(CommandDictionary, LoadCommands) {
-  auto json = CreateDictionaryValue(R"({
-    'robot': {
-      'jump': {
-        'minimalRole': 'manager',
-        'parameters': {
-          'height': 'integer',
-          '_jumpType': ['_withAirFlip', '_withSpin', '_withKick']
-        },
-        'progress': {
-          'progress': 'integer'
-        },
-        'results': {}
-      }
-    }
-  })");
-  CommandDictionary dict;
-  EXPECT_TRUE(dict.LoadCommands(*json, nullptr));
-  EXPECT_EQ(1u, dict.GetSize());
-  EXPECT_NE(nullptr, dict.FindCommand("robot.jump"));
-  json = CreateDictionaryValue(R"({
-    'base': {
-      'reboot': {
-        'minimalRole': 'owner',
-        'parameters': {'delay': 'integer'}
-      },
-      'shutdown': {
-        'minimalRole': 'user'
-      }
-    }
-  })");
-  EXPECT_TRUE(dict.LoadCommands(*json, nullptr));
-  EXPECT_EQ(3u, dict.GetSize());
-  EXPECT_NE(nullptr, dict.FindCommand("robot.jump"));
-  EXPECT_NE(nullptr, dict.FindCommand("base.reboot"));
-  EXPECT_NE(nullptr, dict.FindCommand("base.shutdown"));
-  EXPECT_EQ(nullptr, dict.FindCommand("foo.bar"));
-}
-
-TEST(CommandDictionary, LoadCommands_Failures) {
-  CommandDictionary dict;
-  ErrorPtr error;
-
-  // Command definition is not an object.
-  auto json = CreateDictionaryValue("{'robot':{'jump':0}}");
-  EXPECT_FALSE(dict.LoadCommands(*json, &error));
-  EXPECT_EQ("type_mismatch", error->GetCode());
-  error.reset();
-
-  // Package definition is not an object.
-  json = CreateDictionaryValue("{'robot':'blah'}");
-  EXPECT_FALSE(dict.LoadCommands(*json, &error));
-  EXPECT_EQ("type_mismatch", error->GetCode());
-  error.reset();
-
-  // Empty command name.
-  json = CreateDictionaryValue("{'robot':{'':{'parameters':{},'results':{}}}}");
-  EXPECT_FALSE(dict.LoadCommands(*json, &error));
-  EXPECT_EQ("invalid_command_name", error->GetCode());
-  error.reset();
-
-  // No 'minimalRole'.
-  json = CreateDictionaryValue(R"({
-    'base': {
-      'reboot': {
-        'parameters': {'delay': 'integer'}
-      }
-    }
-  })");
-  EXPECT_FALSE(dict.LoadCommands(*json, &error));
-  EXPECT_EQ("invalid_minimal_role", error->GetCode());
-  error.reset();
-
-  // Invalid 'minimalRole'.
-  json = CreateDictionaryValue(R"({
-    'base': {
-      'reboot': {
-        'minimalRole': 'foo',
-        'parameters': {'delay': 'integer'}
-      }
-    }
-  })");
-  EXPECT_FALSE(dict.LoadCommands(*json, &error));
-  EXPECT_EQ("invalid_minimal_role", error->GetCode());
-  error.reset();
-}
-
-TEST(CommandDictionaryDeathTest, LoadCommands_Redefine) {
-  // Redefine commands.
-  CommandDictionary dict;
-  ErrorPtr error;
-  auto json =
-      CreateDictionaryValue("{'robot':{'jump':{'minimalRole': 'viewer'}}}");
-  dict.LoadCommands(*json, nullptr);
-  ASSERT_DEATH(dict.LoadCommands(*json, &error),
-               ".*Definition for command 'robot.jump' overrides an "
-               "earlier definition");
-}
-
-TEST(CommandDictionary, GetMinimalRole) {
-  CommandDictionary base_dict;
-  auto json = CreateDictionaryValue(R"({
-    'base': {
-      'command1': {
-        'minimalRole': 'viewer',
-        'parameters': {},
-        'results': {}
-      },
-      'command2': {
-        'minimalRole': 'user',
-        'parameters': {},
-        'results': {}
-      },
-      'command3': {
-        'minimalRole': 'manager',
-        'parameters': {},
-        'results': {}
-      },
-      'command4': {
-        'minimalRole': 'owner',
-        'parameters': {},
-        'results': {}
-      }
-    }
-  })");
-  EXPECT_TRUE(base_dict.LoadCommands(*json, nullptr));
-  UserRole role;
-  EXPECT_TRUE(base_dict.GetMinimalRole("base.command1", &role, nullptr));
-  EXPECT_EQ(UserRole::kViewer, role);
-  EXPECT_TRUE(base_dict.GetMinimalRole("base.command2", &role, nullptr));
-  EXPECT_EQ(UserRole::kUser, role);
-  EXPECT_TRUE(base_dict.GetMinimalRole("base.command3", &role, nullptr));
-  EXPECT_EQ(UserRole::kManager, role);
-  EXPECT_TRUE(base_dict.GetMinimalRole("base.command4", &role, nullptr));
-  EXPECT_EQ(UserRole::kOwner, role);
-  EXPECT_FALSE(base_dict.GetMinimalRole("base.command5", &role, nullptr));
-}
-
-}  // namespace weave
diff --git a/src/commands/command_instance.cc b/src/commands/command_instance.cc
index 702a819..da62887 100644
--- a/src/commands/command_instance.cc
+++ b/src/commands/command_instance.cc
@@ -9,7 +9,6 @@
 #include <weave/error.h>
 #include <weave/export.h>
 
-#include "src/commands/command_dictionary.h"
 #include "src/commands/command_queue.h"
 #include "src/commands/schema_constants.h"
 #include "src/json_error_codes.h"
diff --git a/src/commands/command_manager.cc b/src/commands/command_manager.cc
deleted file mode 100644
index 9e9852b..0000000
--- a/src/commands/command_manager.cc
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright 2015 The Weave 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 "src/commands/command_manager.h"
-
-#include <base/values.h>
-#include <weave/enum_to_string.h>
-#include <weave/error.h>
-
-#include "src/commands/schema_constants.h"
-#include "src/utils.h"
-
-namespace weave {
-
-CommandManager::CommandManager() {}
-
-CommandManager::~CommandManager() {}
-
-void CommandManager::AddCommandDefChanged(const base::Closure& callback) {
-  on_command_changed_.push_back(callback);
-  callback.Run();
-}
-
-const CommandDictionary& CommandManager::GetCommandDictionary() const {
-  return dictionary_;
-}
-
-bool CommandManager::LoadCommands(const base::DictionaryValue& dict,
-                                  ErrorPtr* error) {
-  bool result = dictionary_.LoadCommands(dict, error);
-  for (const auto& cb : on_command_changed_)
-    cb.Run();
-  return result;
-}
-
-bool CommandManager::LoadCommands(const std::string& json,
-                                  ErrorPtr* error) {
-  std::unique_ptr<const base::DictionaryValue> dict = LoadJsonDict(json, error);
-  if (!dict)
-    return false;
-  return LoadCommands(*dict, error);
-}
-
-void CommandManager::AddCommand(
-    std::unique_ptr<CommandInstance> command_instance) {
-  command_queue_.Add(std::move(command_instance));
-}
-
-bool CommandManager::AddCommand(const base::DictionaryValue& command,
-                                std::string* id,
-                                ErrorPtr* error) {
-  return AddCommand(command, UserRole::kOwner, id, error);
-}
-
-bool CommandManager::AddCommand(const base::DictionaryValue& command,
-                                UserRole role,
-                                std::string* id,
-                                ErrorPtr* error) {
-  auto command_instance = CommandInstance::FromJson(
-      &command, Command::Origin::kLocal, nullptr, error);
-  if (!command_instance)
-    return false;
-
-  UserRole minimal_role;
-  if (!GetCommandDictionary().GetMinimalRole(command_instance->GetName(),
-                                             &minimal_role, error)) {
-    return false;
-  }
-  if (role < minimal_role) {
-    Error::AddToPrintf(
-        error, FROM_HERE, errors::commands::kDomain, "access_denied",
-        "User role '%s' less than minimal: '%s'", EnumToString(role).c_str(),
-        EnumToString(minimal_role).c_str());
-    return false;
-  }
-
-  command_instance->SetComponent("device");
-  *id = std::to_string(++next_command_id_);
-  command_instance->SetID(*id);
-  AddCommand(std::move(command_instance));
-  return true;
-}
-
-CommandInstance* CommandManager::FindCommand(const std::string& id) {
-  return command_queue_.Find(id);
-}
-
-void CommandManager::AddCommandAddedCallback(
-    const CommandQueue::CommandCallback& callback) {
-  command_queue_.AddCommandAddedCallback(callback);
-}
-
-void CommandManager::AddCommandRemovedCallback(
-    const CommandQueue::CommandCallback& callback) {
-  command_queue_.AddCommandRemovedCallback(callback);
-}
-
-void CommandManager::AddCommandHandler(
-    const std::string& command_name,
-    const Device::CommandHandlerCallback& callback) {
-  CHECK(command_name.empty() || dictionary_.FindCommand(command_name))
-      << "Command undefined: " << command_name;
-  command_queue_.AddCommandHandler("device", command_name, callback);
-}
-
-}  // namespace weave
diff --git a/src/commands/command_manager.h b/src/commands/command_manager.h
deleted file mode 100644
index 644c165..0000000
--- a/src/commands/command_manager.h
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright 2015 The Weave 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 LIBWEAVE_SRC_COMMANDS_COMMAND_MANAGER_H_
-#define LIBWEAVE_SRC_COMMANDS_COMMAND_MANAGER_H_
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include <base/callback.h>
-#include <base/macros.h>
-#include <base/memory/weak_ptr.h>
-
-#include "src/commands/command_dictionary.h"
-#include "src/commands/command_queue.h"
-
-namespace weave {
-
-class CommandInstance;
-
-// CommandManager class that will have a list of all the device command
-// schemas as well as the live command queue of pending command instances
-// dispatched to the device.
-class CommandManager final {
- public:
-  CommandManager();
-
-  ~CommandManager();
-
-  bool AddCommand(const base::DictionaryValue& command,
-                  std::string* id,
-                  ErrorPtr* error);
-  CommandInstance* FindCommand(const std::string& id);
-  void AddCommandAddedCallback(const CommandQueue::CommandCallback& callback);
-  void AddCommandRemovedCallback(const CommandQueue::CommandCallback& callback);
-  void AddCommandHandler(const std::string& command_name,
-                         const Device::CommandHandlerCallback& callback);
-
-  // Sets callback which is called when command definitions is changed.
-  void AddCommandDefChanged(const base::Closure& callback);
-
-  // Returns the command definitions for the device.
-  const CommandDictionary& GetCommandDictionary() const;
-
-  // Loads device command schema.
-  bool LoadCommands(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 LoadCommands(const std::string& json,
-                    ErrorPtr* error);
-
-  // Adds a new command to the command queue.
-  void AddCommand(std::unique_ptr<CommandInstance> command_instance);
-
-  bool AddCommand(const base::DictionaryValue& command,
-                  UserRole role,
-                  std::string* id,
-                  ErrorPtr* error);
-
- private:
-  CommandDictionary dictionary_;  // Registered definitions.
-  CommandQueue command_queue_;
-  std::vector<base::Callback<void()>> on_command_changed_;
-  uint32_t next_command_id_{0};
-
-  DISALLOW_COPY_AND_ASSIGN(CommandManager);
-};
-
-}  // namespace weave
-
-#endif  // LIBWEAVE_SRC_COMMANDS_COMMAND_MANAGER_H_
diff --git a/src/commands/command_manager_unittest.cc b/src/commands/command_manager_unittest.cc
deleted file mode 100644
index 303cafa..0000000
--- a/src/commands/command_manager_unittest.cc
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright 2015 The Weave 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 "src/commands/command_manager.h"
-
-#include <map>
-
-#include <base/json/json_writer.h>
-#include <gtest/gtest.h>
-#include <weave/provider/test/mock_config_store.h>
-#include <weave/test/unittest_utils.h>
-
-#include "src/bind_lambda.h"
-
-using testing::Return;
-
-namespace weave {
-
-using test::CreateDictionaryValue;
-
-namespace {
-
-const char kTestVendorCommands[] = R"({
-  "robot": {
-    "_jump": {
-      "minimalRole": "user",
-      "parameters": {"height": "integer"},
-      "results": {}
-    },
-    "_speak": {
-      "minimalRole": "user",
-      "parameters": {"phrase": "string"},
-      "results": {}
-    }
-  }
-})";
-
-const char kTestTestCommands[] = R"({
-  "test": {
-    "_yo": {
-      "minimalRole": "user",
-      "parameters": {"name": "string"},
-      "results": {}
-    }
-  }
-})";
-
-}  // namespace
-
-TEST(CommandManager, Empty) {
-  CommandManager manager;
-  EXPECT_TRUE(manager.GetCommandDictionary().IsEmpty());
-}
-
-TEST(CommandManager, LoadCommandsDict) {
-  CommandManager manager;
-  auto json = CreateDictionaryValue(kTestVendorCommands);
-  EXPECT_TRUE(manager.LoadCommands(*json, nullptr));
-}
-
-TEST(CommandManager, LoadCommandsJson) {
-  CommandManager manager;
-
-  // Load device-supported commands.
-  auto json_str = R"({
-    "base": {
-      "reboot": {
-        "minimalRole": "user",
-        "parameters": {"delay": "integer"},
-        "results": {}
-      }
-    },
-    "robot": {
-      "_jump": {
-        "minimalRole": "user",
-        "parameters": {"height": "integer"},
-        "results": {}
-      }
-    }
-  })";
-  EXPECT_TRUE(manager.LoadCommands(json_str, nullptr));
-  EXPECT_EQ(2u, manager.GetCommandDictionary().GetSize());
-  EXPECT_NE(nullptr, manager.GetCommandDictionary().FindCommand("base.reboot"));
-  EXPECT_NE(nullptr, manager.GetCommandDictionary().FindCommand("robot._jump"));
-}
-
-TEST(CommandManager, ShouldLoadStandardAndTestDefinitions) {
-  CommandManager manager;
-  ASSERT_TRUE(manager.LoadCommands(kTestVendorCommands, nullptr));
-  ASSERT_TRUE(manager.LoadCommands(kTestTestCommands, nullptr));
-  EXPECT_EQ(3u, manager.GetCommandDictionary().GetSize());
-  EXPECT_NE(nullptr, manager.GetCommandDictionary().FindCommand("robot._jump"));
-  EXPECT_NE(nullptr,
-            manager.GetCommandDictionary().FindCommand("robot._speak"));
-  EXPECT_NE(nullptr, manager.GetCommandDictionary().FindCommand("test._yo"));
-}
-
-}  // namespace weave
diff --git a/src/component_manager.h b/src/component_manager.h
index fbc18aa..5f16ac4 100644
--- a/src/component_manager.h
+++ b/src/component_manager.h
@@ -13,13 +13,19 @@
 #include <base/values.h>
 #include <weave/error.h>
 
-#include "src/commands/command_dictionary.h"
 #include "src/commands/command_queue.h"
 
 namespace weave {
 
 class CommandInstance;
 
+enum class UserRole {
+  kViewer,
+  kUser,
+  kManager,
+  kOwner,
+};
+
 // A simple notification record event to track component state changes.
 // The |timestamp| records the time of the state change.
 // |changed_properties| contains a property set with the new property values
@@ -82,13 +88,22 @@
   virtual void AddComponentTreeChangedCallback(
       const base::Closure& callback) = 0;
 
-  // Parses the command definition from a json dictionary and adds it to the
-  // command queue. The new command ID is returned through optional |id| param.
-  virtual bool AddCommand(const base::DictionaryValue& command,
-                          Command::Origin command_origin,
-                          UserRole role,
-                          std::string* id,
-                          ErrorPtr* error) = 0;
+  // Adds a new command instance to the command queue. The command specified in
+  // |command_instance| must be fully initialized and have its name, component,
+  // id populated.
+  virtual void AddCommand(
+      std::unique_ptr<CommandInstance> command_instance) = 0;
+
+  // Parses the command definition from a json dictionary. The resulting command
+  // instance is populated with all the required fields and partially validated
+  // against syntax/schema.
+  // The new command ID is returned through optional |id| param.
+  virtual std::unique_ptr<CommandInstance> ParseCommandInstance(
+      const base::DictionaryValue& command,
+      Command::Origin command_origin,
+      UserRole role,
+      std::string* id,
+      ErrorPtr* error) = 0;
 
   // Find a command instance with the given ID in the command queue.
   virtual CommandInstance* FindCommand(const std::string& id) = 0;
diff --git a/src/component_manager_impl.cc b/src/component_manager_impl.cc
index 1883739..5b0ab23 100644
--- a/src/component_manager_impl.cc
+++ b/src/component_manager_impl.cc
@@ -18,7 +18,18 @@
 namespace {
 // Max of 100 state update events should be enough in the queue.
 const size_t kMaxStateChangeQueueSize = 100;
-}  // namespace
+
+const EnumToStringMap<UserRole>::Map kMap[] = {
+    {UserRole::kViewer, commands::attributes::kCommand_Role_Viewer},
+    {UserRole::kUser, commands::attributes::kCommand_Role_User},
+    {UserRole::kOwner, commands::attributes::kCommand_Role_Owner},
+    {UserRole::kManager, commands::attributes::kCommand_Role_Manager},
+};
+}  // anonymous namespace
+
+template <>
+LIBWEAVE_EXPORT EnumToStringMap<UserRole>::EnumToStringMap()
+    : EnumToStringMap(kMap) {}
 
 ComponentManagerImpl::ComponentManagerImpl() {}
 
@@ -147,11 +158,17 @@
   callback.Run();
 }
 
-bool ComponentManagerImpl::AddCommand(const base::DictionaryValue& command,
-                                      Command::Origin command_origin,
-                                      UserRole role,
-                                      std::string* id,
-                                      ErrorPtr* error) {
+void ComponentManagerImpl::AddCommand(
+    std::unique_ptr<CommandInstance> command_instance) {
+  command_queue_.Add(std::move(command_instance));
+}
+
+std::unique_ptr<CommandInstance> ComponentManagerImpl::ParseCommandInstance(
+    const base::DictionaryValue& command,
+    Command::Origin command_origin,
+    UserRole role,
+    std::string* id,
+    ErrorPtr* error) {
   std::string command_id;
   auto command_instance = CommandInstance::FromJson(&command, command_origin,
                                                     &command_id, error);
@@ -162,18 +179,18 @@
     *id = command_id;
 
   if (!command_instance)
-    return false;
+    return nullptr;
 
   UserRole minimal_role;
   if (!GetMinimalRole(command_instance->GetName(), &minimal_role, error))
-    return false;
+    return nullptr;
 
   if (role < minimal_role) {
     Error::AddToPrintf(
         error, FROM_HERE, errors::commands::kDomain, "access_denied",
         "User role '%s' less than minimal: '%s'", EnumToString(role).c_str(),
         EnumToString(minimal_role).c_str());
-    return false;
+    return nullptr;
   }
 
   std::string component_path = command_instance->GetComponent();
@@ -188,14 +205,14 @@
           "Unable route command '%s' because there is no component supporting"
           "trait '%s'", command_instance->GetName().c_str(),
           trait_name.c_str());
-      return false;
+      return nullptr;
     }
     command_instance->SetComponent(component_path);
   }
 
   const base::DictionaryValue* component = FindComponent(component_path, error);
   if (!component)
-    return false;
+    return nullptr;
 
   // Check that the command's trait is supported by the given component.
   auto pair = SplitAtFirst(command_instance->GetName(), ".", true);
@@ -218,18 +235,17 @@
                        "trait_not_supported",
                        "Component '%s' doesn't support trait '%s'",
                        component_path.c_str(), pair.first.c_str());
-    return false;
+    return nullptr;
   }
 
   if (command_id.empty()) {
     command_id = std::to_string(++next_command_id_);
     command_instance->SetID(command_id);
+    if (id)
+      *id = command_id;
   }
 
-  if (id)
-    *id = command_id;
-  command_queue_.Add(std::move(command_instance));
-  return true;
+  return command_instance;
 }
 
 CommandInstance* ComponentManagerImpl::FindCommand(const std::string& id) {
diff --git a/src/component_manager_impl.h b/src/component_manager_impl.h
index 9778a93..c59c6d9 100644
--- a/src/component_manager_impl.h
+++ b/src/component_manager_impl.h
@@ -49,13 +49,22 @@
   // Sets callback which is called when new components are added.
   void AddComponentTreeChangedCallback(const base::Closure& callback) override;
 
-  // Parses the command definition from a json dictionary and adds it to the
-  // command queue. The new command ID is returned through optional |id| param.
-  bool AddCommand(const base::DictionaryValue& command,
-                  Command::Origin command_origin,
-                  UserRole role,
-                  std::string* id,
-                  ErrorPtr* error) override;
+  // Adds a new command instance to the command queue. The command specified in
+  // |command_instance| must be fully initialized and have its name, component,
+  // id populated.
+  void AddCommand(
+      std::unique_ptr<CommandInstance> command_instance) override;
+
+  // Parses the command definition from a json dictionary. The resulting command
+  // instance is populated with all the required fields and partially validated
+  // against syntax/schema.
+  // The new command ID is returned through optional |id| param.
+  std::unique_ptr<CommandInstance> ParseCommandInstance(
+      const base::DictionaryValue& command,
+      Command::Origin command_origin,
+      UserRole role,
+      std::string* id,
+      ErrorPtr* error) override;
 
   // Find a command instance with the given ID in the command queue.
   CommandInstance* FindCommand(const std::string& id) override;
@@ -180,6 +189,13 @@
       ErrorPtr* error);
 
   base::Clock* clock_{nullptr};
+  // An ID of last state change update. Each NotifyPropertiesUpdated()
+  // invocation increments this value by 1.
+  UpdateID last_state_change_id_{0};
+  // Callback list for state change queue event sinks.
+  // This member must be defined before |command_queue_|.
+  base::CallbackList<void(UpdateID)> on_server_state_updated_;
+
   base::DictionaryValue traits_;  // Trait definitions.
   base::DictionaryValue components_;  // Component instances.
   CommandQueue command_queue_;  // Command queue containing command instances.
@@ -187,13 +203,7 @@
   std::vector<base::Closure> on_componet_tree_changed_;
   std::vector<base::Closure> on_state_changed_;
   uint32_t next_command_id_{0};
-
   std::map<std::string, std::unique_ptr<StateChangeQueue>> state_change_queues_;
-  // An ID of last state change update. Each NotifyPropertiesUpdated()
-  // invocation increments this value by 1.
-  UpdateID last_state_change_id_{0};
-  // Callback list for state change queue event sinks.
-  base::CallbackList<void(UpdateID)> on_server_state_updated_;
 
   // Legacy API support.
   mutable base::DictionaryValue legacy_state_;  // Device state.
diff --git a/src/component_manager_unittest.cc b/src/component_manager_unittest.cc
index 8c9b386..b35e16a 100644
--- a/src/component_manager_unittest.cc
+++ b/src/component_manager_unittest.cc
@@ -621,7 +621,7 @@
   EXPECT_EQ(nullptr, manager.FindComponent("comp1.comp2[1", nullptr));
 }
 
-TEST(ComponentManager, AddCommand) {
+TEST(ComponentManager, ParseCommandInstance) {
   ComponentManagerImpl manager;
   const char kTraits[] = R"({
     "trait1": {
@@ -635,6 +635,12 @@
         "command1": { "minimalRole": "manager" },
         "command2": { "minimalRole": "owner" }
       }
+    },
+    "trait3": {
+      "commands": {
+        "command1": { "minimalRole": "manager" },
+        "command2": { "minimalRole": "owner" }
+      }
     }
   })";
   auto traits = CreateDictionaryValue(kTraits);
@@ -650,12 +656,14 @@
     "parameters": {}
   })";
   auto command1 = CreateDictionaryValue(kCommand1);
-  EXPECT_TRUE(manager.AddCommand(*command1, Command::Origin::kLocal,
-                                 UserRole::kUser, &id, nullptr));
+  EXPECT_NE(nullptr,
+            manager.ParseCommandInstance(*command1, Command::Origin::kLocal,
+                                         UserRole::kUser, &id, nullptr).get());
   EXPECT_EQ("1234-12345", id);
   // Not enough access rights
-  EXPECT_FALSE(manager.AddCommand(*command1, Command::Origin::kLocal,
-                                  UserRole::kViewer, &id, nullptr));
+  EXPECT_EQ(nullptr,
+            manager.ParseCommandInstance(*command1, Command::Origin::kLocal,
+                                         UserRole::kViewer, &id, nullptr).get());
 
   const char kCommand2[] = R"({
     "name": "trait1.command3",
@@ -664,8 +672,9 @@
   })";
   auto command2 = CreateDictionaryValue(kCommand2);
   // trait1.command3 doesn't exist
-  EXPECT_FALSE(manager.AddCommand(*command2, Command::Origin::kLocal,
-                                  UserRole::kOwner, &id, nullptr));
+  EXPECT_EQ(nullptr,
+            manager.ParseCommandInstance(*command2, Command::Origin::kLocal,
+                                         UserRole::kOwner, &id, nullptr).get());
   EXPECT_TRUE(id.empty());
 
   const char kCommand3[] = R"({
@@ -675,8 +684,9 @@
   })";
   auto command3 = CreateDictionaryValue(kCommand3);
   // Component comp1 doesn't have trait2.
-  EXPECT_FALSE(manager.AddCommand(*command3, Command::Origin::kLocal,
-                                  UserRole::kOwner, &id, nullptr));
+  EXPECT_EQ(nullptr,
+            manager.ParseCommandInstance(*command3, Command::Origin::kLocal,
+                                         UserRole::kOwner, &id, nullptr).get());
 
   // No component specified, find the suitable component
   const char kCommand4[] = R"({
@@ -684,22 +694,60 @@
     "parameters": {}
   })";
   auto command4 = CreateDictionaryValue(kCommand4);
-  EXPECT_TRUE(manager.AddCommand(*command4, Command::Origin::kLocal,
-                                 UserRole::kOwner, &id, nullptr));
-  auto cmd = manager.FindCommand(id);
-  ASSERT_NE(nullptr, cmd);
-  EXPECT_EQ("comp1", cmd->GetComponent());
+  auto command_instance = manager.ParseCommandInstance(
+      *command4, Command::Origin::kLocal, UserRole::kOwner, &id, nullptr);
+  EXPECT_NE(nullptr, command_instance.get());
+  EXPECT_EQ("comp1", command_instance->GetComponent());
 
   const char kCommand5[] = R"({
     "name": "trait2.command1",
     "parameters": {}
   })";
   auto command5 = CreateDictionaryValue(kCommand5);
-  EXPECT_TRUE(manager.AddCommand(*command5, Command::Origin::kLocal,
-                                 UserRole::kOwner, &id, nullptr));
-  cmd = manager.FindCommand(id);
-  ASSERT_NE(nullptr, cmd);
-  EXPECT_EQ("comp2", cmd->GetComponent());
+  command_instance = manager.ParseCommandInstance(
+      *command5, Command::Origin::kLocal, UserRole::kOwner, &id, nullptr);
+  EXPECT_NE(nullptr, command_instance.get());
+  EXPECT_EQ("comp2", command_instance->GetComponent());
+
+  // Cannot route the command, no component with 'trait3'.
+  const char kCommand6[] = R"({
+    "name": "trait3.command1",
+    "parameters": {}
+  })";
+  auto command6 = CreateDictionaryValue(kCommand6);
+  EXPECT_EQ(nullptr,
+            manager.ParseCommandInstance(*command6, Command::Origin::kLocal,
+                                         UserRole::kOwner, &id, nullptr).get());
+}
+
+TEST(ComponentManager, AddCommand) {
+  ComponentManagerImpl manager;
+  const char kTraits[] = R"({
+    "trait1": {
+      "commands": {
+        "command1": { "minimalRole": "user" }
+      }
+    }
+  })";
+  auto traits = CreateDictionaryValue(kTraits);
+  ASSERT_TRUE(manager.LoadTraits(*traits, nullptr));
+  ASSERT_TRUE(manager.AddComponent("", "comp1", {"trait1"}, nullptr));
+
+  std::string id;
+  const char kCommand[] = R"({
+    "name": "trait1.command1",
+    "id": "1234-12345",
+    "component": "comp1",
+    "parameters": {}
+  })";
+  auto command = CreateDictionaryValue(kCommand);
+  auto command_instance = manager.ParseCommandInstance(
+      *command, Command::Origin::kLocal, UserRole::kUser, &id, nullptr);
+  ASSERT_NE(nullptr, command_instance.get());
+  manager.AddCommand(std::move(command_instance));
+  const auto* queued_command = manager.FindCommand(id);
+  ASSERT_NE(nullptr, queued_command);
+  EXPECT_EQ("trait1.command1", queued_command->GetName());
 }
 
 TEST(ComponentManager, AddCommandHandler) {
@@ -738,8 +786,10 @@
     "component": "comp1"
   })";
   auto command1 = CreateDictionaryValue(kCommand1);
-  EXPECT_TRUE(manager.AddCommand(*command1, Command::Origin::kCloud,
-                                 UserRole::kUser, nullptr, nullptr));
+  auto command_instance = manager.ParseCommandInstance(
+      *command1, Command::Origin::kCloud, UserRole::kUser, nullptr, nullptr);
+  ASSERT_NE(nullptr, command_instance.get());
+  manager.AddCommand(std::move(command_instance));
   EXPECT_EQ("1", last_tags);
   last_tags.clear();
 
@@ -748,8 +798,10 @@
     "component": "comp2"
   })";
   auto command2 = CreateDictionaryValue(kCommand2);
-  EXPECT_TRUE(manager.AddCommand(*command2, Command::Origin::kCloud,
-                                 UserRole::kUser, nullptr, nullptr));
+  command_instance = manager.ParseCommandInstance(
+      *command2, Command::Origin::kCloud, UserRole::kUser, nullptr, nullptr);
+  ASSERT_NE(nullptr, command_instance.get());
+  manager.AddCommand(std::move(command_instance));
   EXPECT_EQ("2", last_tags);
   last_tags.clear();
 
@@ -759,8 +811,10 @@
     "parameters": {}
   })";
   auto command3 = CreateDictionaryValue(kCommand3);
-  EXPECT_TRUE(manager.AddCommand(*command3, Command::Origin::kLocal,
-                                 UserRole::kUser, nullptr, nullptr));
+  command_instance = manager.ParseCommandInstance(
+      *command3, Command::Origin::kCloud, UserRole::kUser, nullptr, nullptr);
+  ASSERT_NE(nullptr, command_instance.get());
+  manager.AddCommand(std::move(command_instance));
   EXPECT_EQ("3", last_tags);
   last_tags.clear();
 }
diff --git a/src/device_manager.cc b/src/device_manager.cc
index a44f0db..7a9021f 100644
--- a/src/device_manager.cc
+++ b/src/device_manager.cc
@@ -9,23 +9,16 @@
 #include <base/bind.h>
 
 #include "src/base_api_handler.h"
-#include "src/commands/command_manager.h"
+#include "src/commands/schema_constants.h"
 #include "src/component_manager_impl.h"
 #include "src/config.h"
 #include "src/device_registration_info.h"
 #include "src/privet/privet_manager.h"
-#include "src/states/state_change_queue.h"
-#include "src/states/state_manager.h"
+#include "src/string_utils.h"
+#include "src/utils.h"
 
 namespace weave {
 
-namespace {
-
-// Max of 100 state update events should be enough in the queue.
-const size_t kMaxStateChangeQueueSize = 100;
-
-}  // namespace
-
 DeviceManager::DeviceManager(provider::ConfigStore* config_store,
                              provider::TaskRunner* task_runner,
                              provider::HttpClient* http_client,
@@ -35,16 +28,13 @@
                              provider::Wifi* wifi,
                              provider::Bluetooth* bluetooth) {
   component_manager_.reset(new ComponentManagerImpl);
-  command_manager_ = std::make_shared<CommandManager>();
-  state_change_queue_.reset(new StateChangeQueue(kMaxStateChangeQueueSize));
-  state_manager_ = std::make_shared<StateManager>(state_change_queue_.get());
 
   std::unique_ptr<Config> config{new Config{config_store}};
   config->Load();
 
   device_info_.reset(new DeviceRegistrationInfo(
-      command_manager_, state_manager_, std::move(config), task_runner,
-      http_client, network));
+      component_manager_.get(), std::move(config), task_runner, http_client,
+      network));
   base_api_handler_.reset(new BaseApiHandler{device_info_.get(), this});
 
   device_info_->Start();
@@ -79,7 +69,7 @@
                                 provider::Bluetooth* bluetooth) {
   privet_.reset(new privet::Manager{task_runner});
   privet_->Start(network, dns_sd, http_server, wifi, device_info_.get(),
-                 command_manager_.get(), state_manager_.get());
+                 component_manager_.get());
 }
 
 GcdState DeviceManager::GetGcdState() const {
@@ -151,63 +141,108 @@
 }
 
 void DeviceManager::AddCommandDefinitionsFromJson(const std::string& json) {
-  CHECK(command_manager_->LoadCommands(json, nullptr));
+  auto dict = LoadJsonDict(json, nullptr);
+  CHECK(dict);
+  AddCommandDefinitions(*dict);
 }
 
 void DeviceManager::AddCommandDefinitions(const base::DictionaryValue& dict) {
-  CHECK(command_manager_->LoadCommands(dict, nullptr));
+  CHECK(component_manager_->AddLegacyCommandDefinitions(dict, nullptr));
 }
 
 bool DeviceManager::AddCommand(const base::DictionaryValue& command,
                                std::string* id,
                                ErrorPtr* error) {
-  return command_manager_->AddCommand(command, id, error);
+  auto command_instance =
+      component_manager_->ParseCommandInstance(command, Command::Origin::kLocal,
+                                               UserRole::kOwner, id, error);
+  if (!command_instance)
+    return false;
+  component_manager_->AddCommand(std::move(command_instance));
+  return true;
 }
 
 Command* DeviceManager::FindCommand(const std::string& id) {
-  return command_manager_->FindCommand(id);
+  return component_manager_->FindCommand(id);
 }
 
 void DeviceManager::AddCommandHandler(const std::string& command_name,
                                       const CommandHandlerCallback& callback) {
-  return command_manager_->AddCommandHandler(command_name, callback);
+  if (command_name.empty())
+    return component_manager_->AddCommandHandler("", "", callback);
+
+  auto trait = SplitAtFirst(command_name, ".", true).first;
+  std::string component = component_manager_->FindComponentWithTrait(trait);
+  CHECK(!component.empty());
+  component_manager_->AddCommandHandler(component, command_name, callback);
 }
 
 void DeviceManager::AddStateChangedCallback(const base::Closure& callback) {
-  state_manager_->AddChangedCallback(callback);
+  component_manager_->AddStateChangedCallback(callback);
 }
 
 void DeviceManager::AddStateDefinitionsFromJson(const std::string& json) {
-  CHECK(state_manager_->LoadStateDefinitionFromJson(json, nullptr));
+  auto dict = LoadJsonDict(json, nullptr);
+  CHECK(dict);
+  AddStateDefinitions(*dict);
 }
 
 void DeviceManager::AddStateDefinitions(const base::DictionaryValue& dict) {
-  CHECK(state_manager_->LoadStateDefinition(dict, nullptr));
+  CHECK(component_manager_->AddLegacyStateDefinitions(dict, nullptr));
 }
 
 bool DeviceManager::SetStatePropertiesFromJson(const std::string& json,
                                                ErrorPtr* error) {
-  return state_manager_->SetPropertiesFromJson(json, error);
+  auto dict = LoadJsonDict(json, error);
+  return dict && SetStateProperties(*dict, error);
 }
 
 bool DeviceManager::SetStateProperties(const base::DictionaryValue& dict,
                                        ErrorPtr* error) {
-  return state_manager_->SetProperties(dict, error);
+  for (base::DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) {
+    std::string component =
+        component_manager_->FindComponentWithTrait(it.key());
+    if (component.empty()) {
+      Error::AddToPrintf(
+        error, FROM_HERE, errors::commands::kDomain, "unrouted_state",
+        "Unable to set property value because there is no component supporting "
+        "trait '%s'", it.key().c_str());
+      return false;
+    }
+    base::DictionaryValue trait_state;
+    trait_state.Set(it.key(), it.value().DeepCopy());
+    if (!component_manager_->SetStateProperties(component, trait_state, error))
+      return false;
+  }
+  return true;
 }
 
 const base::Value* DeviceManager::GetStateProperty(
     const std::string& name) const {
-  return state_manager_->GetProperty(name);
+  auto trait = SplitAtFirst(name, ".", true).first;
+  std::string component = component_manager_->FindComponentWithTrait(trait);
+  if (component.empty())
+    return nullptr;
+  return component_manager_->GetStateProperty(component, name, nullptr);
 }
 
 bool DeviceManager::SetStateProperty(const std::string& name,
                                      const base::Value& value,
                                      ErrorPtr* error) {
-  return state_manager_->SetProperty(name, value, error);
+  auto trait = SplitAtFirst(name, ".", true).first;
+  std::string component = component_manager_->FindComponentWithTrait(trait);
+  if (component.empty()) {
+    Error::AddToPrintf(
+      error, FROM_HERE, errors::commands::kDomain, "unrouted_state",
+      "Unable set value of state property '%s' because there is no component "
+      "supporting trait '%s'", name.c_str(), trait.c_str());
+    return false;
+  }
+  return component_manager_->SetStateProperty(component, name, value, error);
 }
 
 const base::DictionaryValue& DeviceManager::GetState() const {
-  return state_manager_->GetState();
+  return component_manager_->GetLegacyState();
 }
 
 void DeviceManager::Register(const std::string& ticket_id,
diff --git a/src/device_manager.h b/src/device_manager.h
index 2a23755..3b042eb 100644
--- a/src/device_manager.h
+++ b/src/device_manager.h
@@ -12,11 +12,8 @@
 
 class BaseApiHandler;
 class Config;
-class CommandManager;
 class ComponentManager;
 class DeviceRegistrationInfo;
-class StateChangeQueue;
-class StateManager;
 
 namespace privet {
 class Manager;
@@ -103,9 +100,6 @@
                    provider::Bluetooth* bluetooth);
 
   std::unique_ptr<ComponentManager> component_manager_;
-  std::shared_ptr<CommandManager> command_manager_;
-  std::unique_ptr<StateChangeQueue> state_change_queue_;
-  std::shared_ptr<StateManager> state_manager_;
   std::unique_ptr<DeviceRegistrationInfo> device_info_;
   std::unique_ptr<BaseApiHandler> base_api_handler_;
   std::unique_ptr<privet::Manager> privet_;
diff --git a/src/device_registration_info.cc b/src/device_registration_info.cc
index 9469d09..abdbb08 100644
--- a/src/device_registration_info.cc
+++ b/src/device_registration_info.cc
@@ -22,13 +22,11 @@
 
 #include "src/bind_lambda.h"
 #include "src/commands/cloud_command_proxy.h"
-#include "src/commands/command_manager.h"
 #include "src/commands/schema_constants.h"
 #include "src/data_encoding.h"
 #include "src/http_constants.h"
 #include "src/json_error_codes.h"
 #include "src/notification/xmpp_channel.h"
-#include "src/states/state_manager.h"
 #include "src/string_utils.h"
 #include "src/utils.h"
 
@@ -239,16 +237,14 @@
 }  // anonymous namespace
 
 DeviceRegistrationInfo::DeviceRegistrationInfo(
-    const std::shared_ptr<CommandManager>& command_manager,
-    const std::shared_ptr<StateManager>& state_manager,
+    ComponentManager* component_manager,
     std::unique_ptr<Config> config,
     provider::TaskRunner* task_runner,
     provider::HttpClient* http_client,
     provider::Network* network)
     : http_client_{http_client},
       task_runner_{task_runner},
-      command_manager_{command_manager},
-      state_manager_{state_manager},
+      component_manager_{component_manager},
       config_{std::move(config)},
       network_{network} {
   cloud_backoff_policy_.reset(new BackoffEntry::Policy{});
@@ -267,10 +263,13 @@
   gcd_state_ =
       revoked ? GcdState::kInvalidCredentials : GcdState::kUnconfigured;
 
-  command_manager_->AddCommandDefChanged(
-      base::Bind(&DeviceRegistrationInfo::OnCommandDefsChanged,
+  component_manager_->AddTraitDefChangedCallback(
+      base::Bind(&DeviceRegistrationInfo::OnTraitDefsChanged,
                  weak_factory_.GetWeakPtr()));
-  state_manager_->AddChangedCallback(base::Bind(
+  component_manager_->AddComponentTreeChangedCallback(base::Bind(
+      &DeviceRegistrationInfo::OnComponentTreeChanged,
+      weak_factory_.GetWeakPtr()));
+  component_manager_->AddStateChangedCallback(base::Bind(
       &DeviceRegistrationInfo::OnStateChanged, weak_factory_.GetWeakPtr()));
 }
 
@@ -479,12 +478,6 @@
 
 std::unique_ptr<base::DictionaryValue>
 DeviceRegistrationInfo::BuildDeviceResource(ErrorPtr* error) {
-  // Limit only to commands that are visible to the cloud.
-  const base::DictionaryValue& commands =
-      command_manager_->GetCommandDictionary().GetCommandsAsJson();
-
-  const base::DictionaryValue& state = state_manager_->GetState();
-
   std::unique_ptr<base::DictionaryValue> resource{new base::DictionaryValue};
   if (!GetSettings().cloud_id.empty())
     resource->SetString("id", GetSettings().cloud_id);
@@ -503,34 +496,12 @@
     channel->SetString("supportedType", "pull");
   }
   resource->Set("channel", channel.release());
-  resource->Set("commandDefs", commands.DeepCopy());
-  resource->Set("state", state.DeepCopy());
+  resource->Set("commandDefs",
+                component_manager_->GetLegacyCommandDefinitions().DeepCopy());
+  resource->Set("state", component_manager_->GetLegacyState().DeepCopy());
+  resource->Set("traits", component_manager_->GetTraits().DeepCopy());
+  resource->Set("components", component_manager_->GetComponents().DeepCopy());
 
-  // TODO(avakulenko): Temporary code to generate a single top-level component
-  // using the new component-trait model. This is to unblock clients to start
-  // implementation on their side.
-  base::DictionaryValue traits;
-  base::DictionaryValue component;
-  std::set<std::string> all_traits;
-  for (const auto& pair : state_manager_->packages()) {
-    all_traits.insert(pair.first);
-    std::string key = base::StringPrintf("%s.state", pair.first.c_str());
-    traits.Set(key, pair.second->types().DeepCopy());
-    key = base::StringPrintf("state.%s", pair.first.c_str());
-    component.Set(key, pair.second->GetValuesAsJson().DeepCopy());
-  }
-  for (base::DictionaryValue::Iterator it(commands); !it.IsAtEnd();
-       it.Advance()) {
-    all_traits.insert(it.key());
-    std::string key = base::StringPrintf("%s.commands", it.key().c_str());
-    traits.Set(key, it.value().DeepCopy());
-  }
-  resource->Set("traits", traits.DeepCopy());
-  base::ListValue* trait_list = new base::ListValue();
-  for (const std::string& trait : all_traits)
-    trait_list->AppendString(trait);
-  component.Set("traits", trait_list);
-  resource->Set("components.device", component.DeepCopy());
   return resource;
 }
 
@@ -1102,8 +1073,8 @@
     const base::DictionaryValue& command) {
   std::string command_id;
   ErrorPtr error;
-  auto command_instance = CommandInstance::FromJson(
-      &command, Command::Origin::kCloud, &command_id, &error);
+  auto command_instance = component_manager_->ParseCommandInstance(
+      command, Command::Origin::kCloud, UserRole::kOwner, &command_id, &error);
   if (!command_instance) {
     LOG(WARNING) << "Failed to parse a command instance: " << command;
     if (!command_id.empty())
@@ -1112,19 +1083,19 @@
   }
 
   // TODO(antonm): Properly process cancellation of commands.
-  if (!command_manager_->FindCommand(command_instance->GetID())) {
+  if (!component_manager_->FindCommand(command_instance->GetID())) {
     LOG(INFO) << "New command '" << command_instance->GetName()
               << "' arrived, ID: " << command_instance->GetID();
     std::unique_ptr<BackoffEntry> backoff_entry{
         new BackoffEntry{cloud_backoff_policy_.get()}};
     std::unique_ptr<CloudCommandProxy> cloud_proxy{new CloudCommandProxy{
-        command_instance.get(), this, state_manager_->GetStateChangeQueue(),
+        command_instance.get(), this, component_manager_,
         std::move(backoff_entry), task_runner_}};
     // CloudCommandProxy::CloudCommandProxy() subscribe itself to Command
     // notifications. When Command is being destroyed it sends
     // ::OnCommandDestroyed() and CloudCommandProxy deletes itself.
     cloud_proxy.release();
-    command_manager_->AddCommand(std::move(command_instance));
+    component_manager_->AddCommand(std::move(command_instance));
   }
 }
 
@@ -1133,18 +1104,18 @@
   if (device_state_update_pending_)
     return;
 
-  StateChangeQueueInterface::UpdateID update_id = 0;
-  std::vector<StateChange> state_changes;
-  std::tie(update_id, state_changes) =
-      state_manager_->GetAndClearRecordedStateChanges();
-  if (state_changes.empty())
+  auto snapshot = component_manager_->GetAndClearRecordedStateChanges();
+  if (snapshot.state_changes.empty())
     return;
 
   std::unique_ptr<base::ListValue> patches{new base::ListValue};
-  for (auto& state_change : state_changes) {
+  for (auto& state_change : snapshot.state_changes) {
     std::unique_ptr<base::DictionaryValue> patch{new base::DictionaryValue};
     patch->SetString("timeMs",
                      std::to_string(state_change.timestamp.ToJavaTime()));
+    // TODO(avakulenko): Uncomment this once server supports "component"
+    // attribute on a state patch object.
+    // patch->SetString("component", state_change.component);
     patch->Set("patch", state_change.changed_properties.release());
     patches->Append(patch.release());
   }
@@ -1157,11 +1128,11 @@
   device_state_update_pending_ = true;
   DoCloudRequest(HttpClient::Method::kPost, GetDeviceURL("patchState"), &body,
                  base::Bind(&DeviceRegistrationInfo::OnPublishStateDone,
-                            AsWeakPtr(), update_id));
+                            AsWeakPtr(), snapshot.update_id));
 }
 
 void DeviceRegistrationInfo::OnPublishStateDone(
-    StateChangeQueueInterface::UpdateID update_id,
+    ComponentManager::UpdateID update_id,
     const base::DictionaryValue& reply,
     ErrorPtr error) {
   device_state_update_pending_ = false;
@@ -1169,7 +1140,7 @@
     LOG(ERROR) << "Permanent failure while trying to update device state";
     return;
   }
-  state_manager_->NotifyStateUpdatedOnServer(update_id);
+  component_manager_->NotifyStateUpdatedOnServer(update_id);
   // See if there were more pending state updates since the previous request
   // had been sent out.
   PublishStateUpdates();
@@ -1183,7 +1154,7 @@
     cb.Run(gcd_state_);
 }
 
-void DeviceRegistrationInfo::OnCommandDefsChanged() {
+void DeviceRegistrationInfo::OnTraitDefsChanged() {
   VLOG(1) << "CommandDefinitionChanged notification received";
   if (!HaveRegistrationCredentials() || !connected_to_cloud_)
     return;
@@ -1200,6 +1171,14 @@
   PublishStateUpdates();
 }
 
+void DeviceRegistrationInfo::OnComponentTreeChanged() {
+  VLOG(1) << "ComponentTreeChanged notification received";
+  if (!HaveRegistrationCredentials() || !connected_to_cloud_)
+    return;
+
+  UpdateDeviceResource(base::Bind(&IgnoreCloudError));
+}
+
 void DeviceRegistrationInfo::OnConnected(const std::string& channel_name) {
   LOG(INFO) << "Notification channel successfully established over "
             << channel_name;
diff --git a/src/device_registration_info.h b/src/device_registration_info.h
index 1399b37..f3b5302 100644
--- a/src/device_registration_info.h
+++ b/src/device_registration_info.h
@@ -21,13 +21,12 @@
 
 #include "src/backoff_entry.h"
 #include "src/commands/cloud_command_update_interface.h"
-#include "src/commands/command_manager.h"
+#include "src/component_manager.h"
 #include "src/config.h"
 #include "src/data_encoding.h"
 #include "src/notification/notification_channel.h"
 #include "src/notification/notification_delegate.h"
 #include "src/notification/pull_channel.h"
-#include "src/states/state_change_queue_interface.h"
 
 namespace base {
 class DictionaryValue;
@@ -54,12 +53,12 @@
       base::Callback<void(const base::DictionaryValue& response,
                           ErrorPtr error)>;
 
-  DeviceRegistrationInfo(const std::shared_ptr<CommandManager>& command_manager,
-                         const std::shared_ptr<StateManager>& state_manager,
-                         std::unique_ptr<Config> config,
-                         provider::TaskRunner* task_runner,
-                         provider::HttpClient* http_client,
-                         provider::Network* network);
+  DeviceRegistrationInfo(
+      ComponentManager* component_manager,
+      std::unique_ptr<Config> config,
+      provider::TaskRunner* task_runner,
+      provider::HttpClient* http_client,
+      provider::Network* network);
 
   ~DeviceRegistrationInfo() override;
 
@@ -236,7 +235,7 @@
   void FetchAndPublishCommands(const std::string& reason);
 
   void PublishStateUpdates();
-  void OnPublishStateDone(StateChangeQueueInterface::UpdateID update_id,
+  void OnPublishStateDone(ComponentManager::UpdateID update_id,
                           const base::DictionaryValue& reply,
                           ErrorPtr error);
   void OnPublishStateError(ErrorPtr error);
@@ -254,7 +253,8 @@
   void SetDeviceId(const std::string& cloud_id);
 
   // Callback called when command definitions are changed to re-publish new CDD.
-  void OnCommandDefsChanged();
+  void OnTraitDefsChanged();
+  void OnComponentTreeChanged();
   void OnStateChanged();
 
   // Overrides from NotificationDelegate.
@@ -299,10 +299,8 @@
   provider::HttpClient* http_client_{nullptr};
 
   provider::TaskRunner* task_runner_{nullptr};
-  // Global command manager.
-  std::shared_ptr<CommandManager> command_manager_;
-  // Device state manager.
-  std::shared_ptr<StateManager> state_manager_;
+  // Global component manager.
+  ComponentManager* component_manager_{nullptr};
 
   std::unique_ptr<Config> config_;
 
diff --git a/src/device_registration_info_unittest.cc b/src/device_registration_info_unittest.cc
index f2fe4c4..c242ee5 100644
--- a/src/device_registration_info_unittest.cc
+++ b/src/device_registration_info_unittest.cc
@@ -14,10 +14,8 @@
 #include <weave/test/unittest_utils.h>
 
 #include "src/bind_lambda.h"
-#include "src/commands/command_manager.h"
+#include "src/component_manager_impl.h"
 #include "src/http_constants.h"
-#include "src/states/mock_state_change_queue_interface.h"
-#include "src/states/state_manager.h"
 
 using testing::_;
 using testing::AtLeast;
@@ -115,17 +113,9 @@
 class DeviceRegistrationInfoTest : public ::testing::Test {
  protected:
   void SetUp() override {
-    EXPECT_CALL(mock_state_change_queue_, GetLastStateChangeId())
-        .WillRepeatedly(Return(0));
-    EXPECT_CALL(mock_state_change_queue_, MockAddOnStateUpdatedCallback(_))
-        .WillRepeatedly(Return(nullptr));
-
-    command_manager_ = std::make_shared<CommandManager>();
-    state_manager_ = std::make_shared<StateManager>(&mock_state_change_queue_);
-
     std::unique_ptr<Config> config{new Config{&config_store_}};
     config_ = config.get();
-    dev_reg_.reset(new DeviceRegistrationInfo{command_manager_, state_manager_,
+    dev_reg_.reset(new DeviceRegistrationInfo{&component_manager_,
                                               std::move(config), &task_runner_,
                                               &http_client_, nullptr});
 
@@ -196,9 +186,7 @@
   base::DictionaryValue data_;
   Config* config_{nullptr};
   std::unique_ptr<DeviceRegistrationInfo> dev_reg_;
-  std::shared_ptr<CommandManager> command_manager_;
-  StrictMock<MockStateChangeQueueInterface> mock_state_change_queue_;
-  std::shared_ptr<StateManager> state_manager_;
+  ComponentManagerImpl component_manager_;
 };
 
 TEST_F(DeviceRegistrationInfoTest, GetServiceURL) {
@@ -352,21 +340,33 @@
 }
 
 TEST_F(DeviceRegistrationInfoTest, RegisterDevice) {
-  auto json_cmds = CreateDictionaryValue(R"({
+  auto json_traits = CreateDictionaryValue(R"({
     'base': {
-      'reboot': {
-        'parameters': {'delay': {'minimum': 10, 'type': 'integer'}},
-        'minimalRole': 'user'
+      'commands': {
+        'reboot': {
+          'parameters': {'delay': {'minimum': 10, 'type': 'integer'}},
+          'minimalRole': 'user'
+        }
+      },
+      'state': {
+        'firmwareVersion': {'type': 'string'}
       }
     },
     'robot': {
-      '_jump': {
-        'parameters': {'_height': {'type': 'integer'}},
-        'minimalRole': 'user'
+      'commands': {
+        '_jump': {
+          'parameters': {'_height': {'type': 'integer'}},
+          'minimalRole': 'user'
+        }
       }
     }
   })");
-  EXPECT_TRUE(command_manager_->LoadCommands(*json_cmds, nullptr));
+  EXPECT_TRUE(component_manager_.LoadTraits(*json_traits, nullptr));
+  EXPECT_TRUE(component_manager_.AddComponent("", "comp", {"base", "robot"},
+                                              nullptr));
+  base::StringValue ver{"1.0"};
+  EXPECT_TRUE(component_manager_.SetStateProperty(
+      "comp", "base.firmwareVersion", ver, nullptr));
 
   std::string ticket_url = dev_reg_->GetServiceURL("registrationTickets/") +
                            test_data::kClaimTicketId;
@@ -395,12 +395,9 @@
         EXPECT_EQ("AAAAA", value);
         EXPECT_TRUE(json->GetString("deviceDraft.name", &value));
         EXPECT_EQ("Coffee Pot", value);
-        base::DictionaryValue* commandDefs = nullptr;
-        EXPECT_TRUE(
-            json->GetDictionary("deviceDraft.commandDefs", &commandDefs));
-        EXPECT_FALSE(commandDefs->empty());
-
-        auto expected = R"({
+        base::DictionaryValue* dict = nullptr;
+        EXPECT_TRUE(json->GetDictionary("deviceDraft.commandDefs", &dict));
+        auto expectedCommandDefs = R"({
             'base': {
               'reboot': {
                 'parameters': {
@@ -423,7 +420,50 @@
               }
             }
           })";
-        EXPECT_JSON_EQ(expected, *commandDefs);
+        EXPECT_JSON_EQ(expectedCommandDefs, *dict);
+
+        EXPECT_TRUE(json->GetDictionary("deviceDraft.state", &dict));
+        auto expectedState = R"({
+            'base': {
+              'firmwareVersion': '1.0'
+            }
+          })";
+        EXPECT_JSON_EQ(expectedState, *dict);
+
+        EXPECT_TRUE(json->GetDictionary("deviceDraft.traits", &dict));
+        auto expectedTraits = R"({
+            'base': {
+              'commands': {
+                'reboot': {
+                  'parameters': {'delay': {'minimum': 10, 'type': 'integer'}},
+                  'minimalRole': 'user'
+                }
+              },
+              'state': {
+                'firmwareVersion': {'type': 'string'}
+              }
+            },
+            'robot': {
+              'commands': {
+                '_jump': {
+                  'parameters': {'_height': {'type': 'integer'}},
+                  'minimalRole': 'user'
+                }
+              }
+            }
+          })";
+        EXPECT_JSON_EQ(expectedTraits, *dict);
+
+        EXPECT_TRUE(json->GetDictionary("deviceDraft.components", &dict));
+        auto expectedComponents = R"({
+            'comp': {
+              'traits': ['base', 'robot'],
+              'state': {
+                'base': { 'firmwareVersion': '1.0' }
+              }
+            }
+          })";
+        EXPECT_JSON_EQ(expectedComponents, *dict);
 
         base::DictionaryValue json_resp;
         json_resp.SetString("id", test_data::kClaimTicketId);
@@ -519,22 +559,27 @@
     ReloadSettings();
     SetAccessToken();
 
-    auto json_cmds = CreateDictionaryValue(R"({
+    auto json_traits = CreateDictionaryValue(R"({
       'robot': {
-        '_jump': {
-          'parameters': {'_height': 'integer'},
-          'progress': {'progress': 'integer'},
-          'results': {'status': 'string'},
-          'minimalRole': 'user'
+        'commands': {
+          '_jump': {
+            'parameters': {'_height': 'integer'},
+            'progress': {'progress': 'integer'},
+            'results': {'status': 'string'},
+            'minimalRole': 'user'
+          }
         }
       }
     })");
-    EXPECT_TRUE(command_manager_->LoadCommands(*json_cmds, nullptr));
+    EXPECT_TRUE(component_manager_.LoadTraits(*json_traits, nullptr));
+    EXPECT_TRUE(component_manager_.AddComponent("", "comp", {"robot"},
+                                                nullptr));
 
     command_url_ = dev_reg_->GetServiceURL("commands/1234");
 
     auto commands_json = CreateValue(R"([{
       'name':'robot._jump',
+      'component': 'comp',
       'id':'1234',
       'parameters': {'_height': 100},
       'minimalRole': 'user'
@@ -543,7 +588,7 @@
     const base::ListValue* command_list = nullptr;
     ASSERT_TRUE(commands_json->GetAsList(&command_list));
     PublishCommands(*command_list);
-    command_ = command_manager_->FindCommand("1234");
+    command_ = component_manager_.FindCommand("1234");
     ASSERT_NE(nullptr, command_);
   }
 
diff --git a/src/mock_component_manager.h b/src/mock_component_manager.h
index aa58177..e30b8b0 100644
--- a/src/mock_component_manager.h
+++ b/src/mock_component_manager.h
@@ -29,7 +29,9 @@
                     ErrorPtr* error));
   MOCK_METHOD1(AddComponentTreeChangedCallback,
                void(const base::Closure& callback));
-  MOCK_METHOD5(AddCommand, bool(const base::DictionaryValue& command,
+  MOCK_METHOD1(MockAddCommand, void(CommandInstance* command_instance));
+  MOCK_METHOD5(MockParseCommandInstance,
+               CommandInstance*(const base::DictionaryValue& command,
                                 Command::Origin command_origin,
                                 UserRole role,
                                 std::string* id,
@@ -89,6 +91,18 @@
                      const base::DictionaryValue&());
 
  private:
+  void AddCommand(std::unique_ptr<CommandInstance> command_instance) override {
+    MockAddCommand(command_instance.get());
+  }
+  std::unique_ptr<CommandInstance> ParseCommandInstance(
+      const base::DictionaryValue& command,
+      Command::Origin command_origin,
+      UserRole role,
+      std::string* id,
+      ErrorPtr* error) {
+    return std::unique_ptr<CommandInstance>{MockParseCommandInstance(
+        command, command_origin, role, id, error)};
+  }
   StateSnapshot GetAndClearRecordedStateChanges() override {
     return std::move(MockGetAndClearRecordedStateChanges());
   }
diff --git a/src/privet/cloud_delegate.cc b/src/privet/cloud_delegate.cc
index 139bfc6..9c8a619 100644
--- a/src/privet/cloud_delegate.cc
+++ b/src/privet/cloud_delegate.cc
@@ -15,11 +15,10 @@
 #include <weave/provider/task_runner.h>
 
 #include "src/backoff_entry.h"
-#include "src/commands/command_manager.h"
+#include "src/component_manager.h"
 #include "src/config.h"
 #include "src/device_registration_info.h"
 #include "src/privet/constants.h"
-#include "src/states/state_manager.h"
 
 namespace weave {
 namespace privet {
@@ -42,26 +41,28 @@
  public:
   CloudDelegateImpl(provider::TaskRunner* task_runner,
                     DeviceRegistrationInfo* device,
-                    CommandManager* command_manager,
-                    StateManager* state_manager)
+                    ComponentManager* component_manager)
       : task_runner_{task_runner},
         device_{device},
-        command_manager_{command_manager},
-        state_manager_{state_manager} {
+        component_manager_{component_manager} {
     device_->GetMutableConfig()->AddOnChangedCallback(base::Bind(
         &CloudDelegateImpl::OnConfigChanged, weak_factory_.GetWeakPtr()));
     device_->AddGcdStateChangedCallback(base::Bind(
         &CloudDelegateImpl::OnRegistrationChanged, weak_factory_.GetWeakPtr()));
 
-    command_manager_->AddCommandDefChanged(base::Bind(
-        &CloudDelegateImpl::OnCommandDefChanged, weak_factory_.GetWeakPtr()));
-    command_manager_->AddCommandAddedCallback(base::Bind(
+    component_manager_->AddTraitDefChangedCallback(base::Bind(
+        &CloudDelegateImpl::NotifyOnTraitDefsChanged,
+        weak_factory_.GetWeakPtr()));
+    component_manager_->AddCommandAddedCallback(base::Bind(
         &CloudDelegateImpl::OnCommandAdded, weak_factory_.GetWeakPtr()));
-    command_manager_->AddCommandRemovedCallback(base::Bind(
+    component_manager_->AddCommandRemovedCallback(base::Bind(
         &CloudDelegateImpl::OnCommandRemoved, weak_factory_.GetWeakPtr()));
-
-    state_manager_->AddChangedCallback(base::Bind(
-        &CloudDelegateImpl::OnStateChanged, weak_factory_.GetWeakPtr()));
+    component_manager_->AddStateChangedCallback(base::Bind(
+        &CloudDelegateImpl::NotifyOnComponentTreeChanged,
+        weak_factory_.GetWeakPtr()));
+    component_manager_->AddComponentTreeChangedCallback(base::Bind(
+        &CloudDelegateImpl::NotifyOnComponentTreeChanged,
+        weak_factory_.GetWeakPtr()));
   }
 
   ~CloudDelegateImpl() override = default;
@@ -139,10 +140,20 @@
                : "";
   }
 
-  const base::DictionaryValue& GetState() const override { return state_; }
+  const base::DictionaryValue& GetLegacyCommandDef() const override {
+    return component_manager_->GetLegacyCommandDefinitions();
+  }
 
-  const base::DictionaryValue& GetCommandDef() const override {
-    return command_defs_;
+  const base::DictionaryValue& GetLegacyState() const override {
+    return component_manager_->GetLegacyState();
+  }
+
+  const base::DictionaryValue& GetComponents() const override {
+    return component_manager_->GetComponents();
+  }
+
+  const base::DictionaryValue& GetTraits() const override {
+    return component_manager_->GetTraits();
   }
 
   void AddCommand(const base::DictionaryValue& command,
@@ -162,11 +173,13 @@
     }
 
     std::string id;
-    if (!command_manager_->AddCommand(command, role, &id, &error))
+    auto command_instance = component_manager_->ParseCommandInstance(
+        command, Command::Origin::kLocal, role, &id, &error);
+    if (!command_instance)
       return callback.Run({}, std::move(error));
-
+    component_manager_->AddCommand(std::move(command_instance));
     command_owners_[id] = user_info.user_id();
-    callback.Run(*command_manager_->FindCommand(id)->ToJson(), nullptr);
+    callback.Run(*component_manager_->FindCommand(id)->ToJson(), nullptr);
   }
 
   void GetCommand(const std::string& id,
@@ -200,7 +213,7 @@
     for (const auto& it : command_owners_) {
       if (CanAccessCommand(it.second, user_info, nullptr)) {
         list_value.Append(
-            command_manager_->FindCommand(it.first)->ToJson().release());
+            component_manager_->FindCommand(it.first)->ToJson().release());
       }
     }
 
@@ -241,21 +254,6 @@
     NotifyOnDeviceInfoChanged();
   }
 
-  void OnStateChanged() {
-    state_.Clear();
-    const auto& state = state_manager_->GetState();
-    state_.MergeDictionary(&state);
-    NotifyOnStateChanged();
-  }
-
-  void OnCommandDefChanged() {
-    command_defs_.Clear();
-    const base::DictionaryValue& commands =
-      command_manager_->GetCommandDictionary().GetCommandsAsJson();
-    command_defs_.MergeDictionary(&commands);
-    NotifyOnCommandDefsChanged();
-  }
-
   void OnRegisterSuccess(const std::string& cloud_id) {
     VLOG(1) << "Device registered: " << cloud_id;
     setup_state_ = SetupState(SetupState::kSuccess);
@@ -304,7 +302,7 @@
         return nullptr;
     }
 
-    auto command = command_manager_->FindCommand(command_id);
+    auto command = component_manager_->FindCommand(command_id);
     if (!command)
       return ReturnNotFound(command_id, error);
 
@@ -329,8 +327,7 @@
 
   provider::TaskRunner* task_runner_{nullptr};
   DeviceRegistrationInfo* device_{nullptr};
-  CommandManager* command_manager_{nullptr};
-  StateManager* state_manager_{nullptr};
+  ComponentManager* component_manager_{nullptr};
 
   // Primary state of GCD.
   ConnectionState connection_state_{ConnectionState::kDisabled};
@@ -338,12 +335,6 @@
   // State of the current or last setup.
   SetupState setup_state_{SetupState::kNone};
 
-  // Current device state.
-  base::DictionaryValue state_;
-
-  // Current commands definitions.
-  base::DictionaryValue command_defs_;
-
   // Map of command IDs to user IDs.
   std::map<std::string, uint64_t> command_owners_;
 
@@ -367,22 +358,21 @@
 std::unique_ptr<CloudDelegate> CloudDelegate::CreateDefault(
     provider::TaskRunner* task_runner,
     DeviceRegistrationInfo* device,
-    CommandManager* command_manager,
-    StateManager* state_manager) {
+    ComponentManager* component_manager) {
   return std::unique_ptr<CloudDelegateImpl>{new CloudDelegateImpl{
-      task_runner, device, command_manager, state_manager}};
+      task_runner, device, component_manager}};
 }
 
 void CloudDelegate::NotifyOnDeviceInfoChanged() {
   FOR_EACH_OBSERVER(Observer, observer_list_, OnDeviceInfoChanged());
 }
 
-void CloudDelegate::NotifyOnCommandDefsChanged() {
-  FOR_EACH_OBSERVER(Observer, observer_list_, OnCommandDefsChanged());
+void CloudDelegate::NotifyOnTraitDefsChanged() {
+  FOR_EACH_OBSERVER(Observer, observer_list_, OnTraitDefsChanged());
 }
 
-void CloudDelegate::NotifyOnStateChanged() {
-  FOR_EACH_OBSERVER(Observer, observer_list_, OnStateChanged());
+void CloudDelegate::NotifyOnComponentTreeChanged() {
+  FOR_EACH_OBSERVER(Observer, observer_list_, OnComponentTreeChanged());
 }
 
 }  // namespace privet
diff --git a/src/privet/cloud_delegate.h b/src/privet/cloud_delegate.h
index 6396519..e1b1887 100644
--- a/src/privet/cloud_delegate.h
+++ b/src/privet/cloud_delegate.h
@@ -22,9 +22,8 @@
 
 namespace weave {
 
-class CommandManager;
+class ComponentManager;
 class DeviceRegistrationInfo;
-class StateManager;
 
 namespace provider {
 class TaskRunner;
@@ -48,8 +47,8 @@
     virtual ~Observer() {}
 
     virtual void OnDeviceInfoChanged() {}
-    virtual void OnCommandDefsChanged() {}
-    virtual void OnStateChanged() {}
+    virtual void OnTraitDefsChanged() {}
+    virtual void OnComponentTreeChanged() {}
   };
 
   // Returns the ID of the device.
@@ -95,11 +94,17 @@
   // Returns cloud id if the registered device or empty string if unregistered.
   virtual std::string GetCloudId() const = 0;
 
-  // Returns dictionary with device state.
-  virtual const base::DictionaryValue& GetState() const = 0;
+  // Returns dictionary with device state (for legacy APIs).
+  virtual const base::DictionaryValue& GetLegacyState() const = 0;
 
-  // Returns dictionary with commands definitions.
-  virtual const base::DictionaryValue& GetCommandDef() const = 0;
+  // Returns dictionary with commands definitions (for legacy APIs).
+  virtual const base::DictionaryValue& GetLegacyCommandDef() const = 0;
+
+  // Returns dictionary with component tree.
+  virtual const base::DictionaryValue& GetComponents() const = 0;
+
+  // Returns dictionary with trait definitions.
+  virtual const base::DictionaryValue& GetTraits() const = 0;
 
   // Adds command created from the given JSON representation.
   virtual void AddCommand(const base::DictionaryValue& command,
@@ -126,15 +131,14 @@
   }
 
   void NotifyOnDeviceInfoChanged();
-  void NotifyOnCommandDefsChanged();
-  void NotifyOnStateChanged();
+  void NotifyOnTraitDefsChanged();
+  void NotifyOnComponentTreeChanged();
 
   // Create default instance.
   static std::unique_ptr<CloudDelegate> CreateDefault(
       provider::TaskRunner* task_runner,
       DeviceRegistrationInfo* device,
-      CommandManager* command_manager,
-      StateManager* state_manager);
+      ComponentManager* component_manager);
 
  private:
   base::ObserverList<Observer> observer_list_;
diff --git a/src/privet/mock_delegates.h b/src/privet/mock_delegates.h
index 2186f2f..0cfa4ed 100644
--- a/src/privet/mock_delegates.h
+++ b/src/privet/mock_delegates.h
@@ -153,8 +153,10 @@
   MOCK_CONST_METHOD0(GetSetupState, const SetupState&());
   MOCK_METHOD3(Setup, bool(const std::string&, const std::string&, ErrorPtr*));
   MOCK_CONST_METHOD0(GetCloudId, std::string());
-  MOCK_CONST_METHOD0(GetState, const base::DictionaryValue&());
-  MOCK_CONST_METHOD0(GetCommandDef, const base::DictionaryValue&());
+  MOCK_CONST_METHOD0(GetLegacyState, const base::DictionaryValue&());
+  MOCK_CONST_METHOD0(GetLegacyCommandDef, const base::DictionaryValue&());
+  MOCK_CONST_METHOD0(GetComponents, const base::DictionaryValue&());
+  MOCK_CONST_METHOD0(GetTraits, const base::DictionaryValue&());
   MOCK_METHOD3(AddCommand,
                void(const base::DictionaryValue&,
                     const UserInfo&,
@@ -185,8 +187,11 @@
     EXPECT_CALL(*this, GetSetupState()).WillRepeatedly(ReturnRef(setup_state_));
     EXPECT_CALL(*this, GetCloudId()).WillRepeatedly(Return("TestCloudId"));
     test_dict_.Set("test", new base::DictionaryValue);
-    EXPECT_CALL(*this, GetCommandDef()).WillRepeatedly(ReturnRef(test_dict_));
-    EXPECT_CALL(*this, GetState()).WillRepeatedly(ReturnRef(test_dict_));
+    EXPECT_CALL(*this, GetLegacyState()).WillRepeatedly(ReturnRef(test_dict_));
+    EXPECT_CALL(*this,
+                GetLegacyCommandDef()).WillRepeatedly(ReturnRef(test_dict_));
+    EXPECT_CALL(*this, GetTraits()).WillRepeatedly(ReturnRef(test_dict_));
+    EXPECT_CALL(*this, GetComponents()).WillRepeatedly(ReturnRef(test_dict_));
   }
 
   ConnectionState connection_state_{ConnectionState::kOnline};
diff --git a/src/privet/privet_handler.cc b/src/privet/privet_handler.cc
index 157feed..d609787 100644
--- a/src/privet/privet_handler.cc
+++ b/src/privet/privet_handler.cc
@@ -378,7 +378,7 @@
     ReplyToUpdateRequest(req.callback);
 }
 
-void PrivetHandler::OnCommandDefsChanged() {
+void PrivetHandler::OnTraitDefsChanged() {
   ++command_defs_fingerprint_;
   auto pred = [this](const UpdateRequestParameters& params) {
     return params.command_defs_fingerprint < 0;
@@ -390,7 +390,7 @@
   update_requests_.erase(last, update_requests_.end());
 }
 
-void PrivetHandler::OnStateChanged() {
+void PrivetHandler::OnComponentTreeChanged() {
   ++state_fingerprint_;
   auto pred = [this](const UpdateRequestParameters& params) {
     return params.state_fingerprint < 0;
@@ -762,8 +762,7 @@
                                 const UserInfo& user_info,
                                 const RequestCallback& callback) {
   base::DictionaryValue output;
-  base::DictionaryValue* defs = cloud_->GetState().DeepCopy();
-  output.Set(kStateKey, defs);
+  output.Set(kStateKey, cloud_->GetLegacyState().DeepCopy());
   output.SetString(kFingerprintKey, std::to_string(state_fingerprint_));
 
   callback.Run(http::kOk, output);
@@ -773,8 +772,7 @@
                                       const UserInfo& user_info,
                                       const RequestCallback& callback) {
   base::DictionaryValue output;
-  base::DictionaryValue* defs = cloud_->GetCommandDef().DeepCopy();
-  output.Set(kCommandsKey, defs);
+  output.Set(kCommandsKey, cloud_->GetLegacyCommandDef().DeepCopy());
   output.SetString(kFingerprintKey, std::to_string(command_defs_fingerprint_));
 
   callback.Run(http::kOk, output);
diff --git a/src/privet/privet_handler.h b/src/privet/privet_handler.h
index fb9cc94..cc80d43 100644
--- a/src/privet/privet_handler.h
+++ b/src/privet/privet_handler.h
@@ -45,8 +45,8 @@
                 WifiDelegate* wifi);
   ~PrivetHandler() override;
 
-  void OnCommandDefsChanged() override;
-  void OnStateChanged() override;
+  void OnTraitDefsChanged() override;
+  void OnComponentTreeChanged() override;
 
   std::vector<std::string> GetHttpPaths() const;
   std::vector<std::string> GetHttpsPaths() const;
diff --git a/src/privet/privet_handler_unittest.cc b/src/privet/privet_handler_unittest.cc
index c212e54..517dda8 100644
--- a/src/privet/privet_handler_unittest.cc
+++ b/src/privet/privet_handler_unittest.cc
@@ -630,7 +630,7 @@
   EXPECT_PRED2(IsEqualJson, "{'state': {'test': {}}, 'fingerprint': '0'}",
                HandleRequest("/privet/v3/state", "{}"));
 
-  cloud_.NotifyOnStateChanged();
+  cloud_.NotifyOnComponentTreeChanged();
 
   EXPECT_PRED2(IsEqualJson, "{'state': {'test': {}}, 'fingerprint': '1'}",
                HandleRequest("/privet/v3/state", "{}"));
@@ -640,7 +640,7 @@
   EXPECT_PRED2(IsEqualJson, "{'commands': {'test':{}}, 'fingerprint': '0'}",
                HandleRequest("/privet/v3/commandDefs", "{}"));
 
-  cloud_.NotifyOnCommandDefsChanged();
+  cloud_.NotifyOnTraitDefsChanged();
 
   EXPECT_PRED2(IsEqualJson, "{'commands': {'test':{}}, 'fingerprint': '1'}",
                HandleRequest("/privet/v3/commandDefs", "{}"));
@@ -735,8 +735,8 @@
 TEST_F(PrivetHandlerSetupTest, CheckForUpdates_NoInput) {
   EXPECT_CALL(device_, GetHttpRequestTimeout())
       .WillOnce(Return(base::TimeDelta::Max()));
-  cloud_.NotifyOnCommandDefsChanged();
-  cloud_.NotifyOnStateChanged();
+  cloud_.NotifyOnTraitDefsChanged();
+  cloud_.NotifyOnComponentTreeChanged();
   const char kInput[] = "{}";
   const char kExpected[] = R"({
    'commandsFingerprint': '1',
@@ -750,8 +750,8 @@
 TEST_F(PrivetHandlerSetupTest, CheckForUpdates_AlreadyChanged) {
   EXPECT_CALL(device_, GetHttpRequestTimeout())
       .WillOnce(Return(base::TimeDelta::Max()));
-  cloud_.NotifyOnCommandDefsChanged();
-  cloud_.NotifyOnStateChanged();
+  cloud_.NotifyOnTraitDefsChanged();
+  cloud_.NotifyOnComponentTreeChanged();
   const char kInput[] = R"({
    'commandsFingerprint': '0',
    'stateFingerprint': '0'
@@ -775,7 +775,7 @@
   EXPECT_PRED2(IsEqualJson, "{}",
                HandleRequest("/privet/v3/checkForUpdates", kInput));
   EXPECT_EQ(0, GetResponseCount());
-  cloud_.NotifyOnCommandDefsChanged();
+  cloud_.NotifyOnTraitDefsChanged();
   EXPECT_EQ(1, GetResponseCount());
   const char kExpected[] = R"({
    'commandsFingerprint': '1',
@@ -794,7 +794,7 @@
   EXPECT_PRED2(IsEqualJson, "{}",
                HandleRequest("/privet/v3/checkForUpdates", kInput));
   EXPECT_EQ(0, GetResponseCount());
-  cloud_.NotifyOnStateChanged();
+  cloud_.NotifyOnComponentTreeChanged();
   EXPECT_EQ(1, GetResponseCount());
   const char kExpected[] = R"({
    'commandsFingerprint': '0',
@@ -812,9 +812,9 @@
   EXPECT_PRED2(IsEqualJson, "{}",
                HandleRequest("/privet/v3/checkForUpdates", kInput));
   EXPECT_EQ(0, GetResponseCount());
-  cloud_.NotifyOnCommandDefsChanged();
+  cloud_.NotifyOnTraitDefsChanged();
   EXPECT_EQ(0, GetResponseCount());
-  cloud_.NotifyOnStateChanged();
+  cloud_.NotifyOnComponentTreeChanged();
   EXPECT_EQ(1, GetResponseCount());
   const char kExpected[] = R"({
    'commandsFingerprint': '1',
@@ -832,9 +832,9 @@
   EXPECT_PRED2(IsEqualJson, "{}",
                HandleRequest("/privet/v3/checkForUpdates", kInput));
   EXPECT_EQ(0, GetResponseCount());
-  cloud_.NotifyOnStateChanged();
+  cloud_.NotifyOnComponentTreeChanged();
   EXPECT_EQ(0, GetResponseCount());
-  cloud_.NotifyOnCommandDefsChanged();
+  cloud_.NotifyOnTraitDefsChanged();
   EXPECT_EQ(1, GetResponseCount());
   const char kExpected[] = R"({
    'commandsFingerprint': '1',
@@ -953,7 +953,7 @@
   EXPECT_PRED2(IsEqualJson, "{}",
                HandleRequest("/privet/v3/checkForUpdates", kInput));
   EXPECT_EQ(0, GetResponseCount());
-  cloud_.NotifyOnCommandDefsChanged();
+  cloud_.NotifyOnTraitDefsChanged();
   EXPECT_EQ(1, GetResponseCount());
   const char kExpected[] = R"({
    'commandsFingerprint': '1',
diff --git a/src/privet/privet_manager.cc b/src/privet/privet_manager.cc
index e3485c0..a308eec 100644
--- a/src/privet/privet_manager.cc
+++ b/src/privet/privet_manager.cc
@@ -18,6 +18,7 @@
 #include <weave/provider/network.h>
 
 #include "src/bind_lambda.h"
+#include "src/component_manager.h"
 #include "src/device_registration_info.h"
 #include "src/http_constants.h"
 #include "src/privet/auth_manager.h"
@@ -47,15 +48,14 @@
                     HttpServer* http_server,
                     Wifi* wifi,
                     DeviceRegistrationInfo* device,
-                    CommandManager* command_manager,
-                    StateManager* state_manager) {
+                    ComponentManager* component_manager) {
   disable_security_ = device->GetSettings().disable_security;
 
   device_ = DeviceDelegate::CreateDefault(
       task_runner_, http_server->GetHttpPort(), http_server->GetHttpsPort(),
       http_server->GetRequestTimeout());
-  cloud_ = CloudDelegate::CreateDefault(task_runner_, device, command_manager,
-                                        state_manager);
+  cloud_ = CloudDelegate::CreateDefault(task_runner_, device,
+                                        component_manager);
   cloud_observer_.Add(cloud_.get());
 
   auth_.reset(new AuthManager(device->GetSettings().secret,
diff --git a/src/privet/privet_manager.h b/src/privet/privet_manager.h
index 95dbbb8..1342584 100644
--- a/src/privet/privet_manager.h
+++ b/src/privet/privet_manager.h
@@ -27,11 +27,10 @@
 
 namespace weave {
 
-class CommandManager;
+class ComponentManager;
 class DeviceRegistrationInfo;
 class DnsServiceDiscovery;
 class Network;
-class StateManager;
 
 namespace privet {
 
@@ -52,8 +51,7 @@
              provider::HttpServer* http_server,
              provider::Wifi* wifi,
              DeviceRegistrationInfo* device,
-             CommandManager* command_manager,
-             StateManager* state_manager);
+             ComponentManager* component_manager);
 
   std::string GetCurrentlyConnectedSsid() const;
 
diff --git a/src/states/error_codes.cc b/src/states/error_codes.cc
deleted file mode 100644
index 4b12a45..0000000
--- a/src/states/error_codes.cc
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2015 The Weave 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 "src/states/error_codes.h"
-
-namespace weave {
-namespace errors {
-namespace state {
-
-const char kDomain[] = "buffet_state";
-
-const char kPackageNameMissing[] = "package_name_missing";
-const char kPropertyNameMissing[] = "property_name_missing";
-const char kPropertyNotDefined[] = "property_not_defined";
-const char kPropertyRedefinition[] = "property_redefinition";
-
-}  // namespace state
-}  // namespace errors
-}  // namespace weave
diff --git a/src/states/error_codes.h b/src/states/error_codes.h
deleted file mode 100644
index 676a199..0000000
--- a/src/states/error_codes.h
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2015 The Weave 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 LIBWEAVE_SRC_STATES_ERROR_CODES_H_
-#define LIBWEAVE_SRC_STATES_ERROR_CODES_H_
-
-namespace weave {
-namespace errors {
-namespace state {
-
-// Error domain for state definitions.
-extern const char kDomain[];
-
-// State-specific error codes.
-extern const char kPackageNameMissing[];
-extern const char kPropertyNameMissing[];
-extern const char kPropertyNotDefined[];
-extern const char kPropertyRedefinition[];
-
-}  // namespace state
-}  // namespace errors
-}  // namespace weave
-
-#endif  // LIBWEAVE_SRC_STATES_ERROR_CODES_H_
diff --git a/src/states/mock_state_change_queue_interface.h b/src/states/mock_state_change_queue_interface.h
deleted file mode 100644
index fc119cd..0000000
--- a/src/states/mock_state_change_queue_interface.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2015 The Weave 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 LIBWEAVE_SRC_STATES_MOCK_STATE_CHANGE_QUEUE_INTERFACE_H_
-#define LIBWEAVE_SRC_STATES_MOCK_STATE_CHANGE_QUEUE_INTERFACE_H_
-
-#include <vector>
-
-#include <gmock/gmock.h>
-
-#include "src/states/state_change_queue_interface.h"
-
-namespace weave {
-
-class MockStateChangeQueueInterface : public StateChangeQueueInterface {
- public:
-  MOCK_CONST_METHOD0(IsEmpty, bool());
-  MOCK_METHOD2(NotifyPropertiesUpdated,
-               bool(base::Time timestamp,
-                    const base::DictionaryValue& changed_properties));
-  MOCK_METHOD0(MockGetAndClearRecordedStateChanges,
-               std::vector<StateChange>&());
-  MOCK_CONST_METHOD0(GetLastStateChangeId, UpdateID());
-  MOCK_METHOD1(MockAddOnStateUpdatedCallback,
-               base::CallbackList<void(UpdateID)>::Subscription*(
-                   const base::Callback<void(UpdateID)>&));
-  MOCK_METHOD1(NotifyStateUpdatedOnServer, void(UpdateID));
-
- private:
-  std::vector<StateChange> GetAndClearRecordedStateChanges() override {
-    return std::move(MockGetAndClearRecordedStateChanges());
-  }
-
-  Token AddOnStateUpdatedCallback(
-      const base::Callback<void(UpdateID)>& callback) override {
-    return Token{MockAddOnStateUpdatedCallback(callback)};
-  }
-};
-
-}  // namespace weave
-
-#endif  // LIBWEAVE_SRC_STATES_MOCK_STATE_CHANGE_QUEUE_INTERFACE_H_
diff --git a/src/states/state_change_queue.cc b/src/states/state_change_queue.cc
index b6c67cd..effe7f3 100644
--- a/src/states/state_change_queue.cc
+++ b/src/states/state_change_queue.cc
@@ -5,7 +5,6 @@
 #include "src/states/state_change_queue.h"
 
 #include <base/logging.h>
-#include <base/values.h>
 
 namespace weave {
 
@@ -38,7 +37,6 @@
     std::swap(element_old->second, element_new->second);
     state_changes_.erase(element_old);
   }
-  ++last_change_id_;
   return true;
 }
 
@@ -52,15 +50,4 @@
   return changes;
 }
 
-StateChangeQueueInterface::Token StateChangeQueue::AddOnStateUpdatedCallback(
-    const base::Callback<void(UpdateID)>& callback) {
-  if (state_changes_.empty())
-    callback.Run(last_change_id_);
-  return Token{callbacks_.Add(callback).release()};
-}
-
-void StateChangeQueue::NotifyStateUpdatedOnServer(UpdateID update_id) {
-  callbacks_.Notify(update_id);
-}
-
 }  // namespace weave
diff --git a/src/states/state_change_queue.h b/src/states/state_change_queue.h
index 857ec8b..3aef8d5 100644
--- a/src/states/state_change_queue.h
+++ b/src/states/state_change_queue.h
@@ -6,29 +6,36 @@
 #define LIBWEAVE_SRC_STATES_STATE_CHANGE_QUEUE_H_
 
 #include <map>
+#include <memory>
 #include <vector>
 
 #include <base/macros.h>
-
-#include "src/states/state_change_queue_interface.h"
+#include <base/time/time.h>
+#include <base/values.h>
 
 namespace weave {
 
+// A simple notification record event to track device state changes.
+// The |timestamp| records the time of the state change.
+// |changed_properties| contains a property set with the new property values
+// which were updated at the time the event was recorded.
+struct StateChange {
+  StateChange(base::Time time,
+              std::unique_ptr<base::DictionaryValue> properties)
+      : timestamp{time}, changed_properties{std::move(properties)} {}
+  base::Time timestamp;
+  std::unique_ptr<base::DictionaryValue> changed_properties;
+};
+
 // An object to record and retrieve device state change notification events.
-class StateChangeQueue : public StateChangeQueueInterface {
+class StateChangeQueue {
  public:
   explicit StateChangeQueue(size_t max_queue_size);
 
-  // Overrides from StateChangeQueueInterface.
-  bool IsEmpty() const override { return state_changes_.empty(); }
   bool NotifyPropertiesUpdated(
       base::Time timestamp,
-      const base::DictionaryValue& changed_properties) override;
-  std::vector<StateChange> GetAndClearRecordedStateChanges() override;
-  UpdateID GetLastStateChangeId() const override { return last_change_id_; }
-  Token AddOnStateUpdatedCallback(
-      const base::Callback<void(UpdateID)>& callback) override;
-  void NotifyStateUpdatedOnServer(UpdateID update_id) override;
+      const base::DictionaryValue& changed_properties);
+  std::vector<StateChange> GetAndClearRecordedStateChanges();
 
  private:
   // Maximum queue size. If it is full, the oldest state update records are
@@ -38,13 +45,6 @@
   // Accumulated list of device state change notifications.
   std::map<base::Time, std::unique_ptr<base::DictionaryValue>> state_changes_;
 
-  // An ID of last state change update. Each NotifyPropertiesUpdated()
-  // invocation increments this value by 1.
-  UpdateID last_change_id_{0};
-
-  // Callback list for state change queue even sinks.
-  base::CallbackList<void(UpdateID)> callbacks_;
-
   DISALLOW_COPY_AND_ASSIGN(StateChangeQueue);
 };
 
diff --git a/src/states/state_change_queue_interface.h b/src/states/state_change_queue_interface.h
deleted file mode 100644
index 7ddce8c..0000000
--- a/src/states/state_change_queue_interface.h
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright 2015 The Weave 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 LIBWEAVE_SRC_STATES_STATE_CHANGE_QUEUE_INTERFACE_H_
-#define LIBWEAVE_SRC_STATES_STATE_CHANGE_QUEUE_INTERFACE_H_
-
-#include <vector>
-
-#include <base/callback_list.h>
-#include <base/time/time.h>
-
-namespace base {
-class DictionaryValue;
-}  // namespace base
-
-namespace weave {
-
-// A simple notification record event to track device state changes.
-// The |timestamp| records the time of the state change.
-// |changed_properties| contains a property set with the new property values
-// which were updated at the time the event was recorded.
-struct StateChange {
-  StateChange(base::Time time,
-              std::unique_ptr<base::DictionaryValue> properties)
-      : timestamp{time}, changed_properties{std::move(properties)} {}
-  base::Time timestamp;
-  std::unique_ptr<base::DictionaryValue> changed_properties;
-};
-
-// An abstract interface to StateChangeQueue to record and retrieve state
-// change notification events.
-class StateChangeQueueInterface {
- public:
-  using UpdateID = uint64_t;
-  using Token =
-      std::unique_ptr<base::CallbackList<void(UpdateID)>::Subscription>;
-
-  // Returns true if the state change notification queue is empty.
-  virtual bool IsEmpty() const = 0;
-
-  // Called by StateManager when device state properties are updated.
-  virtual bool NotifyPropertiesUpdated(
-      base::Time timestamp,
-      const base::DictionaryValue& changed_properties) = 0;
-
-  // Returns the recorded state changes since last time this method was called.
-  virtual std::vector<StateChange> GetAndClearRecordedStateChanges() = 0;
-
-  // Returns an ID of last state change update. Each NotifyPropertiesUpdated()
-  // invocation increments this value by 1.
-  virtual UpdateID GetLastStateChangeId() const = 0;
-
-  // Subscribes for device state update notifications from cloud server.
-  // The |callback| will be called every time a state patch with given ID is
-  // successfully received and processed by GCD server.
-  // Returns a subscription token. As soon as this token is destroyed, the
-  // respective callback is removed from the callback list.
-  virtual Token AddOnStateUpdatedCallback(
-      const base::Callback<void(UpdateID)>& callback) WARN_UNUSED_RESULT = 0;
-
-  virtual void NotifyStateUpdatedOnServer(UpdateID update_id) = 0;
-
- protected:
-  // No one should attempt do destroy the queue through the interface.
-  virtual ~StateChangeQueueInterface() {}
-};
-
-}  // namespace weave
-
-#endif  // LIBWEAVE_SRC_STATES_STATE_CHANGE_QUEUE_INTERFACE_H_
diff --git a/src/states/state_change_queue_unittest.cc b/src/states/state_change_queue_unittest.cc
index b639d37..57cf490 100644
--- a/src/states/state_change_queue_unittest.cc
+++ b/src/states/state_change_queue_unittest.cc
@@ -23,8 +23,6 @@
 };
 
 TEST_F(StateChangeQueueTest, Empty) {
-  EXPECT_TRUE(queue_->IsEmpty());
-  EXPECT_EQ(0u, queue_->GetLastStateChangeId());
   EXPECT_TRUE(queue_->GetAndClearRecordedStateChanges().empty());
 }
 
@@ -32,14 +30,10 @@
   auto timestamp = base::Time::Now();
   ASSERT_TRUE(queue_->NotifyPropertiesUpdated(
       timestamp, *CreateDictionaryValue("{'prop': {'name': 23}}")));
-  EXPECT_FALSE(queue_->IsEmpty());
-  EXPECT_EQ(1u, queue_->GetLastStateChangeId());
   auto changes = queue_->GetAndClearRecordedStateChanges();
-  EXPECT_EQ(1u, queue_->GetLastStateChangeId());
   ASSERT_EQ(1u, changes.size());
   EXPECT_EQ(timestamp, changes.front().timestamp);
   EXPECT_JSON_EQ("{'prop':{'name': 23}}", *changes.front().changed_properties);
-  EXPECT_TRUE(queue_->IsEmpty());
   EXPECT_TRUE(queue_->GetAndClearRecordedStateChanges().empty());
 }
 
@@ -54,15 +48,12 @@
   ASSERT_TRUE(queue_->NotifyPropertiesUpdated(
       timestamp2, *CreateDictionaryValue(state2)));
 
-  EXPECT_EQ(2u, queue_->GetLastStateChangeId());
-  EXPECT_FALSE(queue_->IsEmpty());
   auto changes = queue_->GetAndClearRecordedStateChanges();
   ASSERT_EQ(2u, changes.size());
   EXPECT_EQ(timestamp1, changes[0].timestamp);
   EXPECT_JSON_EQ(state1, *changes[0].changed_properties);
   EXPECT_EQ(timestamp2, changes[1].timestamp);
   EXPECT_JSON_EQ(state2, *changes[1].changed_properties);
-  EXPECT_TRUE(queue_->IsEmpty());
   EXPECT_TRUE(queue_->GetAndClearRecordedStateChanges().empty());
 }
 
@@ -84,7 +75,6 @@
       *CreateDictionaryValue("{'prop': {'name1': 4}}")));
 
   auto changes = queue_->GetAndClearRecordedStateChanges();
-  EXPECT_EQ(4u, queue_->GetLastStateChangeId());
   ASSERT_EQ(2u, changes.size());
 
   const std::string expected1 = "{'prop': {'name1': 3, 'name2': 2}}";
@@ -113,7 +103,6 @@
       start_time + time_delta2,
       *CreateDictionaryValue("{'prop': {'name10': 10, 'name11': 11}}")));
 
-  EXPECT_EQ(3u, queue_->GetLastStateChangeId());
   auto changes = queue_->GetAndClearRecordedStateChanges();
   ASSERT_EQ(2u, changes.size());
 
@@ -128,26 +117,4 @@
   EXPECT_JSON_EQ(expected2, *changes[1].changed_properties);
 }
 
-TEST_F(StateChangeQueueTest, ImmediateStateChangeNotification) {
-  // When queue is empty, registering a new callback will trigger it.
-  bool called = false;
-  auto callback = [&called](StateChangeQueueInterface::UpdateID id) {
-    called = true;
-  };
-  queue_->AddOnStateUpdatedCallback(base::Bind(callback));
-  EXPECT_TRUE(called);
-}
-
-TEST_F(StateChangeQueueTest, DelayedStateChangeNotification) {
-  // When queue is not empty, registering a new callback will not trigger it.
-  ASSERT_TRUE(queue_->NotifyPropertiesUpdated(
-      base::Time::Now(),
-      *CreateDictionaryValue("{'prop': {'name1': 1, 'name3': 2}}")));
-
-  auto callback = [](StateChangeQueueInterface::UpdateID id) {
-    FAIL() << "This should not be called";
-  };
-  queue_->AddOnStateUpdatedCallback(base::Bind(callback));
-}
-
 }  // namespace weave
diff --git a/src/states/state_manager.cc b/src/states/state_manager.cc
deleted file mode 100644
index 128f7d8..0000000
--- a/src/states/state_manager.cc
+++ /dev/null
@@ -1,232 +0,0 @@
-// Copyright 2015 The Weave 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 "src/states/state_manager.h"
-
-#include <base/logging.h>
-#include <base/values.h>
-
-#include "src/json_error_codes.h"
-#include "src/states/error_codes.h"
-#include "src/states/state_change_queue_interface.h"
-#include "src/string_utils.h"
-#include "src/utils.h"
-
-namespace weave {
-
-StateManager::StateManager(StateChangeQueueInterface* state_change_queue)
-    : state_change_queue_(state_change_queue) {
-  CHECK(state_change_queue_) << "State change queue not specified";
-}
-
-StateManager::~StateManager() {}
-
-void StateManager::AddChangedCallback(const base::Closure& callback) {
-  on_changed_.push_back(callback);
-  callback.Run();  // Force to read current state.
-}
-
-const base::DictionaryValue& StateManager::GetState() const {
-  if (!cached_dict_valid_) {
-    cached_dict_.Clear();
-    for (const auto& pair : packages_) {
-      cached_dict_.SetWithoutPathExpansion(
-          pair.first, pair.second->GetValuesAsJson().DeepCopy());
-    }
-    cached_dict_valid_ = true;
-  }
-
-  return cached_dict_;
-}
-
-bool StateManager::SetProperty(const std::string& name,
-                               const base::Value& value,
-                               ErrorPtr* error) {
-  bool result = SetPropertyValue(name, value, base::Time::Now(), error);
-  for (const auto& cb : on_changed_)
-    cb.Run();
-  return result;
-}
-
-const base::Value* StateManager::GetProperty(const std::string& name) const {
-  auto parts = SplitAtFirst(name, ".", true);
-  const std::string& package_name = parts.first;
-  const std::string& property_name = parts.second;
-  if (package_name.empty() || property_name.empty())
-    return nullptr;
-
-  const StatePackage* package = FindPackage(package_name);
-  if (!package)
-    return nullptr;
-
-  return package->GetPropertyValue(property_name, nullptr);
-}
-
-bool StateManager::SetPropertyValue(const std::string& full_property_name,
-                                    const base::Value& value,
-                                    const base::Time& timestamp,
-                                    ErrorPtr* error) {
-  auto parts = SplitAtFirst(full_property_name, ".", true);
-  const std::string& package_name = parts.first;
-  const std::string& property_name = parts.second;
-  const bool split = (full_property_name.find(".") != std::string::npos);
-
-  if (full_property_name.empty() || (split && property_name.empty())) {
-    Error::AddTo(error, FROM_HERE, errors::state::kDomain,
-                 errors::state::kPropertyNameMissing,
-                 "Property name is missing");
-    return false;
-  }
-  if (!split || package_name.empty()) {
-    Error::AddTo(error, FROM_HERE, errors::state::kDomain,
-                 errors::state::kPackageNameMissing,
-                 "Package name is missing in the property name");
-    return false;
-  }
-  StatePackage* package = FindPackage(package_name);
-  if (package == nullptr) {
-    Error::AddToPrintf(error, FROM_HERE, errors::state::kDomain,
-                       errors::state::kPropertyNotDefined,
-                       "Unknown state property package '%s'",
-                       package_name.c_str());
-    return false;
-  }
-  if (!package->SetPropertyValue(property_name, value, error))
-    return false;
-
-  cached_dict_valid_ = false;
-
-  base::DictionaryValue prop_set;
-  prop_set.Set(full_property_name, value.DeepCopy());
-  state_change_queue_->NotifyPropertiesUpdated(timestamp, prop_set);
-  return true;
-}
-
-std::pair<StateChangeQueueInterface::UpdateID, std::vector<StateChange>>
-StateManager::GetAndClearRecordedStateChanges() {
-  return std::make_pair(state_change_queue_->GetLastStateChangeId(),
-                        state_change_queue_->GetAndClearRecordedStateChanges());
-}
-
-void StateManager::NotifyStateUpdatedOnServer(
-    StateChangeQueueInterface::UpdateID id) {
-  state_change_queue_->NotifyStateUpdatedOnServer(id);
-}
-
-bool StateManager::LoadStateDefinition(const base::DictionaryValue& dict,
-                                       ErrorPtr* error) {
-  for (base::DictionaryValue::Iterator iter(dict); !iter.IsAtEnd();
-       iter.Advance()) {
-    std::string package_name = iter.key();
-    if (package_name.empty()) {
-      Error::AddTo(error, FROM_HERE, errors::kErrorDomain,
-                   errors::kInvalidPackageError, "State package name is empty");
-      return false;
-    }
-    const base::DictionaryValue* package_dict = nullptr;
-    if (!iter.value().GetAsDictionary(&package_dict)) {
-      Error::AddToPrintf(error, FROM_HERE, errors::json::kDomain,
-                         errors::json::kObjectExpected,
-                         "State package '%s' must be an object",
-                         package_name.c_str());
-      return false;
-    }
-    StatePackage* package = FindOrCreatePackage(package_name);
-    CHECK(package) << "Unable to create state package " << package_name;
-    if (!package->AddSchemaFromJson(package_dict, error))
-      return false;
-  }
-
-  return true;
-}
-
-bool StateManager::LoadStateDefinitionFromJson(const std::string& json,
-                                               ErrorPtr* error) {
-  std::unique_ptr<const base::DictionaryValue> dict = LoadJsonDict(json, error);
-  if (!dict)
-    return false;
-  if (!LoadStateDefinition(*dict, 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::SetProperties(const base::DictionaryValue& dict,
-                                 ErrorPtr* error) {
-  base::Time timestamp = base::Time::Now();
-  bool all_success = true;
-  for (base::DictionaryValue::Iterator iter(dict); !iter.IsAtEnd();
-       iter.Advance()) {
-    if (iter.key().empty()) {
-      Error::AddTo(error, FROM_HERE, errors::kErrorDomain,
-                   errors::kInvalidPackageError, "State package name is empty");
-      all_success = false;
-      continue;
-    }
-
-    const base::DictionaryValue* package_dict = nullptr;
-    if (!iter.value().GetAsDictionary(&package_dict)) {
-      Error::AddToPrintf(error, FROM_HERE, errors::json::kDomain,
-                         errors::json::kObjectExpected,
-                         "State package '%s' must be an object",
-                         iter.key().c_str());
-      all_success = false;
-      continue;
-    }
-
-    for (base::DictionaryValue::Iterator it_prop(*package_dict);
-         !it_prop.IsAtEnd(); it_prop.Advance()) {
-      if (!SetPropertyValue(iter.key() + "." + it_prop.key(), it_prop.value(),
-                            timestamp, error)) {
-        all_success = false;
-        continue;
-      }
-    }
-  }
-  for (const auto& cb : on_changed_)
-    cb.Run();
-  return all_success;
-}
-
-bool StateManager::SetPropertiesFromJson(const std::string& json,
-                                         ErrorPtr* error) {
-  std::unique_ptr<const base::DictionaryValue> dict = LoadJsonDict(json, error);
-  if (!dict)
-    return false;
-  if (!SetProperties(*dict, error)) {
-    Error::AddToPrintf(error, FROM_HERE, errors::kErrorDomain,
-                       errors::kSchemaError, "Failed to load defaults: '%s'",
-                       json.c_str());
-    return false;
-  }
-  return true;
-}
-
-StatePackage* StateManager::FindPackage(const std::string& package_name) {
-  auto it = packages_.find(package_name);
-  return (it != packages_.end()) ? it->second.get() : nullptr;
-}
-
-const StatePackage* StateManager::FindPackage(
-    const std::string& package_name) const {
-  auto it = packages_.find(package_name);
-  return (it != packages_.end()) ? it->second.get() : nullptr;
-}
-
-StatePackage* StateManager::FindOrCreatePackage(
-    const std::string& package_name) {
-  StatePackage* package = FindPackage(package_name);
-  if (package == nullptr) {
-    std::unique_ptr<StatePackage> new_package{new StatePackage(package_name)};
-    package =
-        packages_.insert(std::make_pair(package_name, std::move(new_package)))
-            .first->second.get();
-  }
-  return package;
-}
-
-}  // namespace weave
diff --git a/src/states/state_manager.h b/src/states/state_manager.h
deleted file mode 100644
index bd1eb92..0000000
--- a/src/states/state_manager.h
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright 2015 The Weave 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 LIBWEAVE_SRC_STATES_STATE_MANAGER_H_
-#define LIBWEAVE_SRC_STATES_STATE_MANAGER_H_
-
-#include <map>
-#include <memory>
-#include <set>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include <base/callback.h>
-#include <base/macros.h>
-#include <weave/error.h>
-
-#include "src/states/state_change_queue_interface.h"
-#include "src/states/state_package.h"
-
-namespace base {
-class DictionaryValue;
-class Time;
-}  // namespace base
-
-namespace weave {
-
-// 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.
-class StateManager final {
- public:
-  explicit StateManager(StateChangeQueueInterface* state_change_queue);
-  ~StateManager();
-
-  void AddChangedCallback(const base::Closure& callback);
-  bool LoadStateDefinition(const base::DictionaryValue& dict, ErrorPtr* error);
-  bool LoadStateDefinitionFromJson(const std::string& json, ErrorPtr* error);
-  bool SetProperties(const base::DictionaryValue& dict, ErrorPtr* error);
-  bool SetPropertiesFromJson(const std::string& json, ErrorPtr* error);
-  const base::Value* GetProperty(const std::string& name) const;
-  bool SetProperty(const std::string& name,
-                   const base::Value& value,
-                   ErrorPtr* error);
-  const base::DictionaryValue& GetState() const;
-
-  // Returns the recorded state changes since last time this method has been
-  // called.
-  std::pair<StateChangeQueueInterface::UpdateID, std::vector<StateChange>>
-  GetAndClearRecordedStateChanges();
-
-  // Called to notify that the state patch with |id| has been successfully sent
-  // to the server and processed.
-  void NotifyStateUpdatedOnServer(StateChangeQueueInterface::UpdateID id);
-
-  StateChangeQueueInterface* GetStateChangeQueue() const {
-    return state_change_queue_;
-  }
-
-  const std::map<std::string, std::unique_ptr<StatePackage>>& packages() const {
-    return packages_;
-  }
-
- private:
-  friend class BaseApiHandlerTest;
-  friend class StateManagerTest;
-
-  // Updates a single property value. |full_property_name| must be the full
-  // name of the property to update in format "package.property".
-  bool SetPropertyValue(const std::string& full_property_name,
-                        const base::Value& value,
-                        const base::Time& timestamp,
-                        ErrorPtr* error);
-
-  // Finds a package by its name. Returns nullptr if not found.
-  StatePackage* FindPackage(const std::string& package_name);
-  const StatePackage* FindPackage(const std::string& package_name) const;
-  // Finds a package by its name. If none exists, one will be created.
-  StatePackage* FindOrCreatePackage(const std::string& package_name);
-
-  StateChangeQueueInterface* state_change_queue_;  // Owned by Manager.
-  std::map<std::string, std::unique_ptr<StatePackage>> packages_;
-
-  std::vector<base::Closure> on_changed_;
-
-  mutable base::DictionaryValue cached_dict_;
-  mutable bool cached_dict_valid_ = false;
-
-  DISALLOW_COPY_AND_ASSIGN(StateManager);
-};
-
-}  // namespace weave
-
-#endif  // LIBWEAVE_SRC_STATES_STATE_MANAGER_H_
diff --git a/src/states/state_manager_unittest.cc b/src/states/state_manager_unittest.cc
deleted file mode 100644
index 918fb89..0000000
--- a/src/states/state_manager_unittest.cc
+++ /dev/null
@@ -1,272 +0,0 @@
-// Copyright 2015 The Weave 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 "src/states/state_manager.h"
-
-#include <cstdlib>  // for abs().
-#include <vector>
-
-#include <base/bind.h>
-#include <base/values.h>
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-#include <weave/provider/test/mock_config_store.h>
-#include <weave/test/unittest_utils.h>
-
-#include "src/commands/schema_constants.h"
-#include "src/states/error_codes.h"
-#include "src/states/mock_state_change_queue_interface.h"
-
-namespace weave {
-
-using testing::_;
-using testing::Return;
-using testing::ReturnRef;
-using test::CreateDictionaryValue;
-
-namespace {
-
-const char kBaseDefinition[] = R"({
-  "base": {
-    "manufacturer":{"type":"string"},
-    "serialNumber":{"type":"string"}
-  },
-  "device": {
-    "state_property":{"type":"string"}
-  }
-})";
-
-std::unique_ptr<base::DictionaryValue> GetTestSchema() {
-  return CreateDictionaryValue(kBaseDefinition);
-}
-
-const char kBaseDefaults[] = R"({
-  "base": {
-    "manufacturer":"Test Factory",
-    "serialNumber":"Test Model"
-  }
-})";
-
-std::unique_ptr<base::DictionaryValue> GetTestValues() {
-  return CreateDictionaryValue(kBaseDefaults);
-}
-
-MATCHER_P(IsState, str, "") {
-  return arg.Equals(CreateDictionaryValue(str).get());
-}
-
-}  // anonymous namespace
-
-class StateManagerTest : public ::testing::Test {
- public:
-  void SetUp() override {
-    // Initial expectations.
-    EXPECT_CALL(mock_state_change_queue_, IsEmpty()).Times(0);
-    EXPECT_CALL(mock_state_change_queue_, NotifyPropertiesUpdated(_, _))
-        .WillRepeatedly(Return(true));
-    EXPECT_CALL(mock_state_change_queue_, MockGetAndClearRecordedStateChanges())
-        .Times(0);
-    mgr_.reset(new StateManager(&mock_state_change_queue_));
-
-    EXPECT_CALL(*this, OnStateChanged()).Times(2);
-    mgr_->AddChangedCallback(
-        base::Bind(&StateManagerTest::OnStateChanged, base::Unretained(this)));
-
-    LoadStateDefinition(GetTestSchema().get(), nullptr);
-    ASSERT_TRUE(mgr_->SetProperties(*GetTestValues().get(), nullptr));
-  }
-  void TearDown() override { mgr_.reset(); }
-
-  void LoadStateDefinition(const base::DictionaryValue* json,
-                           ErrorPtr* error) {
-    ASSERT_TRUE(mgr_->LoadStateDefinition(*json, error));
-  }
-
-  bool SetPropertyValue(const std::string& name,
-                        const base::Value& value,
-                        ErrorPtr* error) {
-    return mgr_->SetPropertyValue(name, value, timestamp_, error);
-  }
-
-  MOCK_CONST_METHOD0(OnStateChanged, void());
-
-  base::Time timestamp_{base::Time::Now()};
-  std::unique_ptr<StateManager> mgr_;
-  testing::StrictMock<MockStateChangeQueueInterface> mock_state_change_queue_;
-};
-
-TEST(StateManager, Empty) {
-  testing::StrictMock<MockStateChangeQueueInterface> mock_state_change_queue;
-  StateManager manager(&mock_state_change_queue);
-}
-
-TEST_F(StateManagerTest, Initialized) {
-  auto expected = R"({
-    'base': {
-      'manufacturer': 'Test Factory',
-      'serialNumber': 'Test Model'
-    },
-    'device': {}
-  })";
-  EXPECT_JSON_EQ(expected, mgr_->GetState());
-}
-
-TEST_F(StateManagerTest, LoadStateDefinition) {
-  auto dict = CreateDictionaryValue(R"({
-    'power': {
-      'battery_level':'integer'
-    }
-  })");
-  LoadStateDefinition(dict.get(), nullptr);
-
-  auto expected = R"({
-    'base': {
-      'manufacturer': 'Test Factory',
-      'serialNumber': 'Test Model'
-    },
-    'power': {},
-    'device': {}
-  })";
-  EXPECT_JSON_EQ(expected, mgr_->GetState());
-}
-
-TEST_F(StateManagerTest, Startup) {
-  StateManager manager(&mock_state_change_queue_);
-
-  auto state_definition = R"({
-    "base": {
-      "firmwareVersion": {"type":"string"},
-      "localDiscoveryEnabled": {"type":"boolean"},
-      "localAnonymousAccessMaxRole": {
-        "type": "string",
-        "enum": ["none", "viewer", "user"]
-      },
-      "localPairingEnabled": {"type":"boolean"}
-    },
-    "power": {"battery_level":{"type":"integer"}}
-  })";
-  ASSERT_TRUE(manager.LoadStateDefinitionFromJson(state_definition, nullptr));
-
-  auto state_values = R"({
-    "base": {
-      "firmwareVersion": "unknown",
-      "localDiscoveryEnabled": false,
-      "localAnonymousAccessMaxRole": "none",
-      "localPairingEnabled": false
-    },
-    "power": {"battery_level":44}
-  })";
-  ASSERT_TRUE(manager.SetPropertiesFromJson(state_values, nullptr));
-
-  auto expected = R"({
-    'base': {
-      'firmwareVersion': 'unknown',
-      'localAnonymousAccessMaxRole': 'none',
-      'localDiscoveryEnabled': false,
-      'localPairingEnabled': false
-    },
-    'power': {
-      'battery_level': 44
-    }
-  })";
-  EXPECT_JSON_EQ(expected, manager.GetState());
-}
-
-TEST_F(StateManagerTest, SetPropertyValue) {
-  const std::string state = "{'device': {'state_property': 'Test Value'}}";
-  EXPECT_CALL(mock_state_change_queue_,
-              NotifyPropertiesUpdated(timestamp_, IsState(state)))
-      .WillOnce(Return(true));
-  ASSERT_TRUE(SetPropertyValue("device.state_property",
-                               base::StringValue{"Test Value"}, nullptr));
-  auto expected = R"({
-    'base': {
-      'manufacturer': 'Test Factory',
-      'serialNumber': 'Test Model'
-    },
-    'device': {
-      'state_property': 'Test Value'
-    }
-  })";
-  EXPECT_JSON_EQ(expected, mgr_->GetState());
-}
-
-TEST_F(StateManagerTest, SetPropertyValue_Error_NoName) {
-  ErrorPtr error;
-  ASSERT_FALSE(SetPropertyValue("", base::FundamentalValue{0}, &error));
-  EXPECT_EQ(errors::state::kDomain, error->GetDomain());
-  EXPECT_EQ(errors::state::kPropertyNameMissing, error->GetCode());
-}
-
-TEST_F(StateManagerTest, SetPropertyValue_Error_NoPackage) {
-  ErrorPtr error;
-  ASSERT_FALSE(
-      SetPropertyValue("state_property", base::FundamentalValue{0}, &error));
-  EXPECT_EQ(errors::state::kDomain, error->GetDomain());
-  EXPECT_EQ(errors::state::kPackageNameMissing, error->GetCode());
-}
-
-TEST_F(StateManagerTest, SetPropertyValue_Error_UnknownPackage) {
-  ErrorPtr error;
-  ASSERT_FALSE(
-      SetPropertyValue("power.level", base::FundamentalValue{0}, &error));
-  EXPECT_EQ(errors::state::kDomain, error->GetDomain());
-  EXPECT_EQ(errors::state::kPropertyNotDefined, error->GetCode());
-}
-
-TEST_F(StateManagerTest, SetPropertyValue_Error_UnknownProperty) {
-  ASSERT_TRUE(
-      SetPropertyValue("base.level", base::FundamentalValue{0}, nullptr));
-}
-
-TEST_F(StateManagerTest, GetAndClearRecordedStateChanges) {
-  EXPECT_CALL(mock_state_change_queue_,
-              NotifyPropertiesUpdated(timestamp_, _))
-      .WillOnce(Return(true));
-  ASSERT_TRUE(SetPropertyValue("device.state_property",
-                               base::StringValue{"Test Value"}, nullptr));
-  std::vector<StateChange> expected_state;
-  const std::string expected_val =
-      "{'device': {'state_property': 'Test Value'}}";
-  expected_state.emplace_back(
-      timestamp_,
-      CreateDictionaryValue(expected_val));
-  EXPECT_CALL(mock_state_change_queue_, MockGetAndClearRecordedStateChanges())
-      .WillOnce(ReturnRef(expected_state));
-  EXPECT_CALL(mock_state_change_queue_, GetLastStateChangeId())
-      .WillOnce(Return(0));
-  auto changes = mgr_->GetAndClearRecordedStateChanges();
-  ASSERT_EQ(1u, changes.second.size());
-  EXPECT_EQ(timestamp_, changes.second.back().timestamp);
-  EXPECT_JSON_EQ(expected_val, *changes.second.back().changed_properties);
-}
-
-TEST_F(StateManagerTest, SetProperties) {
-  const std::string state = "{'base': {'manufacturer': 'No Name'}}";
-  EXPECT_CALL(mock_state_change_queue_,
-              NotifyPropertiesUpdated(_, IsState(state)))
-      .WillOnce(Return(true));
-
-  EXPECT_CALL(*this, OnStateChanged()).Times(1);
-  ASSERT_TRUE(mgr_->SetProperties(
-      *CreateDictionaryValue("{'base':{'manufacturer':'No Name'}}"), nullptr));
-
-  auto expected = R"({
-    'base': {
-      'manufacturer': 'No Name',
-      'serialNumber': 'Test Model'
-    },
-    'device': {}
-  })";
-  EXPECT_JSON_EQ(expected, mgr_->GetState());
-}
-
-TEST_F(StateManagerTest, GetProperty) {
-  EXPECT_JSON_EQ("'Test Model'", *mgr_->GetProperty("base.serialNumber"));
-  EXPECT_EQ(nullptr, mgr_->GetProperty("device.state_property"));
-  EXPECT_EQ(nullptr, mgr_->GetProperty("device.unknown"));
-  EXPECT_EQ(nullptr, mgr_->GetProperty("unknown.state_property"));
-}
-
-}  // namespace weave
diff --git a/src/states/state_package.cc b/src/states/state_package.cc
deleted file mode 100644
index b0ea199..0000000
--- a/src/states/state_package.cc
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright 2015 The Weave 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 "src/states/state_package.h"
-
-#include <base/logging.h>
-#include <base/values.h>
-
-#include "src/states/error_codes.h"
-
-namespace weave {
-
-StatePackage::StatePackage(const std::string& name) : name_(name) {}
-
-bool StatePackage::AddSchemaFromJson(const base::DictionaryValue* json,
-                                     ErrorPtr* error) {
-  // Scan first to make sure we have no property redefinitions.
-  for (base::DictionaryValue::Iterator it(*json); !it.IsAtEnd(); it.Advance()) {
-    if (types_.HasKey(it.key())) {
-      Error::AddToPrintf(error, FROM_HERE, errors::state::kDomain,
-                         errors::state::kPropertyRedefinition,
-                         "State property '%s.%s' is already defined",
-                         name_.c_str(), it.key().c_str());
-      return false;
-    }
-  }
-
-  types_.MergeDictionary(json);
-  return true;
-}
-
-bool StatePackage::AddValuesFromJson(const base::DictionaryValue* json,
-                                     ErrorPtr* error) {
-  for (base::DictionaryValue::Iterator it(*json); !it.IsAtEnd(); it.Advance()) {
-    if (!SetPropertyValue(it.key(), it.value(), error))
-      return false;
-  }
-  return true;
-}
-
-const base::DictionaryValue& StatePackage::GetValuesAsJson() const {
-  return values_;
-}
-
-const base::Value* StatePackage::GetPropertyValue(
-    const std::string& property_name,
-    ErrorPtr* error) const {
-  const base::Value* value = nullptr;
-  if (!values_.Get(property_name, &value)) {
-    Error::AddToPrintf(error, FROM_HERE, errors::state::kDomain,
-                       errors::state::kPropertyNotDefined,
-                       "State property '%s.%s' is not defined", name_.c_str(),
-                       property_name.c_str());
-    return nullptr;
-  }
-
-  return value;
-}
-
-bool StatePackage::SetPropertyValue(const std::string& property_name,
-                                    const base::Value& value,
-                                    ErrorPtr* error) {
-  values_.Set(property_name, value.DeepCopy());
-  return true;
-}
-
-}  // namespace weave
diff --git a/src/states/state_package.h b/src/states/state_package.h
deleted file mode 100644
index afc4c52..0000000
--- a/src/states/state_package.h
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2015 The Weave 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 LIBWEAVE_SRC_STATES_STATE_PACKAGE_H_
-#define LIBWEAVE_SRC_STATES_STATE_PACKAGE_H_
-
-#include <map>
-#include <memory>
-#include <string>
-
-#include <base/macros.h>
-#include <base/values.h>
-#include <weave/error.h>
-
-namespace weave {
-
-// A package is a set of related state properties. GCD specification defines
-// a number of standard state properties in "base" package such as
-// "base.manufacturer", "base.model", "base.firmwareVersion" and so on.
-class StatePackage final {
- public:
-  explicit StatePackage(const std::string& name);
-
-  // Loads state property definitions from a JSON object and adds them
-  // to the current package.
-  bool AddSchemaFromJson(const base::DictionaryValue* json, ErrorPtr* error);
-  // Loads a set of state property values from a JSON object and assigns them
-  // to existing properties.  A property must be defined prior to loading its
-  // value.  We use this when we load default values during buffet startup.
-  bool AddValuesFromJson(const base::DictionaryValue* json, ErrorPtr* error);
-
-  // Returns a set of state properties and their values as a JSON object.
-  // After being aggregated across multiple packages, this becomes the device
-  // state object passed to the GCD server or a local client in the format
-  // described by GCD specification, e.g.:
-  //  {
-  //    "base": {
-  //      "manufacturer":"...",
-  //      "model":"..."
-  //    },
-  //    "printer": {
-  //      "message": "Printer low on cyan ink"
-  //    }
-  //  }
-  const base::DictionaryValue& GetValuesAsJson() const;
-
-  // Gets the value for a specific state property. |property_name| must not
-  // include the package name as part of the property name.
-  const base::Value* GetPropertyValue(const std::string& property_name,
-                                      ErrorPtr* error) const;
-  // Sets the value for a specific state property. |property_name| must not
-  // include the package name as part of the property name.
-  bool SetPropertyValue(const std::string& property_name,
-                        const base::Value& value,
-                        ErrorPtr* error);
-
-  // Returns the name of the this package.
-  const std::string& GetName() const { return name_; }
-
-  const base::DictionaryValue& types() const { return types_; }
-
- private:
-  std::string name_;
-  base::DictionaryValue types_;
-  base::DictionaryValue values_;
-
-  friend class StatePackageTestHelper;
-  DISALLOW_COPY_AND_ASSIGN(StatePackage);
-};
-
-}  // namespace weave
-
-#endif  // LIBWEAVE_SRC_STATES_STATE_PACKAGE_H_
diff --git a/src/states/state_package_unittest.cc b/src/states/state_package_unittest.cc
deleted file mode 100644
index d09625a..0000000
--- a/src/states/state_package_unittest.cc
+++ /dev/null
@@ -1,289 +0,0 @@
-// Copyright 2015 The Weave 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 "src/states/state_package.h"
-
-#include <memory>
-#include <string>
-
-#include <base/values.h>
-#include <gtest/gtest.h>
-#include <weave/test/unittest_utils.h>
-
-#include "src/commands/schema_constants.h"
-#include "src/states/error_codes.h"
-
-namespace weave {
-
-using test::CreateDictionaryValue;
-
-class StatePackageTestHelper {
- public:
-  // Returns the state property definitions (types/constraints/etc).
-  static const base::DictionaryValue& GetTypes(const StatePackage& package) {
-    return package.types_;
-  }
-  // Returns the all state property values in this package.
-  static const base::DictionaryValue& GetValues(const StatePackage& package) {
-    return package.values_;
-  }
-};
-
-namespace {
-std::unique_ptr<base::DictionaryValue> GetTestSchema() {
-  return CreateDictionaryValue(R"({
-    'color': {
-      'type': 'string'
-    },
-    'direction': {
-      'additionalProperties': false,
-      'properties': {
-        'altitude': {
-          'maximum': 90.0,
-          'type': 'number'
-        },
-        'azimuth': {
-          'type': 'number'
-        }
-      },
-      'type': 'object',
-      'required': [ 'azimuth' ]
-    },
-    'iso': {
-      'enum': [50, 100, 200, 400],
-      'type': 'integer'
-    },
-    'light': {
-      'type': 'boolean'
-    }
-  })");
-}
-
-std::unique_ptr<base::DictionaryValue> GetTestValues() {
-  return CreateDictionaryValue(R"({
-      'light': true,
-      'color': 'white',
-      'direction': {'azimuth':57.2957795, 'altitude':89.9},
-      'iso': 200
-  })");
-}
-
-inline const base::DictionaryValue& GetTypes(const StatePackage& package) {
-  return StatePackageTestHelper::GetTypes(package);
-}
-// Returns the all state property values in this package.
-inline const base::DictionaryValue& GetValues(const StatePackage& package) {
-  return StatePackageTestHelper::GetValues(package);
-}
-
-}  // anonymous namespace
-
-class StatePackageTest : public ::testing::Test {
- public:
-  void SetUp() override {
-    package_.reset(new StatePackage("test"));
-    ASSERT_TRUE(package_->AddSchemaFromJson(GetTestSchema().get(), nullptr));
-    ASSERT_TRUE(package_->AddValuesFromJson(GetTestValues().get(), nullptr));
-  }
-  void TearDown() override { package_.reset(); }
-  std::unique_ptr<StatePackage> package_;
-};
-
-TEST(StatePackage, Empty) {
-  StatePackage package("test");
-  EXPECT_EQ("test", package.GetName());
-  EXPECT_TRUE(GetTypes(package).empty());
-  EXPECT_TRUE(GetValues(package).empty());
-}
-
-TEST(StatePackage, AddSchemaFromJson_OnEmpty) {
-  StatePackage package("test");
-  ASSERT_TRUE(package.AddSchemaFromJson(GetTestSchema().get(), nullptr));
-  EXPECT_EQ(4u, GetTypes(package).size());
-  EXPECT_EQ(0u, GetValues(package).size());
-
-  auto expected = R"({
-    'color': {
-      'type': 'string'
-    },
-    'direction': {
-      'additionalProperties': false,
-      'properties': {
-        'altitude': {
-          'maximum': 90.0,
-          'type': 'number'
-        },
-        'azimuth': {
-          'type': 'number'
-        }
-      },
-      'type': 'object',
-      'required': [ 'azimuth' ]
-    },
-    'iso': {
-      'enum': [50, 100, 200, 400],
-      'type': 'integer'
-    },
-    'light': {
-      'type': 'boolean'
-    }
-  })";
-  EXPECT_JSON_EQ(expected, GetTypes(package));
-
-  EXPECT_JSON_EQ("{}", package.GetValuesAsJson());
-}
-
-TEST(StatePackage, AddValuesFromJson_OnEmpty) {
-  StatePackage package("test");
-  ASSERT_TRUE(package.AddSchemaFromJson(GetTestSchema().get(), nullptr));
-  ASSERT_TRUE(package.AddValuesFromJson(GetTestValues().get(), nullptr));
-  EXPECT_EQ(4u, GetValues(package).size());
-  auto expected = R"({
-    'color': 'white',
-    'direction': {
-      'altitude': 89.9,
-      'azimuth': 57.2957795
-    },
-    'iso': 200,
-    'light': true
-  })";
-  EXPECT_JSON_EQ(expected, package.GetValuesAsJson());
-}
-
-TEST_F(StatePackageTest, AddSchemaFromJson_AddMore) {
-  auto dict = CreateDictionaryValue(R"({'brightness':{
-      'enum': ['low', 'medium', 'high'],
-      'type': 'string'
-    }})");
-  ASSERT_TRUE(package_->AddSchemaFromJson(dict.get(), nullptr));
-  EXPECT_EQ(5u, GetTypes(*package_).size());
-  EXPECT_EQ(4u, GetValues(*package_).size());
-  auto expected = R"({
-    'brightness': {
-      'enum': ['low', 'medium', 'high'],
-      'type': 'string'
-    },
-    'color': {
-      'type': 'string'
-    },
-    'direction': {
-      'additionalProperties': false,
-      'properties': {
-        'altitude': {
-          'maximum': 90.0,
-          'type': 'number'
-        },
-        'azimuth': {
-          'type': 'number'
-        }
-      },
-      'type': 'object',
-      'required': [ 'azimuth' ]
-    },
-    'iso': {
-      'enum': [50, 100, 200, 400],
-      'type': 'integer'
-    },
-    'light': {
-      'type': 'boolean'
-    }
-  })";
-  EXPECT_JSON_EQ(expected, GetTypes(*package_));
-
-  expected = R"({
-    'color': 'white',
-    'direction': {
-      'altitude': 89.9,
-      'azimuth': 57.2957795
-    },
-    'iso': 200,
-    'light': true
-  })";
-  EXPECT_JSON_EQ(expected, package_->GetValuesAsJson());
-}
-
-TEST_F(StatePackageTest, AddValuesFromJson_AddMore) {
-  auto dict = CreateDictionaryValue(R"({'brightness':{
-      'enum': ['low', 'medium', 'high'],
-      'type': 'string'
-    }})");
-  ASSERT_TRUE(package_->AddSchemaFromJson(dict.get(), nullptr));
-  dict = CreateDictionaryValue("{'brightness':'medium'}");
-  ASSERT_TRUE(package_->AddValuesFromJson(dict.get(), nullptr));
-  EXPECT_EQ(5u, GetValues(*package_).size());
-  auto expected = R"({
-    'brightness': 'medium',
-    'color': 'white',
-    'direction': {
-      'altitude': 89.9,
-      'azimuth': 57.2957795
-    },
-    'iso': 200,
-    'light': true
-  })";
-  EXPECT_JSON_EQ(expected, package_->GetValuesAsJson());
-}
-
-TEST_F(StatePackageTest, AddSchemaFromJson_Error_Redefined) {
-  auto dict = CreateDictionaryValue(R"({'color':
-    {'type':'string', 'enum':['white', 'blue', 'red']}})");
-  ErrorPtr error;
-  EXPECT_FALSE(package_->AddSchemaFromJson(dict.get(), &error));
-  EXPECT_EQ(errors::state::kDomain, error->GetDomain());
-  EXPECT_EQ(errors::state::kPropertyRedefinition, error->GetCode());
-}
-
-TEST_F(StatePackageTest, AddValuesFromJson_Error_Undefined) {
-  auto dict = CreateDictionaryValue("{'brightness':'medium'}");
-  EXPECT_TRUE(package_->AddValuesFromJson(dict.get(), nullptr));
-}
-
-TEST_F(StatePackageTest, GetPropertyValue) {
-  EXPECT_JSON_EQ("'white'", *package_->GetPropertyValue("color", nullptr));
-  EXPECT_JSON_EQ("true", *package_->GetPropertyValue("light", nullptr));
-  EXPECT_JSON_EQ("200", *package_->GetPropertyValue("iso", nullptr));
-  EXPECT_JSON_EQ("{'altitude': 89.9, 'azimuth': 57.2957795}",
-                 *package_->GetPropertyValue("direction", nullptr));
-}
-
-TEST_F(StatePackageTest, GetPropertyValue_Unknown) {
-  ErrorPtr error;
-  EXPECT_EQ(nullptr, package_->GetPropertyValue("volume", &error));
-  EXPECT_EQ(errors::state::kDomain, error->GetDomain());
-  EXPECT_EQ(errors::state::kPropertyNotDefined, error->GetCode());
-}
-
-TEST_F(StatePackageTest, SetPropertyValue_Simple) {
-  EXPECT_TRUE(
-      package_->SetPropertyValue("color", base::StringValue{"blue"}, nullptr));
-  EXPECT_JSON_EQ("'blue'", *package_->GetPropertyValue("color", nullptr));
-  EXPECT_TRUE(package_->SetPropertyValue("light", base::FundamentalValue{false},
-                                         nullptr));
-  bool light = false;
-  ASSERT_TRUE(
-      package_->GetPropertyValue("light", nullptr)->GetAsBoolean(&light));
-  EXPECT_FALSE(light);
-  EXPECT_TRUE(
-      package_->SetPropertyValue("iso", base::FundamentalValue{400}, nullptr));
-  EXPECT_JSON_EQ("400", *package_->GetPropertyValue("iso", nullptr));
-}
-
-TEST_F(StatePackageTest, SetPropertyValue_Object) {
-  EXPECT_TRUE(package_->SetPropertyValue(
-      "direction",
-      *CreateDictionaryValue("{'altitude': 45.0, 'azimuth': 15.0}"), nullptr));
-
-  auto expected = R"({
-    'color': 'white',
-    'direction': {
-      'altitude': 45.0,
-      'azimuth': 15.0
-    },
-    'iso': 200,
-    'light': true
-  })";
-  EXPECT_JSON_EQ(expected, package_->GetValuesAsJson());
-}
-
-}  // namespace weave