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