Allow TPM firmware update option to be disabled.

The Chrome OS device reset aka powerwash screen can now be configured
via a pref to not force-enable the firmware update option and not let
the user change it.

BUG=chromium:742985, chromium:762030
TEST=Manual: inject pref and observe screen behavior.

Change-Id: I654257ebde46f7d6b2fee0d1bcf0bd5556ea8aff
Reviewed-on: https://chromium-review.googlesource.com/670731
Commit-Queue: Xiyuan Xia <[email protected]>
Reviewed-by: Xiyuan Xia <[email protected]>
Reviewed-by: Dominic Battré <[email protected]>
Cr-Commit-Position: refs/heads/master@{#503743}
diff --git a/chrome/browser/chromeos/login/screens/reset_screen.cc b/chrome/browser/chromeos/login/screens/reset_screen.cc
index d9cd13b2..f440cacd 100644
--- a/chrome/browser/chromeos/login/screens/reset_screen.cc
+++ b/chrome/browser/chromeos/login/screens/reset_screen.cc
@@ -47,6 +47,8 @@
     "tpm-firmware-update-available";
 constexpr const char kContextKeyIsTPMFirmwareUpdateChecked[] =
     "tpm-firmware-update-checked";
+constexpr const char kContextKeyIsTPMFirmwareUpdateEditable[] =
+    "tpm-firmware-update-editable";
 constexpr const char kContextKeyIsConfirmational[] = "is-confirmational-view";
 constexpr const char kContextKeyIsOfficialBuild[] = "is-official-build";
 constexpr const char kContextKeyScreenState[] = "screen-state";
@@ -69,6 +71,7 @@
   context_.SetBoolean(kContextKeyIsRollbackChecked, false);
   context_.SetBoolean(kContextKeyIsTPMFirmwareUpdateAvailable, false);
   context_.SetBoolean(kContextKeyIsTPMFirmwareUpdateChecked, false);
+  context_.SetBoolean(kContextKeyIsTPMFirmwareUpdateEditable, true);
   context_.SetBoolean(kContextKeyIsConfirmational, false);
   context_.SetBoolean(kContextKeyIsOfficialBuild, false);
 #if defined(OFFICIAL_BUILD)
@@ -82,6 +85,13 @@
   DBusThreadManager::Get()->GetUpdateEngineClient()->RemoveObserver(this);
 }
 
+// static
+void ResetScreen::RegisterPrefs(PrefRegistrySimple* registry) {
+  registry->RegisterBooleanPref(prefs::kFactoryResetRequested, false);
+  registry->RegisterBooleanPref(prefs::kFactoryResetTPMFirmwareUpdateRequested,
+                                false);
+}
+
 void ResetScreen::Show() {
   if (view_)
     view_->Show();
@@ -128,7 +138,17 @@
   }
 
   PrefService* prefs = g_browser_process->local_state();
-  prefs->SetBoolean(prefs::kFactoryResetRequested, false);
+  bool tpm_firmware_update_requested =
+      prefs->GetBoolean(prefs::kFactoryResetTPMFirmwareUpdateRequested);
+  context_editor.SetBoolean(kContextKeyIsTPMFirmwareUpdateChecked,
+                            tpm_firmware_update_requested);
+  context_editor.SetBoolean(kContextKeyIsTPMFirmwareUpdateEditable,
+                            !tpm_firmware_update_requested);
+
+  // Clear prefs so the reset screen isn't triggered again the next time the
+  // device is about to show the login screen.
+  prefs->ClearPref(prefs::kFactoryResetRequested);
+  prefs->ClearPref(prefs::kFactoryResetTPMFirmwareUpdateRequested);
   prefs->CommitPendingWrite();
 }
 
