update_engine: Add new rollback device policies.

Add rollback_to_target_version and rollback_allowed_milestones
device policies to update_engine's device_policy_provider.

These are matching the device policies introduced in crrev.com/c/916563.
rollback_to_target_version is describing what should happen when the
target_version_prefix policy has a lower value than the current OS
value. rollback_allowed_milestones is setting the number of milestones
rollback protection should be postponed for enterprise enrolled devices.

BUG=chromium:813036
TEST='cros_run_unit_tests --board=cyan --packages update_engine'
CQ-DEPEND=CL:923971

Change-Id: I310690882f10fcbb57cc9b957fad5388c3a06bc9
Reviewed-on: https://chromium-review.googlesource.com/928723
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/device_policy_provider.h b/update_manager/device_policy_provider.h
index 3537d13..22613a1 100644
--- a/update_manager/device_policy_provider.h
+++ b/update_manager/device_policy_provider.h
@@ -24,6 +24,7 @@
 #include <policy/libpolicy.h>
 
 #include "update_engine/update_manager/provider.h"
+#include "update_engine/update_manager/rollback_prefs.h"
 #include "update_engine/update_manager/shill_provider.h"
 #include "update_engine/update_manager/variable.h"
 
@@ -46,6 +47,15 @@
 
   virtual Variable<std::string>* var_target_version_prefix() = 0;
 
+  // Variable returning what should happen if the target_version_prefix is
+  // earlier than the current Chrome OS version.
+  virtual Variable<RollbackToTargetVersion>*
+      var_rollback_to_target_version() = 0;
+
+  // Variable returning the number of Chrome milestones rollback should be
+  // possible. Rollback protection will be postponed by this many versions.
+  virtual Variable<int>* var_rollback_allowed_milestones() = 0;
+
   // Returns a non-negative scatter interval used for updates.
   virtual Variable<base::TimeDelta>* var_scatter_factor() = 0;
 
diff --git a/update_manager/fake_device_policy_provider.h b/update_manager/fake_device_policy_provider.h
index 9e4f5b7..957341c 100644
--- a/update_manager/fake_device_policy_provider.h
+++ b/update_manager/fake_device_policy_provider.h
@@ -50,6 +50,15 @@
     return &var_target_version_prefix_;
   }
 
+  FakeVariable<RollbackToTargetVersion>* var_rollback_to_target_version()
+      override {
+    return &var_rollback_to_target_version_;
+  }
+
+  FakeVariable<int>* var_rollback_allowed_milestones() override {
+    return &var_rollback_allowed_milestones_;
+  }
+
   FakeVariable<base::TimeDelta>* var_scatter_factor() override {
     return &var_scatter_factor_;
   }
@@ -86,6 +95,10 @@
       "update_disabled", kVariableModePoll};
   FakeVariable<std::string> var_target_version_prefix_{
       "target_version_prefix", kVariableModePoll};
+  FakeVariable<RollbackToTargetVersion> var_rollback_to_target_version_{
+      "rollback_to_target_version", kVariableModePoll};
+  FakeVariable<int> var_rollback_allowed_milestones_{
+      "rollback_allowed_milestones", kVariableModePoll};
   FakeVariable<base::TimeDelta> var_scatter_factor_{
       "scatter_factor", kVariableModePoll};
   FakeVariable<std::set<chromeos_update_engine::ConnectionType>>
diff --git a/update_manager/real_device_policy_provider.cc b/update_manager/real_device_policy_provider.cc
index d9880c3..96f8739 100644
--- a/update_manager/real_device_policy_provider.cc
+++ b/update_manager/real_device_policy_provider.cc
@@ -126,6 +126,23 @@
   }
 }
 
+bool RealDevicePolicyProvider::ConvertRollbackToTargetVersion(
+    RollbackToTargetVersion* rollback_to_target_version) const {
+  int rollback_to_target_version_int;
+  if (!policy_provider_->GetDevicePolicy().GetRollbackToTargetVersion(
+          &rollback_to_target_version_int)) {
+    return false;
+  }
+  if (rollback_to_target_version_int < 0 ||
+      rollback_to_target_version_int >=
+          static_cast<int>(RollbackToTargetVersion::kMaxValue)) {
+    return false;
+  }
+  *rollback_to_target_version =
+      static_cast<RollbackToTargetVersion>(rollback_to_target_version_int);
+  return true;
+}
+
 bool RealDevicePolicyProvider::ConvertAllowedConnectionTypesForUpdate(
       set<ConnectionType>* allowed_types) const {
   set<string> allowed_types_str;
@@ -176,6 +193,10 @@
   UpdateVariable(&var_update_disabled_, &DevicePolicy::GetUpdateDisabled);
   UpdateVariable(&var_target_version_prefix_,
                  &DevicePolicy::GetTargetVersionPrefix);
+  UpdateVariable(&var_rollback_to_target_version_,
+                 &RealDevicePolicyProvider::ConvertRollbackToTargetVersion);
+  UpdateVariable(&var_rollback_allowed_milestones_,
+                 &DevicePolicy::GetRollbackAllowedMilestones);
   UpdateVariable(&var_scatter_factor_,
                  &RealDevicePolicyProvider::ConvertScatterFactor);
   UpdateVariable(
diff --git a/update_manager/real_device_policy_provider.h b/update_manager/real_device_policy_provider.h
index 5b5ee58..54216f1 100644
--- a/update_manager/real_device_policy_provider.h
+++ b/update_manager/real_device_policy_provider.h
@@ -20,6 +20,7 @@
 #include <memory>
 #include <set>
 #include <string>
+#include <utility>
 
 #include <brillo/message_loops/message_loop.h>
 #include <gtest/gtest_prod.h>  // for FRIEND_TEST
@@ -71,6 +72,14 @@
     return &var_target_version_prefix_;
   }
 
+  Variable<RollbackToTargetVersion>* var_rollback_to_target_version() override {
+    return &var_rollback_to_target_version_;
+  }
+
+  Variable<int>* var_rollback_allowed_milestones() override {
+    return &var_rollback_allowed_milestones_;
+  }
+
   Variable<base::TimeDelta>* var_scatter_factor() override {
     return &var_scatter_factor_;
   }
@@ -130,6 +139,11 @@
       AsyncCopyVariable<T>* var,
       bool (RealDevicePolicyProvider::*getter_method)(T*) const);
 
