Don't allow rollback when we are enterprise enrolled.

As stated (and verified) by the device_policy protobuf, we can determine
whether a device is enterprise enrolled by checking if GetOwner is empty.
We use this knowledge to not allow rollback when powerwash is also requested (
the default).

As part of this CL I've figured out how to unittest Rollback and added tests
for both enterprise and non-enterprise rollback.

BUG=chromium:254829
TEST=Tested on both an enrolled and non-enrolled device. Verified only the
latter actually did a powerwash while the other aborted correctly. Also ran
new unittests

Change-Id: Idfe6bfef88819fe1bab7da6b31854faf7642c9ce
Reviewed-on: https://gerrit.chromium.org/gerrit/61645
Reviewed-by: David Zeuthen <zeuthen@chromium.org>
Commit-Queue: Chris Sosa <sosa@chromium.org>
Tested-by: Chris Sosa <sosa@chromium.org>
diff --git a/update_attempter_unittest.cc b/update_attempter_unittest.cc
index 095de23..2de8ca2 100644
--- a/update_attempter_unittest.cc
+++ b/update_attempter_unittest.cc
@@ -10,6 +10,7 @@
 #include "update_engine/action_mock.h"
 #include "update_engine/action_processor_mock.h"
 #include "update_engine/filesystem_copier_action.h"
+#include "update_engine/install_plan.h"
 #include "update_engine/mock_dbus_interface.h"
 #include "update_engine/mock_http_fetcher.h"
 #include "update_engine/mock_payload_state.h"
@@ -74,8 +75,13 @@
 
   void UpdateTestStart();
   void UpdateTestVerify();
+  void RollbackTestStart(bool enterprise_rollback);
+  void RollbackTestVerify();
   static gboolean StaticUpdateTestStart(gpointer data);
   static gboolean StaticUpdateTestVerify(gpointer data);
+  static gboolean StaticRollbackTestStart(gpointer data);
+  static gboolean StaticEnterpriseRollbackTestStart(gpointer data);
+  static gboolean StaticRollbackTestVerify(gpointer data);
 
   void PingOmahaTestStart();
   static gboolean StaticPingOmahaTestStart(gpointer data);
@@ -302,6 +308,21 @@
   return FALSE;
 }
 
+gboolean UpdateAttempterTest::StaticRollbackTestStart(gpointer data) {
+  reinterpret_cast<UpdateAttempterTest*>(data)->RollbackTestStart(false);
+  return FALSE;
+}
+
+gboolean UpdateAttempterTest::StaticEnterpriseRollbackTestStart(gpointer data) {
+  reinterpret_cast<UpdateAttempterTest*>(data)->RollbackTestStart(true);
+  return FALSE;
+}
+
+gboolean UpdateAttempterTest::StaticRollbackTestVerify(gpointer data) {
+  reinterpret_cast<UpdateAttempterTest*>(data)->RollbackTestVerify();
+  return FALSE;
+}
+
 gboolean UpdateAttempterTest::StaticPingOmahaTestStart(gpointer data) {
   reinterpret_cast<UpdateAttempterTest*>(data)->PingOmahaTestStart();
   return FALSE;
@@ -350,7 +371,8 @@
 }
 
 namespace {
-const string kActionTypes[] = {
+// Actions that will be built as part of an update check.
+const string kUpdateActionTypes[] = {
   OmahaRequestAction::StaticType(),
   OmahaResponseHandlerAction::StaticType(),
   FilesystemCopierAction::StaticType(),
@@ -363,15 +385,22 @@
   PostinstallRunnerAction::StaticType(),
   OmahaRequestAction::StaticType()
 };
+
+// Actions that will be built as part of a user-initiated rollback.
+const string kRollbackActionTypes[] = {
+  InstallPlanAction::StaticType(),
+  PostinstallRunnerAction::StaticType(),
+};
+
 }  // namespace {}
 
 void UpdateAttempterTest::UpdateTestStart() {
   attempter_.set_http_response_code(200);
   InSequence s;
-  for (size_t i = 0; i < arraysize(kActionTypes); ++i) {
+  for (size_t i = 0; i < arraysize(kUpdateActionTypes); ++i) {
     EXPECT_CALL(*processor_,
                 EnqueueAction(Property(&AbstractAction::Type,
-                                       kActionTypes[i]))).Times(1);
+                                       kUpdateActionTypes[i]))).Times(1);
   }
   EXPECT_CALL(*processor_, StartProcessing()).Times(1);
 