@@ -206,6 +226,7 @@
 void ResetScreen::OnRestart() {
   PrefService* prefs = g_browser_process->local_state();
   prefs->SetBoolean(prefs::kFactoryResetRequested, true);
+  prefs->ClearPref(prefs::kFactoryResetTPMFirmwareUpdateRequested);
   prefs->CommitPendingWrite();
 
   chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->RequestRestart(
diff --git a/chrome/browser/chromeos/login/screens/reset_screen.h b/chrome/browser/chromeos/login/screens/reset_screen.h
index aef88e5..687d3a7 100644
--- a/chrome/browser/chromeos/login/screens/reset_screen.h
+++ b/chrome/browser/chromeos/login/screens/reset_screen.h
@@ -15,6 +15,7 @@
 #include "chrome/browser/chromeos/login/screens/base_screen.h"
 #include "chromeos/dbus/update_engine_client.h"
 
+class PrefRegistrySimple;
 
 namespace chromeos {
 
@@ -31,6 +32,9 @@
   // Called when view is destroyed so there's no dead reference to it.
   void OnViewDestroyed(ResetView* view);
 
+  // Registers Local State preferences.
+  static void RegisterPrefs(PrefRegistrySimple* registry);
+
  private:
   // BaseScreen implementation:
   void Show() override;
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index 1d56ca9..0f30e03 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -208,6 +208,7 @@
 #include "chrome/browser/chromeos/login/quick_unlock/pin_storage.h"
 #include "chrome/browser/chromeos/login/quick_unlock/quick_unlock_utils.h"
 #include "chrome/browser/chromeos/login/saml/saml_offline_signin_limiter.h"
+#include "chrome/browser/chromeos/login/screens/reset_screen.h"
 #include "chrome/browser/chromeos/login/session/user_session_manager.h"
 #include "chrome/browser/chromeos/login/startup_utils.h"
 #include "chrome/browser/chromeos/login/users/avatar/user_image_manager.h"
@@ -238,7 +239,6 @@
 #include "chrome/browser/metrics/chromeos_metrics_provider.h"
 #include "chrome/browser/ui/webui/chromeos/login/enable_debugging_screen_handler.h"
 #include "chrome/browser/ui/webui/chromeos/login/hid_detection_screen_handler.h"
-#include "chrome/browser/ui/webui/chromeos/login/reset_screen_handler.h"
 #include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h"
 #include "chromeos/audio/audio_devices_pref_handler_impl.h"
 #include "chromeos/chromeos_switches.h"
@@ -411,7 +411,7 @@
   chromeos::NetworkThrottlingObserver::RegisterPrefs(registry);
   chromeos::Preferences::RegisterPrefs(registry);
   chromeos::RegisterDisplayLocalStatePrefs(registry);
-  chromeos::ResetScreenHandler::RegisterPrefs(registry);
+  chromeos::ResetScreen::RegisterPrefs(registry);
   chromeos::ResourceReporter::RegisterPrefs(registry);
   chromeos::ServicesCustomizationDocument::RegisterPrefs(registry);
   chromeos::SigninScreenHandler::RegisterPrefs(registry);
diff --git a/chrome/browser/resources/chromeos/login/oobe_reset.html b/chrome/browser/resources/chromeos/login/oobe_reset.html
index 23b4fd1..2ca1e50 100644
--- a/chrome/browser/resources/chromeos/login/oobe_reset.html
+++ b/chrome/browser/resources/chromeos/login/oobe_reset.html
@@ -70,6 +70,7 @@
             hidden="[[!tpmFirmwareUpdateAvailable_]]">
           <paper-checkbox id="tpmFirmwareUpdateCheckbox"
               checked="{{tpmFirmwareUpdateChecked_}}"
+              disabled="{{!tpmFirmwareUpdateEditable_}}"
               on-change="onTPMFirmwareUpdateChanged_">
             <div id="tpmFirmwareUpdateContainer">
               <span i18n-content="resetTPMFirmwareUpdate"></span>
diff --git a/chrome/browser/resources/chromeos/login/oobe_reset.js b/chrome/browser/resources/chromeos/login/oobe_reset.js
index 501aa72..c63e695 100644
--- a/chrome/browser/resources/chromeos/login/oobe_reset.js
+++ b/chrome/browser/resources/chromeos/login/oobe_reset.js
@@ -32,6 +32,11 @@
     tpmFirmwareUpdateChecked_: Boolean,
 
     /**
+     * If the checkbox to request a TPM firmware update is editable.
+     */
+    tpmFirmwareUpdateEditable_: Boolean,
+
+    /**
      * Reference to OOBE screen object.
      * @type {!OobeTypes.Screen}
      */
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_reset.js b/chrome/browser/resources/chromeos/login/oobe_screen_reset.js
index f857afe..a091a6bc 100644
--- a/chrome/browser/resources/chromeos/login/oobe_screen_reset.js
+++ b/chrome/browser/resources/chromeos/login/oobe_screen_reset.js
@@ -18,6 +18,7 @@
   var CONTEXT_KEY_TPM_FIRMWARE_UPDATE_AVAILABLE =
       'tpm-firmware-update-available';
   var CONTEXT_KEY_TPM_FIRMWARE_UPDATE_CHECKED = 'tpm-firmware-update-checked';
+  var CONTEXT_KEY_TPM_FIRMWARE_UPDATE_EDITABLE = 'tpm-firmware-update-editable';
   var CONTEXT_KEY_IS_OFFICIAL_BUILD = 'is-official-build';
   var CONTEXT_KEY_IS_CONFIRMATIONAL_VIEW = 'is-confirmational-view';
   var CONTEXT_KEY_SCREEN_STATE = 'screen-state';
@@ -94,6 +95,10 @@
             self.setTPMFirmwareUpdateView_();
           });
       this.context.addObserver(
+          CONTEXT_KEY_TPM_FIRMWARE_UPDATE_EDITABLE, function() {
+            self.setTPMFirmwareUpdateView_();
+          });
+      this.context.addObserver(
           CONTEXT_KEY_TPM_FIRMWARE_UPDATE_AVAILABLE, function() {
             self.setTPMFirmwareUpdateView_();
           });
@@ -297,6 +302,8 @@
           this.context.get(CONTEXT_KEY_TPM_FIRMWARE_UPDATE_AVAILABLE);
       $('oobe-reset-md').tpmFirmwareUpdateChecked_ =
           this.context.get(CONTEXT_KEY_TPM_FIRMWARE_UPDATE_CHECKED);
+      $('oobe-reset-md').tpmFirmwareUpdateEditable_ =
+          this.context.get(CONTEXT_KEY_TPM_FIRMWARE_UPDATE_EDITABLE);
     },
 
     onTPMFirmwareUpdateChanged_: function(value) {
diff --git a/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.cc
index ae698ed9..8608f08 100644
--- a/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.cc
@@ -11,12 +11,10 @@
 #include "chrome/browser/chromeos/login/help_app_launcher.h"
 #include "chrome/browser/chromeos/login/oobe_screen.h"
 #include "chrome/browser/chromeos/login/screens/reset_screen.h"
-#include "chrome/common/pref_names.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
 #include "chromeos/dbus/session_manager_client.h"
 #include "components/login/localized_values_builder.h"
-#include "components/prefs/pref_registry_simple.h"
 #include "components/strings/grit/components_strings.h"
 
 namespace {
@@ -95,11 +93,6 @@
   builder->Add("confirmResetButton", IDS_RESET_SCREEN_POPUP_CONFIRM_BUTTON);
 }
 
-// static
-void ResetScreenHandler::RegisterPrefs(PrefRegistrySimple* registry) {
-  registry->RegisterBooleanPref(prefs::kFactoryResetRequested, false);
-}
-
 void ResetScreenHandler::Initialize() {
   if (!page_is_ready())
     return;
diff --git a/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.h
index ff95443..f6dc3f2 100644
--- a/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.h
@@ -11,8 +11,6 @@
 #include "chrome/browser/ui/webui/chromeos/login/base_screen_handler.h"
 #include "content/public/browser/web_ui.h"
 
-class PrefRegistrySimple;
-
 namespace chromeos {
 
 // WebUI implementation of ResetScreenActor.
@@ -33,9 +31,6 @@
       ::login::LocalizedValuesBuilder* builder) override;
   void Initialize() override;
 
-  // Registers Local State preferences.
-  static void RegisterPrefs(PrefRegistrySimple* registry);
-
  private:
   ResetScreen* screen_ = nullptr;