update_engine: Populate UpdateCheckParams with rollback policies.

These are the policies introduced in crrev.com/c/916563,
controlling what should happen if target_version_prefix is
earlier than the current Chrome OS version, and how long Chrome
OS rollback protection should be postponed.

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

Change-Id: I33cf3b8975b52ca4b647a4b69a2d7879a9115d3c
Reviewed-on: https://chromium-review.googlesource.com/929321
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 5fbda46..92ab95f 100644
--- a/update_manager/android_things_policy.cc
+++ b/update_manager/android_things_policy.cc
@@ -53,6 +53,8 @@
   result->updates_enabled = true;
   result->target_channel.clear();
   result->target_version_prefix.clear();
+  result->rollback_to_target_version = RollbackToTargetVersion::kUnspecified;
+  result->rollback_allowed_milestones = -1;
   result->is_interactive = false;
 
   // Build a list of policies to consult.  Note that each policy may modify the
diff --git a/update_manager/boxed_value.cc b/update_manager/boxed_value.cc
index a437c02..b2505ee 100644
--- a/update_manager/boxed_value.cc
+++ b/update_manager/boxed_value.cc
@@ -26,6 +26,7 @@
 
 #include "update_engine/common/utils.h"
 #include "update_engine/connection_utils.h"
+#include "update_engine/update_manager/rollback_prefs.h"
 #include "update_engine/update_manager/shill_provider.h"
 #include "update_engine/update_manager/updater_provider.h"
 
@@ -133,6 +134,25 @@
   return "Unknown";
 }
 
+template <>
+string BoxedValue::ValuePrinter<RollbackToTargetVersion>(const void* value) {
+  const RollbackToTargetVersion* val =
+      reinterpret_cast<const RollbackToTargetVersion*>(value);
+  switch (*val) {
+    case RollbackToTargetVersion::kUnspecified:
+      return "Unspecified";
+    case RollbackToTargetVersion::kDisabled:
+      return "Disabled";
+    case RollbackToTargetVersion::kRollbackWithFullPowerwash:
+      return "Rollback with full powerwash";
+    case RollbackToTargetVersion::kMaxValue:
+      NOTREACHED();
+      return "Max value";
+  }
+  NOTREACHED();
+  return "Unknown";
+}
+
 template<>
 string BoxedValue::ValuePrinter<Stage>(const void* value) {
   const Stage* val = reinterpret_cast<const Stage*>(value);
diff --git a/update_manager/boxed_value_unittest.cc b/update_manager/boxed_value_unittest.cc
index 4aeaec8..04de3d4 100644
--- a/update_manager/boxed_value_unittest.cc
+++ b/update_manager/boxed_value_unittest.cc
@@ -26,6 +26,7 @@
 #include <base/strings/stringprintf.h>
 #include <base/time/time.h>
 
+#include "update_engine/update_manager/rollback_prefs.h"
 #include "update_engine/update_manager/shill_provider.h"
 #include "update_engine/update_manager/umtest_utils.h"
 #include "update_engine/update_manager/updater_provider.h"
@@ -192,6 +193,21 @@
             .ToString());
 }
 
