reset_screen_handler.cc revision cedac228d2dd51db4b79ea1e72c7f249408ee061
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/bind.h" 10#include "base/bind_helpers.h" 11#include "base/callback.h" 12#include "base/command_line.h" 13#include "base/file_util.h" 14#include "base/files/file_path.h" 15#include "base/memory/scoped_ptr.h" 16#include "base/metrics/histogram.h" 17#include "base/prefs/pref_service.h" 18#include "base/values.h" 19#include "chrome/browser/browser_process.h" 20#include "chrome/browser/chromeos/login/help_app_launcher.h" 21#include "chrome/browser/chromeos/reset/metrics.h" 22#include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h" 23#include "chrome/common/pref_names.h" 24#include "chromeos/chromeos_switches.h" 25#include "chromeos/dbus/dbus_thread_manager.h" 26#include "chromeos/dbus/power_manager_client.h" 27#include "chromeos/dbus/session_manager_client.h" 28#include "chromeos/dbus/update_engine_client.h" 29#include "content/public/browser/browser_thread.h" 30#include "grit/browser_resources.h" 31#include "grit/chromium_strings.h" 32#include "grit/generated_resources.h" 33#include "ui/base/l10n/l10n_util.h" 34 35namespace { 36 37const char kJsScreenPath[] = "login.ResetScreen"; 38 39// Reset screen id. 40const char kResetScreen[] = "reset"; 41 42const int kErrorUIStateRollback = 7; 43 44static const char kRollbackFlagFile[] = "/tmp/.enable_rollback_ui"; 45 46void CheckRollbackFlagFileExists(bool *file_exists) { 47 DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); 48 *file_exists = base::PathExists(base::FilePath(kRollbackFlagFile)); 49} 50 51} // namespace 52 53namespace chromeos { 54 55ResetScreenHandler::ResetScreenHandler() 56 : BaseScreenHandler(kJsScreenPath), 57 delegate_(NULL), 58 show_on_init_(false), 59 restart_required_(true), 60 reboot_was_requested_(false), 61 rollback_available_(false), 62 weak_ptr_factory_(this) { 63} 64 65ResetScreenHandler::~ResetScreenHandler() { 66 if (delegate_) 67 delegate_->OnActorDestroyed(this); 68 DBusThreadManager::Get()->GetUpdateEngineClient()->RemoveObserver(this); 69} 70 71void ResetScreenHandler::PrepareToShow() { 72} 73 74void ResetScreenHandler::ShowWithParams() { 75 int dialog_type; 76 if (reboot_was_requested_) { 77 dialog_type = rollback_available_ ? 78 reset::DIALOG_SHORTCUT_CONFIRMING_POWERWASH_AND_ROLLBACK : 79 reset::DIALOG_SHORTCUT_CONFIRMING_POWERWASH_ONLY; 80 } else { 81 dialog_type = rollback_available_ ? 82 reset::DIALOG_SHORTCUT_OFFERING_ROLLBACK_AVAILABLE : 83 reset::DIALOG_SHORTCUT_OFFERING_ROLLBACK_UNAVAILABLE; 84 } 85 UMA_HISTOGRAM_ENUMERATION("Reset.ChromeOS.PowerwashDialogShown", 86 dialog_type, 87 reset::DIALOG_VIEW_TYPE_SIZE); 88 89 base::DictionaryValue reset_screen_params; 90 reset_screen_params.SetBoolean("showRestartMsg", restart_required_); 91 reset_screen_params.SetBoolean( 92 "showRollbackOption", rollback_available_ && !reboot_was_requested_); 93 reset_screen_params.SetBoolean( 94 "simpleConfirm", reboot_was_requested_ && !rollback_available_); 95 reset_screen_params.SetBoolean( 96 "rollbackConfirm", reboot_was_requested_ && rollback_available_); 97 98 PrefService* prefs = g_browser_process->local_state(); 99 prefs->SetBoolean(prefs::kFactoryResetRequested, false); 100 prefs->SetBoolean(prefs::kRollbackRequested, false); 101 prefs->CommitPendingWrite(); 102 ShowScreen(kResetScreen, &reset_screen_params); 103} 104 105void ResetScreenHandler::Show() { 106 if (!page_is_ready()) { 107 show_on_init_ = true; 108 return; 109 } 110 111 ChooseAndApplyShowScenario(); 112} 113 114void ResetScreenHandler::ChooseAndApplyShowScenario() { 115 PrefService* prefs = g_browser_process->local_state(); 116 restart_required_ = !CommandLine::ForCurrentProcess()->HasSwitch( 117 switches::kFirstExecAfterBoot); 118 reboot_was_requested_ = false; 119 rollback_available_ = false; 120 if (!restart_required_) // First exec after boot. 121 reboot_was_requested_ = prefs->GetBoolean(prefs::kFactoryResetRequested); 122 123 // Check Rollback flag-file. 124 scoped_ptr<bool> file_exists(new bool(false)); 125 base::Closure checkfile_closure = base::Bind( 126 &CheckRollbackFlagFileExists, 127 base::Unretained(file_exists.get())); 128 base::Closure on_check_done = base::Bind( 129 &ResetScreenHandler::OnRollbackFlagFileCheckDone, 130 weak_ptr_factory_.GetWeakPtr(), 131 base::Passed(file_exists.Pass())); 132 if (!content::BrowserThread::PostBlockingPoolTaskAndReply( 133 FROM_HERE, 134 checkfile_closure, 135 on_check_done)) { 136 LOG(WARNING) << "Failed to check flag file for Rollback reset option"; 137 on_check_done.Run(); 138 } 139} 140 141void ResetScreenHandler::OnRollbackFlagFileCheckDone( 142 scoped_ptr<bool> file_exists) { 143 if (!(*file_exists) && !CommandLine::ForCurrentProcess()->HasSwitch( 144 switches::kEnableRollbackOption)) { 145 rollback_available_ = false; 146 ShowWithParams(); 147 } else if (!restart_required_ && reboot_was_requested_) { 148 // First exec after boot. 149 PrefService* prefs = g_browser_process->local_state(); 150 rollback_available_ = prefs->GetBoolean(prefs::kRollbackRequested); 151 ShowWithParams(); 152 } else { 153 chromeos::DBusThreadManager::Get()->GetUpdateEngineClient()-> 154 CanRollbackCheck(base::Bind(&ResetScreenHandler::OnRollbackCheck, 155 weak_ptr_factory_.GetWeakPtr())); 156 } 157} 158 159void ResetScreenHandler::Hide() { 160 DBusThreadManager::Get()->GetUpdateEngineClient()->RemoveObserver(this); 161} 162 163void ResetScreenHandler::SetDelegate(Delegate* delegate) { 164 delegate_ = delegate; 165 if (page_is_ready()) 166 Initialize(); 167} 168 169void ResetScreenHandler::DeclareLocalizedValues( 170 LocalizedValuesBuilder* builder) { 171 builder->Add("resetScreenTitle", IDS_RESET_SCREEN_TITLE); 172 builder->Add("resetScreenAccessibleTitle", IDS_RESET_SCREEN_TITLE); 173 builder->Add("resetScreenIconTitle",IDS_RESET_SCREEN_ICON_TITLE); 174 builder->Add("cancelButton", IDS_CANCEL); 175 176 builder->Add("resetWarningDataDetails", 177 IDS_RESET_SCREEN_WARNING_DETAILS_DATA); 178 builder->Add("resetRestartMessage", IDS_RESET_SCREEN_RESTART_MSG); 179 builder->AddF("resetRollbackOption", 180 IDS_RESET_SCREEN_ROLLBACK_OPTION, 181 IDS_SHORT_PRODUCT_NAME); 182 builder->AddF("resetRevertPromise", 183 IDS_RESET_SCREEN_PREPARING_REVERT_PROMISE, 184 IDS_SHORT_PRODUCT_NAME); 185 builder->AddF("resetRevertSpinnerMessage", 186 IDS_RESET_SCREEN_PREPARING_REVERT_SPINNER_MESSAGE, 187 IDS_SHORT_PRODUCT_NAME); 188 189 // Different variants of the same UI elements for all dialog cases. 190 builder->Add("resetButtonReset", IDS_RESET_SCREEN_RESET); 191 builder->Add("resetButtonRelaunch", IDS_RELAUNCH_BUTTON); 192 builder->Add("resetButtonPowerwash", IDS_RESET_SCREEN_POWERWASH); 193 194 builder->AddF( 195 "resetAndRollbackWarningTextConfirmational", 196 IDS_RESET_SCREEN_CONFIRMATION_WARNING_POWERWASH_AND_ROLLBACK_MSG, 197 IDS_SHORT_PRODUCT_NAME); 198 builder->AddF("resetWarningTextConfirmational", 199 IDS_RESET_SCREEN_CONFIRMATION_WARNING_POWERWASH_MSG, 200 IDS_SHORT_PRODUCT_NAME); 201 builder->AddF("resetWarningTextInitial", 202 IDS_RESET_SCREEN_WARNING_MSG, 203 IDS_SHORT_PRODUCT_NAME); 204 205 builder->AddF( 206 "resetAndRollbackWarningDetailsConfirmational", 207 IDS_RESET_SCREEN_CONFIRMATION_WARNING_ROLLBACK_DETAILS, 208 IDS_SHORT_PRODUCT_NAME); 209 builder->AddF("resetWarningDetailsConfirmational", 210 IDS_RESET_SCREEN_CONFIRMATION_WARNING_DETAILS, 211 IDS_SHORT_PRODUCT_NAME); 212 builder->AddF("resetWarningDetailsInitial", 213 IDS_RESET_SCREEN_WARNING_DETAILS, 214 IDS_SHORT_PRODUCT_NAME); 215} 216 217// Invoked from call to CanRollbackCheck upon completion of the DBus call. 218void ResetScreenHandler::OnRollbackCheck(bool can_rollback) { 219 VLOG(1) << "Callback from CanRollbackCheck, result " << can_rollback; 220 rollback_available_ = can_rollback; 221 ShowWithParams(); 222} 223 224void ResetScreenHandler::Initialize() { 225 if (!page_is_ready() || !delegate_) 226 return; 227 228 if (show_on_init_) { 229 Show(); 230 show_on_init_ = false; 231 } 232} 233 234void ResetScreenHandler::RegisterMessages() { 235 AddCallback("cancelOnReset", &ResetScreenHandler::HandleOnCancel); 236 AddCallback("restartOnReset", &ResetScreenHandler::HandleOnRestart); 237 AddCallback("powerwashOnReset", &ResetScreenHandler::HandleOnPowerwash); 238 AddCallback("resetOnLearnMore", &ResetScreenHandler::HandleOnLearnMore); 239} 240 241void ResetScreenHandler::HandleOnCancel() { 242 if (delegate_) 243 delegate_->OnExit(); 244 DBusThreadManager::Get()->GetUpdateEngineClient()->RemoveObserver(this); 245} 246 247void ResetScreenHandler::HandleOnRestart(bool should_rollback) { 248 PrefService* prefs = g_browser_process->local_state(); 249 prefs->SetBoolean(prefs::kFactoryResetRequested, true); 250 prefs->SetBoolean(prefs::kRollbackRequested, should_rollback); 251 prefs->CommitPendingWrite(); 252 253 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->RequestRestart(); 254} 255 256void ResetScreenHandler::HandleOnPowerwash(bool rollback_checked) { 257 if (rollback_available_ && (rollback_checked || reboot_was_requested_)) { 258 CallJS("updateViewOnRollbackCall"); 259 DBusThreadManager::Get()->GetUpdateEngineClient()->AddObserver(this); 260 chromeos::DBusThreadManager::Get()->GetUpdateEngineClient()->Rollback(); 261 } else { 262 if (rollback_checked && !rollback_available_) { 263 NOTREACHED() << 264 "Rollback was checked but not available. Starting powerwash."; 265 } 266 chromeos::DBusThreadManager::Get()->GetSessionManagerClient()-> 267 StartDeviceWipe(); 268 } 269} 270 271void ResetScreenHandler::HandleOnLearnMore() { 272 if (!help_app_.get()) 273 help_app_ = new HelpAppLauncher(GetNativeWindow()); 274 help_app_->ShowHelpTopic(HelpAppLauncher::HELP_POWERWASH); 275} 276 277void ResetScreenHandler::UpdateStatusChanged( 278 const UpdateEngineClient::Status& status) { 279 VLOG(1) << "Update status change to " << status.status; 280 if (status.status == UpdateEngineClient::UPDATE_STATUS_ERROR) { 281 // Show error screen. 282 base::DictionaryValue params; 283 params.SetInteger("uiState", kErrorUIStateRollback); 284 ShowScreen(OobeUI::kScreenErrorMessage, ¶ms); 285 } else if (status.status == 286 UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT) { 287 DBusThreadManager::Get()->GetPowerManagerClient()->RequestRestart(); 288 } 289} 290 291} // namespace chromeos 292