@@ -382,9 +411,9 @@
 void UpdateAttempterTest::UpdateTestVerify() {
   EXPECT_EQ(0, attempter_.http_response_code());
   EXPECT_EQ(&attempter_, processor_->delegate());
-  EXPECT_EQ(arraysize(kActionTypes), attempter_.actions_.size());
-  for (size_t i = 0; i < arraysize(kActionTypes); ++i) {
-    EXPECT_EQ(kActionTypes[i], attempter_.actions_[i]->Type());
+  EXPECT_EQ(arraysize(kUpdateActionTypes), attempter_.actions_.size());
+  for (size_t i = 0; i < arraysize(kUpdateActionTypes); ++i) {
+    EXPECT_EQ(kUpdateActionTypes[i], attempter_.actions_[i]->Type());
   }
   EXPECT_EQ(attempter_.response_handler_action_.get(),
             attempter_.actions_[1].get());
@@ -396,6 +425,62 @@
   g_main_loop_quit(loop_);
 }
 
+void UpdateAttempterTest::RollbackTestStart(bool enterprise_rollback) {
+  // Create a device policy so that we can change settings.
+  policy::MockDevicePolicy* device_policy = new policy::MockDevicePolicy();
+  attempter_.policy_provider_.reset(new policy::PolicyProvider(device_policy));
+
+  EXPECT_CALL(*device_policy, LoadPolicy()).WillRepeatedly(Return(true));
+  EXPECT_CALL(mock_system_state_, device_policy()).WillRepeatedly(
+      Return(device_policy));
+
+  string install_path = "/dev/sda3";
+
+  // Non-enterprise enrolled device account with an owner in the device policy.
+  if (!enterprise_rollback) {
+    EXPECT_CALL(*device_policy, GetOwner(_)).WillOnce(
+        DoAll(SetArgumentPointee<0>(std::string("fake.mail@fake.com")),
+        Return(true)));
+
+    InSequence s;
+    for (size_t i = 0; i < arraysize(kRollbackActionTypes); ++i) {
+      EXPECT_CALL(*processor_,
+                  EnqueueAction(Property(&AbstractAction::Type,
+                                         kRollbackActionTypes[i]))).Times(1);
+    }
+    EXPECT_CALL(*processor_, StartProcessing()).Times(1);
+
+    EXPECT_TRUE(attempter_.Rollback(true, &install_path));
+    g_idle_add(&StaticRollbackTestVerify, this);
+  } else {
+    // We return an empty owner as this is an enterprise.
+    EXPECT_CALL(*device_policy, GetOwner(_)).WillOnce(
+            DoAll(SetArgumentPointee<0>(std::string("")),
+            Return(true)));
+
+    // We do not currently support rollbacks for enterprises.
+    EXPECT_FALSE(attempter_.Rollback(true, &install_path));
+    g_main_loop_quit(loop_);
+  }
+}
+
+void UpdateAttempterTest::RollbackTestVerify() {
+  // Verifies the actions that were enqueued.
+  EXPECT_EQ(&attempter_, processor_->delegate());
+  EXPECT_EQ(arraysize(kRollbackActionTypes), attempter_.actions_.size());
+  for (size_t i = 0; i < arraysize(kRollbackActionTypes); ++i) {
+    EXPECT_EQ(kRollbackActionTypes[i], attempter_.actions_[i]->Type());
+  }
+  EXPECT_EQ(UPDATE_STATUS_ATTEMPTING_ROLLBACK, attempter_.status());
+  InstallPlanAction* install_plan_action =
+        dynamic_cast<InstallPlanAction*>(attempter_.actions_[0].get());
+  InstallPlan* install_plan = install_plan_action->install_plan();
+  EXPECT_EQ(install_plan->install_path, string("/dev/sda3"));
+  EXPECT_EQ(install_plan->kernel_install_path, string("/dev/sda2"));
+  EXPECT_EQ(install_plan->powerwash_required, true);
+  g_main_loop_quit(loop_);
+}
+
 TEST_F(UpdateAttempterTest, UpdateTest) {
   loop_ = g_main_loop_new(g_main_context_default(), FALSE);
   g_idle_add(&StaticUpdateTestStart, this);
@@ -404,6 +489,22 @@
   loop_ = NULL;
 }
 
+TEST_F(UpdateAttempterTest, RollbackTest) {
+  loop_ = g_main_loop_new(g_main_context_default(), FALSE);
+  g_idle_add(&StaticRollbackTestStart, this);
+  g_main_loop_run(loop_);
+  g_main_loop_unref(loop_);
+  loop_ = NULL;
+}
+
+TEST_F(UpdateAttempterTest, EnterpriseRollbackTest) {
+  loop_ = g_main_loop_new(g_main_context_default(), FALSE);
+  g_idle_add(&StaticEnterpriseRollbackTestStart, this);
+  g_main_loop_run(loop_);
+  g_main_loop_unref(loop_);
+  loop_ = NULL;
+}
+
 void UpdateAttempterTest::PingOmahaTestStart() {
   EXPECT_CALL(*processor_,
               EnqueueAction(Property(&AbstractAction::Type,