update_engine: Add rollback_allowed policy in Omaha requests

Send rollback_allowed="true" parameter to Omaha if rollback is
allowed through enterprise policy.

This parameter indicates to Omaha that the returned image might
be a rollback image, if the targetversionprefix parameter is set
and it is an earlier version than the one which is currently on
the device.

Also, this CL changes update_engine behavior to only send
targetversionprefix to Omaha if it's not empty.

BUG=chromium:814830
TEST='cros_run_unit_tests --board=cyan --packages update_engine'

Change-Id: Iaa5503e217631311fb9ba3a5237ccbfedf04afe9
Reviewed-on: https://chromium-review.googlesource.com/932123
Commit-Ready: Marton Hunyady <hunyadym@chromium.org>
Tested-by: Marton Hunyady <hunyadym@chromium.org>
Reviewed-by: Amin Hassani <ahassani@chromium.org>
diff --git a/update_manager/android_things_policy.cc b/update_manager/android_things_policy.cc
index 92ab95f..259ca2b 100644
--- a/update_manager/android_things_policy.cc
+++ b/update_manager/android_things_policy.cc
@@ -53,7 +53,7 @@
   result->updates_enabled = true;
   result->target_channel.clear();
   result->target_version_prefix.clear();
-  result->rollback_to_target_version = RollbackToTargetVersion::kUnspecified;
+  result->rollback_allowed = false;
   result->rollback_allowed_milestones = -1;
   result->is_interactive = false;
 
diff --git a/update_manager/chromeos_policy.cc b/update_manager/chromeos_policy.cc
index 585ea19..c389d8b 100644
--- a/update_manager/chromeos_policy.cc
+++ b/update_manager/chromeos_policy.cc
@@ -199,7 +199,7 @@
   result->updates_enabled = true;
   result->target_channel.clear();
   result->target_version_prefix.clear();
-  result->rollback_to_target_version = RollbackToTargetVersion::kUnspecified;
+  result->rollback_allowed = false;
   result->rollback_allowed_milestones = -1;
   result->is_interactive = false;
 
diff --git a/update_manager/chromeos_policy_unittest.cc b/update_manager/chromeos_policy_unittest.cc
index 9538c4e..c7380e8 100644
--- a/update_manager/chromeos_policy_unittest.cc
+++ b/update_manager/chromeos_policy_unittest.cc
@@ -189,9 +189,6 @@
   // Override specific device policy attributes.
   fake_state_.device_policy_provider()->var_target_version_prefix()->
       reset(new string("1.2"));
-  fake_state_.device_policy_provider()->var_rollback_to_target_version()->reset(
-      new RollbackToTargetVersion(
-          RollbackToTargetVersion::kRollbackWithFullPowerwash));
   fake_state_.device_policy_provider()
       ->var_rollback_allowed_milestones()
       ->reset(new int(5));
@@ -205,13 +202,70 @@
                      &Policy::UpdateCheckAllowed, &result);
   EXPECT_TRUE(result.updates_enabled);
   EXPECT_EQ("1.2", result.target_version_prefix);
-  EXPECT_EQ(RollbackToTargetVersion::kRollbackWithFullPowerwash,
-            result.rollback_to_target_version);
   EXPECT_EQ(5, result.rollback_allowed_milestones);
   EXPECT_EQ("foo-channel", result.target_channel);
   EXPECT_FALSE(result.is_interactive);
 }
 