+TEST(UmBoxedValueTest, RollbackToTargetVersionToString) {
+  EXPECT_EQ("Unspecified",
+            BoxedValue(new RollbackToTargetVersion(
+                           RollbackToTargetVersion::kUnspecified))
+                .ToString());
+  EXPECT_EQ("Disabled",
+            BoxedValue(
+                new RollbackToTargetVersion(RollbackToTargetVersion::kDisabled))
+                .ToString());
+  EXPECT_EQ("Rollback with full powerwash",
+            BoxedValue(new RollbackToTargetVersion(
+                           RollbackToTargetVersion::kRollbackWithFullPowerwash))
+                .ToString());
+}
+
 TEST(UmBoxedValueTest, SetConnectionTypeToString) {
   set<ConnectionType>* set1 = new set<ConnectionType>;
   set1->insert(ConnectionType::kWimax);
diff --git a/update_manager/chromeos_policy.cc b/update_manager/chromeos_policy.cc
index 51af63b..585ea19 100644
--- a/update_manager/chromeos_policy.cc
+++ b/update_manager/chromeos_policy.cc
@@ -199,6 +199,8 @@
   result->updates_enabled = true;
   result->target_channel.clear();
   result->target_version_prefix.clear();
+  result->rollback_to_target_version = RollbackToTargetVersion::kUnspecified;
+  result->rollback_allowed_milestones = -1;
   result->is_interactive = false;
 
   EnoughSlotsAbUpdatesPolicyImpl enough_slots_ab_updates_policy;
diff --git a/update_manager/chromeos_policy_unittest.cc b/update_manager/chromeos_policy_unittest.cc
index df29e8c..9538c4e 100644
--- a/update_manager/chromeos_policy_unittest.cc
+++ b/update_manager/chromeos_policy_unittest.cc
@@ -189,8 +189,14 @@
   // 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_release_channel_delegated()->
-      reset(new bool(false));
+  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));
+  fake_state_.device_policy_provider()->var_release_channel_delegated()->reset(
+      new bool(false));
   fake_state_.device_policy_provider()->var_release_channel()->
       reset(new string("foo-channel"));
 
@@ -199,6 +205,9 @@
                      &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);
 }
diff --git a/update_manager/default_policy.cc b/update_manager/default_policy.cc
index 5da1520..0cd58fb 100644
--- a/update_manager/default_policy.cc
+++ b/update_manager/default_policy.cc
@@ -40,6 +40,8 @@
   result->updates_enabled = true;
   result->target_channel.clear();
   result->target_version_prefix.clear();
+  result->rollback_to_target_version = RollbackToTargetVersion::kUnspecified;
+  result->rollback_allowed_milestones = -1;  // No version rolls should happen.
   result->is_interactive = false;
 
   // Ensure that the minimum interval is set. If there's no clock, this defaults
diff --git a/update_manager/enterprise_device_policy_impl.cc b/update_manager/enterprise_device_policy_impl.cc
index 94518a1..2cb1d9c 100644
--- a/update_manager/enterprise_device_policy_impl.cc
+++ b/update_manager/enterprise_device_policy_impl.cc
@@ -71,14 +71,26 @@
                 << (kiosk_required_platform_version_p
                         ? *kiosk_required_platform_version_p
                         : std::string("latest"));
+      // TODO(hunyadym): Add support of rollback for kiosk apps.
     } else {
       // Determine whether a target version prefix is dictated by policy.
       const string* target_version_prefix_p =
           ec->GetValue(dp_provider->var_target_version_prefix());
       if (target_version_prefix_p)
         result->target_version_prefix = *target_version_prefix_p;
+
+      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;
     }
 
+    // Determine allowed milestones for rollback
+    const int* rollback_allowed_milestones_p =
+        ec->GetValue(dp_provider->var_rollback_allowed_milestones());
+    if (rollback_allowed_milestones_p)
+      result->rollback_allowed_milestones = *rollback_allowed_milestones_p;
+
     // Determine whether a target channel is dictated by policy.
     const bool* release_channel_delegated_p =
         ec->GetValue(dp_provider->var_release_channel_delegated());
diff --git a/update_manager/policy.h b/update_manager/policy.h
index b60c4da..c651846 100644
--- a/update_manager/policy.h
+++ b/update_manager/policy.h
@@ -24,6 +24,7 @@
 #include "update_engine/common/error_code.h"
 #include "update_engine/payload_consumer/install_plan.h"
 #include "update_engine/update_manager/evaluation_context.h"
+#include "update_engine/update_manager/rollback_prefs.h"
 #include "update_engine/update_manager/state.h"
 
 namespace chromeos_update_manager {
@@ -47,6 +48,14 @@
   //
   // 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 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
+  // roll-forward should happen.
+  int rollback_allowed_milestones;
   // A target channel, if so imposed by policy; otherwise, an empty string.
   std::string target_channel;