buffet: Add RegistrationStatus::InvalidCredentials

If the device has been deleted from GCD then an oauth request will
return an error of invalid_grant. Make sure we handle this and set
the registration status to InvalidCredentials.

BUG=brillo:16
TEST=FEATURES=test emerge-${BOARD} buffet (I also tested this manually
by deregistering the device using
https://gcd.sandbox.google.com/clouddevices#) and
test_that <ipaddress> buffet_Registration buffet_BasicDBusAPI

Change-Id: I60aa68186d9c6f3a7ce812e4dddfda626ea2b42f
Reviewed-on: https://chromium-review.googlesource.com/254170
Reviewed-by: Alex Vakulenko <avakulenko@chromium.org>
Commit-Queue: Nathan Bullock <nathanbullock@google.com>
Tested-by: Nathan Bullock <nathanbullock@google.com>
diff --git a/buffet/device_registration_info.cc b/buffet/device_registration_info.cc
index e482d81..0b98cb7 100644
--- a/buffet/device_registration_info.cc
+++ b/buffet/device_registration_info.cc
@@ -66,27 +66,6 @@
   return {chromeos::http::request_header::kAuthorization, authorization};
 }
 
-std::unique_ptr<base::DictionaryValue> ParseOAuthResponse(
-    const chromeos::http::Response* response, chromeos::ErrorPtr* error) {
-  int code = 0;
-  auto resp = chromeos::http::ParseJsonResponse(response, &code, error);
-  if (resp && code >= chromeos::http::status_code::BadRequest) {
-    if (error) {
-      std::string error_code, error_message;
-      if (resp->GetString("error", &error_code) &&
-          resp->GetString("error_description", &error_message)) {
-        chromeos::Error::AddTo(error, FROM_HERE, buffet::kErrorDomainOAuth2,
-                               error_code, error_message);
-      } else {
-        chromeos::Error::AddTo(error, FROM_HERE, buffet::kErrorDomainOAuth2,
-                               "unexpected_response", "Unexpected OAuth error");
-      }
-    }
-    return std::unique_ptr<base::DictionaryValue>();
-  }
-  return resp;
-}
-
 inline void SetUnexpectedError(chromeos::ErrorPtr* error) {
   chromeos::Error::AddTo(error, FROM_HERE, buffet::kErrorDomainGCD,
                          "unexpected_response", "Unexpected GCD error");
@@ -94,9 +73,6 @@
 
 void ParseGCDError(const base::DictionaryValue* json,
                    chromeos::ErrorPtr* error) {
-  if (!error)
-    return;
-
   const base::Value* list_value = nullptr;
   const base::ListValue* error_list = nullptr;
   if (!json->Get("error.errors", &list_value) ||
@@ -310,6 +286,31 @@
   return have_credentials;
 }
 
+std::unique_ptr<base::DictionaryValue>
+DeviceRegistrationInfo::ParseOAuthResponse(
+    const chromeos::http::Response* response, chromeos::ErrorPtr* error) {
+  int code = 0;
+  auto resp = chromeos::http::ParseJsonResponse(response, &code, error);
+  if (resp && code >= chromeos::http::status_code::BadRequest) {
+    std::string error_code, error_message;
+    if (!resp->GetString("error", &error_code)) {
+      error_code = "unexpected_response";
+    }
+    if (error_code == "invalid_grant") {
+      LOG(INFO) << "The device's registration has been revoked.";
+      SetRegistrationStatus(RegistrationStatus::kInvalidCredentials);
+    }
+    // I have never actually seen an error_description returned.
+    if (!resp->GetString("error_description", &error_message)) {
+      error_message = "Unexpected OAuth error";
+    }
+    chromeos::Error::AddTo(error, FROM_HERE, buffet::kErrorDomainOAuth2,
+                           error_code, error_message);
+    return std::unique_ptr<base::DictionaryValue>();
+  }
+  return resp;
+}
+
 bool DeviceRegistrationInfo::ValidateAndRefreshAccessToken(
     chromeos::ErrorPtr* error) {
   LOG(INFO) << "Checking access token expiration.";