+TEST_F(UmChromeOSPolicyTest, UpdateCheckAllowedRollbackAllowed) {
+  // Update check is allowed, response includes attributes for use in the
+  // request.
+  SetUpdateCheckAllowed(true);
+
+  // Override RollbackToTargetVersion device policy attribute.
+  fake_state_.device_policy_provider()->var_rollback_to_target_version()->reset(
+      new RollbackToTargetVersion(
+          RollbackToTargetVersion::kRollbackWithFullPowerwash));
+
+  UpdateCheckParams result;
+  ExpectPolicyStatus(
+      EvalStatus::kSucceeded, &Policy::UpdateCheckAllowed, &result);
+  EXPECT_TRUE(result.rollback_allowed);
+}
+
+TEST_F(UmChromeOSPolicyTest, UpdateCheckAllowedRollbackDisabled) {
+  // Update check is allowed, response includes attributes for use in the
+  // request.
+  SetUpdateCheckAllowed(true);
+
+  // Override RollbackToTargetVersion device policy attribute.
+  fake_state_.device_policy_provider()->var_rollback_to_target_version()->reset(
+      new RollbackToTargetVersion(RollbackToTargetVersion::kDisabled));
+
+  UpdateCheckParams result;
+  ExpectPolicyStatus(
+      EvalStatus::kSucceeded, &Policy::UpdateCheckAllowed, &result);
+  EXPECT_FALSE(result.rollback_allowed);
+}
+
+TEST_F(UmChromeOSPolicyTest, UpdateCheckAllowedRollbackUnspecified) {
+  // Update check is allowed, response includes attributes for use in the
+  // request.
+  SetUpdateCheckAllowed(true);
+
+  // Override RollbackToTargetVersion device policy attribute.
+  fake_state_.device_policy_provider()->var_rollback_to_target_version()->reset(
+      new RollbackToTargetVersion(RollbackToTargetVersion::kUnspecified));
+
+  UpdateCheckParams result;
+  ExpectPolicyStatus(
+      EvalStatus::kSucceeded, &Policy::UpdateCheckAllowed, &result);
+  EXPECT_FALSE(result.rollback_allowed);
+}
+
+TEST_F(UmChromeOSPolicyTest, UpdateCheckAllowedRollbackNotSet) {
+  // Update check is allowed, response includes attributes for use in the
+  // request.
+  SetUpdateCheckAllowed(true);
+
+  // Don't set RollbackToTargetVersion device policy attribute.
+
+  UpdateCheckParams result;
+  ExpectPolicyStatus(
+      EvalStatus::kSucceeded, &Policy::UpdateCheckAllowed, &result);
+  EXPECT_FALSE(result.rollback_allowed);
+}
+
 TEST_F(UmChromeOSPolicyTest,
        UpdateCheckAllowedUpdatesDisabledForUnofficialBuilds) {
   // UpdateCheckAllowed should return kAskMeAgainLater if this is an unofficial
diff --git a/update_manager/default_policy.cc b/update_manager/default_policy.cc
index 0cd58fb..17d0e3e 100644
--- a/update_manager/default_policy.cc
+++ b/update_manager/default_policy.cc
@@ -40,7 +40,7 @@
   result->updates_enabled = true;
   result->target_channel.clear();
   result->target_version_prefix.clear();
-  result->rollback_to_target_version = RollbackToTargetVersion::kUnspecified;
+  result->rollback_allowed = false;
   result->rollback_allowed_milestones = -1;  // No version rolls should happen.
   result->is_interactive = false;
 
diff --git a/update_manager/enterprise_device_policy_impl.cc b/update_manager/enterprise_device_policy_impl.cc
index 2cb1d9c..94ae5e7 100644
--- a/update_manager/enterprise_device_policy_impl.cc
+++ b/update_manager/enterprise_device_policy_impl.cc
@@ -81,8 +81,21 @@
 
       const RollbackToTargetVersion* rollback_to_target_version_p =
           ec->GetValue(dp_provider->var_rollback_to_target_version());
-      if (rollback_to_target_version_p)
-        result->rollback_to_target_version = *rollback_to_target_version_p;
+      if (rollback_to_target_version_p) {
+        switch (*rollback_to_target_version_p) {
+          case RollbackToTargetVersion::kUnspecified:
+          case RollbackToTargetVersion::kDisabled:
+            result->rollback_allowed = false;
+            break;
+          case RollbackToTargetVersion::kRollbackWithFullPowerwash:
+            result->rollback_allowed = true;
+            break;
+          case RollbackToTargetVersion::kMaxValue:
+            NOTREACHED();
+            // Don't add a default case to let the compiler warn about newly
+            // added enum values which should be added here.
+        }
+      }
     }
 
     // Determine allowed milestones for rollback
diff --git a/update_manager/policy.h b/update_manager/policy.h
index c651846..7089c30 100644
--- a/update_manager/policy.h
+++ b/update_manager/policy.h
@@ -48,9 +48,8 @@
   //
   // A target version prefix, if imposed by policy; otherwise, an empty string.
   std::string target_version_prefix;
-  // Specifies what should happen if target_version_prefix specifies an earlier
-  // version than the current version of the OS.
-  RollbackToTargetVersion rollback_to_target_version;
+  // Specifies whether rollback images are allowed by device policy.
+  bool rollback_allowed;
   // Specifies the number of Chrome milestones rollback should be allowed,
   // starting from the stable version at any time. Value is -1 if unspecified
   // (e.g. no device policy is available yet), in this case no version