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.
5 #include "chrome/browser/ui/webui/chromeos/login/reset_screen_handler.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_registry_simple.h"
18 #include "base/prefs/pref_service.h"
19 #include "base/values.h"
20 #include "chrome/browser/browser_process.h"
21 #include "chrome/browser/chromeos/login/help_app_launcher.h"
22 #include "chrome/browser/chromeos/reset/metrics.h"
23 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
24 #include "chrome/common/pref_names.h"
25 #include "chromeos/chromeos_switches.h"
26 #include "chromeos/dbus/dbus_thread_manager.h"
27 #include "chromeos/dbus/power_manager_client.h"
28 #include "chromeos/dbus/session_manager_client.h"
29 #include "chromeos/dbus/update_engine_client.h"
30 #include "content/public/browser/browser_thread.h"
31 #include "grit/browser_resources.h"
32 #include "grit/chromium_strings.h"
33 #include "grit/generated_resources.h"
34 #include "ui/base/l10n/l10n_util.h"
38 const char kJsScreenPath[] = "login.ResetScreen";
41 const char kResetScreen[] = "reset";
43 const int kErrorUIStateRollback = 7;
45 static const char kRollbackFlagFile[] = "/tmp/.enable_rollback_ui";
47 void CheckRollbackFlagFileExists(bool *file_exists) {
48 DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
49 *file_exists = base::PathExists(base::FilePath(kRollbackFlagFile));
56 ResetScreenHandler::ResetScreenHandler()
57 : BaseScreenHandler(kJsScreenPath),
60 restart_required_(true),
61 reboot_was_requested_(false),
62 rollback_available_(false),
63 preparing_for_rollback_(false),
64 weak_ptr_factory_(this) {
67 ResetScreenHandler::~ResetScreenHandler() {
69 delegate_->OnActorDestroyed(this);
70 DBusThreadManager::Get()->GetUpdateEngineClient()->RemoveObserver(this);
73 void ResetScreenHandler::PrepareToShow() {
76 void ResetScreenHandler::ShowWithParams() {
78 if (reboot_was_requested_) {
79 dialog_type = rollback_available_ ?
80 reset::DIALOG_SHORTCUT_CONFIRMING_POWERWASH_AND_ROLLBACK :
81 reset::DIALOG_SHORTCUT_CONFIRMING_POWERWASH_ONLY;
83 dialog_type = rollback_available_ ?
84 reset::DIALOG_SHORTCUT_OFFERING_ROLLBACK_AVAILABLE :
85 reset::DIALOG_SHORTCUT_OFFERING_ROLLBACK_UNAVAILABLE;
87 UMA_HISTOGRAM_ENUMERATION("Reset.ChromeOS.PowerwashDialogShown",
89 reset::DIALOG_VIEW_TYPE_SIZE);
91 base::DictionaryValue reset_screen_params;
92 reset_screen_params.SetBoolean("showRestartMsg", restart_required_);
93 reset_screen_params.SetBoolean(
94 "showRollbackOption", rollback_available_ && !reboot_was_requested_);
95 reset_screen_params.SetBoolean(
96 "simpleConfirm", reboot_was_requested_ && !rollback_available_);
97 reset_screen_params.SetBoolean(
98 "rollbackConfirm", reboot_was_requested_ && rollback_available_);
100 PrefService* prefs = g_browser_process->local_state();
101 prefs->SetBoolean(prefs::kFactoryResetRequested, false);
102 prefs->SetBoolean(prefs::kRollbackRequested, false);
103 prefs->CommitPendingWrite();
104 ShowScreen(kResetScreen, &reset_screen_params);
107 void ResetScreenHandler::Show() {
108 if (!page_is_ready()) {
109 show_on_init_ = true;
113 ChooseAndApplyShowScenario();
116 void ResetScreenHandler::ChooseAndApplyShowScenario() {
117 PrefService* prefs = g_browser_process->local_state();
118 restart_required_ = !CommandLine::ForCurrentProcess()->HasSwitch(
119 switches::kFirstExecAfterBoot);
120 reboot_was_requested_ = false;
121 rollback_available_ = false;
122 preparing_for_rollback_ = false;
123 if (!restart_required_) // First exec after boot.
124 reboot_was_requested_ = prefs->GetBoolean(prefs::kFactoryResetRequested);
126 // Check Rollback flag-file.
127 scoped_ptr<bool> file_exists(new bool(false));
128 base::Closure checkfile_closure = base::Bind(
129 &CheckRollbackFlagFileExists,
130 base::Unretained(file_exists.get()));
131 base::Closure on_check_done = base::Bind(
132 &ResetScreenHandler::OnRollbackFlagFileCheckDone,
133 weak_ptr_factory_.GetWeakPtr(),
134 base::Passed(file_exists.Pass()));
135 if (!content::BrowserThread::PostBlockingPoolTaskAndReply(
139 LOG(WARNING) << "Failed to check flag file for Rollback reset option";
144 void ResetScreenHandler::OnRollbackFlagFileCheckDone(
145 scoped_ptr<bool> file_exists) {
146 if (!(*file_exists) && !CommandLine::ForCurrentProcess()->HasSwitch(
147 switches::kEnableRollbackOption)) {
148 rollback_available_ = false;
150 } else if (!restart_required_ && reboot_was_requested_) {
151 // First exec after boot.
152 PrefService* prefs = g_browser_process->local_state();
153 rollback_available_ = prefs->GetBoolean(prefs::kRollbackRequested);
156 chromeos::DBusThreadManager::Get()->GetUpdateEngineClient()->
157 CanRollbackCheck(base::Bind(&ResetScreenHandler::OnRollbackCheck,
158 weak_ptr_factory_.GetWeakPtr()));
162 void ResetScreenHandler::Hide() {
163 DBusThreadManager::Get()->GetUpdateEngineClient()->RemoveObserver(this);
166 void ResetScreenHandler::SetDelegate(Delegate* delegate) {
167 delegate_ = delegate;
172 void ResetScreenHandler::DeclareLocalizedValues(
173 LocalizedValuesBuilder* builder) {
174 builder->Add("resetScreenTitle", IDS_RESET_SCREEN_TITLE);
175 builder->Add("resetScreenAccessibleTitle", IDS_RESET_SCREEN_TITLE);
176 builder->Add("resetScreenIconTitle",IDS_RESET_SCREEN_ICON_TITLE);
177 builder->Add("cancelButton", IDS_CANCEL);
179 builder->Add("resetWarningDataDetails",
180 IDS_RESET_SCREEN_WARNING_DETAILS_DATA);
181 builder->Add("resetRestartMessage", IDS_RESET_SCREEN_RESTART_MSG);
182 builder->AddF("resetRollbackOption",
183 IDS_RESET_SCREEN_ROLLBACK_OPTION,
184 IDS_SHORT_PRODUCT_NAME);
185 builder->AddF("resetRevertPromise",
186 IDS_RESET_SCREEN_PREPARING_REVERT_PROMISE,
187 IDS_SHORT_PRODUCT_NAME);
188 builder->AddF("resetRevertSpinnerMessage",
189 IDS_RESET_SCREEN_PREPARING_REVERT_SPINNER_MESSAGE,
190 IDS_SHORT_PRODUCT_NAME);
192 // Different variants of the same UI elements for all dialog cases.
193 builder->Add("resetButtonReset", IDS_RESET_SCREEN_RESET);
194 builder->Add("resetButtonRelaunch", IDS_RELAUNCH_BUTTON);
195 builder->Add("resetButtonPowerwash", IDS_RESET_SCREEN_POWERWASH);
198 "resetAndRollbackWarningTextConfirmational",
199 IDS_RESET_SCREEN_CONFIRMATION_WARNING_POWERWASH_AND_ROLLBACK_MSG,
200 IDS_SHORT_PRODUCT_NAME);
201 builder->AddF("resetWarningTextConfirmational",
202 IDS_RESET_SCREEN_CONFIRMATION_WARNING_POWERWASH_MSG,
203 IDS_SHORT_PRODUCT_NAME);
204 builder->AddF("resetWarningTextInitial",
205 IDS_RESET_SCREEN_WARNING_MSG,
206 IDS_SHORT_PRODUCT_NAME);
209 "resetAndRollbackWarningDetailsConfirmational",
210 IDS_RESET_SCREEN_CONFIRMATION_WARNING_ROLLBACK_DETAILS,
211 IDS_SHORT_PRODUCT_NAME);
212 builder->AddF("resetWarningDetailsConfirmational",
213 IDS_RESET_SCREEN_CONFIRMATION_WARNING_DETAILS,
214 IDS_SHORT_PRODUCT_NAME);
215 builder->AddF("resetWarningDetailsInitial",
216 IDS_RESET_SCREEN_WARNING_DETAILS,
217 IDS_SHORT_PRODUCT_NAME);
220 // Invoked from call to CanRollbackCheck upon completion of the DBus call.
221 void ResetScreenHandler::OnRollbackCheck(bool can_rollback) {
222 VLOG(1) << "Callback from CanRollbackCheck, result " << can_rollback;
223 rollback_available_ = can_rollback;
228 void ResetScreenHandler::RegisterPrefs(PrefRegistrySimple* registry) {
229 registry->RegisterBooleanPref(prefs::kFactoryResetRequested, false);
230 registry->RegisterBooleanPref(prefs::kRollbackRequested, false);
233 void ResetScreenHandler::Initialize() {
234 if (!page_is_ready() || !delegate_)
239 show_on_init_ = false;
243 void ResetScreenHandler::RegisterMessages() {
244 AddCallback("cancelOnReset", &ResetScreenHandler::HandleOnCancel);
245 AddCallback("restartOnReset", &ResetScreenHandler::HandleOnRestart);
246 AddCallback("powerwashOnReset", &ResetScreenHandler::HandleOnPowerwash);
247 AddCallback("resetOnLearnMore", &ResetScreenHandler::HandleOnLearnMore);
250 void ResetScreenHandler::HandleOnCancel() {
251 if (preparing_for_rollback_)
255 DBusThreadManager::Get()->GetUpdateEngineClient()->RemoveObserver(this);
258 void ResetScreenHandler::HandleOnRestart(bool should_rollback) {
259 PrefService* prefs = g_browser_process->local_state();
260 prefs->SetBoolean(prefs::kFactoryResetRequested, true);
261 prefs->SetBoolean(prefs::kRollbackRequested, should_rollback);
262 prefs->CommitPendingWrite();
264 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->RequestRestart();
267 void ResetScreenHandler::HandleOnPowerwash(bool rollback_checked) {
268 if (rollback_available_ && (rollback_checked || reboot_was_requested_)) {
269 preparing_for_rollback_ = true;
270 CallJS("updateViewOnRollbackCall");
271 DBusThreadManager::Get()->GetUpdateEngineClient()->AddObserver(this);
272 chromeos::DBusThreadManager::Get()->GetUpdateEngineClient()->Rollback();
274 if (rollback_checked && !rollback_available_) {
276 "Rollback was checked but not available. Starting powerwash.";
278 chromeos::DBusThreadManager::Get()->GetSessionManagerClient()->
283 void ResetScreenHandler::HandleOnLearnMore() {
284 if (!help_app_.get())
285 help_app_ = new HelpAppLauncher(GetNativeWindow());
286 help_app_->ShowHelpTopic(HelpAppLauncher::HELP_POWERWASH);
289 void ResetScreenHandler::UpdateStatusChanged(
290 const UpdateEngineClient::Status& status) {
291 VLOG(1) << "Update status change to " << status.status;
292 if (status.status == UpdateEngineClient::UPDATE_STATUS_ERROR ||
294 UpdateEngineClient::UPDATE_STATUS_REPORTING_ERROR_EVENT) {
295 preparing_for_rollback_ = false;
296 // Show error screen.
297 base::DictionaryValue params;
298 params.SetInteger("uiState", kErrorUIStateRollback);
299 ShowScreen(OobeUI::kScreenErrorMessage, ¶ms);
300 } else if (status.status ==
301 UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT) {
302 DBusThreadManager::Get()->GetPowerManagerClient()->RequestRestart();
306 } // namespace chromeos