1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/ui/webui/chromeos/login/reset_screen_handler.h" 6 7#include <string> 8 9#include "base/command_line.h" 10#include "base/metrics/histogram.h" 11#include "base/prefs/pref_registry_simple.h" 12#include "base/prefs/pref_service.h" 13#include "base/values.h" 14#include "chrome/browser/browser_process.h" 15#include "chrome/browser/chromeos/login/help_app_launcher.h" 16#include "chrome/browser/chromeos/reset/metrics.h" 17#include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h" 18#include "chrome/common/pref_names.h" 19#include "chrome/grit/chromium_strings.h" 20#include "chrome/grit/generated_resources.h" 21#include "chromeos/chromeos_switches.h" 22#include "chromeos/dbus/dbus_thread_manager.h" 23#include "chromeos/dbus/power_manager_client.h" 24#include "chromeos/dbus/session_manager_client.h" 25#include "chromeos/dbus/update_engine_client.h" 26#include "content/public/browser/browser_thread.h" 27 28namespace { 29 30const char kJsScreenPath[] = "login.ResetScreen"; 31 32// Reset screen id. 33const char kResetScreen[] = "reset"; 34 35const int kErrorUIStateRollback = 7; 36 37} // namespace 38 39namespace chromeos { 40 41ResetScreenHandler::ResetScreenHandler() 42 : BaseScreenHandler(kJsScreenPath), 43 delegate_(NULL), 44 show_on_init_(false), 45 restart_required_(true), 46 reboot_was_requested_(false), 47 rollback_available_(false), 48 rollback_checked_(false), 49 preparing_for_rollback_(false), 50 weak_ptr_factory_(this) { 51} 52 53ResetScreenHandler::~ResetScreenHandler() { 54 if (delegate_) 55 delegate_->OnActorDestroyed(this); 56 DBusThreadManager::Get()->GetUpdateEngineClient()->RemoveObserver(this); 57} 58 59void ResetScreenHandler::PrepareToShow() { 60} 61 62void ResetScreenHandler::ShowWithParams() { 63 int dialog_type; 64 if (restart_required_) { 65 dialog_type = reset::DIALOG_SHORTCUT_RESTART_REQUIRED; 66 } else { 67 dialog_type = reset::DIALOG_SHORTCUT_OFFERING_ROLLBACK_UNAVAILABLE; 68 } 69 UMA_HISTOGRAM_ENUMERATION("Reset.ChromeOS.PowerwashDialogShown", 70 dialog_type, 71 reset::DIALOG_VIEW_TYPE_SIZE); 72 73 PrefService* prefs = g_browser_process->local_state(); 74 prefs->SetBoolean(prefs::kFactoryResetRequested, false); 75 prefs->CommitPendingWrite(); 76 base::DictionaryValue reset_screen_params; 77 reset_screen_params.SetBoolean("restartRequired", restart_required_); 78 reset_screen_params.SetBoolean("rollbackAvailable", rollback_available_); 79 ShowScreen(kResetScreen, &reset_screen_params); 80} 81 82void ResetScreenHandler::Show() { 83 if (!page_is_ready()) { 84 show_on_init_ = true; 85 return; 86 } 87 88 ChooseAndApplyShowScenario(); 89} 90 91void ResetScreenHandler::ChooseAndApplyShowScenario() { 92 PrefService* prefs = g_browser_process->local_state(); 93 restart_required_ = !CommandLine::ForCurrentProcess()->HasSwitch( 94 switches::kFirstExecAfterBoot); 95 96 reboot_was_requested_ = false; 97 rollback_available_ = false; 98 preparing_for_rollback_ = false; 99 if (!restart_required_) // First exec after boot. 100 reboot_was_requested_ = prefs->GetBoolean(prefs::kFactoryResetRequested); 101 102 if (!CommandLine::ForCurrentProcess()->HasSwitch( 103 switches::kEnableRollbackOption)) { 104 rollback_available_ = false; 105 ShowWithParams(); 106 } else if (!restart_required_ && reboot_was_requested_) { 107 // First exec after boot. 108 chromeos::DBusThreadManager::Get()->GetUpdateEngineClient()-> 109 CanRollbackCheck(base::Bind(&ResetScreenHandler::OnRollbackCheck, 110 weak_ptr_factory_.GetWeakPtr())); 111 } else { 112 // Will require restart. 113 ShowWithParams(); 114 } 115} 116 117void ResetScreenHandler::Hide() { 118 DBusThreadManager::Get()->GetUpdateEngineClient()->RemoveObserver(this); 119} 120 121void ResetScreenHandler::SetDelegate(Delegate* delegate) { 122 delegate_ = delegate; 123 if (page_is_ready()) 124 Initialize(); 125} 126 127void ResetScreenHandler::DeclareLocalizedValues( 128 LocalizedValuesBuilder* builder) { 129 builder->Add("resetScreenTitle", IDS_RESET_SCREEN_TITLE); 130 builder->Add("resetScreenAccessibleTitle", IDS_RESET_SCREEN_TITLE); 131 builder->Add("resetScreenIconTitle", IDS_RESET_SCREEN_ICON_TITLE); 132 builder->Add("cancelButton", IDS_CANCEL); 133 builder->Add("resetButtonReset", IDS_RESET_SCREEN_RESET); 134 builder->Add("resetButtonRestart", IDS_RELAUNCH_BUTTON); 135 builder->Add("resetButtonPowerwash", IDS_RESET_SCREEN_POWERWASH); 136 builder->Add("resetButtonPowerwashAndRollback", 137 IDS_RESET_SCREEN_POWERWASH_AND_REVERT); 138 139 builder->Add("resetWarningDataDetails", 140 IDS_RESET_SCREEN_WARNING_DETAILS_DATA); 141 builder->Add("resetRestartMessage", IDS_RESET_SCREEN_RESTART_MSG); 142 builder->AddF("resetRevertPromise", 143 IDS_RESET_SCREEN_PREPARING_REVERT_PROMISE, 144 IDS_SHORT_PRODUCT_NAME); 145 builder->AddF("resetRevertSpinnerMessage", 146 IDS_RESET_SCREEN_PREPARING_REVERT_SPINNER_MESSAGE, 147 IDS_SHORT_PRODUCT_NAME); 148 149 // Variants for screen title. 150 builder->AddF("resetWarningTitle", 151 IDS_RESET_SCREEN_WARNING_MSG, 152 IDS_SHORT_PRODUCT_NAME); 153 builder->AddF("resetPowerwashWarningTitle", 154 IDS_RESET_SCREEN_WARNING_POWERWASH_MSG, 155 IDS_SHORT_PRODUCT_NAME); 156 builder->AddF("resetPowerwasAndRollbackhWarningTitle", 157 IDS_RESET_SCREEN_WARNING_POWERWASH_AND_ROLLBACK_MSG, 158 IDS_SHORT_PRODUCT_NAME); 159 160 // Variants for screen message. 161 builder->AddF("resetPowerwashWarningDetails", 162 IDS_RESET_SCREEN_WARNING_DETAILS, 163 IDS_SHORT_PRODUCT_NAME); 164 builder->AddF("resetPowerwashRollbackWarningDetails", 165 IDS_RESET_SCREEN_WARNING_POWERWASH_AND_ROLLBACK_MSG, 166 IDS_SHORT_PRODUCT_NAME); 167 builder->AddF("resetPowerwashConfirmationDetails", 168 IDS_RESET_SCREEN_CONFIRMATION_WARNING_DETAILS, 169 IDS_SHORT_PRODUCT_NAME); 170 builder->AddF("resetPowerwashRollbackConfirmationDetails", 171 IDS_RESET_SCREEN_CONFIRMATION_WARNING_ROLLBACK_DETAILS, 172 IDS_SHORT_PRODUCT_NAME); 173} 174 175// Invoked from call to CanRollbackCheck upon completion of the DBus call. 176void ResetScreenHandler::OnRollbackCheck(bool can_rollback) { 177 VLOG(1) << "Callback from CanRollbackCheck, result " << can_rollback; 178 rollback_available_ = can_rollback; 179 ShowWithParams(); 180} 181 182// static 183void ResetScreenHandler::RegisterPrefs(PrefRegistrySimple* registry) { 184 registry->RegisterBooleanPref(prefs::kFactoryResetRequested, false); 185} 186 187void ResetScreenHandler::Initialize() { 188 if (!page_is_ready() || !delegate_) 189 return; 190 191 if (show_on_init_) { 192 Show(); 193 show_on_init_ = false; 194 } 195} 196 197void ResetScreenHandler::RegisterMessages() { 198 AddCallback("cancelOnReset", &ResetScreenHandler::HandleOnCancel); 199 AddCallback("restartOnReset", &ResetScreenHandler::HandleOnRestart); 200 AddCallback("powerwashOnReset", &ResetScreenHandler::HandleOnPowerwash); 201 AddCallback("resetOnLearnMore", &ResetScreenHandler::HandleOnLearnMore); 202 AddCallback( 203 "showRollbackOnResetScreen", &ResetScreenHandler::HandleOnShowRollback); 204 AddCallback( 205 "hideRollbackOnResetScreen", &ResetScreenHandler::HandleOnHideRollback); 206 AddCallback( 207 "showConfirmationOnReset", &ResetScreenHandler::HandleOnShowConfirm); 208} 209 210void ResetScreenHandler::HandleOnCancel() { 211 if (preparing_for_rollback_) 212 return; 213 if (delegate_) 214 delegate_->OnExit(); 215 DBusThreadManager::Get()->GetUpdateEngineClient()->RemoveObserver(this); 216} 217 218void ResetScreenHandler::HandleOnRestart() { 219 PrefService* prefs = g_browser_process->local_state(); 220 prefs->SetBoolean(prefs::kFactoryResetRequested, true); 221 prefs->CommitPendingWrite(); 222 223 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->RequestRestart(); 224} 225 226void ResetScreenHandler::HandleOnPowerwash(bool rollback_checked) { 227 if (rollback_available_ && rollback_checked) { 228 preparing_for_rollback_ = true; 229 CallJS("updateViewOnRollbackCall"); 230 DBusThreadManager::Get()->GetUpdateEngineClient()->AddObserver(this); 231 VLOG(1) << "Starting Rollback"; 232 chromeos::DBusThreadManager::Get()->GetUpdateEngineClient()->Rollback(); 233 } else { 234 if (rollback_checked && !rollback_available_) { 235 NOTREACHED() << 236 "Rollback was checked but not available. Starting powerwash."; 237 } 238 VLOG(1) << "Starting Powerwash"; 239 chromeos::DBusThreadManager::Get()->GetSessionManagerClient()-> 240 StartDeviceWipe(); 241 } 242} 243 244void ResetScreenHandler::HandleOnLearnMore() { 245 if (!help_app_.get()) 246 help_app_ = new HelpAppLauncher(GetNativeWindow()); 247 help_app_->ShowHelpTopic(HelpAppLauncher::HELP_POWERWASH); 248} 249 250void ResetScreenHandler::HandleOnShowRollback() { 251 VLOG(1) << "Requested rollback availability" << rollback_available_; 252 if (rollback_available_) { 253 UMA_HISTOGRAM_ENUMERATION( 254 "Reset.ChromeOS.PowerwashDialogShown", 255 reset::DIALOG_SHORTCUT_OFFERING_ROLLBACK_AVAILABLE, 256 reset::DIALOG_VIEW_TYPE_SIZE); 257 CallJS("showRollbackOption"); 258 rollback_checked_ = true; 259 } 260} 261 262void ResetScreenHandler::HandleOnHideRollback() { 263 if (rollback_available_ && rollback_checked_) { 264 CallJS("hideRollbackOption"); 265 rollback_checked_ = false; 266 } 267} 268 269void ResetScreenHandler::HandleOnShowConfirm() { 270 int dialog_type = rollback_checked_ ? 271 reset::DIALOG_SHORTCUT_CONFIRMING_POWERWASH_AND_ROLLBACK : 272 reset::DIALOG_SHORTCUT_CONFIRMING_POWERWASH_ONLY; 273 UMA_HISTOGRAM_ENUMERATION( 274 "Reset.ChromeOS.PowerwashDialogShown", 275 dialog_type, 276 reset::DIALOG_VIEW_TYPE_SIZE); 277} 278 279void ResetScreenHandler::UpdateStatusChanged( 280 const UpdateEngineClient::Status& status) { 281 VLOG(1) << "Update status change to " << status.status; 282 if (status.status == UpdateEngineClient::UPDATE_STATUS_ERROR || 283 status.status == 284 UpdateEngineClient::UPDATE_STATUS_REPORTING_ERROR_EVENT) { 285 preparing_for_rollback_ = false; 286 // Show error screen. 287 base::DictionaryValue params; 288 params.SetInteger("uiState", kErrorUIStateRollback); 289 ShowScreen(OobeUI::kScreenErrorMessage, ¶ms); 290 } else if (status.status == 291 UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT) { 292 DBusThreadManager::Get()->GetPowerManagerClient()->RequestRestart(); 293 } 294} 295 296} // namespace chromeos 297