buffet: Expose RegistrationStatus over DBus

This new property lets applications monitor Buffet's connection to
cloud services.

BUG=brillo:16
TEST=Unittests, buffet_Registration has been expanded appropriately.
CQ-DEPEND=CL:*199337
Change-Id: I30253e8199cb65068a74dd8b780a8ab0954bf9fa
Reviewed-on: https://chromium-review.googlesource.com/250011
Reviewed-by: Alex Vakulenko <avakulenko@chromium.org>
Tested-by: Christopher Wiley <wiley@chromium.org>
Commit-Queue: Christopher Wiley <wiley@chromium.org>
diff --git a/buffet/device_registration_info.cc b/buffet/device_registration_info.cc
index 3e8fd00..16f576a 100644
--- a/buffet/device_registration_info.cc
+++ b/buffet/device_registration_info.cc
@@ -146,12 +146,14 @@
     const std::shared_ptr<StateManager>& state_manager,
     std::unique_ptr<chromeos::KeyValueStore> config_store,
     const std::shared_ptr<chromeos::http::Transport>& transport,
-    const std::shared_ptr<StorageInterface>& state_store)
+    const std::shared_ptr<StorageInterface>& state_store,
+    const StatusHandler& status_handler)
     : transport_{transport},
       storage_{state_store},
       command_manager_{command_manager},
       state_manager_{state_manager},
-      config_store_{std::move(config_store)} {
+      config_store_{std::move(config_store)},
+      registration_status_handler_{status_handler} {
 }
 
 DeviceRegistrationInfo::~DeviceRegistrationInfo() = default;
@@ -251,6 +253,9 @@
   description_          = description;
   location_             = location;
 
+  if (HaveRegistrationCredentials(nullptr))
+    SetRegistrationStatus(RegistrationStatus::kOffline);
+
   return true;
 }
 
@@ -286,19 +291,23 @@
 }
 
 bool DeviceRegistrationInfo::CheckRegistration(chromeos::ErrorPtr* error) {
-  LOG(INFO) << "Checking device registration record.";
-  if (refresh_token_.empty() ||
-      device_id_.empty() ||
-      device_robot_account_.empty()) {
-    LOG(INFO) << "No valid device registration record found.";
+  return HaveRegistrationCredentials(error) &&
+         ValidateAndRefreshAccessToken(error);
+}
+
+bool DeviceRegistrationInfo::HaveRegistrationCredentials(
+    chromeos::ErrorPtr* error) {
+  const bool have_credentials = !refresh_token_.empty() &&
+                                !device_id_.empty() &&
+                                !device_robot_account_.empty();
+
+  VLOG(1) << "Device registration record "
+          << ((have_credentials) ? "found" : "not found.");
+  if (!have_credentials)
     chromeos::Error::AddTo(error, FROM_HERE, kErrorDomainGCD,
                            "device_not_registered",
                            "No valid device registration record found");
-    return false;
-  }
-
-  LOG(INFO) << "Device registration record found.";
-  return ValidateAndRefreshAccessToken(error);
+  return have_credentials;
 }
 
 bool DeviceRegistrationInfo::ValidateAndRefreshAccessToken(
@@ -543,6 +552,7 @@
   // We're going to respond with our success immediately and we'll StartDevice
   // shortly after.
   ScheduleStartDevice(base::TimeDelta::FromSeconds(0));
+  SetRegistrationStatus(RegistrationStatus::kRegistered);
   return device_id_;
 }
 
@@ -704,7 +714,6 @@
 void DeviceRegistrationInfo::StartDevice(chromeos::ErrorPtr* error) {
   if (!CheckRegistration(error))
     return;
-
   base::Bind(
       &DeviceRegistrationInfo::UpdateDeviceResource,
       base::Unretained(this),
@@ -820,6 +829,10 @@
       base::Bind(&DeviceRegistrationInfo::PublishStateUpdates,
                  base::Unretained(this)),
       base::TimeDelta::FromSeconds(7));
+  // TODO(wiley): This is the very bare minimum of state to report to local
+  //              services interested in our GCD state.  Build a more
+  //              robust model of our state with respect to the server.
+  SetRegistrationStatus(RegistrationStatus::kRegistered);
 }
 
 void DeviceRegistrationInfo::PublishCommands(const base::ListValue& commands) {
@@ -915,4 +928,14 @@
   return false;
 }
 
+void DeviceRegistrationInfo::SetRegistrationStatus(
+    RegistrationStatus new_status) {
+  if (new_status == registration_status_)
+    return;
+  VLOG(1) << "Changing registration status to " << StatusToString(new_status);
+  registration_status_ = new_status;
+  if (!registration_status_handler_.is_null())
+    registration_status_handler_.Run(registration_status_);
+}
+
 }  // namespace buffet