UpdateManager: Do not schedule update checks if booted from removable device.

This abides by the current logic, as found in
UpdateCheckScheduler::Run(). New unit test added to verify this
behavior.

BUG=chromium:358269
TEST=Unit tests.

Change-Id: I5720b2b3c85c7de7f64eec4f7da000d3e13c778d
Reviewed-on: https://chromium-review.googlesource.com/207230
Reviewed-by: Alex Deymo <deymo@chromium.org>
Tested-by: Gilad Arnold <garnold@chromium.org>
Commit-Queue: Gilad Arnold <garnold@chromium.org>
diff --git a/update_manager/chromeos_policy.cc b/update_manager/chromeos_policy.cc
index fd2f882..adbef4f 100644
--- a/update_manager/chromeos_policy.cc
+++ b/update_manager/chromeos_policy.cc
@@ -164,6 +164,14 @@
     return EvalStatus::kSucceeded;
   }
 
+  // Do not perform any automatic update checks if booted from removable device.
+  const bool* is_boot_device_removable_p = ec->GetValue(
+      state->system_provider()->var_is_boot_device_removable());
+  if (is_boot_device_removable_p && *is_boot_device_removable_p) {
+    result->updates_enabled = false;
+    return EvalStatus::kSucceeded;
+  }
+
   DevicePolicyProvider* const dp_provider = state->device_policy_provider();
 
   const bool* device_policy_is_loaded_p = ec->GetValue(
diff --git a/update_manager/chromeos_policy_unittest.cc b/update_manager/chromeos_policy_unittest.cc
index 0537a65..17eda83 100644
--- a/update_manager/chromeos_policy_unittest.cc
+++ b/update_manager/chromeos_policy_unittest.cc
@@ -63,6 +63,8 @@
         new bool(true));
     fake_state_.system_provider()->var_is_oobe_complete()->reset(
         new bool(true));
+    fake_state_.system_provider()->var_is_boot_device_removable()->reset(
+        new bool(false));
 
     // Connection is wifi, untethered.
     fake_state_.shill_provider()->var_conn_type()->
@@ -291,6 +293,20 @@
   EXPECT_FALSE(result.updates_enabled);
 }
 
+TEST_F(UmChromeOSPolicyTest,
+       UpdateCheckAllowedUpdatesDisabledForRemovableBootDevice) {
+  // UpdateCheckAllowed should return false (kSucceeded) if the image booted
+  // from a removable device.
+
+  fake_state_.system_provider()->var_is_boot_device_removable()->reset(
+      new bool(true));
+
+  UpdateCheckParams result;
+  ExpectPolicyStatus(EvalStatus::kSucceeded,
+                     &Policy::UpdateCheckAllowed, &result);
+  EXPECT_FALSE(result.updates_enabled);
+}
+
 TEST_F(UmChromeOSPolicyTest, UpdateCheckAllowedUpdatesDisabledByPolicy) {
   // UpdateCheckAllowed should return kAskMeAgainLater because a device policy
   // is loaded and prohibits updates.
diff --git a/update_manager/fake_system_provider.h b/update_manager/fake_system_provider.h
index a05f630..47cd5ac 100644
--- a/update_manager/fake_system_provider.h
+++ b/update_manager/fake_system_provider.h
@@ -27,13 +27,20 @@
     return &var_is_oobe_complete_;
   }
 
+  virtual FakeVariable<bool>* var_is_boot_device_removable() override {
+    return &var_is_boot_device_removable_;
+  }
+
  private:
-  FakeVariable<bool> var_is_normal_boot_mode_{
-      "is_normal_boot_mode", kVariableModeConst};
-  FakeVariable<bool> var_is_official_build_{
-      "is_official_build", kVariableModeConst};
-  FakeVariable<bool> var_is_oobe_complete_{
-      "is_oobe_complete", kVariableModePoll};
+  FakeVariable<bool> var_is_normal_boot_mode_{  // NOLINT(whitespace/braces)
+    "is_normal_boot_mode", kVariableModeConst};
+  FakeVariable<bool> var_is_official_build_{  // NOLINT(whitespace/braces)
+    "is_official_build", kVariableModeConst};
+  FakeVariable<bool> var_is_oobe_complete_{  // NOLINT(whitespace/braces)
+    "is_oobe_complete", kVariableModePoll};
+  FakeVariable<bool>
+      var_is_boot_device_removable_{  // NOLINT(whitespace/braces)
+        "is_boot_device_removable", kVariableModePoll};
 
   DISALLOW_COPY_AND_ASSIGN(FakeSystemProvider);
 };
diff --git a/update_manager/real_system_provider.cc b/update_manager/real_system_provider.cc
index c397027..8d5f4f4 100644
--- a/update_manager/real_system_provider.cc
+++ b/update_manager/real_system_provider.cc
@@ -43,6 +43,10 @@
           base::Bind(&chromeos_update_engine::HardwareInterface::IsOOBEComplete,
                      base::Unretained(hardware_), nullptr)));
 
+  var_is_boot_device_removable_.reset(
+      new ConstCopyVariable<bool>("is_boot_device_removable",
+                                  hardware_->IsBootDeviceRemovable()));
+
   return true;
 }
 
diff --git a/update_manager/real_system_provider.h b/update_manager/real_system_provider.h
index 590a077..d1e20be 100644
--- a/update_manager/real_system_provider.h
+++ b/update_manager/real_system_provider.h
@@ -36,10 +36,15 @@
     return var_is_oobe_complete_.get();
   }
 
+  virtual Variable<bool>* var_is_boot_device_removable() override {
+    return var_is_boot_device_removable_.get();
+  }
+
  private:
   scoped_ptr<Variable<bool>> var_is_normal_boot_mode_;
   scoped_ptr<Variable<bool>> var_is_official_build_;
   scoped_ptr<Variable<bool>> var_is_oobe_complete_;
+  scoped_ptr<Variable<bool>> var_is_boot_device_removable_;
 
   chromeos_update_engine::HardwareInterface* hardware_;
 
diff --git a/update_manager/system_provider.h b/update_manager/system_provider.h
index caaecd0..8688b9c 100644
--- a/update_manager/system_provider.h
+++ b/update_manager/system_provider.h
@@ -27,6 +27,9 @@
   // Returns a variable that tells whether OOBE was completed.
   virtual Variable<bool>* var_is_oobe_complete() = 0;
 
+  // Returns a variable that tells the boot device is removable (USB stick etc).
+  virtual Variable<bool>* var_is_boot_device_removable() = 0;
+
  protected:
   SystemProvider() {}