+  // Wrapper for DevicePolicy::GetRollbackToTargetVersion() that converts the
+  // result to RollbackToTargetVersion.
+  bool ConvertRollbackToTargetVersion(
+      RollbackToTargetVersion* rollback_to_target_version) const;
+
   // Wrapper for DevicePolicy::GetScatterFactorInSeconds() that converts the
   // result to a base::TimeDelta. It returns the same value as
   // GetScatterFactorInSeconds().
@@ -164,6 +178,10 @@
   AsyncCopyVariable<bool> var_update_disabled_{"update_disabled"};
   AsyncCopyVariable<std::string> var_target_version_prefix_{
       "target_version_prefix"};
+  AsyncCopyVariable<RollbackToTargetVersion> var_rollback_to_target_version_{
+      "rollback_to_target_version"};
+  AsyncCopyVariable<int> var_rollback_allowed_milestones_{
+      "rollback_allowed_milestones"};
   AsyncCopyVariable<base::TimeDelta> var_scatter_factor_{"scatter_factor"};
   AsyncCopyVariable<std::set<chromeos_update_engine::ConnectionType>>
       var_allowed_connection_types_for_update_{
diff --git a/update_manager/real_device_policy_provider_unittest.cc b/update_manager/real_device_policy_provider_unittest.cc
index 167cbd9..6396e3f 100644
--- a/update_manager/real_device_policy_provider_unittest.cc
+++ b/update_manager/real_device_policy_provider_unittest.cc
@@ -178,6 +178,10 @@
   UmTestUtils::ExpectVariableNotSet(provider_->var_release_channel_delegated());
   UmTestUtils::ExpectVariableNotSet(provider_->var_update_disabled());
   UmTestUtils::ExpectVariableNotSet(provider_->var_target_version_prefix());
+  UmTestUtils::ExpectVariableNotSet(
+      provider_->var_rollback_to_target_version());
+  UmTestUtils::ExpectVariableNotSet(
+      provider_->var_rollback_allowed_milestones());
   UmTestUtils::ExpectVariableNotSet(provider_->var_scatter_factor());
   UmTestUtils::ExpectVariableNotSet(
       provider_->var_allowed_connection_types_for_update());
@@ -218,6 +222,23 @@
       true, provider_->var_allow_kiosk_app_control_chrome_version());
 }
 
+TEST_F(UmRealDevicePolicyProviderTest, RollbackToTargetVersionConverted) {
+  SetUpExistentDevicePolicy();
+  EXPECT_CALL(mock_device_policy_, GetRollbackToTargetVersion(_))
+#if USE_DBUS
+      .Times(2)
+#else
+      .Times(1)
+#endif  // USE_DBUS
+      .WillRepeatedly(DoAll(SetArgPointee<0>(2), Return(true)));
+  EXPECT_TRUE(provider_->Init());
+  loop_.RunOnce(false);
+
+  UmTestUtils::ExpectVariableHasValue(
+      RollbackToTargetVersion::kRollbackWithFullPowerwash,
+      provider_->var_rollback_to_target_version());
+}
+
 TEST_F(UmRealDevicePolicyProviderTest, ScatterFactorConverted) {
   SetUpExistentDevicePolicy();
   EXPECT_CALL(mock_device_policy_, GetScatterFactorInSeconds(_))
diff --git a/update_manager/rollback_prefs.h b/update_manager/rollback_prefs.h
new file mode 100644
index 0000000..0305a46
--- /dev/null
+++ b/update_manager/rollback_prefs.h
@@ -0,0 +1,35 @@
+//
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef UPDATE_ENGINE_UPDATE_MANAGER_ROLLBACK_PREFS_H_
+#define UPDATE_ENGINE_UPDATE_MANAGER_ROLLBACK_PREFS_H_
+
+namespace chromeos_update_manager {
+
+// Whether the device should roll back to the target version, and if yes, which
+// type of rollback should it do. Matches chrome_device_policy.proto's
+// AutoUpdateSettingsProto::RollbackToTargetVersion.
+enum class RollbackToTargetVersion {
+  kUnspecified = 0,
+  kDisabled = 1,
+  kRollbackWithFullPowerwash = 2,
+  // This value must be the last entry.
+  kMaxValue = 3
+};
+
+}  // namespace chromeos_update_manager
+
+#endif  // UPDATE_ENGINE_UPDATE_MANAGER_ROLLBACK_PREFS_H_